Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Difference between revisions of "BPMN2-Modeler/DeveloperTutorials/Validation"
(→Coming Soon!) |
|||
(One intermediate revision by the same user not shown) | |||
Line 3: | Line 3: | ||
==The Basics== | ==The Basics== | ||
− | BPMN2 model validation builds on the [https://www.eclipse.org/emf-validation/ EMF Validation Framework] and supports both "Live" and "Batch" mode validation. There are lots of resources and tutorials on the web that discuss EMF validation; to get started, define | + | BPMN2 model validation builds on the [https://www.eclipse.org/emf-validation/ EMF Validation Framework] and supports both "Live" and "Batch" mode validation. There are lots of resources and tutorials on the web that discuss EMF validation; to get started, define a Constraint Provider extension point in your plugin. This extension point defines all of the validation constraints that will be evaluated, and when. In a nutshell, a '''<constraintProvider>''' contains one or more '''<constraint>''' definitions, and each corresponds to a BPMN2 model type. When model validation is required, EMF traverses the entire model and invokes each of the constraint rules that apply to each model object. This includes base types as well so if, for example, we have a constraint for '''Task''' objects and one for '''Activity''' objects, both of these will be evaluated for each '''Task''' and subclasses of '''Task''' (e.g. '''UserTask''', '''ReceiveTask''', etc.) |
− | ===Live vs Batch Validation | + | Here is a typical constraint provider for a BPMN2 '''Process''' object: |
+ | <pre> | ||
+ | <extension point="org.eclipse.emf.validation.constraintProviders"> | ||
+ | <category | ||
+ | name="jBPM Validation" | ||
+ | id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.category"/> | ||
+ | <constraintProvider cache="true"> | ||
+ | <package namespaceUri="http://www.omg.org/spec/BPMN/20100524/MODEL-XMI"/> | ||
+ | <constraints categories="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.category"> | ||
+ | <constraint | ||
+ | lang="Java" | ||
+ | class="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.JbpmModelConstraint" | ||
+ | severity="ERROR" | ||
+ | mode="Batch" | ||
+ | name="Business Rule Task" | ||
+ | id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.BusinessRuleTask" | ||
+ | statusCode="1"> | ||
+ | <message>{0}</message> | ||
+ | <target class="BusinessRuleTask"/> | ||
+ | </constraint> | ||
+ | </constraints> | ||
+ | </constraintProvider> | ||
+ | </pre> | ||
+ | |||
+ | The discussions that follow will provide a more detailed explanation. | ||
+ | |||
+ | ==Live vs Batch Validation== | ||
"Live" validation is performed just prior to a model change is committed; if the validation result is anything but '''IStatus.OK''', then the change transaction is rolled back and the error message from the constraint handler is displayed in the Workbench status bar. These types of validations are useful for preventing the model from becoming corrupted, and possibly unreadable. A good example of this is BaseElement ID validation: ID strings must follow the [http://stackoverflow.com/questions/1631396/what-is-an-xsncname-type-and-when-should-it-be-used NCName] naming convention, and they must be unique within the file since EMF uses these to resolve forward references of objects. Saving a file with an invalid ID may result in the file being unreadable since the object is not resolvable. | "Live" validation is performed just prior to a model change is committed; if the validation result is anything but '''IStatus.OK''', then the change transaction is rolled back and the error message from the constraint handler is displayed in the Workbench status bar. These types of validations are useful for preventing the model from becoming corrupted, and possibly unreadable. A good example of this is BaseElement ID validation: ID strings must follow the [http://stackoverflow.com/questions/1631396/what-is-an-xsncname-type-and-when-should-it-be-used NCName] naming convention, and they must be unique within the file since EMF uses these to resolve forward references of objects. Saving a file with an invalid ID may result in the file being unreadable since the object is not resolvable. | ||
− | "Batch" validation is performed whenever the file is saved, or if the model is manually validated (right-click on the diagram, then "Validate".) This type of validation is more common and checks for semantic problems in the model; the model is essentially valid, well-formed and syntactically correct, but there may be specific conditions that must be met for the model to make sense. For example, if a Process has been defined as "executable", all data items must specify a data type (i.e., '''ItemAwareElement.itemSubjectRef''' may not be null.) | + | "Batch" validation is performed whenever the file is saved, or if the model is manually validated (right-click on the diagram, then "Validate".) This type of validation is more common and checks for semantic problems in the model; the model is essentially valid, well-formed and syntactically correct, but there may be specific conditions that must be met for the model to make sense. For example, if a '''Process''' has been defined as "executable", all data items must specify a data type (i.e., '''ItemAwareElement.itemSubjectRef''' may not be null.) |
− | + | ==Constraint Languages== | |
− | EMF allows you to write your validation rules in either [https://en.wikipedia.org/wiki/Object_Constraint_Language OCL] or Java | + | EMF allows you to write your validation rules in either [https://en.wikipedia.org/wiki/Object_Constraint_Language OCL] or Java. |
− | + | We have found that for most situations it is best to use Java for writing validation rules simply because many of the constraints are very complex, sometimes involving lookups and validation of referenced elements as well. Your model constraint Java class must extend the EMF AbstractModelConstraint base class. | |
− | EMF constraint providers must declare a namespace URI which defines the model being validated; in our case, this is the BPMN 2.0 model and the namespace URI should be "http://www.omg.org/spec/BPMN/20100524/MODEL-XMI". The constraints declared | + | |
+ | ==Target Classes== | ||
+ | EMF constraint providers must declare a namespace URI which defines the model being validated; in our case, this is the BPMN 2.0 model and the namespace URI should be "http://www.omg.org/spec/BPMN/20100524/MODEL-XMI". The constraints declared within a constraint provider then simply refer to the model type to which the constraint applies. | ||
If however, you have found it necessary to provide an external model for your extension elements (see [https://wiki.eclipse.org/BPMN2-Modeler/DeveloperTutorials/ModelExtension BYOM!]), and you need to perform validation on those objects, there is a caveat: the constraint definition must qualify the Target Class with the namespace URI of your external model. For example, the jBPM extension defines an object named '''GlobalType''' in an external EMF model; this model has the namespace URI "http://www.jboss.org/drools". To define a constraint for a '''GlobalType''' object, we would simply define it like so: | If however, you have found it necessary to provide an external model for your extension elements (see [https://wiki.eclipse.org/BPMN2-Modeler/DeveloperTutorials/ModelExtension BYOM!]), and you need to perform validation on those objects, there is a caveat: the constraint definition must qualify the Target Class with the namespace URI of your external model. For example, the jBPM extension defines an object named '''GlobalType''' in an external EMF model; this model has the namespace URI "http://www.jboss.org/drools". To define a constraint for a '''GlobalType''' object, we would simply define it like so: | ||
Line 32: | Line 60: | ||
</constraint> | </constraint> | ||
</pre> | </pre> | ||
+ | |||
+ | ==Categories== | ||
+ | Constraint categories are used to group constraints, and categories can be enabled or disabled in the User Preference page. The BPMN2 Modeler defines the special category ID "org.eclipse.bpmn2.modeler.core.validation.category.override". This can be used to override BPMN2 core validation constraints defined by the editor. For example, to override core validation of '''Process''' objects, a plugin would define: | ||
+ | |||
+ | <pre> | ||
+ | <extension point="org.eclipse.emf.validation.constraintProviders"> | ||
+ | <!-- These constraints override the ones in BPMN2 Modeler Core Validation --> | ||
+ | <constraintProvider cache="true"> | ||
+ | <package namespaceUri="http://www.omg.org/spec/BPMN/20100524/MODEL-XMI"/> | ||
+ | <constraints categories="org.eclipse.bpmn2.modeler.core.validation.category.override"> | ||
+ | <constraint | ||
+ | lang="Java" | ||
+ | class="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.JbpmModelConstraint" | ||
+ | severity="ERROR" | ||
+ | mode="Batch" | ||
+ | name="Process" | ||
+ | id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.Process" | ||
+ | statusCode="1"> | ||
+ | <message>{0}</message> | ||
+ | <target class="Process"/> | ||
+ | </constraint> | ||
+ | </constraints> | ||
+ | </constraintProvider> | ||
+ | </pre> | ||
+ | |||
+ | Of course, the validation class (if using Java as the Constraint Language) can still invoke the core validator class for '''Process''' if it needs to. | ||
+ | |||
+ | ==Constraint Bindings== | ||
+ | If you need to define your own constraint categories (see above) then you must also define a Constraint Binding extension point. This binds a constraint context to a category. Bindings can be dynamically enabled by defining '''<enablement>''' expressions. For example, you may want to evaluate a certain set of constraints '''only''' for files recognized by your extension plugin. The jBPM plugin for example, uses this to evaluate constraints only if the file defines the jBPM Target Runtime: | ||
+ | |||
+ | <pre> | ||
+ | <extension | ||
+ | point="org.eclipse.emf.validation.constraintBindings"> | ||
+ | <clientContext | ||
+ | default="false" | ||
+ | id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.context"> | ||
+ | <enablement> | ||
+ | <test | ||
+ | property="org.eclipse.bpmn2.modeler.property.targetRuntimeId" | ||
+ | value="org.jboss.runtime.jbpm5"/> | ||
+ | </enablement> | ||
+ | </clientContext> | ||
+ | <binding | ||
+ | context="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.context" | ||
+ | category="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.category"> | ||
+ | </binding> | ||
+ | </extension> | ||
+ | </pre> | ||
+ | |||
+ | The workspace property "org.eclipse.bpmn2.modeler.property.targetRuntimeId" is defined by the BPMN2 Modeler plugin and is set to the Target Runtime for the file currently being edited. |
Latest revision as of 19:20, 16 June 2015
Contents
Versions
This Tutorial was developed with Eclipse 4.4 (Luna) and BPMN2-Plugin version 1.1.3.
The Basics
BPMN2 model validation builds on the EMF Validation Framework and supports both "Live" and "Batch" mode validation. There are lots of resources and tutorials on the web that discuss EMF validation; to get started, define a Constraint Provider extension point in your plugin. This extension point defines all of the validation constraints that will be evaluated, and when. In a nutshell, a <constraintProvider> contains one or more <constraint> definitions, and each corresponds to a BPMN2 model type. When model validation is required, EMF traverses the entire model and invokes each of the constraint rules that apply to each model object. This includes base types as well so if, for example, we have a constraint for Task objects and one for Activity objects, both of these will be evaluated for each Task and subclasses of Task (e.g. UserTask, ReceiveTask, etc.)
Here is a typical constraint provider for a BPMN2 Process object:
<extension point="org.eclipse.emf.validation.constraintProviders"> <category name="jBPM Validation" id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.category"/> <constraintProvider cache="true"> <package namespaceUri="http://www.omg.org/spec/BPMN/20100524/MODEL-XMI"/> <constraints categories="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.category"> <constraint lang="Java" class="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.JbpmModelConstraint" severity="ERROR" mode="Batch" name="Business Rule Task" id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.BusinessRuleTask" statusCode="1"> <message>{0}</message> <target class="BusinessRuleTask"/> </constraint> </constraints> </constraintProvider>
The discussions that follow will provide a more detailed explanation.
Live vs Batch Validation
"Live" validation is performed just prior to a model change is committed; if the validation result is anything but IStatus.OK, then the change transaction is rolled back and the error message from the constraint handler is displayed in the Workbench status bar. These types of validations are useful for preventing the model from becoming corrupted, and possibly unreadable. A good example of this is BaseElement ID validation: ID strings must follow the NCName naming convention, and they must be unique within the file since EMF uses these to resolve forward references of objects. Saving a file with an invalid ID may result in the file being unreadable since the object is not resolvable.
"Batch" validation is performed whenever the file is saved, or if the model is manually validated (right-click on the diagram, then "Validate".) This type of validation is more common and checks for semantic problems in the model; the model is essentially valid, well-formed and syntactically correct, but there may be specific conditions that must be met for the model to make sense. For example, if a Process has been defined as "executable", all data items must specify a data type (i.e., ItemAwareElement.itemSubjectRef may not be null.)
Constraint Languages
EMF allows you to write your validation rules in either OCL or Java.
We have found that for most situations it is best to use Java for writing validation rules simply because many of the constraints are very complex, sometimes involving lookups and validation of referenced elements as well. Your model constraint Java class must extend the EMF AbstractModelConstraint base class.
Target Classes
EMF constraint providers must declare a namespace URI which defines the model being validated; in our case, this is the BPMN 2.0 model and the namespace URI should be "http://www.omg.org/spec/BPMN/20100524/MODEL-XMI". The constraints declared within a constraint provider then simply refer to the model type to which the constraint applies.
If however, you have found it necessary to provide an external model for your extension elements (see BYOM!), and you need to perform validation on those objects, there is a caveat: the constraint definition must qualify the Target Class with the namespace URI of your external model. For example, the jBPM extension defines an object named GlobalType in an external EMF model; this model has the namespace URI "http://www.jboss.org/drools". To define a constraint for a GlobalType object, we would simply define it like so:
<constraint lang="Java" class="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.JbpmModelConstraint" severity="ERROR" mode="Batch" name="Global Type" id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.GlobalType" statusCode="1"> <message>{0}</message> <!-- Note use of namespace URI to qualify GlobalType --> <target class="GlobalType:http://www.jboss.org/drools"/> </constraint>
Categories
Constraint categories are used to group constraints, and categories can be enabled or disabled in the User Preference page. The BPMN2 Modeler defines the special category ID "org.eclipse.bpmn2.modeler.core.validation.category.override". This can be used to override BPMN2 core validation constraints defined by the editor. For example, to override core validation of Process objects, a plugin would define:
<extension point="org.eclipse.emf.validation.constraintProviders"> <!-- These constraints override the ones in BPMN2 Modeler Core Validation --> <constraintProvider cache="true"> <package namespaceUri="http://www.omg.org/spec/BPMN/20100524/MODEL-XMI"/> <constraints categories="org.eclipse.bpmn2.modeler.core.validation.category.override"> <constraint lang="Java" class="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.JbpmModelConstraint" severity="ERROR" mode="Batch" name="Process" id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.Process" statusCode="1"> <message>{0}</message> <target class="Process"/> </constraint> </constraints> </constraintProvider>
Of course, the validation class (if using Java as the Constraint Language) can still invoke the core validator class for Process if it needs to.
Constraint Bindings
If you need to define your own constraint categories (see above) then you must also define a Constraint Binding extension point. This binds a constraint context to a category. Bindings can be dynamically enabled by defining <enablement> expressions. For example, you may want to evaluate a certain set of constraints only for files recognized by your extension plugin. The jBPM plugin for example, uses this to evaluate constraints only if the file defines the jBPM Target Runtime:
<extension point="org.eclipse.emf.validation.constraintBindings"> <clientContext default="false" id="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.context"> <enablement> <test property="org.eclipse.bpmn2.modeler.property.targetRuntimeId" value="org.jboss.runtime.jbpm5"/> </enablement> </clientContext> <binding context="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.context" category="org.eclipse.bpmn2.modeler.runtime.jboss.jbpm5.validation.category"> </binding> </extension>
The workspace property "org.eclipse.bpmn2.modeler.property.targetRuntimeId" is defined by the BPMN2 Modeler plugin and is set to the Target Runtime for the file currently being edited.