Liferay Dynamic Data Mapping API provides comprehensive APIs for creating, managing, and processing dynamic forms and data structures within Liferay Portal.
—
The DDM API's core data models and services provide the foundation for all Dynamic Data Mapping operations. This includes entity models for structures, templates, forms, and data records, along with comprehensive service layers for CRUD operations, business logic, and database persistence.
Core entity models representing the main DDM data structures.
// Core structure model - defines form schemas and field definitions
interface DDMStructure extends PersistedModel, MVCCModel, StagedModel {
long getStructureId();
long getGroupId();
long getClassNameId();
String getStructureKey();
String getName();
String getDescription();
String getDefinition();
String getStorageType();
int getType();
DDMForm getDDMForm();
DDMFormLayout getDDMFormLayout();
}
// Template model - defines rendering templates for structures
interface DDMTemplate extends PersistedModel, MVCCModel, StagedModel, WorkflowedModel {
long getTemplateId();
long getGroupId();
long getClassNameId();
long getClassPK();
String getTemplateKey();
String getName();
String getDescription();
String getType();
String getMode();
String getLanguage();
String getScript();
String getSmallImageURL();
}
// Form instance model - represents deployed forms based on structures
interface DDMFormInstance extends PersistedModel, MVCCModel, StagedModel, WorkflowedModel {
long getFormInstanceId();
long getGroupId();
long getStructureId();
String getName();
String getDescription();
DDMFormInstanceSettings getSettings();
String getVersion();
}
// Form submission record - represents individual form submissions
interface DDMFormInstanceRecord extends PersistedModel, MVCCModel, StagedModel, WorkflowedModel {
long getFormInstanceRecordId();
long getGroupId();
long getFormInstanceId();
String getFormInstanceVersion();
long getStorageId();
String getVersion();
DDMFormValues getDDMFormValues();
}
// Content storage model - stores serialized form data
interface DDMContent extends PersistedModel {
long getContentId();
long getGroupId();
String getName();
String getDescription();
String getData();
}
// Data provider instance model - external data source configuration
interface DDMDataProviderInstance extends PersistedModel, MVCCModel, StagedModel {
long getDataProviderInstanceId();
long getGroupId();
String getName();
String getDescription();
String getDefinition();
String getType();
DDMDataProviderInstanceSettings getSettings();
}Services for managing data structures that define form schemas and field definitions.
interface DDMStructureLocalService extends BaseLocalService, PersistedModelLocalService {
/**
* Adds a new structure with form definition and layout
*/
DDMStructure addStructure(
long userId, long groupId, long parentStructureId, long classNameId,
String structureKey, Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
DDMForm ddmForm, DDMFormLayout ddmFormLayout, String storageType,
int type, ServiceContext serviceContext) throws PortalException;
/**
* Updates an existing structure
*/
DDMStructure updateStructure(
long userId, long structureId, long parentStructureId,
Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
DDMForm ddmForm, DDMFormLayout ddmFormLayout, ServiceContext serviceContext)
throws PortalException;
/**
* Deletes a structure and its associated data
*/
DDMStructure deleteStructure(long structureId) throws PortalException;
/**
* Retrieves structures by group
*/
List<DDMStructure> getStructures(long groupId);
/**
* Retrieves structures by group and class name
*/
List<DDMStructure> getStructures(long groupId, long classNameId);
/**
* Searches for structures with pagination
*/
Hits search(long companyId, long[] groupIds, long classNameId, String keywords,
int type, int status, int start, int end, Sort sort) throws PortalException;
}
interface DDMStructureService extends BaseService {
/**
* Remote service methods (subset of LocalService with permission checks)
*/
DDMStructure addStructure(long groupId, long parentStructureId, long classNameId,
String structureKey, Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
DDMForm ddmForm, DDMFormLayout ddmFormLayout, String storageType,
int type, ServiceContext serviceContext) throws PortalException;
DDMStructure updateStructure(long structureId, long parentStructureId,
Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
DDMForm ddmForm, DDMFormLayout ddmFormLayout, ServiceContext serviceContext)
throws PortalException;
}Services for managing templates that define how structures are rendered.
interface DDMTemplateLocalService extends BaseLocalService, PersistedModelLocalService {
/**
* Adds a new template with script and configuration
*/
DDMTemplate addTemplate(
long userId, long groupId, long classNameId, long classPK,
long resourceClassNameId, String templateKey, Map<Locale, String> nameMap,
Map<Locale, String> descriptionMap, String type, String mode,
String language, String script, boolean cacheable,
boolean smallImage, String smallImageURL, File smallImageFile,
ServiceContext serviceContext) throws PortalException;
/**
* Updates an existing template
*/
DDMTemplate updateTemplate(
long userId, long templateId, long classPK, Map<Locale, String> nameMap,
Map<Locale, String> descriptionMap, String type, String mode,
String language, String script, boolean cacheable,
boolean smallImage, String smallImageURL, File smallImageFile,
ServiceContext serviceContext) throws PortalException;
/**
* Copies a template to create a new one
*/
DDMTemplate copyTemplate(long userId, long templateId, ServiceContext serviceContext)
throws PortalException;
/**
* Retrieves templates by group and class name
*/
List<DDMTemplate> getTemplates(long groupId, long classNameId);
/**
* Retrieves templates by group, class name, class PK and type
*/
List<DDMTemplate> getTemplates(long groupId, long classNameId, long classPK, String type);
}Services for managing form instances - deployable forms based on structures.
interface DDMFormInstanceLocalService extends BaseLocalService, PersistedModelLocalService {
/**
* Creates a new form instance
*/
DDMFormInstance addFormInstance(
long userId, long groupId, long structureId, Map<Locale, String> nameMap,
Map<Locale, String> descriptionMap, DDMForm ddmForm, DDMFormLayout ddmFormLayout,
DDMFormInstanceSettings settings, ServiceContext serviceContext)
throws PortalException;
/**
* Updates an existing form instance
*/
DDMFormInstance updateFormInstance(
long userId, long formInstanceId, Map<Locale, String> nameMap,
Map<Locale, String> descriptionMap, DDMForm ddmForm, DDMFormLayout ddmFormLayout,
DDMFormInstanceSettings settings, ServiceContext serviceContext)
throws PortalException;
/**
* Publishes a form instance making it available for submissions
*/
void updateFormInstanceWorkflowStatus(long userId, long formInstanceId, int status,
ServiceContext serviceContext) throws PortalException;
/**
* Retrieves form instances by group
*/
List<DDMFormInstance> getFormInstances(long groupId);
/**
* Searches form instances with pagination
*/
BaseModelSearchResult<DDMFormInstance> searchFormInstances(
SearchContext searchContext) throws PortalException;
}Services for managing form submissions and their data.
interface DDMFormInstanceRecordLocalService extends BaseLocalService, PersistedModelLocalService {
/**
* Adds a new form submission record
*/
DDMFormInstanceRecord addFormInstanceRecord(
long userId, long groupId, long formInstanceId, DDMFormValues ddmFormValues,
ServiceContext serviceContext) throws PortalException;
/**
* Updates an existing form record
*/
DDMFormInstanceRecord updateFormInstanceRecord(
long userId, long formInstanceRecordId, DDMFormValues ddmFormValues,
ServiceContext serviceContext) throws PortalException;
/**
* Updates form record status (e.g., draft, approved)
*/
DDMFormInstanceRecord updateStatus(
long userId, long formInstanceRecordId, int status,
ServiceContext serviceContext) throws PortalException;
/**
* Retrieves form records by form instance
*/
List<DDMFormInstanceRecord> getFormInstanceRecords(long formInstanceId);
/**
* Retrieves form records with pagination
*/
List<DDMFormInstanceRecord> getFormInstanceRecords(
long formInstanceId, int status, int start, int end,
OrderByComparator<DDMFormInstanceRecord> orderByComparator);
/**
* Exports form records to various formats
*/
byte[] getFormInstanceRecordsCSV(long formInstanceId, int status) throws PortalException;
}Services for managing external data providers that populate form field options.
interface DDMDataProviderInstanceLocalService extends BaseLocalService, PersistedModelLocalService {
/**
* Adds a new data provider instance
*/
DDMDataProviderInstance addDataProviderInstance(
long userId, long groupId, Map<Locale, String> nameMap,
Map<Locale, String> descriptionMap, DDMForm ddmForm, String type,
ServiceContext serviceContext) throws PortalException;
/**
* Updates an existing data provider instance
*/
DDMDataProviderInstance updateDataProviderInstance(
long userId, long dataProviderInstanceId, Map<Locale, String> nameMap,
Map<Locale, String> descriptionMap, DDMForm ddmForm, String type,
ServiceContext serviceContext) throws PortalException;
/**
* Fetches data from a data provider
*/
DDMDataProviderResponse getData(DDMDataProviderRequest ddmDataProviderRequest)
throws PortalException;
/**
* Retrieves data provider instances by group and type
*/
List<DDMDataProviderInstance> getDataProviderInstances(long groupId, String type);
}@Component
public class FormCreationExample {
@Reference
private DDMStructureLocalService structureLocalService;
@Reference
private DDMFormInstanceLocalService formInstanceLocalService;
@Reference
private DDMFormInstanceRecordLocalService recordLocalService;
public void createCompleteForm(long groupId, long userId) throws PortalException {
ServiceContext serviceContext = new ServiceContext();
serviceContext.setScopeGroupId(groupId);
// 1. Create a structure with form definition
DDMForm ddmForm = createSampleForm();
DDMFormLayout ddmFormLayout = DDMFormLayout.getDefaultDDMFormLayout(ddmForm);
Map<Locale, String> nameMap = Collections.singletonMap(Locale.US, "Contact Form");
Map<Locale, String> descriptionMap = Collections.singletonMap(Locale.US, "Customer contact form");
DDMStructure structure = structureLocalService.addStructure(
userId, groupId,
DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID,
PortalUtil.getClassNameId(DDMContent.class),
null, // auto-generate structure key
nameMap, descriptionMap, ddmForm, ddmFormLayout,
"json", DDMStructureConstants.TYPE_DEFAULT, serviceContext
);
// 2. Create form instance from structure
DDMFormInstanceSettings settings = new DDMFormInstanceSettings();
settings.setRequireAuthentication(false);
settings.setStorageType("json");
DDMFormInstance formInstance = formInstanceLocalService.addFormInstance(
userId, groupId, structure.getStructureId(),
nameMap, descriptionMap, ddmForm, ddmFormLayout,
settings, serviceContext
);
// 3. Publish the form
formInstanceLocalService.updateFormInstanceWorkflowStatus(
userId, formInstance.getFormInstanceId(),
WorkflowConstants.STATUS_APPROVED, serviceContext
);
// 4. Add a sample submission
DDMFormValues formValues = createSampleSubmission(ddmForm);
recordLocalService.addFormInstanceRecord(
userId, groupId, formInstance.getFormInstanceId(),
formValues, serviceContext
);
}
private DDMForm createSampleForm() {
DDMForm ddmForm = new DDMForm();
ddmForm.setDefaultLocale(Locale.US);
ddmForm.addAvailableLocale(Locale.US);
// Name field
DDMFormField nameField = new DDMFormField("name", "text");
nameField.setLabel(new LocalizedValue(Locale.US, "Full Name"));
nameField.setRequired(true);
ddmForm.addDDMFormField(nameField);
// Email field
DDMFormField emailField = new DDMFormField("email", "text");
emailField.setLabel(new LocalizedValue(Locale.US, "Email Address"));
emailField.setRequired(true);
emailField.setDataType("email");
ddmForm.addDDMFormField(emailField);
// Message field
DDMFormField messageField = new DDMFormField("message", "textarea");
messageField.setLabel(new LocalizedValue(Locale.US, "Message"));
messageField.setRequired(false);
ddmForm.addDDMFormField(messageField);
return ddmForm;
}
}@Component
public class FormDataExportExample {
@Reference
private DDMFormInstanceRecordLocalService recordLocalService;
public void exportFormSubmissions(long formInstanceId) throws PortalException {
// Get all approved form records
List<DDMFormInstanceRecord> records = recordLocalService.getFormInstanceRecords(
formInstanceId, WorkflowConstants.STATUS_APPROVED,
QueryUtil.ALL_POS, QueryUtil.ALL_POS, null
);
// Process each submission
for (DDMFormInstanceRecord record : records) {
DDMFormValues formValues = record.getDDMFormValues();
processFormSubmission(record, formValues);
}
// Export to CSV
byte[] csvData = recordLocalService.getFormInstanceRecordsCSV(
formInstanceId, WorkflowConstants.STATUS_APPROVED
);
// Save or stream the CSV data
saveCSVData(csvData, "form-submissions.csv");
}
private void processFormSubmission(DDMFormInstanceRecord record, DDMFormValues formValues) {
Map<String, List<DDMFormFieldValue>> fieldValuesMap = formValues.getDDMFormFieldValuesMap();
// Extract specific field values
String name = getFieldValue(fieldValuesMap, "name");
String email = getFieldValue(fieldValuesMap, "email");
String message = getFieldValue(fieldValuesMap, "message");
System.out.printf("Submission %d: %s (%s) - %s%n",
record.getFormInstanceRecordId(), name, email, message);
}
private String getFieldValue(Map<String, List<DDMFormFieldValue>> fieldValuesMap, String fieldName) {
List<DDMFormFieldValue> fieldValues = fieldValuesMap.get(fieldName);
if (fieldValues != null && !fieldValues.isEmpty()) {
Value value = fieldValues.get(0).getValue();
return value.getString(Locale.getDefault());
}
return "";
}
}class DDMFormValues {
Map<String, List<DDMFormFieldValue>> getDDMFormFieldValuesMap();
void setDDMFormFieldValues(List<DDMFormFieldValue> ddmFormFieldValues);
void setDefaultLocale(Locale defaultLocale);
void setAvailableLocales(Set<Locale> availableLocales);
}
class DDMFormFieldValue {
String getName();
Value getValue();
String getInstanceId();
List<DDMFormFieldValue> getNestedDDMFormFieldValues();
}
class DDMForm {
Set<Locale> getAvailableLocales();
Locale getDefaultLocale();
List<DDMFormField> getDDMFormFields();
Map<String, DDMFormField> getDDMFormFieldsMap(boolean includeNestedFields);
}
class DDMFormField {
String getName();
String getType();
String getDataType();
LocalizedValue getLabel();
LocalizedValue getTip();
boolean isRequired();
boolean isRepeatable();
Map<String, Object> getProperties();
}
class DDMFormLayout {
List<DDMFormLayoutPage> getDDMFormLayoutPages();
Locale getDefaultLocale();
Set<Locale> getAvailableLocales();
}
class ServiceContext {
void setScopeGroupId(long scopeGroupId);
void setWorkflowAction(int workflowAction);
void setAttribute(String name, Serializable value);
}Install with Tessl CLI
npx tessl i tessl/maven-com-liferay--com-liferay-dynamic-data-mapping-api