Skip to main content

Quick Start

Introduction​

A lightweight Maven library for integrating AG Grid Server-Side Mode with backend applications using JPA. This solution simplifies querying mapped entities for AG Grid and supports advanced server-side operations, including sorting, filtering, pagination, row grouping, and pivoting.

Active Development

This project is under active development. Breaking changes may occur between versions.

Installation​

Available via maven dependency

Version
<dependency>
<groupId>io.github.smolcan</groupId>
<artifactId>ag-grid-jpa-adapter</artifactId>
<version>${ag-grid-jpa-adapter.version}</version>
</dependency>

Requirements πŸ› οΈ

  • Java: Version 11 or higher.
  • JPA: Version 3.1.0.
  • JPA static metamodel: an annotation processor that generates the *_ metamodel classes (e.g. hibernate-jpamodelgen) β€” see step 2 below.

Using AG Grid JPA Adapter​

When enabling 'serverSide' row model type in your AG Grid, you must provide datasource, which is used to fetch rows for the grid, such as:

AG Grid example of datasource
const createDatasource = server => {
return {
// called by the grid when more rows are required
getRows: params => {

// get data for request from server
const response = server.getData(params.request);

if (response.success) {
// supply rows for requested block to grid
params.success({
rowData: response.rows
});
} else {
// inform grid request failed
params.fail();
}
}
};
}

AG Grid JPA Adapter can process the AG Grid’s request and return corresponding data using JPA abstraction, which avoids the use of native queries, ensures compatibility with multiple databases, and promotes maintainable and scalable code.

The only entrypoint you interact with is QueryBuilder, and its method getRows, which processes a ServerSideGetRowsRequest object, builds the query using JPA Criteria API, executes it and returns a LoadSuccessParams object which you can return directly to the grid.

Complete Example​

1. Your JPA entity:

@Entity
@Table(name = "trade")
public class Trade {
@Id
private Long id;
private String product;
private String portfolio;
private BigDecimal currentValue;
// getters / setters
}

2. Generate the JPA static metamodel:

Columns are declared with the generated JPA static metamodel attributes (Trade_.product), so you need a metamodel generator on your build β€” for example hibernate-jpamodelgen:

<annotationProcessorPaths>
<path>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>${hibernate.version}</version>
</path>
</annotationProcessorPaths>

3. Build a QueryBuilder once (e.g. in a Spring @Service):

@Service
public class TradeService {

// type parameters are <entity, id type, master-detail detail type>;
// use Void for the detail type when not using master-detail
private final QueryBuilder<Trade, Long, Void> queryBuilder;

public TradeService(@Autowired EntityManager entityManager) {
// pass the entity's @Id attribute as the second argument
this.queryBuilder = QueryBuilder.builder(Trade.class, Trade_.id, entityManager)
.colDefs(
ColDef.builder(Trade_.id).sortable(true).build(),
ColDef.builder(Trade_.product).filter(new AgTextColumnFilter()).build(),
ColDef.builder(Trade_.portfolio).filter(AgSetColumnFilter.forString()).build(),
ColDef.builder(Trade_.currentValue)
.filter(new AgNumberColumnFilter<BigDecimal>())
.enableValue(true)
// row grouping needs a converter from the string group key to the column type
.enableRowGroup(true, BigDecimal::new)
.build()
)
.build();
}

public LoadSuccessParams getRows(ServerSideGetRowsRequest request) {
return this.queryBuilder.getRows(request);
}
}

To map a column onto a related entity, build the path with FieldPath instead of a single attribute:

ColDef.builder(FieldPath.of(Trade_.submitter).to(Submitter_.id))
.filter(new AgNumberColumnFilter<Long>())
.build()

4. Expose an endpoint:

@RestController
@RequestMapping("/api/trades")
public class TradeController {

private final TradeService tradeService;

@PostMapping("/getRows")
public LoadSuccessParams getRows(@RequestBody ServerSideGetRowsRequest request) {
return tradeService.getRows(request);
}
}

5. Point AG Grid at your endpoint:

const datasource = {
getRows: (params) => {
fetch('/api/trades/getRows', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params.request),
})
.then(res => res.json())
.then(data => params.success({ rowData: data.rowData, rowCount: data.rowCount }))
.catch(() => params.fail());
}
};
gridApi.setGridOption('serverSideDatasource', datasource);