Skip to content

Customising AutoCrud behaviour

AutoCrud<T> and FilteredAutoCrud<Filters, T> cover the common case out of the box. When you need to go further — custom search queries, pre-populated creation forms, or a custom read-only view — override the protected hooks directly in your subclass. No extra class is needed.


These methods are public in FilteredAutoCrud and can be overridden in any AutoCrud or FilteredAutoCrud subclass:

MethodDefault behaviourOverride to…
fetchRows(searchText, filters, pageable, httpRequest)In-memory filter via toString() / Searchable.searchableText()Query a database or external service
buildNamedView(id, httpRequest)Loads via repository().findById(id), wraps in AutoNamedViewReturn a custom view (pre-loaded data, extra context, etc.)
buildCreationForm(httpRequest)Instantiates a new T, wraps in AutoNamedViewPre-populate fields on the creation form

@Service
@UI("/products")
public class ProductCrud extends FilteredAutoCrud<ProductFilters, Product> {
private final ProductRepository repository;
public ProductCrud(ProductRepository repository) {
this.repository = repository;
}
@Override
public Class filtersClass() {
return ProductFilters.class;
}
@Override
public CrudRepository<Product> repository() {
return repository;
}
@Override
public ListingData<Product> fetchRows(
String searchText, ProductFilters filters,
Pageable pageable, HttpRequest httpRequest) {
return repository.search(searchText, filters.category(), filters.active(), pageable);
}
}

@Service
@UI("/orders")
public class OrderCrud extends AutoCrud<Order> {
private final OrderRepository repository;
public OrderCrud(OrderRepository repository) {
this.repository = repository;
}
@Override
public CrudRepository<Order> repository() {
return repository;
}
@Override
public AutoNamedView<Order> buildCreationForm(HttpRequest httpRequest) {
var order = new Order();
order.setDate(LocalDate.now());
order.setStatus(OrderStatus.DRAFT);
return new AutoNamedView<>(Order.class, order, repository());
}
}

AutoNamedView<T> is what buildNamedView and buildCreationForm return by default. It wraps any T extends Identifiable and wires all CRUD contracts to the entity and the repository:

new AutoNamedView<>(entityClass, entity, repository)
Constructor parameterPurpose
entityClassDetermines which fields to render
entityThe object serialised as form state
repositoryCalled by save() and create() to persist

If the view, editor, and creation form need to be genuinely different types (different fields, different DTOs), step up to Crud<View,Editor,CreationForm,Filters,Row,Id> and implement CrudAdapter directly.