MetaModelService / PageSchemaService
MetaModelService and PageSchemaService are the canonical read APIs for AuraBoot's metadata catalog — every model, field, and page definition contributed by core or by an installed plugin. They hide the on-disk JSON layout, plugin overlay precedence, and cache resolution behind a set of in-memory lookup methods.
Concept
At plugin import time, the host parses models.json, pages.json, commands.json, bindingRules.json, permissions.json, etc. from every plugin and merges them into a single tenant-scoped metadata catalog. Subsequent calls to MetaModelService go through the in-memory cache. The metadata is read-only at runtime; mutations go through the import path and trigger a cache refresh.
To answer "what fields does model X have?", use these services — never re-parse the JSON yourself.
Interface signature
package com.auraboot.framework.meta.service;
public interface MetaModelService {
Optional<ModelDefinition> getModelDefinition(String modelCode);
FieldDefinition getFieldDefinition(String modelCode, String fieldCode);
List<FieldDefinition> getModelFields(String modelCode); // all fields of the model
/** Dynamic table name for a model — e.g. "crm_lead" → "mt_crm_lead". */
String getTableName(String modelCode);
boolean isModelExists(String modelCode);
boolean isFieldExists(String modelCode, String fieldCode);
void refreshModelCache(String modelCode);
}Page definitions are served by the separate PageSchemaService:
package com.auraboot.framework.meta.service;
public interface PageSchemaService {
PageSchemaDTO findByPageKey(String pageKey); // e.g. "crm_lead-list"
List<PageSchemaDTO> findByModelCode(String modelCode); // list/form/detail kinds
List<PageSchemaDTO> findByKind(String kind);
}ModelDefinition and FieldDefinition are Lombok @Data DTOs with raw config plus convenience accessors (isRequired(), isSearchable(), isDisplayField(), getDefaultValue()).
Implementation example
A custom report service that builds a column list dynamically from a model's field definitions:
package com.acme.report;
import com.auraboot.framework.meta.service.MetaModelService;
import com.auraboot.framework.meta.dto.FieldDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ReportColumnService {
@Autowired private MetaModelService metaModelService;
public List<ReportColumn> columnsFor(String modelCode) {
return metaModelService.getModelFields(modelCode).stream()
.filter(FieldDefinition::isSearchable)
.map(f -> new ReportColumn(
f.getCode(),
f.getDisplayName(),
f.getDataType(),
f.isRequired()))
.toList();
}
}A page-aware example that resolves the dynamic table for a list page:
PageSchemaDTO page = pageSchemaService.findByPageKey("crm_lead-list");
String table = metaModelService.getTableName(page.getModelCode()); // "mt_crm_lead"Registration
MetaModelService and PageSchemaService are both host-managed Spring beans. Inject them via @Autowired from any plugin extension or platform service. There is no SPI to implement — they are services, not extension points. The metadata cache is refreshed automatically on plugin enable/disable and on model.published events.
Common pitfalls
- Calling
getTableName(modelCode)and assumingab_dyn_<code>. The actual prefix ismt_<modelCode>(constantSystemFieldConstants.DYNAMIC_TABLE_PREFIX, see red line §15). Always call the API. - Caching
ModelDefinition/FieldDefinitionreferences across plugin reload. The cache refresh produces new instances; old references are stale. Cache the code and look up on demand. - Reading JSON files directly. Bypasses overlay precedence and validation. Always go through the service.
- Assuming
findByPageKey(modelCode + "-list")returns a user-defined page.MetaModelServiceImpl.autoCreateDefaultPagessilently creates empty stubs on model publish — check whether its blocks are empty before treating it as real.