Adding exports to a new domain
- Add the export module as a dependency in your POM
- Create a new class extending
ExportEntityType
and add a new type in accordance to the domain that you're adding exports to Create an admin extension handler to add a button for exporting on the page that you want exporting to be done in the admin
Most likely this would be done by creating a class that extends
AbstractAdminAbstractControllerExtensionHandler
and implementsaddAdditionalMainActions()
. Be sure that one of the button classes isexport-standard-action
in order for the JavaScript in the export module to automatically setup the onclick listener for it. Example:@Override public ExtensionResultStatusType addAdditionalMainActions(String sectionClassName, List<EntityFormAction> actions) { if (sectionClassName.equals(CustomerSegment.class.getName()) || sectionClassName.equals(CustomerSegmentImpl.class.getName())) { actions.add(new EntityFormAction("export-customer-segment") .withDisplayText("export_customer_segments") .withIconClass("icon-upload") .withButtonClass("export-standard-action") .withUrlOverride("/export/customer-segment") ); return ExtensionResultStatusType.HANDLED_CONTINUE; } return ExtensionResultStatusType.NOT_HANDLED; }
Create a controller class extending
AdminAbstractExportController
Override the
viewConfigurePrompt
anduploadExport
methods with the url you chose for the.withUrlOverride
property.
In order to use the default modal popup provided in the export module be sure that the GET returnssuper.viewConfigurePrompt(request, response, model)
, which will return the default modal view"views/configureExportPrompt"
.
An example of the GET and POST overriding methods for the CustomerSegment export is shown below/** * Shows the form that the allows the user to create an export file */ @GetMapping(value = "/customer-segment") public String viewConfigurePrompt(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception { return super.viewConfigurePrompt(request, response, model); } /** * Used by the Export Prompt to schedule a job so that the export can be processed later. */ @PostMapping(value = "/customer-segment", produces = MediaType.APPLICATION_JSON_VALUE) public @ResponseBody Map<String, String> uploadExport(HttpServletRequest request, HttpServletResponse response, @ModelAttribute(name = "exportContext") ExportContext exportContext, BindingResult result) { return super.uploadExport(request, response, exportContext, result); }
Override the
getDefaultFriendlyName()
method and return a default name you want to use for the exported file if the user didn't enter any file friendly name.@Override protected String getDefaultFriendlyName() { return "My Customer Segment Export"; }
Override the
getExportScheduler()
method and return yourExportScheduler
that will be defined in the next step.@Override protected ExportScheduler getExportScheduler() { return customerSegmentExportScheduler; }
Override the
canUseDateRange()
method and returntrue
if you want to allow users to specify a date range for the export.@Override protected boolean canUseDateRange() { return true; }
Next create an export event scheduler that extends
AbstractExportScheduler
, and override thegetTotalRecords()
andgetProcessType()
methods. The rest will be handled by theAbstractExportScheduler
. For example:@Component @ConditionalOnExport public class CustomerSegmentExportScheduler extends AbstractExportScheduler { @Resource protected CustomerSegmentService customerSegmentService; @Override protected Long getTotalRecords() { return customerSegmentService.getTotalRecordsCount(); } @Override protected String getProcessType() { return CustomerSegmentExportProcessExecutor.PROCESS_TYPE; } }
Then create an
ExportProcessExector
that extendsAbstractExportProcessExecutor
. Override the following methods so that theAbstractExportProcessExecutor
can properly handle the export job. For example:@ConditionalOnExport @Component("blCustomerSegmentExportProcessExecutor") public class CustomerSegmentExportProcessExecutor extends AbstractExportProcessExecutor { public static final String DEFAULT_EXPORT_FILENAME = "customerSegmentExport"; public static final String PROCESS_TYPE = "CUSTOMER_SEG_EXPORT"; public static final String ENTITY_TYPE = "CUSTOMER"; public static final String CUSTOMER_SEGMENT_EXPORT_BATCH_SIZE_PROPERTY = "customerSegments.export.batchSize"; @Resource(name = "blCustomerSegmentExportService") protected CustomerSegmentExportService customerSegmentExportService; @Override protected ExportService<?> getExportService() { return customerSegmentExportService; } @Override protected String getBatchSizePropertyName() { return CUSTOMER_SEGMENT_EXPORT_BATCH_SIZE_PROPERTY; } @Override protected String getDefaultExportFileName() { return DEFAULT_EXPORT_FILENAME; } @Override protected String getEntityType() { return ENTITY_TYPE; } @Override public String getProcessType() { return PROCESS_TYPE; } }
Lastly, create a service to actually do the work of exporting. The Executor will call
YourEventConsumer.export()
method,
which is implemented inAbstractExportService
. ExtendAbstractExportService<T, D>
and override the necessary methods for a
clean and easy implementation. For example:@ConditionalOnExport @Service("blCustomerSegmentExportService") public class CustomerSegmentExportServiceImpl extends AbstractExportService<CustomerCustomerSegmentXref, CustomerSegmentDTO> implements CustomerSegmentExportService { @Resource(name = "blCustomerSegmentService") protected CustomerSegmentService customerSegmentService; @Override public List<CustomerCustomerSegmentXref> readBatch(int recordStartingPoint, ExportProcessExecutorContext context) { return customerSegmentService.findBatchCustomerCustomerSegXrefs(recordStartingPoint, context.getBatchSize()); } @Override protected CustomerSegmentDTO wrap(CustomerCustomerSegmentXref customerSegment, ExportProcessExecutorContext exportProcessContext) { CustomerSegmentDTO dto = applicationContext.getBean(CustomerSegmentDTO.class); return dto.wrap(customerSegment); } @Override protected Class<? extends CustomerSegmentDTO> getDtoClass() { return CustomerSegmentDTO.class; } @Override public Long getTotalRecordsCount() { return customerSegmentService.readNumberOfCustomerSegments(); } }
}
If you would wish for your export to support additional formats or encodings then it's advised to create classes extending
SupportedExportEncoding
and/orSupportedExportType
.