1. Activiti External Form Rendering
Reference: Activiti in Action
Reference: Activiti 5.10 User Guide. http://activiti.org/userguide/index.html#externalFormRendering
Reference: http://rongjih.blog.163.com/blog/static/33574461201263124922670/
We should be aware of the difference of StartForm and TaskForm.
Fact 1: FormService Interface should be implemented by myself
StartForm Methods |
TaskForm Methods | Note |
getStartFormData | getTaskFormData | no template involved |
getRenderedStartForm | getRenderedTaskForm | template loaded, and script like juel in template evaluated |
submitStartFormData | submitTaskFormData |
Any reference implementation of FormService interface? YES! org.activiti.engine.impl.FormServiceImpl
public class FormServiceImpl extends ServiceImpl implements FormService { //HERE COMMAND PATTERN APPLIED public Object getRenderedStartForm(String processDefinitionId) { return commandExecutor.execute(new GetRenderedStartFormCmd(processDefinitionId, null)); } public Object getRenderedStartForm(String processDefinitionId, String engineName) { return commandExecutor.execute(new GetRenderedStartFormCmd(processDefinitionId, engineName)); } public Object getRenderedTaskForm(String taskId) { return commandExecutor.execute(new GetRenderedTaskFormCmd(taskId, null)); } public Object getRenderedTaskForm(String taskId, String engineName) { return commandExecutor.execute(new GetRenderedTaskFormCmd(taskId, engineName)); } public StartFormData getStartFormData(String processDefinitionId) { return commandExecutor.execute(new GetStartFormCmd(processDefinitionId)); } public TaskFormData getTaskFormData(String taskId) { return commandExecutor.execute(new GetTaskFormCmd(taskId)); } public ProcessInstance submitStartFormData(String processDefinitionId, Map<String, String> properties) { return commandExecutor.execute(new SubmitStartFormCmd(processDefinitionId, null, properties)); } public ProcessInstance submitStartFormData(String processDefinitionId, String businessKey, Map<String, String> properties) { return commandExecutor.execute(new SubmitStartFormCmd(processDefinitionId, businessKey, properties)); } public void submitTaskFormData(String taskId, Map<String, String> properties) { commandExecutor.execute(new SubmitTaskFormCmd(taskId, properties)); } public String getStartFormKey(String processDefinitionId) { return commandExecutor.execute(new GetFormKeyCmd(processDefinitionId)); } public String getTaskFormKey(String processDefinitionId, String taskDefinitionKey) { return commandExecutor.execute(new GetFormKeyCmd(processDefinitionId, taskDefinitionKey)); } }
public class GetRenderedStartFormCmd implements Command<Object>, Serializable { private static final long serialVersionUID = 1L; protected String processDefinitionId; protected String formEngineName; public GetRenderedStartFormCmd(String processDefinitionId, String formEngineName) { this.processDefinitionId = processDefinitionId; this.formEngineName = formEngineName; } public Object execute(CommandContext commandContext) { ProcessDefinitionEntity processDefinition = Context .getProcessEngineConfiguration() .getDeploymentCache() .findDeployedProcessDefinitionById(processDefinitionId); if (processDefinition == null) { throw new ActivitiException("Process Definition '" + processDefinitionId +"' not found"); } StartFormHandler startFormHandler = processDefinition.getStartFormHandler(); if (startFormHandler == null) { return null; } FormEngine formEngine = Context .getProcessEngineConfiguration() .getFormEngines() .get(formEngineName); if (formEngine==null) { throw new ActivitiException("No formEngine '" + formEngineName +"' defined process engine configuration"); } StartFormData startForm = startFormHandler.createStartFormData(processDefinition); return formEngine.renderStartForm(startForm); } }
Noteworthy: business key
/** * Start a new process instance with the user data that was entered as properties in a start form. * * A business key can be provided to associate the process instance with a * certain identifier that has a clear business meaning. For example in an * order process, the business key could be an order id. This business key can * then be used to easily look up that process instance , see * {@link ProcessInstanceQuery#processInstanceBusinessKey(String)}. Providing such a business * key is definitely a best practice. * * Note that a business key MUST be unique for the given process definition. * Process instance from different process definition are allowed to have the * same business key. * * @param processDefinitionId the id of the process definition, cannot be null. * @param businessKey a key that uniquely identifies the process instance in the context or the * given process definition. * @param properties the properties to pass, can be null. */ ProcessInstance submitStartFormData(String processDefinitionId, String businessKey, Map<String, String> properties);
public abstract class AbstractFormType implements FormType { //What does this mean? public abstract Object convertFormValueToModelValue(String propertyValue); public abstract String convertModelValueToFormValue(Object modelValue); public Object getInformation(String key) { return null; } }
public abstract class FormDataImpl implements FormData, Serializable { private static final long serialVersionUID = 1L; //UNDERSTANDING protected String formKey; protected String deploymentId; protected List<FormProperty> formProperties = new ArrayList<FormProperty>();
public interface FormHandler { ThreadLocal<FormHandler> current = new ThreadLocal<FormHandler>(); void parseConfiguration(Element activityElement, DeploymentEntity deployment, ProcessDefinitionEntity processDefinition, BpmnParse bpmnParse); void submitFormProperties(Map<String, String> properties, ExecutionEntity execution); }