![]() |
![]() |
|
|
Defining Plug-In Components
This section explains how to define plug-in components. It includes the following topics:
Overview
As described in How BPM Discovers a Deployed Plug-In, the plug-in is responsible for enabling the BPM to:
This functionality is provided by the plug-in component. The following table describes the plug-in component requirements for supporting the specified functionality.
Table 4-1 Plug-In Component Requirements
To enable the plug-in to read (parse) incoming data, both the plug-in data interface and run-time component class must implement the load() (parsing) method of their parent interface, com.bea.wlpi.common.plugin.PluginObject.
Lastly, you must define the plug-in component value object to describe the component data.
The following sections describe the PluginObject interface, explain how to define the plug-in component to support the functionality listed in the previous table, and define the plug-in component value object.
Note: For a summary of the steps that must be accomplished to define each type of plug-in component, see Plug-In Component Definition Roadmap.
PluginObject Interface
The com.bea.wlpi.common.plugin.PluginObject interface enables the plug-in to read (parse) the plug-in data.
This interface must be extended by:
The PluginObject interface defines one method, load(), as shown in the following table.
Table 4-2 PluginObject Interface Method
The Plug-in Manager calls the load() method when it encounters the plug-in section (for example, a <plugin-data> element) in an XML document. This might happen, for example, when the Plug-in Manager opens a template, template definition, or plug-in configuration XML document in the WebLogic Integration Studio.
Note: For information about the BPM DTDs, see DTD Formats in Programming BPM Client Applications.
You must also implement required content handler methods, including the startElement() and endElement() methods. The Plug-in Manager sets the plug-in as the parser content handler, and uses the startElement() and endElement() methods as the first and last calls to the content handler when a <plugin-data> element is reached. The content handler uses the intervening SAX notifications to store the plug-in-specific data. For more information about the content handler methods, see the org.xml.sax Javadoc.
In the plug-in sample, a separate class file is provided for certain plug-in components that extends the PluginObject interface and defines the required methods. This file does not need to be defined separately. It is useful in this case, however, because it provides a single definition for the multiple classes in the example that share the file.
The following sections provide code examples showing how the PluginObject interface for plug-in Done and Start nodes is implemented.
In addition to these examples, refer to the following files in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory:
This file . . . |
Illustrates PluginObject implementation for a . . . |
---|---|
EventObject.java |
Plug-in event |
CheckInventoryActionObject.java |
Plug-in action |
SendConfirmActionObject.java |
Plug-in action |
For more information about the plug-in sample, see BPM Plug-In Sample.
Done Node Example
The following code listing shows how to define a class that implements the PluginObject interface for a Done node. The input to the example code is a user response to a decision dialog box (yes or no). Notable lines of code are shown in bold.
Note: This class is not available as part of the plug-in sample.
Listing 4-1 Implementing the PluginObject Interface for a Done Node
package com.bea.wlpi.test.plugin;
import java.io.IOException;
import com.bea.wlpi.common.plugin.PluginObject;
import org.xml.sax.*;
public class DoneObject implements PluginObject
{
protected String yesOrNo = null;
protected static String YESORNO_TAG = "yesorno";
protected transient String lastValue;
public DoneObject()
{
}
public DoneObject(String yesOrNo)
{
this.yesOrNo = yesOrNo;
}
public void load(XMLReader parser)
{
}
void setYesOrNo(String decision)
{
yesOrNo = decision;
}
String getYesOrNo()
{
return yesOrNo;
}
public void setDocumentLocator(Locator locator)
{
}
public void startDocument()
throws SAXException
{
}
public void endDocument()
throws SAXException
{
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException
{
}
public void endPrefixMapping(String prefix)
throws SAXException
{
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException
{
lastValue = null;
}
public void endElement(String namespaceURI, String localName, String name)
throws SAXException
{
if(name.equals(YESORNO_TAG))
yesOrNo = lastValue;
}
public void characters(char[] ch, int start, int length)
throws SAXException
{
String value = new String(ch, start, length);
if(lastValue == null)
lastValue = value;
else
lastValue = lastValue + value;
}
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException
{
}
public void processingInstruction(String target, String data)
throws SAXException
{
}
public void skippedEntity(String name)
throws SAXException
{
}
}
Refer to the following related example listings:
Start Node Example
The following code listing is an excerpt from the plug-in sample that shows how to define a class that implements the PluginObject interface for a Start node. Note that the load(), startelement(), and endelement() method are defined. This excerpt is taken from the StartObject.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Listing 4-2 Implementing the PluginObject Interface for a Start Node
public class StartObject implements PluginObject {
.
.
.
public void load(XMLReader parser) {
}
.
.
.
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException {
lastValue = null;
}
public void endElement(String namespaceURI, String localName, String name)
throws SAXException {
if (name.equals(EVENTDESC_TAG))
eventDesc = lastValue;
}
.
.
.
Refer to the following related example listings:
For more information about the plug-in sample, see BPM Plug-In Sample.
Reading and Saving Plug-In Data
To read (parse) and save plug-in data in XML format, you must implement the plug-in data interface.
To enable the plug-in to read (parse) incoming data, the plug-in data interface class must implement the load() (parsing) method of its parent interface, com.bea.wlpi.common.plugin.PluginObject.
To enable the plug-in to save its data in XML format, you must implement one of the plug-in data interfaces defined in the following table based on the type of plug-in component being defined. Data must be saved in XML format, for example, when you are saving a template, template definition, or plug-in configuration XML document in the Studio.
Note: You do not need to implement the plug-in data interface to read and save data for the following plug-in components: functions, message types, and variable types.
Table 4-3 Plug-In Data Interfaces
Note: For information about the BPM DTDs and examples of plug-in-specific output, see DTD Formats in Programming BPM Client Applications.
Each plug-in data interface is defined in more detail in the following sections.
Implementing the PluginData Interface
You must implement the com.bea.wlpi.common.plugin.PluginData interface to enable the plug-in component to save its data in XML format.
Note: When defining actions, you should implement the PluginActionData interface, as described in Implementing the PluginActionData Interface.
The following table describes the methods defined by the PluginData interface that you must implement.
Note: The contents of the PluginData interface methods may be empty or simply return a message to the log, but they must be implemented.
Table 4-4 PluginData Interface Methods
The following sections provide code examples showing how the PluginData interface is implemented.
Done Node Example
The following code listing shows how to define a class that implements the PluginData interface for a Done node. Notable lines of code are shown in bold.
Note: This class is not available as part of the plug-in sample.
Listing 4-3 Implementing the PluginData Interface for a Done Node
package com.bea.wlpi.test.plugin;
import com.bea.wlpi.common.XMLWriter;
import com.bea.wlpi.common.plugin.PluginData;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.xml.sax.*;
public class DoneNodeData extends DoneObject implements PluginData
{
public static int count = 0;
private int c;
public DoneNodeData()
{
c=count++;
}
public DoneNodeData(String yesOrNo)
{
super(yesOrNo);
c=count++;
}
public void save(XMLWriter writer, int indent) throws IOException
{
writer.saveElement(indent, YESORNO_TAG, yesOrNo);
}
}
Refer to the following related example listings:
Event Node Example
The following code listing is an excerpt from the plug-in sample that shows how to define a class that implements the PluginData interface for an Event node. This excerpt is taken from the EventNodeData.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Listing 4-4 Implementing the PluginData Interface for an Event Node
package com.bea.wlpi.tour.po.plugin;
import com.bea.wlpi.common.XMLWriter;
import com.bea.wlpi.common.plugin.PluginData;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Map;
import org.xml.sax.*;
public class EventNodeData extends EventObject implements PluginData {
private SampleBundle bundle;
public EventNodeData() {
this(Locale.getDefault());
}
public EventNodeData(Locale lc) {
eventDesc = SamplePluginConstants.CONFIRM_EVENT;
bundle = new SampleBundle(lc);
}
public void save(XMLWriter writer, int indent) throws IOException {
writer.saveElement(indent, EVENTDESC_TAG, eventDesc);
}
public List getReferencedPublishables(Map publishables) {
return null;
}
public String getPrintableData() {
return bundle.getString("confirmOrderName");
}
public Object clone() {
return new EventNodeData(bundle.getLocale());
}
}
Refer to the following related example listings:
For more information about the plug-in sample, see BPM Plug-In Sample.
Start Node Example
The following code listing is an excerpt from the plug-in sample that shows how to define a class that implements the PluginData interface for a Start node. This excerpt is taken from the StartNodeData.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Listing 4-5 Implementing the PluginData Interface for a Start Node
package com.bea.wlpi.tour.po.plugin;
import com.bea.wlpi.common.XMLWriter;
import com.bea.wlpi.common.plugin.PluginData;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Map;
import org.xml.sax.*;
public class StartNodeData extends StartObject implements PluginData {
private SampleBundle bundle;
public StartNodeData() {
this(Locale.getDefault());
}
public StartNodeData(Locale lc) {
eventDesc = SamplePluginConstants.START_ORDER_EVENT;
bundle = new SampleBundle(lc);
}
public void save(XMLWriter writer, int indent) throws IOException {
writer.saveElement(indent, EVENTDESC_TAG, eventDesc);
}
public List getReferencedPublishables(Map publishables) {
return null;
}
public String getPrintableData() {
return bundle.getString("startOrderLabel");
}
public Object clone() {
return new StartNodeData(bundle.getLocale());
}
}
Refer to the following related example listings:
For more information about the plug-in sample, see BPM Plug-In Sample.
Workflow Template Properties Example
The following code listing shows how to define a class that implements the PluginData interface for workflow template properties. The code reads and saves the user's response to a decision dialog box (yes or no). Notable lines of code are shown in bold.
Note: This class is not available as part of the plug-in sample.
Listing 4-6 Implementing the PluginData Interface for Workflow Template Properties
package com.bea.wlpi.test.plugin;
import com.bea.wlpi.common.XMLWriter;
import com.bea.wlpi.common.plugin.PluginData;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.xml.sax.*;
public class TemplatePropertiesData extends DoneObject implements PluginData {
public TemplatePropertiesData() {
}
public TemplatePropertiesData(String yesOrNo){
super(yesOrNo);
}
public void save(XMLWriter writer, int indent) throws IOException {
writer.saveElement(indent, YESORNO_TAG, yesOrNo);
}
public List getReferencedPublishables(Map publishables) {
return null;
}
public String getPrintableData() {
return null;
}
}
Refer to the following related example listings:
Workflow Template Definition Properties Example
The following code listing shows how to define a class that implements the PluginData interface for workflow template definition properties. The code reads and saves the user's response to a decision dialog box (yes or no). Notable lines of code are shown in bold.
Note: This class is not available as part of the plug-in sample.
Listing 4-7 Implementing the PluginData Interface for Workflow Template Definition Properties
package com.bea.wlpi.test.plugin;
import com.bea.wlpi.common.XMLWriter;
import com.bea.wlpi.common.plugin.PluginData;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.xml.sax.*;
public class TemplateDefinitionPropertiesData extends DoneObject implements PluginData
{
public TemplateDefinitionPropertiesData()
{
}
public TemplateDefinitionPropertiesData(String yesOrNo)
{
super(yesOrNo);
}
public void save(XMLWriter writer, int indent) throws IOException
{
writer.saveElement(indent, YESORNO_TAG, yesOrNo);
}
public List getReferencedPublishables(Map publishables) {
return null;
}
public String getPrintableData() {
return null;
}
public Object clone() {
return new TemplateDefinitionPropertiesData(yesOrNo);
}
}
Refer to the following related example listings:
Implementing the PluginActionData Interface
You must implement the com.bea.wlpi.common.plugin.PluginActionData interface to enable the plug-in action to save its data in XML format.
Note: The PluginActionData interface extends the PluginData interface. For more information about the PluginData interface methods, see the table PluginData Interface Methods.
The following table describes the method defined by the PluginActionData interface that you must implement.
Note: The contents of the PluginActionData interface methods may be empty or simply return a message to the log, but they must be implemented.
Table 4-5 PluginActionData Interface Method
Method |
Description |
---|---|
public java.lang.String getLabel() |
Gets the formatted label of the plug-in action that is specified in the actions list. |
The following code listing is an excerpt from the plug-in sample that shows how to define a class that implements the PluginActionData interface. This excerpt is taken from the CheckInventoryActionData.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Note: Refer to SendConfirmationActionData.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory for another example of how to define a class the implements the PluginActionData interface.
Listing 4-8 Implementing the PluginActionData Interface
package com.bea.wlpi.tour.po.plugin;
import com.bea.wlpi.common.XMLWriter;
import com.bea.wlpi.common.plugin.PluginData;
import com.bea.wlpi.common.plugin.PluginActionData;
import java.io.IOException;
import java.util.ResourceBundle;
import java.util.Locale;
import java.util.List;
import java.util.Map;
import org.xml.sax.*;
public class CheckInventoryActionData extends CheckInventoryActionObject
implements PluginActionData {
private SampleBundle bundle;
public CheckInventoryActionData() {
getBundle(Locale.getDefault());
}
public CheckInventoryActionData(Locale lc) {
getBundle(lc);
}
public CheckInventoryActionData(Locale lc, String inputVariableName,
String outputVariableName) {
super(inputVariableName, outputVariableName);
getBundle(lc);
}
public void save(XMLWriter writer, int indent) throws IOException {
writer.saveElement(indent, INPUTVARIABLE_TAG, inputVariableName);
writer.saveElement(indent, OUTPUTVARIABLE_TAG, outputVariableName);
}
private void getBundle(Locale lc) {
bundle = new SampleBundle(lc);
}
public List getReferencedPublishables(Map publishables) {
return null;
}
public String getPrintableData() {
return bundle.getString("checkInventoryDesc");
}
public Object clone() {
return new CheckInventoryActionData(bundle.getLocale(),
new String(this.inputVariableName),
new String(this.outputVariableName));
}
public String getLabel() {
return bundle.getString("checkInventoryDesc");
}
}
Refer to the following related example listings:
For more information about the plug-in sample, see BPM Plug-In Sample.
Displaying the Plug-In GUI Component
To display the plug-in GUI component within the design client, all plug-ins must define a class that extends the plug-in panel class.
For example, in the figure Plug-In Example: Start Node, when a user selects the Start Order event as the Start node trigger, the Plug-in Manager obtains an instance of the plug-in panel class, StartNodePanel, from the plug-in using object manufacturing, and returns the data to the Studio client. The Studio client subsequently displays the plug-in GUI component in the Start Properties dialog box. (For more information about object manufacturing, see Accessing the Plug-In Implementation (Object Manufacturing).)
The following table describes the plug-in panel class that you must extend based on the type of plug-in component being defined.
Note: You do not need to implement the plug-in panel interface to display a GUI component for the following plug-in components: functions and message types.
Table 4-6 Plug-In Panel Classes
Note: All plug-in panel classes must provide a public constructor that requires no arguments, and that functions properly when invoked on the client side, picking up the locale by calling the getDefault() method to the java.util.Locale interface.
Each plug-in panel class is defined in more detail in the following sections.
Defining the PluginPanel Class
To define the plug-in GUI component displayed in the design client, you must define a class that extends the com.bea.wlpi.common.plugin.PluginPanel class.
Note: When defining actions, Start or Event nodes, or variable types, you should extend the corresponding plug-in panel class defined in the table Plug-In Panel Classes, which extends the PluginPanel class.
The following table describes the class methods defined by the PluginPanel class.
Note: You can override any method that is not declared as final.
Table 4-7 PluginPanel Class Methods
The following sections provide code examples showing how the PluginPanel class is defined.
Done Node Example
The following code listing shows how to define the PluginPanel class for a Done node. The code displays a decision dialog box (yes or no) within the Done Properties dialog box. Notable lines of code are shown in bold.
Note: This class is not available as part of the plug-in sample.
Listing 4-9 Defining the PluginPanel Class for a Done Node
package com.bea.wlpi.test.plugin;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import java.util.List;
import java.util.Locale;
import com.bea.wlpi.common.plugin.PluginPanel;
import com.bea.wlpi.common.plugin.PluginPanelContext;
import com.bea.wlpi.client.studio.Studio;
import com.bea.wlpi.common.VariableInfo;
public class DoneNodePanel extends PluginPanel
{
JPanel ButtonPanel = new JPanel();
ButtonGroup YesNoButtonGroup = new ButtonGroup();
JRadioButton YesButton = new JRadioButton();
JRadioButton NoButton = new JRadioButton();
TitledBorder titledBorder = new TitledBorder(new EtchedBorder());
public DoneNodePanel()
{
super(Locale.getDefault(), "jackolantern");
setLayout(null);
setBounds(12,12,420,300);
setPreferredSize(new Dimension(420,300));
ButtonPanel.setBorder(titledBorder);
ButtonPanel.setLayout(null);
add(ButtonPanel);
ButtonPanel.setBounds(72,60,300,144);
YesButton.setText("Yes");
YesButton.setSelected(true);
YesNoButtonGroup.add(YesButton);
ButtonPanel.add(YesButton);
YesButton.setBounds(60,36,46,23);
NoButton.setText("No");
YesNoButtonGroup.add(NoButton);
ButtonPanel.add(NoButton);
NoButton.setBounds(60,60,46,23);
titledBorder.setTitle("Yes or No?");
}
public void load() {
DoneNodeData myData = (DoneNodeData)getData();
if(myData != null) {
if(myData.getYesOrNo() != null && myData.getYesOrNo().equals(TestPluginConstants.DONE_NO)) {
NoButton.setSelected(true);
} else {
YesButton.setSelected(true);
}
}
}
public boolean validateAndSave()
{
DoneNodeData myData = (DoneNodeData)getData();
if(myData != null) {
if(YesButton.isSelected()) {
myData.setYesOrNo(TestPluginConstants.DONE_YES);
} else {
myData.setYesOrNo(TestPluginConstants.DONE_NO);
}
}
return true;
}
The following figure illustrates the resulting PluginPanel GUI component.
Figure 4-1 PluginPanel GUI Component for a Done Node
Refer to the following related example listings:
Workflow Template Properties Example
The following code listing shows how to define the PluginPanel class for workflow template properties. The code displays a decision dialog box (yes or no) within the Workflow Template Properties dialog box. Notable lines of code are shown in bold.
Note: This class is not available as part of the plug-in sample.
Listing 4-10 Defining the PluginPanel Class for Workflow Template Properties
package com.bea.wlpi.test.plugin;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import java.util.List;
import java.util.Locale;
import com.bea.wlpi.common.plugin.PluginPanel;
import com.bea.wlpi.common.plugin.PluginPanelContext;
import com.bea.wlpi.client.studio.Studio;
import com.bea.wlpi.common.VariableInfo;
public class TemplatePropertiesPanel extends PluginPanel
{
JPanel ButtonPanel = new JPanel();
ButtonGroup YesNoButtonGroup = new ButtonGroup();
JRadioButton YesButton = new JRadioButton();
JRadioButton NoButton = new JRadioButton();
TitledBorder titledBorder = new TitledBorder(new EtchedBorder());
public TemplatePropertiesPanel()
{
super(Locale.getDefault(), "stpatty");
setLayout(null);
setBounds(12,12,420,300);
ButtonPanel.setBorder(titledBorder);
ButtonPanel.setLayout(null);
add(ButtonPanel);
ButtonPanel.setBounds(72,60,300,144);
YesButton.setText("Yes");
YesButton.setSelected(true);
YesNoButtonGroup.add(YesButton);
ButtonPanel.add(YesButton);
YesButton.setBounds(60,36,46,23);
NoButton.setText("No");
YesNoButtonGroup.add(NoButton);
ButtonPanel.add(NoButton);
NoButton.setBounds(60,60,46,23);
titledBorder.setTitle("Yes or No?");
}
public void load() {
TemplatePropertiesData myData = (TemplatePropertiesData)getData();
if(myData != null) {
if(myData.getYesOrNo() != null && myData.getYesOrNo().equals(TestPluginConstants.DONE_NO)) {
NoButton.setSelected(true);
} else {
YesButton.setSelected(true);
}
}
}
public boolean validateAndSave()
{
TemplatePropertiesData myData = (TemplatePropertiesData)getData();
if(myData != null) {
if(YesButton.isSelected()) {
myData.setYesOrNo(TestPluginConstants.DONE_YES);
} else {
myData.setYesOrNo(TestPluginConstants.DONE_NO);
}
}
return true;
}
The following figure illustrates the resulting PluginPanel GUI component.
Figure 4-2 PluginPanel GUI Component for Workflow Template Properties
Refer to the following related example listings:
Workflow Template Definition Properties Example
The following code listing shows how to define the PluginPanel class for workflow template definition properties. The code displays a decision dialog box (yes or no) within the Workflow Template Definition Properties dialog box. Notable lines of code are shown in bold.
Note: This class is not available as part of the plug-in sample.
Listing 4-11 Defining the PluginPanel Class for Workflow Template Definition Properties
package com.bea.wlpi.test.plugin;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import java.util.List;
import java.util.Locale;
import com.bea.wlpi.common.plugin.PluginPanel;
import com.bea.wlpi.common.plugin.PluginPanelContext;
import com.bea.wlpi.client.studio.Studio;
import com.bea.wlpi.common.VariableInfo;
public class TemplateDefinitionPropertiesPanel extends PluginPanel
{
JPanel ButtonPanel = new JPanel();
ButtonGroup YesNoButtonGroup = new ButtonGroup();
JRadioButton YesButton = new JRadioButton();
JRadioButton NoButton = new JRadioButton();
TitledBorder titledBorder = new TitledBorder(new EtchedBorder());
public TemplateDefinitionPropertiesPanel()
{
super(Locale.getDefault(), "valentine");
setLayout(null);
setBounds(12,12,420,300);
ButtonPanel.setBorder(titledBorder);
ButtonPanel.setLayout(null);
add(ButtonPanel);
ButtonPanel.setBounds(72,60,300,144);
YesButton.setText("Yes");
YesButton.setSelected(true);
YesNoButtonGroup.add(YesButton);
ButtonPanel.add(YesButton);
YesButton.setBounds(60,36,46,23);
NoButton.setText("No");
YesNoButtonGroup.add(NoButton);
ButtonPanel.add(NoButton);
NoButton.setBounds(60,60,46,23);
titledBorder.setTitle("Yes or No?");
}
public void load() {
TemplateDefinitionPropertiesData myData = (TemplateDefinitionPropertiesData)getData();
if(myData != null) {
if(myData.getYesOrNo() != null && myData.getYesOrNo().equals(TestPluginConstants.DONE_NO)) {
NoButton.setSelected(true);
} else {
YesButton.setSelected(true);
}
}
}
public boolean validateAndSave()
{
TemplateDefinitionPropertiesData myData = (TemplateDefinitionPropertiesData)getData();
if(myData != null) {
if(YesButton.isSelected()) {
myData.setYesOrNo(TestPluginConstants.DONE_YES);
} else {
myData.setYesOrNo(TestPluginConstants.DONE_NO);
}
}
return true;
}
The following figure illustrates the resulting PluginPanel GUI component.
Figure 4-3 PluginPanel GUI Component for Workflow Template Definition Properties
Refer to the following related example listings:
Defining the PluginActionPanel Class
To define the GUI component displayed in the design client when defining a plug-in action, you must define a class that extends the com.bea.wlpi.common.plugin.PluginActionPanel class. In the Studio, the PluginActionPanel class is used by the Action Plugin dialog box, which provides generic support for subactions.
The PluginActionPanel class defines no additional methods.
Note: The PluginActionPanel class extends the PluginPanel class. For more information about the PluginPanel class methods, see the table PluginPanel Class Methods.
The following code listing is an excerpt from the plug-in sample that shows how to define the PluginActionPanel class. This excerpt is taken from the CheckInventoryActionPanel.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Note: Refer to the SendConfirmationActionPanel.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory for another example of how to define a PluginActionPanel class.
Listing 4-12 Defining the PluginActionPanel Class
package com.bea.wlpi.tour.po.plugin;
import java.awt.*;
import javax.swing.*;
import java.util.List;
import java.util.Locale;
import com.bea.wlpi.common.VariableInfo;
import com.bea.wlpi.common.plugin.PluginActionPanel;
import com.bea.wlpi.common.plugin.PluginPanelContext;
public class CheckInventoryActionPanel extends PluginActionPanel {
private JLabel inputLabel = new JLabel();
private JLabel outputLabel = new JLabel();
private JComboBox inputComboBox = new JComboBox();
private JComboBox outputComboBox = new JComboBox();
private List variables = null;
public CheckInventoryActionPanel() {
this(Locale.getDefault());
}
public CheckInventoryActionPanel(Locale lc) {
super(lc, "checkinventory");
setLayout(null);
setBounds(12, 12, 420, 210);
setPreferredSize(new Dimension(420, 210));
add(inputLabel);
inputLabel.setBounds(12, 48, 96, 24);
add(outputLabel);
outputLabel.setBounds(12, 108, 166, 24);
add(inputComboBox);
inputComboBox.setBounds(190, 48, 212, 24);
inputComboBox.setEditable(true);
add(outputComboBox);
outputComboBox.setBounds(190, 108, 212, 24);
outputComboBox.setEditable(true);
}
public void load() {
setResourceBundle("com.bea.wlpi.tour.po.plugin.SamplePlugin");
inputLabel.setText(getString("inputLabel"));
outputLabel.setText(getString("outputLabel"));
CheckInventoryActionData myData = (CheckInventoryActionData)getData();
variables = getContext().getVariableList(VariableInfo.TYPE_INT);
// load is called before displaying this panel each time. Make sure to
// remove items from the combo box before filling with currently
// defined variables.
inputComboBox.removeAllItems();
String inputVar = myData.getInputVariableName();
int n = variables == null ? 0 : variables.size();
for (int i = 0; i < n; i++) {
VariableInfo varInfo = (VariableInfo)variables.get(i);
inputComboBox.addItem(varInfo.getName());
if (inputVar != null && inputVar.equals(varInfo.getName())) {
inputComboBox.setSelectedIndex(i);
}
}
if (inputVar == null && n > 0)
inputComboBox.setSelectedIndex(0);
outputComboBox.removeAllItems();
String outputVar = myData.getOutputVariableName();
for (int i = 0; i < n; i++) {
VariableInfo varInfo = (VariableInfo)variables.get(i);
outputComboBox.addItem(varInfo.getName());
if (outputVar != null && outputVar.equals(varInfo.getName())) {
outputComboBox.setSelectedIndex(i);
}
}
if (outputVar == null && n > 0)
outputComboBox.setSelectedIndex(0);
}
public boolean validateAndSave() {
CheckInventoryActionData myData = (CheckInventoryActionData)getData();
String input = (String)inputComboBox.getEditor().getItem();
try {
VariableInfo varInfo = getContext().checkVariable(input,
new String[]{ VariableInfo.TYPE_INT });
if (varInfo == null)
return false;
if (!(varInfo.getType().equals(VariableInfo.TYPE_INT))) {
JOptionPane.showMessageDialog(SwingUtilities.windThe following figure illustrates the resulting PluginActionPanel GUI component.
Figure 4-4 PluginActionPanel GUI Component
![]()
Refer to the following related example listings:
- CheckInventoryActionObject.java in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory shows how to read the plug-in data in XML format.
- Implementing the PluginActionData Interface shows how to read and save the plug-in data in XML format. This class extends the CheckInventoryActionObject class.
- Defining the Run-Time Component Class for an Action shows how to define the execution information for the plug-in.
- Customizing an Action Tree shows how to customize the actions and/or action categories listed in the action trees that are displayed in various dialog boxes within the Studio.
For more information about the plug-in sample, see BPM Plug-In Sample.
Defining the PluginTriggerPanel Class
To define the GUI component to be displayed in the design client when defining a plug-in Start or Event node, you must defne a class that extends the com.bea.wlpi.common.plugin.PluginTriggerPanel class. In the Studio, the Start and Event node PluginTriggerPanel classes are used by the Start Properties and Event Properties dialog box, respectively.
The following table describes the class methods that are defined by the PluginTriggerPanel class.
Note: The PluginTriggerPanel class extends the PluginPanel class. For more information about the PluginPanel class methods, see the table PluginPanel Class Methods.
Table 4-8 PluginTriggerPanel Class Methods
The following sections provide code examples showing how the PluginTriggerPanel class is defined.
Start Node Example
The following code listing is an excerpt from the plug-in sample that shows how to define the PluginTriggerPanel class for a Start node. This excerpt is taken from the StartNodePanel.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Listing 4-13 Defining the PluginTriggerPanel Class for a Start Node
package com.bea.wlpi.tour.po.plugin;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import java.util.List;
import java.util.Locale;
import com.bea.wlpi.common.plugin.PluginTriggerPanel;
import com.bea.wlpi.common.plugin.PluginPanelContext;
import com.bea.wlpi.common.VariableInfo;
public class StartNodePanel extends PluginTriggerPanel {
private JLabel StartOrderLabel = new JLabel();
private JTextArea StartOrderText = new JTextArea();
public StartNodePanel() {
this(Locale.getDefault());
}
public StartNodePanel(Locale lc) {
super(lc, "startorder");
setLayout(null);
setBounds(12, 12, 420, 240);
setPreferredSize(new Dimension(420, 240));
add(StartOrderLabel);
StartOrderLabel.setFont(new Font("Dialog", Font.BOLD, 16));
StartOrderLabel.setBounds(120, 12, 156, 24);
StartOrderText.setLineWrap(true);
StartOrderText.setWrapStyleWord(true);
StartOrderText.setEditable(false);
add(StartOrderText);
StartOrderText.setBounds(30, 48, 348, 144);
}
public void load() {
setResourceBundle("com.bea.wlpi.tour.po.plugin.SamplePlugin");
StartOrderLabel.setText(getString("startOrderLabel"));
StartOrderText.setText(getString("startOrderText"));
}
public boolean validateAndSave() {
return true;
}
public String[] getFields() {
return SamplePluginConstants.ORDER_FIELDS;
}
public String getEventDescriptor() {
return SamplePluginConstants.START_ORDER_EVENT;
}
}The START_ORDER_EVENT and ORDER_FIELDS field element values are included within the SamplePluginConstants.java class file. They define the plug-in Start node event descriptor and field element values as follows:
final static String START_ORDER_EVENT = "startOrder";
final static String[] ORDER_FIELDS = {
"CustomerName", "CustomerID", "OrderStatus", "OrderID",
"CustomerEmail", "ItemName", "ItemID", "ItemQuantity",
"CustomerState"
};For more information about defining the plug-in field to access a plug-in-specific external event, see Defining the Run-Time Component Class for a Message Type.
The following figure illustrates the resulting PluginTriggerPanel GUI component.
Figure 4-5 PluginTriggerPanel GUI Component for a Start Node
![]()
Refer to the following related example listings:
- Implementing the PluginObject Interface for a Start Node shows how to read the plug-in data in XML format.
- Implementing the PluginData Interface for a Start Node shows how to read and save the plug-in data in XML format.
- Defining the Run-Time Component Class for a Start Node shows how to define the execution information for the plug-in.
- Using Plug-In Run-Time Contexts shows how to define the plug-in fields that can be referenced from an evaluator expression.
For more information about the plug-in sample, see BPM Plug-In Sample.
Event Node Example
The following code listing is an excerpt from the plug-in sample that shows how to define the PluginTriggerPanel class for an Event node. This excerpt is taken from the EventNodePanel.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Listing 4-14 Defining the PluginTriggerPanel Class for an Event Node
package com.bea.wlpi.tour.po.plugin;
import java.awt.*;
import javax.swing.*;
import java.util.Locale;
import com.bea.wlpi.common.plugin.PluginTriggerPanel;
import com.bea.wlpi.common.plugin.PluginPanelContext;
import com.bea.wlpi.common.VariableInfo;
public class EventNodePanel extends PluginTriggerPanel {
private JLabel confirmOrderLabel = new JLabel();
private JTextArea confirmOrderText = new JTextArea();
/**
* Create a new EventNodePanel.
*/
public EventNodePanel() {
this(Locale.getDefault());
}
public EventNodePanel(Locale lc) {
super(lc, "confirmevent");
setLayout(null);
setBounds(12, 12, 420, 240);
setPreferredSize(new Dimension(420, 240));
add(confirmOrderLabel);
confirmOrderLabel.setFont(new Font("Dialog", Font.BOLD, 16));
confirmOrderLabel.setBounds(144, 12, 120, 24);
confirmOrderText.setRequestFocusEnabled(false);
confirmOrderText.setLineWrap(true);
confirmOrderText.setWrapStyleWord(true);
confirmOrderText.setEditable(false);
add(confirmOrderText);
confirmOrderText.setBounds(30, 48, 348, 144);
}
public void load() {
setResourceBundle("com.bea.wlpi.tour.po.plugin.SamplePlugin");
confirmOrderLabel.setText(getString("confirmOrderLabel"));
confirmOrderText.setText(getString("confirmOrderText"));
}
public boolean validateAndSave() {
// There are no UI controls on this panel which accept user input.
// Therefore, there is nothing to do in this method.
return true;
}
public String[] getFields() {
return SamplePluginConstants.CONFIRM_FIELDS;
}
public String getEventDescriptor() {
return SamplePluginConstants.CONFIRM_EVENT;
}
}The CONFIRM_EVENT and CONFIRM_FIELD are included within the SamplePluginConstants.java class. They define the plug-in Event node event descriptor and field element values as follows:
final static String CONFIRM_EVENT = "confirmOrder";
final static String[] CONFIRM_FIELDS = { "Status", "TotalPrice" };For more information about defining the plug-in field to access a plug-in-specific external event, see Defining the Run-Time Component Class for a Message Type.
The following figure illustrates the resulting PluginTriggerPanel GUI component.
Figure 4-6 PluginTriggerPanel GUI Component for a Event Node
![]()
Refer to the following related example listings:
- EventObject.java in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory shows how to implement the PluginObject interface to read plug-in data.
- Implementing the PluginData Interface for an Event Node shows how to read and save the plug-in data. This class extends the EventObject class.
- Defining the Run-Time Component Class for an Event Node shows how to define the execution information for the plug-in.
For more information about the plug-in sample, see BPM Plug-In Sample.
Defining the PluginVariablePanel Class
To define the GUI component displayed in the design client when defining a plug-in variable that enables users to edit a plug-in variable type, you must define a class that extends the com.bea.wlpi.common.plugin.PluginVariablePanel class. In the Studio, the PluginVariablePanel class is used by the Update Variable dialog box.
The following table describes the class methods that are defined by the PluginVariablePanel class.
Note: The PluginVariablePanel class extends the PluginPanel class. For more information about the PluginPanel class methods, see the table PluginPanel Class Methods.
Table 4-9 PluginVariablePanel Class Methods
The following code listing shows how to define the PluginVariablePanel class. Notable lines of code are shown in bold.
Note: This class is not available as part of the plug-in sample.
Listing 4-15 Defining the PluginVariablePanel Class
package com.bea.wlpi.test.plugin;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import java.util.List;
import java.util.Locale;
import com.bea.wlpi.client.studio.Studio;
import com.bea.wlpi.common.VariableInfo;
import com.bea.wlpi.common.plugin.PluginVariablePanel;
public class VariablePanel extends PluginVariablePanel {
JTextField highField, lowField;
public VariablePanel() {
super(Locale.getDefault(), "augustus");
setLayout(null);
setBounds(12,12,420,60);
highField = new JTextField();
highField.setLocation(20, 10);
highField.setSize(300, 20);
add(highField);
lowField = new JTextField();
lowField.setLocation(20, 40);
lowField.setSize(300, 20);
add(lowField);
}
public void load() {
if (variableValue != null) {
highField.setText(((MySpecificObject)variableValue).getHigh());
lowField.setText(((MySpecificObject)variableValue).getLow());
} else {
highField.setText("");
lowField.setText("");
}
}
public boolean validateAndSave() {
try {
variableValue = new MySpecificObject(lowField.getText(), highField.getText());
} catch (Exception e) {
return false;
}
return true;
}
}The following figure illustrates the resulting PluginVariablePanel GUI component.
Figure 4-7 PluginVariablePanel GUI Component
![]()
Refer to the related example listing, Defining the Run-Time Component Class for a Variable Type, which shows how to define the execution information for the plug-in.
Executing the Plug-In
To execute the plug-in, you must define the run-time component class for the plug-in.
The following table describes the plug-in component interfaces that you must implement based on the type of plug-in component being created. To enable the plug-in to read (parse) the incoming data, the run-time component class must implement the load() (parsing) method of its parent interface, com.bea.wlpi.common.plugin.PluginObject.
Note: The following two plug-in components do not need to define execution information: workflow template properties, or workflow template definition properties.
Table 4-10 Plug-In Run-Time Component Interfaces
Note: At run time you can use context interfaces that are passed by the Plug-in Manager to access the run-time context and services for the associated plug-in. For information about the context interfaces, see Using Plug-In Run-Time Contexts.
The following sections explain in detail how to define each of the plug-in run-time component classes.
Defining the Run-Time Component Class for an Action
To define the run-time component class for a plug-in action, you must:
- Implement the com.bea.wlpi.server.plugin.PluginAction interface to define the plug-in action execution information.
- Customize the actions and/or action categories listed in the action trees that are displayed in various dialog boxes within the Studio.
Defining the Execution Information for a Plug-In Action
To define the execution information for a plug-in action, you must implement the com.bea.wlpi.server.plugin.PluginAction interface and its methods, as described in the following table.
Table 4-11 PluginAction Interface Methods
The following code listing is an excerpt from the plug-in sample that shows how to define the run-time component class for an action. This excerpt is taken from the CheckInventoryAction.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Note: Refer to the SendConfirmationAction.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory for another example of how to define the plug-in action run-time component class.
Listing 4-16 Defining the Run-Time Component Class for an Action
package com.bea.wlpi.tour.po.plugin;
import java.io.IOException;
import com.bea.wlpi.server.plugin.PluginAction;
import com.bea.wlpi.common.WorkflowException;
import com.bea.wlpi.common.plugin.PluginException;
import com.bea.wlpi.common.Messages;
import com.bea.wlpi.common.VariableInfo;
import com.bea.wlpi.evaluator.Expression;
import com.bea.wlpi.evaluator.EvaluatorException;
import com.bea.wlpi.server.common.ExecutionContext;
import com.bea.wlpi.evaluator.ExpressionParser;
import com.bea.wlpi.server.plugin.ActionContext;
import org.xml.sax.*;
public class CheckInventoryAction extends CheckInventoryActionObject
implements PluginAction {
private Expression inputValueExpression;
static int[] quantities = {
250, 120, 5, 75, 0, 300, 550, 25, 16, 630, 3
};
public CheckInventoryAction() {
}
public void fixup(ExpressionParser parser) {
System.out.println("SamplePlugin: CheckInventoryAction.fixup called");
try {
inputValueExpression =
inputVariableName != null
? new Expression("$" + inputVariableName, parser) : null;
} catch (EvaluatorException ee) {
System.out.println("EvaluationException ocurred in CheckInventoryAction");
}
}
public int execute(ActionContext actionContext, ExecutionContext context)
throws WorkflowException {
System.out.println("SamplePlugin: CheckInventoryAction.execute called");
Object valueObject = inputValueExpression != null
? inputValueExpression.evaluate(context) : null;
if (valueObject == null)
throw new PluginException("Sample Plugin", "itemNo is null");
if (!(valueObject instanceof Long))
throw new PluginException("Sample Plugin", "itemNo not an integer");
int itemNo = ((Long)valueObject).intValue();
int quantity = quantities[itemNo % quantities.length] + itemNo;
System.out.println("CheckInventoryAction: Output = " + quantity);
context.setVariableValue(outputVariableName, new Long(quantity));
return ExecutionContext.CONTINUE;
}
public void response(ActionContext actionContext, ExecutionContext execContext, Object data)
throws WorkflowException {
}
public void startedWorkflowDone(ActionContext actionContext,
ExecutionContext context,
VariableInfo[] output) {
}Refer to the following related example listings:
- CheckInventoryActionObject.java in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory shows how to read the plug-in data in XML format.
- Implementing the PluginActionData Interface shows how to read and save the plug-in data in XML format. This class extends the CheckInventoryActionObject class.
- Defining the PluginActionPanel Class shows how to display the plug-in GUI component in the design client.
- Customizing an Action Tree shows how to customize the actions and/or action categories listed in the action trees that are displayed in various dialog boxes within the Studio.
For more information about the plug-in sample, see BPM Plug-In Sample.
Customizing the Action Tree
To support plug-in actions, you must customize the actions and/or action categories listed in the action trees that are displayed in various dialog boxes within the Studio.
For example, the following figure illustrates the Add Action dialog box with a customized version of the action tree.
Figure 4-8 Customized Action Tree
![]()
As shown in the previous figure, the BPM action tree has been customized to add one new action category, Sample Actions, that provides the following plug-in actions:
- Checks available inventory for an item
- Sends Confirm Order Event
You can customize the action tree by performing the following steps:
- Define a com.bea.wlpi.common.plugin.CategoryInfo object that, in turn, defines the custom plug-in actions and/or action categories.
For information about creating a CategoryInfo object, see Defining Plug-In Value Objects.
- Implement the com.bea.wlpi.server.plugin.Plugin remote interface getPluginCapabilitiesInfo() method to define the com.bea.wlpi.common.plugin.PluginCapabilitiesInfo object.
Use the CategoryInfo object defined in step 1 to define the custom action tree characteristics.
When the Plug-in Manager calls the getPluginCapabilitiesInfo() method, it must pass the existing action category tree as a com.bea.wlpi.common.plugin.CategoryInfo object to enable the plug-in to traverse the tree and determine where to add the custom actions and/or action categories. Once the Plug-in Manager retrieves this valid tree structure, it merges the retrieved tree structure with the existing tree structure and assigns a new systemID to each new category.
The Plug-in Manager can call the getPluginCapabilitiesInfo() method multiple times, and you must return a newly initialized action tree each time. If you reuse an existing CategoryInfo object, the Plug-in Manager raises an IllegalStateException when it calls the setSystemID() method for the second time.
You can add new actions and/or subcategories to existing action categories at any leve., You cannot, however, remove actions or subcategories from an existing category.
The following code listing is an excerpt from the plug-in sample that shows how to define the following methods:
- getCategoryInfo() method, which lets you define a CategoryInfo object that, in turn, defines the custom plug-in actions and action categories.
- getPluginCapabilitiesInfo() method, which enables you to customize the action tree.
This excerpt is taken from the SamplePluginBean.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. The example defines both the Check Inventory and Send Confirmation actions. Notable lines of code are shown in bold.
Listing 4-17 Customizing an Action Tree
private CategoryInfo[] getCategoryInfo(SampleBundle bundle) {
ActionInfo checkInventoryAction =
new ActionInfo(SamplePluginConstants.PLUGIN_NAME, 1,
bundle.getString("checkInventoryName"),
bundle.getString("checkInventoryDesc"), ICON_BYTE_ARRAY,
ActionCategoryInfo.ID_NEW,
ActionInfo.ACTION_STATE_ALL,
SamplePluginConstants.CHECKINV_CLASSES);
ActionInfo sendConfirmAction =
new ActionInfo(SamplePluginConstants.PLUGIN_NAME, 2,
bundle.getString("sendConfirmName"),
bundle.getString("sendConfirmDesc"), ICON_BYTE_ARRAY,
ActionCategoryInfo.ID_NEW,
ActionInfo.ACTION_STATE_ALL,
SamplePluginConstants.SENDCONF_CLASSES);
ActionCategoryInfo[] actions =
new ActionCategoryInfo[]{ checkInventoryAction, sendConfirmAction};
CategoryInfo[] catInfo =
new CategoryInfo[]{ new CategoryInfo(SamplePluginConstants.PLUGIN_NAME,
0, bundle.getString("catName"),
bundle.getString("catDesc"),
ActionCategoryInfo.ID_NEW,
actions)};
return catInfo;
}
public PluginCapabilitiesInfo getPluginCapabilitiesInfo(Locale lc,
CategoryInfo[] info) {
PluginInfo pi;
FieldInfo orderFieldInfo;
FieldInfo confirmFieldInfo;
FieldInfo[] fieldInfo;
FunctionInfo fi;
FunctionInfo[] functionInfo;
StartInfo si;
StartInfo[] startInfo;
EventInfo ei;
EventInfo[] eventInfo;
SampleBundle bundle = new SampleBundle(lc);
log("getPluginCapabilities called");
pi = createPluginInfo(lc);
orderFieldInfo =
new FieldInfo(SamplePluginConstants.PLUGIN_NAME, 3,
bundle.getString("orderFieldName"),
bundle.getString("orderFieldDesc"),
SamplePluginConstants.ORDER_FIELD_CLASSES, false);
confirmFieldInfo =
new FieldInfo(SamplePluginConstants.PLUGIN_NAME, 4,
bundle.getString("confirmFieldName"),
bundle.getString("confirmFieldDesc"),
SamplePluginConstants.CONFIRM_FIELD_CLASSES, false);
fieldInfo = new FieldInfo[]{ orderFieldInfo, confirmFieldInfo};
ei = new EventInfo(SamplePluginConstants.PLUGIN_NAME, 6,
bundle.getString("confirmOrderName"),
bundle.getString("confirmOrderDesc"), ICON_BYTE_ARRAY,
SamplePluginConstants.EVENT_CLASSES,
confirmFieldInfo);
eventInfo = new EventInfo[]{ ei};
fi = new FunctionInfo(SamplePluginConstants.PLUGIN_NAME, 7,
bundle.getString("calcTotalName"),
bundle.getString("calcTotalDesc"),
bundle.getString("calcTotalHint"),
SamplePluginConstants.FUNCTION_CLASSES, 3, 3);
functionInfo = new FunctionInfo[]{ fi};
si = new StartInfo(SamplePluginConstants.PLUGIN_NAME, 5,
bundle.getString("startOrderName"),
bundle.getString("startOrderDesc"), ICON_BYTE_ARRAY,
SamplePluginConstants.START_CLASSES, orderFieldInfo);
startInfo = new StartInfo[]{ si};
PluginCapabilitiesInfo pci = new PluginCapabilitiesInfo(pi,
getCategoryInfo(bundle), eventInfo, fieldInfo, functionInfo, startInfo,
null, null, nulRefer to the following related example listings:
- CheckInventoryActionObject.java in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory shows how to read the plug-in data in XML format.
- Implementing the PluginActionData Interface shows how to read and save the plug-in data in XML format. This class extends the CheckInventoryActionObject class.
- Defining the PluginActionPanel Class shows how to display the plug-in GUI component in the design client.
- Defining the Run-Time Component Class for an Action shows how to define the plug-in execution information.
For more information about the plug-in sample, see BPM Plug-In Sample.
Defining the Run-Time Component Class for a Done Node
To define the run-time component class for a Done node, implement the com.bea.wlpi.server.plugin.PluginDone interface.
Note: The PluginDone interface extends com.bea.wlpi.server.plugin.PluginTemplateNode. For more information about the PluginTemplateNode interface and its methods, see PluginTemplateNode Interface.
The PluginDone interface adds no other methods.
The following code listing shows how to define the run-time component class for a Done node. Notable lines of code are shown in bold.
Note: This class is not available as part of the plug-in sample.
Listing 4-18 Defining the Run-Time Component Class for a Done Node
package com.bea.wlpi.test.plugin;
import com.bea.wlpi.common.Messages;
import com.bea.wlpi.common.WorkflowException;
import com.bea.wlpi.evaluator.ExpressionParser;
import com.bea.wlpi.server.common.ExecutionContext;
import com.bea.wlpi.server.plugin.PluginDone;
import java.io.IOException;
import java.util.Map;
import org.xml.sax.*;
public class DoneNode extends DoneObject implements PluginDone {
public DoneNode() {
}
public int activate(ExecutionContext context)
throws WorkflowException {
System.out.println("TestPlugin: DoneNode activated");
// Initialize the plugin instance data.
Map instanceData = (Map)context.getPluginInstanceData(TestPluginConstants.PLUGIN_NAME);
if (instanceData != null) {
Object started = instanceData.get(TestPluginConstants.INST_DATA_STARTED);
System.out.println("instance data = " + started);
}
int stopMode;
if (yesOrNo.equals(TestPluginConstants.DONE_YES)) {
System.out.println("TestPlugin: DoneNode = YES");
stopMode = ExecutionContext.CONTINUE;
} else {
System.out.println("TestPlugin: DoneNode = NO");
stopMode = ExecutionContext.STOP;
}
return stopMode;
}
public void fixup(ExpressionParser parser) {
}Refer to the following related example listings:
- Implementing the PluginObject Interface for a Done Node shows how to read the plug-in data in XML format.
- Implementing the PluginData Interface for a Done Node shows how to read and save the plug-in data in XML format. This class extends the PluginObject class.
- Defining the PluginPanel Class for a Done Node shows how to define plug-in GUI component.
Defining the Run-Time Component Class for an Event Node
To define the run-time component class for an event node, implement the com.bea.wlpi.server.plugin.PluginEvent interface.
The following table describes the PluginEvent interface methods that you must implement as part of the run-time component class.
Table 4-12 PluginEvent Interface Methods
The following code listing is an excerpt from the plug-in sample that shows how to define the run-time component class for an Event node. This excerpt is taken from the StartNode.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Listing 4-19 Defining the Run-Time Component Class for an Event Node
package com.bea.wlpi.tour.po.plugin;
import java.io.IOException;
import com.bea.wlpi.server.plugin.PluginEvent;
import com.bea.wlpi.common.WorkflowException;
import com.bea.wlpi.common.Messages;
import com.bea.wlpi.evaluator.Expression;
import com.bea.wlpi.evaluator.EvaluatorException;
import com.bea.wlpi.server.common.ExecutionContext;
import com.bea.wlpi.server.plugin.EventContext;
import com.bea.wlpi.server.workflow.Workflow;
import com.bea.wlpi.server.workflow.Variable;
import com.bea.wlpi.evaluator.ExpressionParser;
import com.bea.wlpi.server.workflow.TemplateNode;
import org.xml.sax.*;
public class EventNode extends EventObject implements PluginEvent {
public EventNode() {
}
public int activate(EventContext eventContext, ExecutionContext execContext)
throws WorkflowException {
System.out.println("SamplePlugin: EventNode activated");
eventContext.activateEvent(execContext,
SamplePluginConstants.CONTENTTYPE,
eventDesc, null, null);
return ExecutionContext.CONTINUE;
}
public int trigger(EventContext context, ExecutionContext execContext)
throws WorkflowException {
System.out.println("SamplePlugin: EventNode triggered");
context.removeEventWatch(execContext);
return ExecutionContext.CONTINUE;
}
public void fixup(ExpressionParser parser) {
}
}Refer to the following related example listings:
- EventObject.java in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory shows how to implement the PluginObject interface to read plug-in data.
- Implementing the PluginData Interface for an Event Node shows how to read and save the plug-in data. This class extends the EventObject class.
- Defining the PluginTriggerPanel Class for an Event Node shows how to display the plug-in GUI component in the design client.
For more information about the plug-in sample, see BPM Plug-In Sample.
Defining the Run-Time Component Class for a Function
To define the run-time component class for a function, implement the com.bea.wlpi.common.plugin.PluginFunction interface. The following table describes the PluginFunction interface method that you must implement.
Table 4-13 PluginFunction Interface Method
The following code listing is an excerpt from the plug-in sample that shows how to define the run-time component class for a function. This excerpt is taken from the CalculateTotalPriceFunction.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Listing 4-20 Defining a Run-Time Component Class for a Function
package com.bea.wlpi.tour.po.plugin;
import com.bea.wlpi.common.Messages;
import com.bea.wlpi.common.plugin.PluginFunction;
import com.bea.wlpi.common.plugin.PluginException;
import com.bea.wlpi.evaluator.*;
import com.bea.wlpi.tour.po.BadStateException;
import java.lang.NumberFormatException;
/**
* This sample function calculates the total price of an order. The price is
* calculated using the itemID, quantity, and the State/Province of the order.
* The State/Province is used to look up the sales tax rate.
*/
public class CalculateTotalPriceFunction implements PluginFunction {
static StateTax[] stateTax = {
new StateTax("AB", 0.07), new StateTax("AK", 0.06),
new StateTax("AL", 0.06), new StateTax("AR", 0.03),
new StateTax("AZ", 0.05), new StateTax("BC", 0.05),
new StateTax("CA", 0.04), new StateTax("CO", 0.08),
new StateTax("CT", 0.03), new StateTax("DC", 0.05),
new StateTax("DE", 0.05), new StateTax("FL", 0.00),
new StateTax("GA", 0.06), new StateTax("HI", 0.07),
new StateTax("IA", 0.07), new StateTax("ID", 0.08),
new StateTax("IL", 0.06), new StateTax("IN", 0.03),
new StateTax("KS", 0.05), new StateTax("KY", 0.07),
new StateTax("LA", 0.06), new StateTax("MA", 0.05),
new StateTax("MB", 0.05), new StateTax("MD", 0.04),
new StateTax("ME", 0.04), new StateTax("MI", 0.03),
new StateTax("MN", 0.05), new StateTax("MO", 0.06),
new StateTax("MS", 0.07), new StateTax("MT", 0.07),
new StateTax("NB", 0.08), new StateTax("NC", 0.07),
new StateTax("ND", 0.08), new StateTax("NE", 0.03),
new StateTax("NF", 0.06), new StateTax("NH", 0.09),
new StateTax("NJ", 0.03), new StateTax("NM", 0.06),
new StateTax("NV", 0.03), new StateTax("NY", 0.06),
new StateTax("NS", 0.08), new StateTax("NT", 0.07),
new StateTax("OH", 0.07), new StateTax("OK", 0.02),
new StateTax("ON", 0.08), new StateTax("OR", 0.08),
new StateTax("PA", 0.07), new StateTax("PE", 0.07),
new StateTax("PQ", 0.05), new StateTax("RI", 0.05),
new StateTax("SC", 0.05), new StateTax("SD", 0.04),
new StateTax("SK", 0.04), new StateTax("TN", 0.06),
new StateTax("TX", 0.06), new StateTax("UT", 0.07),
new StateTax("VA", 0.07), new StateTax("VT", 0.08),
new StateTax("WA", 0.07), new StateTax("WI", 0.07),
new StateTax("WV", 0.08), new StateTax("WY", 0.05),
new StateTax("YT", 0.07)
};
static double[] prices = {
29.95, 524.79, 33.21, 9.99, 12.28, 152.50, 43.55, 32.90, 328.55, 72.50,
87.50
};
public CalculateTotalPriceFunction() throws EvaluatorException {
System.out.println("CalculateTotalPriceFunction: constructor called");
}
public Object evaluate(EvaluationContext context, Object[] args)
throws PluginException {
int itemNo;
int quantity;
String state;
System.out.println("CalculateTotalPriceFunction: evaluate called");
try {
itemNo = ((Long)args[0]).intValue();
} catch (Exception e) {
throw new PluginException(SamplePluginConstants.PLUGIN_NAME,
"Invalid ItemID argument");
}
try {
quantity = ((Long)args[1]).intValue();
} catch (Exception e2) {
e2.printStackTrace();
throw new PluginException(SamplePluginConstants.PLUGIN_NAME,
"Invalid Quantity argument");
}
For more information about the plug-in sample, see BPM Plug-In Sample.
Defining the Run-Time Component Class for a Message Type
To define the run-time component class for a message type, you must implement the com.bea.wlpi.common.plugin.PluginField interface to define a plug-in field. A plug-in field enables you to parse custom plug-in data that is associated with an external event received by a Start or Event node. The data can then be referenced from an evaluator expression. The plug-in determines the content type of the external event by accessing the associated event descriptor.
The plug-in framework uses the plug-in field data to populate the Expression Builder dialog box. For example, the following figure shows an Expression Builder dialog box in which the plug-in Fields category is selected, resulting in the display of a list of valid field elements.
Figure 4-9 Plug-In Fields Displayed in an Expression Builder Dialog Box
![]()
To define a plug-in field, implement the com.bea.wlpi.common.plugin.PluginField interface. The following table describes the PluginField interface methods that you must implement.
Table 4-14 PluginField Interface Methods
The following code listing is an excerpt from the plug-in sample that shows how to define a run-time component class for a message type. The plug-in field processes a single message type containing data associated with a customer order. The data is in String format, and the individual data elements are separated by semicolons. The plug-in field expects the external event data to be provided as a string buffer containing values that are delimited by semicolons. In the execute() method, the class performs some simple validation of the event data, and returns the String object for the requested field name. This excerpt is taken from the OrderField.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Listing 4-21 Defining the Run-Time Component Class for a Message Type
package com.bea.wlpi.tour.po.plugin;
import com.bea.wlpi.common.plugin.PluginException;
import com.bea.wlpi.common.plugin.PluginField;
import com.bea.wlpi.evaluator.EvaluationContext;
import com.bea.wlpi.server.eventprocessor.EventData;
import java.util.StringTokenizer;
/*
* This sample field type expects a string buffer with semicolon delimited
* field values. The fields are in a fixed order.
*/
public final class OrderField implements PluginField {
private String docType;
private String name;
public void init(String name, String eventDescriptor)
throws PluginException {
this.name = name;
docType = eventDescriptor;
}
public void setQualifier(PluginField qualifier) throws PluginException {
System.out.println("OrderField.setQualifier(" + qualifier + ')');
throw new PluginException(SamplePluginConstants.PLUGIN_NAME,
"Qualifiers are not supported");
}
public Object evaluate(EvaluationContext context) throws PluginException {
// Get the event data and check that it is a String object.
EventData eventData = context.getEventData();
if (eventData == null)
throw new PluginException(SamplePluginConstants.PLUGIN_NAME,
"The event data is null.");
docType = eventData.getEventDescriptor();
if (!docType.equals(SamplePluginConstants.START_ORDER_EVENT))
throw new PluginException(SamplePluginConstants.PLUGIN_NAME,
"The event descriptor is invalid.");
Object object = eventData.getContent();
if (!(object instanceof String))
throw new PluginException(SamplePluginConstants.PLUGIN_NAME,
"The event data is invalid.");
// Check to make sure the field name is valid
int i;
for (i = 0; i < SamplePluginConstants.ORDER_FIELDS.length; i++) {
if (SamplePluginConstants.ORDER_FIELDS[i].equals(name))
break;
}
// Was the field name found in the list of valid field names?
if (i == SamplePluginConstants.ORDER_FIELDS.length)
throw new PluginException(SamplePluginConstants.PLUGIN_NAME,
"The field name " + name
+ " is invalid.");
String data = (String)object;
StringTokenizer st = new StringTokenizer(data, ";");
String token = null;
while (st.hasMoreTokens() && i >= 0) {
token = st.nextToken();
i--;
}
// Did the data ran out of fields prior to finding the one required?
if (i >= 0) {
throw new PluginException(SamplePluginConstants.PLUGIN_NAME,
"The event data is invalid.");
}
String value = token;
System.out.println("OrderField: name = " + name + ", value = " + value);
// Return the text value.
return value;
}
}The ORDER_FIELDS value is defined within the SamplePluginConstants.java class file as follows:
final static String[] ORDER_FIELDS = {
"CustomerName", "CustomerID", "OrderStatus", "OrderID",
"CustomerEmail", "ItemName", "ItemID", "ItemQuantity",
"CustomerState"
};The figure Plug-In Fields Displayed in an Expression Builder Dialog Box shows the field elements populated within the Expression Builder dialog box.
For more information about the plug-in sample, see BPM Plug-In Sample.
Defining the Run-Time Component Class for a Start Node
To define the run-time component class for a Start node, implement the com.bea.wlpi.server.plugin.PluginStart2 interface. The following table describes the PluginStart2 interface method that you must implement.
Note: The PluginStart2 interface inherits methods from the com.bea.wlpi.server.plugin.PluginTemplateNode interface. For more information, see PluginTemplateNode Interface.
Table 4-15 PluginStart2 Interface Method
The following code listing is an excerpt from the plug-in sample that shows how to define the run-time component class for a Start node. This excerpt is taken from the StartNode.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Listing 4-22 Defining the Run-Time Component Class for a Start Node
package com.bea.wlpi.tour.po.plugin;
import java.io.IOException;
import com.bea.wlpi.server.plugin.PluginStart2;
.
.
.
public class StartNode extends StartObject implements PluginStart2 {
public StartNode() {
}
.
.
.
public void setTrigger(EventContext context, String orgExpr,
boolean orgIsExpr)
throws WorkflowException {
System.out.println("SamplePlugin: StartNode - setTrigger called");
context.postStartWatch(SamplePluginConstants.CONTENTTYPE, eventDesc,
null, null);
}
public void fixup(ExpressionParser parser) {
}
}Refer to the following related example listings:
- Implementing the PluginObject Interface for a Start Node shows how to read the plug-in data in XML format.
- Implementing the PluginData Interface for a Start Node shows how to read and save plug-in data in XML format. This example extends the StartObject class.
- Defining the PluginTriggerPanel Class for a Start Node shows how to display the plug-in GUI component in the design client.
- Using Plug-In Run-Time Contexts shows how to define the plug-in fields that can be referenced from an evaluator expression.
For more information about the plug-in sample, see BPM Plug-In Sample.
Defining the Run-Time Component Class for a Variable Type
To define thye run-time component class for a variable type to be displayed in the cell of a javax.swing.JTable, implement the com.bea.wlpi.common.plugin.PluginVariableRenderer interface.
Note: Classes implementing this interface must be subclasses of java.awt.Component.
The following table describes the PluginVariableRenderer interface method that you must implement.
Table 4-16 PluginVariableRenderer Interface Method
The following code listing shows how to define the run-time component class for a variable type. Notable lines of code are shown in bold.
Note: This class is not available as part of the plug-in sample.
Listing 4-23 Defining the Run-Time Component Class for a Variable Type
package com.bea.wlpi.test.plugin;
import java.io.Serializable;
import javax.swing.JLabel;
import com.bea.wlpi.common.plugin.PluginVariableRenderer;
public class VariableRenderer extends JLabel implements PluginVariableRenderer, Serializable {
public VariableRenderer() {
}
public void setValue(Object value) {
if (value == null)
setText("null");
else
setText(value.toString());
}
}Refer to Defining the PluginVariablePanel Class, which shows how to display the plug-in GUI component in the design client.
PluginTemplateNode Interface
The com.bea.wlpi.server.plugin.PluginTemplateNode interface provides methods for activating Done and Start nodes, and compiling their expressions.
The PluginTemplateNode interface is extended by the following interfaces:
- com.bea.wlpi.server.plugin.PluginDone
- com.bea.wlpi.server.plugin.PluginStart2
The following table describes the PluginTemplateNode interface methods that you must implement as part of the run-time component class when defining a Done or Start node.
Table 4-17 PluginTemplateNode Interface Methods
For more information about the PluginTemplateNode interface, see the com.bea.wlpi.server.plugin.PluginTemplateNode Javadoc.
Using Plug-In Run-Time Contexts
To define the run-time execution information for the plug-in, you must implement a run-time interface for the plug-in component, as defined in Executing the Plug-In. At run time, the plug-in communicates with the process engine using a process called context passing: the Plug-in Manager obtains an instance of the plug-in component run-time interface and passes the context to it.
The following figure illustrates context passing.
Figure 4-10 Context Passing
![]()
Each context interface provides restricted access to the Plug-in Manager functionality, enabling the plug-in to execute and manage its own application logic, and introduce the plug-in instance data into the BPM run-time environment.
The following table describes the plug-in run-time context interfaces.
Table 4-18 Plug-In Run-Time Context Interfaces
The following section describes the context interfaces in more detail.
Action Context
The com.bea.wlpi.server.plugin.ActionContext interface provides the run-time context and services for plug-in actions. This context is passed via the com.bea.wlpi.server.plugin.PluginAction interface execute() method.
The following table describes the ActionContext interface methods that you can use to access information about the action context.
Table 4-19 ActionContext Interface Methods
Evaluation Context
The com.bea.wlpi.evaluator.EvaluationContext interface provides the run-time evaluation parameters for the elements in an expression. This context is passed via the evaluate() method to the com.bea.wlpi.server.plugin.PluginField interface and the com.bea.wlpi.server.plugin.PluginFunction interface.
The following table describes the EvaluationContext interface methods that you can use to access information about the evaluation context.
Table 4-20 EvaluationContext Interface Methods
Event Context
The com.bea.wlpi.server.plugin.EventContext interface provides the run-time context and services to plug-in events. This context is passed via the following methods:
- activate() and trigger() methods to the com.bea.wlpi.server.plugin.PluginEvent interface
- settrigger() method to the com.bea.wlpi.server.plugin.PluginStart2 interface
The following table describes the EventContext interface methods that you can use to access information about the event context.
Table 4-21 Event Context Interface Methods
Execution Context
The com.bea.wlpi.server.common.ExecutionContext interface provides the run-time context and services for a running workflow instance. This context is passed via the following methods:
- com.bea.wlpi.server.plugin.PluginAction interface execute(), response(), and startedWorkflowDone() methods
- com.bea.wlpi.server.plugin.PluginEvent interface activate() and trigger() methods
- com.bea.wlpi.server.plugin.PluginTemplateNode interface activate() method (used by the Start and Done nodes)
The following table describes the ExecutionContext interface methods that you can use to access information about the action context.
Table 4-22 ExecutionContext Interface Methods
For more information, see the com.bea.wlpi.server.common.ExecutionContext Javadoc.
PluginPanelContext
The com.bea.wlpi.common.plugin.PluginPanelContext interface provides the run-time context and services for the design client (for example, the Studio), including:
- Access to plug-in template and template definition data
- Services to launch the Expression Builder, validate and manipulate expressions, and invoke the Add Variable dialog box.
Note: Not all methods are applicable in all dialog box contexts. If the plug-in invokes a method in an invalid context, a java.lang.UnsupportedOperationException exception is thrown.
You can access the plug-in panel context using the com.bea.wlpi.common.plugin.PluginPanel get and set methods defined in the table PluginPanel Class Methods.
The following table describes the PluginPanelContext interface methods that you can use to access information about the action context.
Table 4-23 PluginPanelContext Interface Methods
For more information, see the com.bea.wlpi.server.plugin.PluginPanelContext Javadoc.
Defining the Plug-In Component Value Objects
The final step consists of defining the value object for the plug-in component to further define the component data. To define the plug-in component value object, use the associated constructor. Each of the plug-in value objects described in the table Plug-In Value Objects, provides one or more constructors for creating object data. The constructors for creating value objects are described in Plug-In Value Object Summary.
You must pass the plug-in value objects for each of the plug-in components when defining the com.bea.wlpi.common.plugin.PluginCapabilitiesInfo object, as described in the getPluginCapabilities() method description, in the table Remote Interface Plug-In Information Methods.
The following code listing is an excerpt from the plug-in sample that shows how to implement the getPluginCapabilitiesInfo() method. This excerpt is taken from the SamplePluginBean.java file in the WLI_HOME/samples/bpm_api/plugin/src/com/bea/wlpi/tour/po/plugin directory. Notable lines of code are shown in bold.
Listing 4-24 Implementing the getPluginCapabilitiesInfo() Method
public PluginCapabilitiesInfo getPluginCapabilitiesInfo(Locale lc,
CategoryInfo[] info) {
PluginInfo pi;
FieldInfo orderFieldInfo;
FieldInfo confirmFieldInfo;
FieldInfo[] fieldInfo;
FunctionInfo fi;
FunctionInfo[] functionInfo;
StartInfo si;
StartInfo[] startInfo;
EventInfo ei;
EventInfo[] eventInfo;
SampleBundle bundle = new SampleBundle(lc);
log("getPluginCapabilities called");
pi = createPluginInfo(lc);
orderFieldInfo =
new FieldInfo(SamplePluginConstants.PLUGIN_NAME, 3,
bundle.getString("orderFieldName"),
bundle.getString("orderFieldDesc"),
SamplePluginConstants.ORDER_FIELD_CLASSES, false);
confirmFieldInfo =
new FieldInfo(SamplePluginConstants.PLUGIN_NAME, 4,
bundle.getString("confirmFieldName"),
bundle.getString("confirmFieldDesc"),
SamplePluginConstants.CONFIRM_FIELD_CLASSES, false);
fieldInfo = new FieldInfo[]{ orderFieldInfo, confirmFieldInfo };
ei = new EventInfo(SamplePluginConstants.PLUGIN_NAME, 6,
bundle.getString("confirmOrderName"),
bundle.getString("confirmOrderDesc"), ICON_BYTE_ARRAY,
SamplePluginConstants.EVENT_CLASSES,
confirmFieldInfo);
eventInfo = new EventInfo[]{ ei };
fi = new FunctionInfo(SamplePluginConstants.PLUGIN_NAME, 7,
bundle.getString("calcTotalName"),
bundle.getString("calcTotalDesc"),
bundle.getString("calcTotalHint"),
SamplePluginConstants.FUNCTION_CLASSES, 3, 3);
functionInfo = new FunctionInfo[]{ fi };
si = new StartInfo(SamplePluginConstants.PLUGIN_NAME, 5,
bundle.getString("startOrderName"),
bundle.getString("startOrderDesc"), ICICON_BYTE_ARRAYON,
SamplePluginConstants.START_CLASSES, orderFieldInfo);
startInfo = new StartInfo[]{ si };
PluginCapabilitiesInfo pci = new PluginCapabilitiesInfo(pi,
getCategoryInfo(bundle), eventInfo,
fieldInfo, functionInfo, startInfo,
null, null, null, null, null);
return pci;
}
![]()
![]()
![]()
Copyright © 2001 BEA Systems, Inc. All rights reserved.
Required browser: Netscape 4.0 or higher, or Microsoft Internet Explorer 4.0 or higher.