The next thing to do is to write the adapter run-time classes. Let’s first define the constants that will be used in our adapter, in the demo.MathAdapterConstants interface:
MathAdapterConstants.java
package demo;
public interface MathAdapterConstants {
public final static String OPERATION_ADD = "add";
public final static String OPERATION_SUB = "sub";
public final static String OPERATION_MUL = "mul";
public final static String OPERATION_DIV = "div";
public final static String PARAM_OPERATION = "OPERATION";
public final static String PARAM_ROUNDING = "ROUNDING";
public final static String PARAM_X = "X";
public final static String PARAM_Y = "Y";
public final static String PARAM_RESULT = "RESULT";
}
Here, we defined strings for the various operations as well as the names of all the input, output and configuration parameters.
The actual adapter class is shown in the following code sample:
MathAdapter.java
Note: For the sake of simplicity, in the above source we have omitted many fault checks and safeguards (for example, checking for illegal division by zero).
Each managed adapter must extend the com.savvion.sbm.adapters.framework.ManagedAdapter class (line 6).
A custom managed adapter is expected to overwrite the "execute()" method (lines 10-37). Due to the backward compatibility requirements, the "execute()" method does not have parameters and does not return a value. Instead, a pair of Objects, "input" and "output", that are defined in the ManagedAdapter base class, are used to move data in and out of the adapter. Although "input" and "output" can be of any Serializable java type, when using the default Business Process Server mappers (as in this case), the content of the "input" object is a java.util.Hashtable and the "output" object is expected to be set to another Hashtable from the adapter. In order to avoid type casting in the adapter code, we mapped those two objects to two Hashtables – "inputs" and "outputs" (line 11 and lines 34-36).
Note: The data type of the objects, contained in the input Hashtable will match the types specified in the "config.xml" file. For example, the "X" parameter will always come to the adapter as "java.lang.Double", because this is how it was defined in "config.xml" (see Writingthe Adapter Configurator). When the data type of a dataslot does not match the required data type of an output, the adapter framework will take care of the necessary conversions. List of the supported data type conversions is given in Supporteddata types.
The "inputs" Hashtable will contain all adapter inputs and configuration parameters. On lines 13-14 we extract from the "inputs" Hashtable the "X" and "Y" input parameters. The operation name (a configuration parameter) is also supplied in the "inputs" Hashtable (line 17).
Lines 18-29 use the "OPERATION" parameter and the "X" and "Y" inputs to calculate the result. In case the operation name is invalid (it may happen, if the adapter is not properly configured), an error message is logged in the adapter’s own log file (located in the OEBPS_HOME/ebmsapps/<application>/logs directory on the server) and an exception is thrown. Throwing an exception allows the workstep to become suspended and also logs an error message in the Progress Developer Studio for OpenEdge log file.
Note: The "log()" method, provided by the ManagedAdapter base class, accepts two parameters – an integer log-level, and the message text string. The log-level can be any non-negative integer; a higher number indicates a lower-priority message. Messages will be logged in the adapter file only if the log-level of the adapter, specified in the mapping.prop file, is higher than or equal to the log-level of the message.
On lines 31-32, we check the value of the "ROUNDING" configuration parameter. If this parameter is set to "true", the result is rounded to the nearest integer.
Finally, on lines 34-36, we store the result in the "RESULT" output parameter. Again, note the way the Hashtable is returned through the "output" Object.