Skip to main content

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.

Jump to: navigation, search

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 an "org.eclipse.emf.validation.constraintProviders" extension point in your plugin. This extension point defines all of the validation constraints that will be evaluated, and when.
+
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 Language===
+
==Constraint Languages==
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.
+
EMF allows you to write your validation rules in either [https://en.wikipedia.org/wiki/Object_Constraint_Language OCL] or Java.
  
===Target Classes===
+
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 withing a constraint provider then simply refer to the model type to which the constraint applies.
+
 
 +
==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

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.

Back to the top