Jmix View
Any Jmix view can serve as a process form. This enables more complex user interactions compared to Input Dialog.
Creating a Process Form
A Jmix view process form is a regular application view that includes annotations to carry process-related details.
Converting Existing View
To convert a regular view to process form:
-
Add the @ProcessForm annotation to the controller class. Declare outcomes, parameters, and output variables as appropriate.
-
Inject and bind process variables using @ProcessVariable.
-
Handle button clicks to complete the task using ProcessFormContext.
| Avoid converting views that are already in use. It is best to create a new view to serve as a process form. |
Using Jmix Studio
To create a process form using Jmix Studio:
-
Click New → View to open View Creation Wizard.
-
Select the BPM Process form template.

-
Configure the form template and the element it is intended for:
-
Select Form template from the two options:
-
Process Form with Process Variables: this form will render components to a set of process variables you select.
-
Process Form for Entity Instance: this form will render components for specific entity instance attributes along with any added process variables.
-
-
Select Form type:
-
User task form: this form is intended for user task elements.
-
Start form: this form is intended for start event elements.

-
-
-
In case of Process form for entity instance, specify the entity class, variable name, and configure the fetch plan.
-
Specify process variables.
-
In case of User task form specify form outcomes. The defaults are
submitandreject. Edit these or add more. -
Add localizable messages.
-
Click Create.
The form will appear among other views in your applications.
Setting up Element with a Process Form
Once you created a process form, you can set up an element to use it. Follow the steps below:
-
Open the Modeler.
-
Select the appropriate element (User Task or Start Event).

-
Set Form type to
Jmix view. -
Set Open mode:
-
Dialog: to display form in a dialog.
-
Navigate: to display form as a view at its own URL.
-
-
Specify View id. The list of options will include all application views annotated with
@ProcessForm. Modeler will recognize the process form and complete the remaining settings based on its annotations. -
If there are any form parameters, configure them with value source accordingly.
The process form is now set up for use in the selected element.
@ProcessForm
Adding @ProcessForm to a view controller class converts a view to a process form and makes the Modeler aware of it. This annotation can include the following attributes:
-
To restrict the use of a form to specific processes, specify the process keys in the
allowedProcessKeysattribute:@ProcessForm(allowedProcessKeys = {"process-1", "process-2"}) -
To declare form outcomes, use the
outcomesattribute:@ProcessForm( outcomes = { (1) @Outcome(id = "approve"), @Outcome(id = "reject") } ) -
To specify output variables, use the
outputVariablesattribute:@ProcessForm( outputVariables = { @OutputVariable(name = "order", type = Order.class), @OutputVariable(name = "comment", type = String.class) } ) -
To set a process variable only upon completing a task with a specific outcome, combine the
outcomesandoutputVariablesattributes as follows:@ProcessForm( outcomes = { @Outcome( id = "approve", outputVariables = { @OutputVariable(name = "nextActor", type = User.class) (1) } ), @Outcome( id = "reject", outputVariables = { @OutputVariable(name = "rejectionReason", type = String.class) (2) } ) }, outputVariables = { @OutputVariable(name = "comment", type = String.class) (3) } )1 The nextActorvariable is set when the task is completed with theapproveoutcome.2 The rejectionReasonvariable is set when the task is completed with therejectoutcome.3 The commentvariable is set in all cases. -
To declare form parameters use the
paramsattribute. Then, set@ProcessFormParamon class fields to link them to those parameters.@ProcessForm( params = { @Param(name = "nextActor"), @Param(name = "entityPickerCaption") } ) //... @ProcessFormParam private String nextActor; @ProcessFormParam private String entityPickerCaption;@ProcessFormParamcan take anameattribute. If no name is explicitly specified, the default name is derived from the field name.
@ProcessVariable
@ProcessVariable can be set on class fields and view components. It indicates that the process variable’s value will be set to that field when the process form opens. In the case of a view component, the variable’s value will be set in that component.
@ProcessVariable
private Date date;
@ViewComponent
@ProcessVariable(name = "order")
private EntityPicker<Order> orderEntityPicker;
If no name is explicitly specified, the default process variable name is derived from the field name.
ProcessFormContext
The ProcessFormContext object contains information about the definition of the process being started or the user task that needs to be completed. Use ProcessFormContext when the process form is opened from the Start Process or My Tasks views. To open a process form with an injected ProcessFormContext programmatically, use the ProcessFormViews bean.
Consider the following example of starting a process:
@ProcessVariable
private Date date;
@ViewComponent
@ProcessVariable(name = "order")
private EntityPicker<Order> orderEntityPicker;
@Autowired
private ProcessFormContext processFormContext;
@Subscribe("startProcessBtn")
public void onStartProcessBtnClick(ClickEvent<JmixButton> event) {
processFormContext.processStarting() (1)
.withBusinessKey("order-1") (2)
.addProcessVariable("date", date)
.addProcessVariable("order", orderEntityPicker.getValue()) (3)
.start(); (4)
closeWithDefaultAction(); (5)
}
| 1 | Creates a ProcessStarting instance. |
| 2 | Sets a business key to the process instance. |
| 3 | Adds a process variable. |
| 4 | Starts the actual process. |
| 5 | Closes the opened window. |
Consider the following example of completing a user task:
@Autowired
private ProcessFormContext processFormContext;
@Subscribe("rejectBtn")
protected void onRejectBtnClick(ClickEvent<JmixButton> event) {
processFormContext.taskCompletion() (1)
.withOutcome("reject") (2)
.saveInjectedProcessVariables() (3)
.complete(); (4)
closeWithDefaultAction(); (5)
}
| 1 | Creates a TaskCompletion instance. |
| 2 | Sets a task outcome. |
| 3 | Indicates that values of class fields annotated with the @ProcessVariables should be collected and saved as process variables. |
| 4 | Completes the actual task. |
| 5 | Closes the opened window. |
Examples
Start Process Form
Let’s look at the example of the process form that is used as a start form. The form displays two fields:
-
A text field to enter the order number.
-
An
entityPickerto select the manager. The manager can be the next process actor.
View XML descriptor:
<view xmlns="http://jmix.io/schema/flowui/view"
title="msg://com.company.bpmex1.view.forms/startProcessForm.title">
<layout>
<formLayout>
<textField id="orderNumber"
label="msg://com.company.bpmex1.view.forms/orderNumber"
datatype="string"/>
<entityPicker id="managerEntityPicker"
metaClass="User"
label="msg://managerEntityPicker.caption">
<actions>
<action id="lookup" type="entity_lookup"/>
<action id="clear" type="entity_clear"/>
</actions>
</entityPicker>
</formLayout>
<hbox id="actionsPanel" spacing="true">
<button id="startProcessBtn"
icon="CHECK"
text="msg://com.company.bpmex1.view.forms/startProcessBtn.text"/>
</hbox>
</layout>
</view>
View controller:
@ViewController("OrderApprovalStartForm")
@ViewDescriptor("order-approval-start-form.xml")
@ProcessForm (1)
public class OrderApprovalStartForm extends StandardView {
@ViewComponent
@ProcessVariable (2)
private TypedTextField<String> orderNumber;
@ViewComponent
@ProcessVariable(name = "manager") (3)
private EntityPicker<User> managerEntityPicker;
@Autowired
private ProcessFormContext processFormContext; (4)
@Subscribe("startProcessBtn")
public void onStartProcessBtnClick(ClickEvent<JmixButton> event) {
processFormContext.processStarting()
.withBusinessKey(orderNumber.getValue()) (5)
.saveInjectedProcessVariables() (6)
.start();
closeWithDefaultAction();
}
}
| 1 | The @ProcessForm annotation indicates that this view is a process form and the view will be available in the modeler. |
| 2 | We declare that the injected orderNumber UI component is a process variable. Since we develop a start process form,
the variable has no value yet, but the annotation will be used on process start. |
| 3 | The same as 2, but here the manager process variable name differs from the managerEntityPicker field name. |
| 4 | ProcessFormContext is the object that we use to start the process. |
| 5 | When we start the process, we can pass an optional process instance business key.
We use the orderNumber here. |
| 6 | The saveInjectedProcessVariables() saves values of the fields annotated with
the @ProcessVariables as process variables on process start.
Instead of using
|
Task Process Form
Let’s look at the example of the task process form that displays two fields:
-
The first one will display a value of the existing process variable -
orderNumber. -
The second field will be used for the new process variable -
comment.
Approve and Reject buttons complete the user task with the corresponding outcome.
View XML descriptor:
<view xmlns="http://jmix.io/schema/flowui/view"
title="msg://orderApprovalTaskForm.title">
<layout>
<formLayout>
<textField id="orderNumber" readOnly="true"
label="msg://orderNumber"/>
<textField id="commentField" label="msg://comment"/>
</formLayout>
<hbox id="actionsPanel" spacing="true">
<button id="approveBtn" icon="CHECK" text="msg://approveBtn.text"/>
<button id="rejectBtn" icon="BAN" text="msg://rejectBtn.text"/>
</hbox>
</layout>
</view>
View controller:
@ViewController("OrderApprovalTaskForm")
@ViewDescriptor("order-approval-task-form.xml")
@ProcessForm(
outcomes = { (1)
@Outcome(id = "approve"),
@Outcome(id = "reject")
}
)
public class OrderApprovalTaskForm extends StandardView {
@ViewComponent
@ProcessVariable (2)
private TypedTextField<String> orderNumber;
@ViewComponent
@ProcessVariable(name = "comment") (3)
private TypedTextField<String> commentField;
@Autowired
private ProcessFormContext processFormContext;
@Subscribe("approveBtn")
protected void onApproveBtnClick(ClickEvent<JmixButton> event) {
processFormContext.taskCompletion()
.withOutcome("approve")
.saveInjectedProcessVariables() (4)
.complete();
closeWithDefaultAction();
}
@Subscribe("rejectBtn")
protected void onRejectBtnClick(ClickEvent<JmixButton> event) {
processFormContext.taskCompletion()
.withOutcome("reject")
.addProcessVariable("comment", commentField.getValue()) (5)
.complete();
closeWithDefaultAction();
}
}
| 1 | The form defines two possible outcomes that can be used in a sequence flow node condition in the modeler. This information is used by the modeler only. |
| 2 | The orderNumber variable has been already set on process start.
Because of the @ProcessVariable annotation,
the value of the orderNumber process variables will be set to the orderNumber text field when the form is displayed. |
| 3 | The comment variable is not set yet, but the @ProcessVariable annotation will be taken into account
when we complete the task in the button click listener. |
| 4 | Values of all fields annotated with the @ProcessVariable will be saved as process variables on task completion. |
| 5 | An alternative way to define process variables. Instead of using the saveInjectedProcessVariables() method,
you can define process variables directly. |
Opening Forms Programmatically
Use the ProcessFormViews service to open start process forms and task process forms defined in the modeler.
In the example below, the button in the list view opens the start process form.
@Autowired
private RepositoryService repositoryService;
@Autowired
protected ProcessFormViews processFormViews;
@Subscribe("startProcessBtn")
public void onStartProcessBtnClick(final ClickEvent<JmixButton> event) {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() (1)
.processDefinitionKey("order-process")
.latestVersion()
.singleResult();
processFormViews.openStartProcessForm(processDefinition, this); (2)
}
| 1 | Get a process definition by key. |
| 2 | Show the start process form with the provided process definition. |
To open a task form, use the openTaskProcessForm() method:
@Autowired
private TaskService taskService;
@Autowired
private ProcessFormViews processFormViews;
@Subscribe("openTaskBtn")
public void onOpenTaskBtnClick(ClickEvent<JmixButton> event) {
Task task = taskService.createTaskQuery()
.processDefinitionKey("approve-order-process")
.taskAssignee("admin")
.active()
.orderByTaskCreateTime()
.list()
.get(0);
processFormViews.openTaskProcessForm(task, this);
}
Process Form with Parameters
Process forms can accept external parameters to adjust their behavior or appearance, such as changing component captions. In contrast to process variables, these form parameters have a narrower scope and are only available within the specific form (unless you save their value to a process variable).
Form parameters are declared with the @ProcessForm annotation and its params attribute. They are linked to a class field using the @ProcessFormParam annotation.
|
To illustrate, let’s consider the scenario where you need a form for selecting the next process actor. This form should feature an EntityPicker component to select a user that is then saved to a process variable. Also, this form will be reused at various steps in the process, so it would be nice to parametrize caption for the entity picker.
There will be two form parameters overall:
-
nextActor– to save the user selected in theEntityPickerfor further use in the process. -
entityPickerCaption– to customize the caption on theEntityPickercomponent based on the process step.
View XML descriptor:
<view xmlns="http://jmix.io/schema/flowui/view"
title="msg://com.company.bpmex1.view.forms/actorSelectionForm.title">
<layout spacing="true">
<formLayout width="20em">
<entityPicker id="userEntityPicker"
metaClass="User"
property="username">
<actions>
<action id="lookup" type="entity_lookup"/>
<action id="clear" type="entity_clear"/>
</actions>
</entityPicker>
</formLayout>
<hbox spacing="true">
<button id="completeTaskBtn" icon="CHECK" text="msg://completeTask"/>
</hbox>
</layout>
</view>
View controller:
@ProcessForm(
params = {
@Param(name = "nextActor"),
@Param(name = "entityPickerCaption")
}
)
public class ActorSelectionForm extends StandardView {
@Autowired
private ProcessFormContext processFormContext;
@ViewComponent
private EntityPicker<String> userEntityPicker;
//...
@ProcessFormParam
private String nextActor;
@ProcessFormParam
private String entityPickerCaption;
@Subscribe
private void onBeforeShow(BeforeShowEvent event) {
userEntityPicker.setLabel(entityPickerCaption);
}
@Subscribe("completeTaskBtn")
private void onCompleteTaskBtnClick(ClickEvent<JmixButton> event) {
processFormContext.taskCompletion()
.addProcessVariable(nextActor, userEntityPicker.getValue())
.complete();
closeWithDefaultAction();
}
}
|
To get a full list of process form parameters, use the
|