For architecture and usage, see README.md. This document covers how to build, test, and extend the library.
# Build and test
gradle build
# Tests only
gradle testThere are four moving parts:
| Class | Role |
|---|---|
Attribute<T> |
A sealed interface. Each nested record is one HTML attribute. It owns HTML rendering and server-side validation. |
IDomain<S, U> |
Abstract base for a form field. Holds a value and a list of Attributes. Doubles as a JPA AttributeConverter. |
IDedEntity<I> |
JPA base class for entities. Discovers IDomain fields via reflection and coordinates validation. |
AbstractEntityFormController<S, T> |
Abstract Spring controller. Provides create, edit, update, and ids endpoints for any entity. |
- Add a
recordto thepermitsclause ofAttributeinAttribute.java. - Implement
name()andhtmlValue(). - Override
validate(...)if the attribute has a server-side constraint; leave it as the no-op default if it is render-only.
// Example: a render-only "readonly" attribute
record ReadOnly() implements Attribute<Object> {
@Override public String name() { return "readonly"; }
@Override public String htmlValue() { return "true"; }
}- Create a class that extends
IDomain<S, U>whereSis the Java/DB type andUis the class itself. - Implement
getType()(returns the HTML input type string). - Implement
convertToDatabaseColumnandconvertToEntityAttributefor JPA persistence. - Annotate the class with
@Converter(autoApply = true). - Implement whichever constraint interfaces apply (
IRangeable,IStringControls,IPlaceHolder, etc.) by delegating toaddAttribute(...).
@Converter(autoApply = true)
public class SearchDomain extends IDomain<String, SearchDomain>
implements IPlaceHolder<SearchDomain> {
@Override public String getType() { return "search"; }
@Override public String convertToDatabaseColumn(SearchDomain d) { return d == null ? null : d.getValue(); }
@Override public SearchDomain convertToEntityAttribute(String s) {
SearchDomain d = new SearchDomain();
d.setValue(s);
return d;
}
@Override public SearchDomain placeholder(String text) { return addAttribute(new Attribute.Placeholder(text)); }
}If your domain needs date/time types registered with Spring's ConversionService, they are provided automatically by FormmvcAutoConfiguration — no extra config needed.