As EasyBPEL is based on EasyVIPER, an extended behavior is expected to be developed for each extended activity in EasyBPEL.
First we consider an extended behavior is available (see the specific [how-to|easyviper:How to implement an extended behaviour in EasyVIPER?] on EasyVIPER page).
The following figure shows this principle of EasyBPEL activity mapped into an EasyVIPER behaviour. For the *Invoke* activity defined in the BPEL specification, a corresponding *Send* behavior has been implemented in EasyVIPER. In a same way, any extended activity defined at EasyBPEL level corresponds to an extended behavior at EasyVIPER level.
!extended_activity.gif|border=1,width=600!
First of all, an XSD schema must be created, corresponding to the extended activity. In particular, you must create a type that extends the Extended activity type defined in the BPEL 2.0 specification.
{code:xml|title=Excerpt of the extended activity schema.|borderStyle=solid}
<xsd:complexType name="tMyExtendedActivity">
<xsd:complexContent>
<xsd:extension base="bpel:tExtentedActivity">
<xsd:sequence>
<xsd:element ref="tns:myExtendedActivityElement" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="myExtendedActivityElement" type="..." />
{code}
This schema must be able to generate Java source code. The following excerpt is a way to do that thanks to a maven plugin:
{code:xml}
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<configuration>
<schemaDirectory>
${basedir}/src/main/resources
</schemaDirectory>
<schemaIncludes>
<include>MyExtendedActivity.xsd</include>
</schemaIncludes>
<bindingIncludes>
<include>binding.xjb</include>
</bindingIncludes>
</configuration>
</plugin>
{code}
Here is an example of binding.xjb:
{code:xml|title=binding.xjb|borderStyle=solid}
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jaxb:bindings schemaLocation="InvokeAddressingActivity.xsd"
node="/xs:schema">
<jaxb:schemaBindings>
<jaxb:package name="mypackage.myextendedactivity..." />
</jaxb:schemaBindings>
</jaxb:bindings>
<jaxb:bindings schemaLocation="schema/bpel/2_0/ws-bpel_executable.xsd"
node="/xs:schema">
<jaxb:schemaBindings>
<jaxb:package name="com.ebmwebsourcing.easybpel.model.bpel.executable" />
</jaxb:schemaBindings>
</jaxb:bindings>
</jaxb:bindings>
{code}
An extended activity implementation must then be composed of a JAVA interface extending the {{ExtendedActivity}} interface:
{code:title=MyExtendedActivity.java|borderStyle=solid}
import com.ebmwebsourcing.easybpel.model.bpel.api.activity.extension.ExtendedActivity;
public interface MyExtendedActivity extends ExtendedActivity {
//Some specific stuff related to MyExtendedActivity
}
{code}
An abstract class should be created, extending the {{AbstractExtendedActivityImpl}} abstract class and implementing the interface above.
Here is an example:
{code:title=AbstractExtendedActivityImpl.java|borderStyle=solid}
...
import com.ebmwebsourcing.easybpel.model.bpel.api.activity.extension.AbstractExtendedActivityImpl;
import com.ebmwebsourcing.easybpel.model.bpel.api.activity.extension.ExtensionActivity;
import com.ebmwebsourcing.easybpel.model.bpel.api.containers.SourcesImpl;
import com.ebmwebsourcing.easybpel.model.bpel.api.containers.TargetsImpl;
import com.ebmwebsourcing.easybpel.model.bpel.executable.TCondition;
import com.ebmwebsourcing.easybpel.model.bpel.executable.TSources;
import com.ebmwebsourcing.easybpel.model.bpel.executable.TTargets;
...
public abstract class MyExtendedActivityPackageExtendedActivityImpl<E extends TExtentedActivity> extends AbstractExtendedActivityImpl<E> implements MyExtendedActivity {
public MyExtendedActivityPackageExtendedActivityImpl(final QName name, final E model, final ExtensionActivity parent) throws BPELException {
super(name, model, parent);
copySourcesAndTargets(model);
}
public MyExtendedActivityPackageExtendedActivityImpl(QName tag, Element elmt,
ExtensionActivity parent) throws BPELException {
super(tag, elmt, parent);
copySourcesAndTargets(model);
}
private void copySourcesAndTargets(final E model) {
if(model != null) {
if(this.model.getSources() != null) {
TSources sources = new TSources();
sources.getOtherAttributes().putAll(this.model.getSources().getOtherAttributes());
sources.getSource().addAll((List)this.model.getSources().getSource());
sources.getAny().addAll(this.model.getSources().getAny());
this.sources = new SourcesImpl(sources, this);
}
if(this.model.getTargets() != null) {
TTargets targets = new TTargets();
targets.getOtherAttributes().putAll(this.model.getTargets().getOtherAttributes());
targets.getTarget().addAll((List)this.model.getTargets().getTarget());
targets.getAny().addAll(this.model.getTargets().getAny());
TCondition condition = new TCondition();
condition.getContent().addAll(this.model.getTargets().getJoinCondition().getContent());
condition.setExpressionLanguage(this.model.getTargets().getJoinCondition().getExpressionLanguage());
condition.getOtherAttributes().putAll(this.model.getTargets().getJoinCondition().getOtherAttributes());
targets.setJoinCondition(condition);
this.targets = new TargetsImpl(targets, this);
}
}
}
public boolean getSuppressJoinFailure() {
return Boolean.valueOf(this.model.getSuppressJoinFailure().value());
}
public String getName() {
return this.model.getName();
}
public void setName(String name) {
this.model.setName(name);
}
public void loadJaxbContext() throws BPELException {
try {
List<Class> list = new ArrayList<Class>();
list.add(mypackage.ObjectFactory.class);
SchemaJAXBContext.getInstance().addOtherObjectFactory(list);
this.jaxbContext = SchemaJAXBContext.getInstance().getJaxbContext();
} catch (final SchemaException e) {
throw new BPELException(e);
}
}
}
{code}
A JAVA class must implement the {{MyExtendedActivity}} interface and extend the {{MyExtendedActivityPackageExtendedActivityImpl}} abstract class:
{code:title=MyExtendedActivityImpl.java|borderStyle=solid}
...
import mypackage.MyExtendedActivity;
...
@org.oasisopen.sca.annotation.Scope("COMPOSITE")
@org.oasisopen.sca.annotation.Service(value=MyExtendedActivity.class,names="service")
@PolicySets("frascati:scaEasyPrimitive")
public class MyExtendedActivityImpl extends MyExtendedActivityPackageExtendedActivityImpl<TMyExtendedActivity> implements MyExtendedActivity {
public MyExtendedActivityImpl(QName tag, Element elmt, ExtensionActivity parent)
throws BPELException {
super(tag, elmt, parent);
//Some specific stuff related to MyExtendedActivityImpl
}
@Override
public void validate(BPELStaticAnalysis analyzer) {
//Some specific stuff related to MyExtendedActivityImpl
}
@Override
public Node generate(Scope scope) throws CoreException {
//Some specific stuff related to MyExtendedActivityImpl
}
@Override
protected TMyExtendedActivity convertElementToModel(Element elmt)
throws BPELException {
TMyExtendedActivity res = null;
try {
JAXBElement<TMyExtendedActivity> jaxb = this.getJaxbContext().createUnmarshaller().unmarshal(elmt, TMyExtendedActivity.class);
res = jaxb.getValue();
} catch (JAXBException e) {
throw new BPELException(e);
} catch(SchemaException e){
throw new BPELException(e);
}
return res;
}
}
{code}
You have to fill the constructor (at least with a {{super()}} method), the {{convertElementToModel()}}, {{validate()}} and {{generate()}} methods.
The {{validate}} method SHOULD be filled whereas the {{generate}} method MUST be filled. It consists basically in instantiating the extended behavior developed at EasyVIPER level. Here is an example of {{generate}} method:
{code:title=MyExtendedActivityImpl.java excerpt|borderStyle=solid}
@Override
public Node generate(Scope scope) throws CoreException {
MyExtendedBehavior myExtendedBehavior = new MyExtendedBehaviorImpl();
// myExtendedBehavior.foo()
Node behaviourNode = scope.createNode(this.model.getName(), myExtendedBehavior);
return behaviourNode;
}
{code}
Your extended activity is completed. You only needs to add it in dependency of your BPEL engine and to set or create an ExtendedActivityInitialization.xml file that can be found for instance in the src/main/jbi of the JBI component that embeds EasyBPEL.
{code:xml|title=ExtendedActivityInitialization.xml|borderStyle=solid}
<?xml version="1.0" encoding="UTF-8"?>
<tns:ExtendedActivitiesInitialization
xmlns:tns="http://com.ebmwebsourcing.easybpel/ExtendedActivityInitialization"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://com.ebmwebsourcing.easybpel/ExtendedActivityInitialization
../../main/resources/ExtendedActivityInitialization.xsd ">
<tns:extendedActivityInitialization>
<tns:definition>MyExtendedActivityPackageConfiguration.xml</tns:definition>
<tns:implementation>mypackage.MyExtendedActivityImpl-....jar</tns:implementation>
</tns:extendedActivityInitialization>
</tns:ExtendedActivitiesInitialization>
{code}
You can see in {{definition}} a file is set, that must be present in the extended activity project and that contains configuration. This configuratioon file details what is the namespace of the extended activity, and for each activity of this namespace, the tag associated to the extended activity (in the taken example, there was only one extended activity).
{code:xml|title=MyExtendedActivityPackageConfiguration.xml|borderStyle=solid}
<?xml version="1.0" encoding="UTF-8"?>
<tns:ExtendedActivityConfigurationList
xmlns:tns="http://com.ebmwebsourcing.easybpel/ExtendedActivityConfiguration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:my="http://mynamespace/mypackage/MyExtendedActivity">
<tns:extendedActivityConf>
<tns:tag>my:myactivity</tns:tag>
<tns:className>mypackage.MyExtendedActivityImpl</tns:className>
</tns:extendedActivityConf>
[...]
</tns:ExtendedActivityConfigurationList>
{code}
First we consider an extended behavior is available (see the specific [how-to|easyviper:How to implement an extended behaviour in EasyVIPER?] on EasyVIPER page).
The following figure shows this principle of EasyBPEL activity mapped into an EasyVIPER behaviour. For the *Invoke* activity defined in the BPEL specification, a corresponding *Send* behavior has been implemented in EasyVIPER. In a same way, any extended activity defined at EasyBPEL level corresponds to an extended behavior at EasyVIPER level.
!extended_activity.gif|border=1,width=600!
First of all, an XSD schema must be created, corresponding to the extended activity. In particular, you must create a type that extends the Extended activity type defined in the BPEL 2.0 specification.
{code:xml|title=Excerpt of the extended activity schema.|borderStyle=solid}
<xsd:complexType name="tMyExtendedActivity">
<xsd:complexContent>
<xsd:extension base="bpel:tExtentedActivity">
<xsd:sequence>
<xsd:element ref="tns:myExtendedActivityElement" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:element name="myExtendedActivityElement" type="..." />
{code}
This schema must be able to generate Java source code. The following excerpt is a way to do that thanks to a maven plugin:
{code:xml}
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<configuration>
<schemaDirectory>
${basedir}/src/main/resources
</schemaDirectory>
<schemaIncludes>
<include>MyExtendedActivity.xsd</include>
</schemaIncludes>
<bindingIncludes>
<include>binding.xjb</include>
</bindingIncludes>
</configuration>
</plugin>
{code}
Here is an example of binding.xjb:
{code:xml|title=binding.xjb|borderStyle=solid}
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jaxb:bindings schemaLocation="InvokeAddressingActivity.xsd"
node="/xs:schema">
<jaxb:schemaBindings>
<jaxb:package name="mypackage.myextendedactivity..." />
</jaxb:schemaBindings>
</jaxb:bindings>
<jaxb:bindings schemaLocation="schema/bpel/2_0/ws-bpel_executable.xsd"
node="/xs:schema">
<jaxb:schemaBindings>
<jaxb:package name="com.ebmwebsourcing.easybpel.model.bpel.executable" />
</jaxb:schemaBindings>
</jaxb:bindings>
</jaxb:bindings>
{code}
An extended activity implementation must then be composed of a JAVA interface extending the {{ExtendedActivity}} interface:
{code:title=MyExtendedActivity.java|borderStyle=solid}
import com.ebmwebsourcing.easybpel.model.bpel.api.activity.extension.ExtendedActivity;
public interface MyExtendedActivity extends ExtendedActivity {
//Some specific stuff related to MyExtendedActivity
}
{code}
An abstract class should be created, extending the {{AbstractExtendedActivityImpl}} abstract class and implementing the interface above.
Here is an example:
{code:title=AbstractExtendedActivityImpl.java|borderStyle=solid}
...
import com.ebmwebsourcing.easybpel.model.bpel.api.activity.extension.AbstractExtendedActivityImpl;
import com.ebmwebsourcing.easybpel.model.bpel.api.activity.extension.ExtensionActivity;
import com.ebmwebsourcing.easybpel.model.bpel.api.containers.SourcesImpl;
import com.ebmwebsourcing.easybpel.model.bpel.api.containers.TargetsImpl;
import com.ebmwebsourcing.easybpel.model.bpel.executable.TCondition;
import com.ebmwebsourcing.easybpel.model.bpel.executable.TSources;
import com.ebmwebsourcing.easybpel.model.bpel.executable.TTargets;
...
public abstract class MyExtendedActivityPackageExtendedActivityImpl<E extends TExtentedActivity> extends AbstractExtendedActivityImpl<E> implements MyExtendedActivity {
public MyExtendedActivityPackageExtendedActivityImpl(final QName name, final E model, final ExtensionActivity parent) throws BPELException {
super(name, model, parent);
copySourcesAndTargets(model);
}
public MyExtendedActivityPackageExtendedActivityImpl(QName tag, Element elmt,
ExtensionActivity parent) throws BPELException {
super(tag, elmt, parent);
copySourcesAndTargets(model);
}
private void copySourcesAndTargets(final E model) {
if(model != null) {
if(this.model.getSources() != null) {
TSources sources = new TSources();
sources.getOtherAttributes().putAll(this.model.getSources().getOtherAttributes());
sources.getSource().addAll((List)this.model.getSources().getSource());
sources.getAny().addAll(this.model.getSources().getAny());
this.sources = new SourcesImpl(sources, this);
}
if(this.model.getTargets() != null) {
TTargets targets = new TTargets();
targets.getOtherAttributes().putAll(this.model.getTargets().getOtherAttributes());
targets.getTarget().addAll((List)this.model.getTargets().getTarget());
targets.getAny().addAll(this.model.getTargets().getAny());
TCondition condition = new TCondition();
condition.getContent().addAll(this.model.getTargets().getJoinCondition().getContent());
condition.setExpressionLanguage(this.model.getTargets().getJoinCondition().getExpressionLanguage());
condition.getOtherAttributes().putAll(this.model.getTargets().getJoinCondition().getOtherAttributes());
targets.setJoinCondition(condition);
this.targets = new TargetsImpl(targets, this);
}
}
}
public boolean getSuppressJoinFailure() {
return Boolean.valueOf(this.model.getSuppressJoinFailure().value());
}
public String getName() {
return this.model.getName();
}
public void setName(String name) {
this.model.setName(name);
}
public void loadJaxbContext() throws BPELException {
try {
List<Class> list = new ArrayList<Class>();
list.add(mypackage.ObjectFactory.class);
SchemaJAXBContext.getInstance().addOtherObjectFactory(list);
this.jaxbContext = SchemaJAXBContext.getInstance().getJaxbContext();
} catch (final SchemaException e) {
throw new BPELException(e);
}
}
}
{code}
A JAVA class must implement the {{MyExtendedActivity}} interface and extend the {{MyExtendedActivityPackageExtendedActivityImpl}} abstract class:
{code:title=MyExtendedActivityImpl.java|borderStyle=solid}
...
import mypackage.MyExtendedActivity;
...
@org.oasisopen.sca.annotation.Scope("COMPOSITE")
@org.oasisopen.sca.annotation.Service(value=MyExtendedActivity.class,names="service")
@PolicySets("frascati:scaEasyPrimitive")
public class MyExtendedActivityImpl extends MyExtendedActivityPackageExtendedActivityImpl<TMyExtendedActivity> implements MyExtendedActivity {
public MyExtendedActivityImpl(QName tag, Element elmt, ExtensionActivity parent)
throws BPELException {
super(tag, elmt, parent);
//Some specific stuff related to MyExtendedActivityImpl
}
@Override
public void validate(BPELStaticAnalysis analyzer) {
//Some specific stuff related to MyExtendedActivityImpl
}
@Override
public Node generate(Scope scope) throws CoreException {
//Some specific stuff related to MyExtendedActivityImpl
}
@Override
protected TMyExtendedActivity convertElementToModel(Element elmt)
throws BPELException {
TMyExtendedActivity res = null;
try {
JAXBElement<TMyExtendedActivity> jaxb = this.getJaxbContext().createUnmarshaller().unmarshal(elmt, TMyExtendedActivity.class);
res = jaxb.getValue();
} catch (JAXBException e) {
throw new BPELException(e);
} catch(SchemaException e){
throw new BPELException(e);
}
return res;
}
}
{code}
You have to fill the constructor (at least with a {{super()}} method), the {{convertElementToModel()}}, {{validate()}} and {{generate()}} methods.
The {{validate}} method SHOULD be filled whereas the {{generate}} method MUST be filled. It consists basically in instantiating the extended behavior developed at EasyVIPER level. Here is an example of {{generate}} method:
{code:title=MyExtendedActivityImpl.java excerpt|borderStyle=solid}
@Override
public Node generate(Scope scope) throws CoreException {
MyExtendedBehavior myExtendedBehavior = new MyExtendedBehaviorImpl();
// myExtendedBehavior.foo()
Node behaviourNode = scope.createNode(this.model.getName(), myExtendedBehavior);
return behaviourNode;
}
{code}
Your extended activity is completed. You only needs to add it in dependency of your BPEL engine and to set or create an ExtendedActivityInitialization.xml file that can be found for instance in the src/main/jbi of the JBI component that embeds EasyBPEL.
{code:xml|title=ExtendedActivityInitialization.xml|borderStyle=solid}
<?xml version="1.0" encoding="UTF-8"?>
<tns:ExtendedActivitiesInitialization
xmlns:tns="http://com.ebmwebsourcing.easybpel/ExtendedActivityInitialization"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://com.ebmwebsourcing.easybpel/ExtendedActivityInitialization
../../main/resources/ExtendedActivityInitialization.xsd ">
<tns:extendedActivityInitialization>
<tns:definition>MyExtendedActivityPackageConfiguration.xml</tns:definition>
<tns:implementation>mypackage.MyExtendedActivityImpl-....jar</tns:implementation>
</tns:extendedActivityInitialization>
</tns:ExtendedActivitiesInitialization>
{code}
You can see in {{definition}} a file is set, that must be present in the extended activity project and that contains configuration. This configuratioon file details what is the namespace of the extended activity, and for each activity of this namespace, the tag associated to the extended activity (in the taken example, there was only one extended activity).
{code:xml|title=MyExtendedActivityPackageConfiguration.xml|borderStyle=solid}
<?xml version="1.0" encoding="UTF-8"?>
<tns:ExtendedActivityConfigurationList
xmlns:tns="http://com.ebmwebsourcing.easybpel/ExtendedActivityConfiguration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:my="http://mynamespace/mypackage/MyExtendedActivity">
<tns:extendedActivityConf>
<tns:tag>my:myactivity</tns:tag>
<tns:className>mypackage.MyExtendedActivityImpl</tns:className>
</tns:extendedActivityConf>
[...]
</tns:ExtendedActivityConfigurationList>
{code}