How to create an adapter service implementation?
About this task
An adapter service defines an operation that the adapter performs on an adapter resource. Adapter services operate like IBM webMethods Integration Server flow services or Java services. Adapter services have input and output signatures, you call them within flow services, and you can audit them from the Integration Server's audit system.
- IBM webMethods Integration Server 9.12 or later installed.
- Designer 9.12 or later installed.
- Integration Server Administrator access.
- Java 1.8 or later installed.
- Basic understanding of IBM webMethods Integration Server, Designer, Integration Server Administrator, Java.
How to create a basic adapter service implementation without any elements?
Procedure
- Start the editor to create Java files for the adapter service implementation.
-
Create directories corresponding to your Java package structure
in the
IBM webMethods
package you created using
Designer.
For example:
com\mycompany\adapter\myAdapter\services. In
the example, the folder created is
com\wm\MyAdapter\services.
Note: You should create your Java package and classes in the adapterPackageName\code\source folder in the IBM webMethods package you created using Designer.
-
Create a class by extending the
com.wm.adk.cci.interaction.WmAdapterService base
class.
In the example, created MockDbUpdate class:
package com.wm.MyAdapter.services; import com.wm.adk.cci.interaction.WmAdapterService; import com.wm.adk.cci.record.WmRecord; import com.wm.adk.cci.record.WmRecordFactory; import com.wm.adk.connection.WmManagedConnection; import com.wm.adk.metadata.WmTemplateDescriptor; import java.util.Hashtable; import java.util.Locale; import javax.resource.ResourceException; import com.wm.MyAdapter.MyAdapter;public class MockDbUpdate extends WmAdapterService { public void fillWmTemplateDescriptor(WmTemplateDescriptor d,Locale l) throws ResourceException { } public WmRecord execute(WmManagedConnection connection, WmRecord input) throws ResourceException { return null; } } -
Update the resource bundle implementation class to add the
display name and description of the adapter service.
In the example, updated MyAdapterResource class:
package com.wm.MyAdapter; .. .. import com.wm.MyAdapter.services.MockDbUpdate; public class MyAdapterResource extends ListResourceBundle implements MyAdapterConstants{ .. .. static final Object[][] _contents = { .. .. //Adapter Services ,{MockDbUpdate.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Mock Update Service"} ,{MockDbUpdate.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Simulates a database update service"} } protected Object[][] getContents() { // TODO Auto-generated method stub return _contents; } } -
Register the adapter service by updating your
fillResourceAdapterMetadataInfo method in your
WmManagedConnectionFactory connection factory
implementation class.
In the example, the MockDbUpdate class is registered using fillResourceAdapterMetadataInfo method in the SimpleConnectionFactory connection factory class:
package com.wm.MyAdapter.connections; import com.wm.adk.connection.WmManagedConnectionFactory; import com.wm.adk.connection.WmManagedConnection; import com.wm.adk.info.ResourceAdapterMetadataInfo; import com.wm.adk.metadata.WmDescriptor; import com.wm.adk.error.AdapterException; import java.util.Locale; import com.wm.MyAdapter.MyAdapter; import com.wm.MyAdapter.MyAdapterConstants; import com.wm.MyAdapter.services.MockDbUpdate; public class SimpleConnectionFactory extends WmManagedConnectionFactory implements MyAdapterConstants { .. .. .. public void fillResourceAdapterMetadataInfo(ResourceAdapterMetadataInfo info, Locale locale) { info.addServiceTemplate(MockDbUpdate.class.getName()); } } -
Execute the ANT script created in the adapter definition to
compile, and deploy the adapter in
Integration Server.
Use the files build.xml and build.properties.
ant deploy - Restart Integration Server.
- Start Integration Server Administrator.
-
Select
Adapters >
MyAdapter > Connections.
The screen lists the adapters' connection configured:
-
In the
Adapters >
MyAdapter > Connections screen,
select
Configure New Connection.
The screen lists the adapters' connection types:
-
In the
Adapters >
MyAdapter > Connection Types
screen, select the connection type
Simple Connection.
The screen lists the adapters' connection properties to configure:
-
In the
Adapters >
MyAdapter > Configure Connection
Type screen, add the details and click
Save Connection.
The Adapters > MyAdapter > Connections screen lists the connection you added.
-
In the
Adapters >
MyAdapter > Connections screen,
click
No in the
Enabled column for the connection you added.
The Enabled column now shows Yes.
-
In
Designer,
create the adapter service.
- In Package Navigator, select the Default package.
-
Select
File > New > Folder.
-
Enter the
Folder name. For example:
TestMyAdapter.
- In the Package Navigator, select the Default > TestMyAdapter.
-
Select
File > New > Adapter Service.
-
Enter the
Element name and click
Next. For example:
TestMyAdapterService.
-
In the
Select Adapter Type, select an adapter
type for which you want to create the service. For example:
MyAdapter.
-
In the
Select an Adapter Connection Alias,
select an adapter connection. For example:
TestMyAdapter:Conn1.
-
In the
Select a Template, select an adapter
template and click
Finish. For example:
Mock Update Service.
Results
- MockDbUpdate.
- Adapter Settings
- Input/Output
- Logged Fields
- Comments
How to display elements in an adapter service?
Procedure
-
Update the
com.wm.adk.cci.interaction.WmAdapterService
implementation class.
-
Create a class attribute, and a corresponding set method for
each metadata parameter. For example, a class attribute
_tableName, and a corresponding set method
setTableName for the parameter table name.
For example class MockDbUpdate:
Class Attribute Name Class Attribute Set Method Name _tableName setTableName _columnNames setColumnNames _columnTypes setColumnTypes _repeating setRepeating _overrideTypes setOverrideTypes package com.wm.MyAdapter.services; import com.wm.adk.cci.interaction.WmAdapterService; import com.wm.adk.cci.record.WmRecord; import com.wm.adk.cci.record.WmRecordFactory; import com.wm.adk.connection.WmManagedConnection; import com.wm.adk.metadata.WmTemplateDescriptor; import java.util.Hashtable; import java.util.Locale; import javax.resource.ResourceException; import com.wm.MyAdapter.MyAdapter;public class MockDbUpdate extends WmAdapterService { private String _tableName; private String[] _columnNames; private String[] _columnTypes; private boolean _repeating; private String[] _overrideTypes; public static final String TABLE_NAME_PARM = "tableName"; public static final String COLUMN_NAMES_PARM = "columnNames"; public static final String COLUMN_TYPES_PARM = "columnTypes"; public static final String REPEATING_PARM = "repeating"; public static final String OVERRIDE_TYPES_PARM = "overrideTypes"; public void setTableName(String val){ _tableName = val;} public void setColumnNames(String[] val){ _columnNames = val;} public void setColumnTypes(String[] val){ _columnTypes = val;} public void setRepeating(boolean val){ _repeating = val;} public void setOverrideTypes(String[] val){_overrideTypes = val;}public void fillWmTemplateDescriptor(WmTemplateDescriptor d,Locale l) throws ResourceException { } public WmRecord execute(WmManagedConnection connection, WmRecord input) throws ResourceException { return null; } }
-
Create a class attribute, and a corresponding set method for
each metadata parameter. For example, a class attribute
_tableName, and a corresponding set method
setTableName for the parameter table name.
-
Update the resource bundle implementation class to add the
display name and description of the adapter service.
In the example, the class is MyAdapterResource:
package com.wm.MyAdapter; .. .. import com.wm.MyAdapter.services.MockDbUpdate; public class MyAdapterResource extends ListResourceBundle implements MyAdapterConstants{ .. .. static final Object[][] _contents = { .. .. //Adapter Services ,{MockDbUpdate.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Mock Update Service"} ,{MockDbUpdate.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Simulates a database update service"} } protected Object[][] getContents() { // TODO Auto-generated method stub return _contents; } } -
Register the adapter service by updating your
fillResourceAdapterMetadataInfo method in your
WmManagedConnectionFactory implementation class.
In the example, the adapter service MockDbUpdate is registered using the method fillResourceAdapterMetadataInfo in the connection factory class SimpleConnectionFactory class:
package com.wm.MyAdapter.connections; import com.wm.adk.connection.WmManagedConnectionFactory; import com.wm.adk.connection.WmManagedConnection; import com.wm.adk.info.ResourceAdapterMetadataInfo; import com.wm.adk.metadata.WmDescriptor; import com.wm.adk.error.AdapterException; import java.util.Locale; import com.wm.MyAdapter.MyAdapter; import com.wm.MyAdapter.MyAdapterConstants; import com.wm.MyAdapter.services.MockDbUpdate; public class SimpleConnectionFactory extends WmManagedConnectionFactory implements MyAdapterConstants { .. .. .. public void fillResourceAdapterMetadataInfo(ResourceAdapterMetadataInfo info, Locale locale) { info.addServiceTemplate(MockDbUpdate.class.getName()); } } -
Execute the ANT script created in the adapter definition to
compile, and deploy the adapter in
Integration Server.
Use the files build.xml and build.properties.
ant deploy - Restart Integration Server.
- Start Integration Server Administrator.
- In Designer, create the adapter service.
Results
How to group elements, display data in tables and perform lookups in an adapter service?
Procedure
-
Update the
com.wm.adk.cci.interaction.WmAdapterService
implementation class.
-
Create a class attribute, a set method, a constant, and a
resource domain for each metadata parameter. For example, a class attribute
_tableName, a set method
setTableName, a constant
TABLE_NAME_PARM, and a resource domain
TABLES_RD (which needs to lookup) for the
parameter table name.
Class Attribute Name Class Attribute Set Method Name Class Attribute Name Constant Resource Domain Name Constant _tableName setTableName TABLE_NAME_PARM TABLES_RD _columnNames setColumnNames COLUMN_NAMES_PARM COLUMN_NAMES_RD _columnTypes setColumnTypes COLUMN_TYPES_PARM COLUMN_TYPES_RD _repeating setRepeating REPEATING_PARM None _overrideTypes setOverrideTypes OVERRIDE_TYPES_PARM OVERRIDE_TYPES_RD - In the fillWmTemplateDescriptor method, call WmTemplateDescriptor.createGroup method, WmTemplateDescriptor.createFieldMap method, and WmTemplateDescriptor.createTuple method.
- In the fillWmTemplateDescriptor method, call WmTemplateDescriptor.setResourceDomain method, and WmTemplateDescriptor.setDescriptions method.
- Create the private Hashtable[] unpackRequest(WmRecord request) method to process and convert the IBM webMethods's datatype WmRecord to Hashtable[].
- Create the private WmRecord packResonse(Hashtable[] response) method to process and convert the Hashtable[] to IBM webMethods's datatype WmRecord.
- In the execute method, call unpackRequest method, and packResonse method.
For example, MockDbUpdate class :package com.wm.MyAdapter.services; import com.wm.adk.cci.interaction.WmAdapterService; import com.wm.adk.cci.record.WmRecord; import com.wm.adk.cci.record.WmRecordFactory; import com.wm.adk.connection.WmManagedConnection; import com.wm.adk.metadata.WmTemplateDescriptor; import com.wm.data.IData; import com.wm.data.IDataCursor; import com.wm.data.IDataFactory; import com.wm.data.IDataUtil; import java.util.Hashtable; import java.util.Locale; import javax.resource.ResourceException; import com.wm.MyAdapter.MyAdapter;public class MockDbUpdate extends WmAdapterService { //MockDB Group public static final String UPD_SETTINGS_GRP = "Mock Settings"; public static final String TABLE_NAME_PARM = "tableName"; public static final String COLUMN_NAMES_PARM = "columnNames"; public static final String COLUMN_TYPES_PARM = "columnTypes"; public static final String REPEATING_PARM = "repeating"; public static final String OVERRIDE_TYPES_PARM = "overrideTypes"; private String _tableName; private String[] _columnNames; private String[] _columnTypes; private boolean _repeating; private String[] _overrideTypes; public void setTableName(String val){ _tableName = val;} public void setColumnNames(String[] val){ _columnNames = val;} public void setColumnTypes(String[] val){ _columnTypes = val;} public void setRepeating(boolean val){ _repeating = val;} public void setOverrideTypes(String[] val){_overrideTypes = val;} public static final String TABLES_RD = "tablesRD"; public static final String COLUMN_NAMES_RD = "columnNamesRD"; public static final String COLUMN_TYPES_RD = "columnTypesRD"; public static final String OVERRIDE_TYPES_RD = "overrideTypesRD";public void fillWmTemplateDescriptor(WmTemplateDescriptor d,Locale l) throws ResourceException { //MockDB Grouping and resource domain setup d.createGroup(UPD_SETTINGS_GRP, new String [] { TABLE_NAME_PARM, REPEATING_PARM, COLUMN_NAMES_PARM, COLUMN_TYPES_PARM, OVERRIDE_TYPES_PARM} ); d.createFieldMap(new String[] { COLUMN_NAMES_PARM, COLUMN_TYPES_PARM, OVERRIDE_TYPES_PARM}, true); d.createTuple(new String[]{COLUMN_NAMES_PARM,COLUMN_TYPES_PARM}); d.setResourceDomain(TABLE_NAME_PARM,TABLES_RD,null); d.setResourceDomain(COLUMN_NAMES_PARM,COLUMN_NAMES_RD, new String[]{TABLE_NAME_PARM}); d.setResourceDomain(COLUMN_TYPES_PARM,COLUMN_TYPES_RD, new String[]{TABLE_NAME_PARM}); d.setResourceDomain(OVERRIDE_TYPES_PARM,OVERRIDE_TYPES_RD,null); //Call to setDescriptions d.setDescriptions(MyAdapter.getInstance(). getAdapterResourceBundleManager(),l); } public WmRecord execute(WmManagedConnection connection, WmRecord input) throws ResourceException { Hashtable[] request = this.unpackRequest(input); return this.packResonse(request); } private Hashtable[] unpackRequest(WmRecord request) throws ResourceException { Hashtable data[] = null; IData mainIData = request.getIData(); IDataCursor mainCursor = mainIData.getCursor(); try { String tableName = this._tableName; String[] columnNames = this._columnNames; if(mainCursor.first(tableName)) { IData[] recordIData; if(this._repeating) { recordIData = IDataUtil.getIDataArray (mainCursor,tableName); data = new Hashtable[recordIData.length]; } else { recordIData = new IData[] {IDataUtil.getIData(mainCursor)}; data = new Hashtable[1]; } for(int rec=0;rec<recordIData.length;rec++) { IDataCursor recordCursor = recordIData[rec].getCursor(); data[rec] = new Hashtable(); for(int c = 0; c < columnNames.length;c++) { if(recordCursor.first(columnNames[c])) { data[rec].put(tableName + "." + columnNames[c], recordCursor.getValue()); } } recordCursor.destroy(); } } else { throw MyAdapter.getInstance().createAdapterException(9999, new String[] {"No Request Data"}); } } catch (Throwable t) { throw MyAdapter.getInstance().createAdapterException(9999, new String[] {"Error unpacking request data"},t); } finally { mainCursor.destroy(); } return data; } private WmRecord packResonse(Hashtable[] response) throws ResourceException { WmRecord data = null; try { IData[] recordIData = new IData[response.length]; String tableName = this._tableName; String[] columnNames = this._columnNames; for(int rec = 0; rec < response.length; rec++) { recordIData[rec] = IDataFactory.create(); IDataCursor recordCursor = recordIData[rec].getCursor(); for(int col = 0; col < columnNames.length;col++) { IDataUtil.put(recordCursor,columnNames[col], response[rec].get(tableName + "." + columnNames[col])); } recordCursor.destroy(); } IData mainIData = IDataFactory.create(); IDataCursor mainCursor = mainIData.getCursor(); if(this._repeating) { IDataUtil.put(mainCursor,tableName,recordIData); } else { IDataUtil.put(mainCursor,tableName,recordIData[0]); } mainCursor.destroy(); data = WmRecordFactory.getFactory().createWmRecord("nameNotUsed"); data.setIData(mainIData); } catch (Throwable t) { throw MyAdapter.getInstance().createAdapterException(9999, new String[] {"Error packing response data"},t); } return data; } } -
Create a class attribute, a set method, a constant, and a
resource domain for each metadata parameter. For example, a class attribute
_tableName, a set method
setTableName, a constant
TABLE_NAME_PARM, and a resource domain
TABLES_RD (which needs to lookup) for the
parameter table name.
-
Update the
WmManagedConnection implementation class.
- Add the data for the mock tables in the adapter service.
- Add the methods adapterCheckValue, adapterResourceDomainLookup, and registerResourceDomain
package com.wm.MyAdapter.connections; import com.wm.adk.connection.WmManagedConnection; import com.wm.adk.metadata.*; import com.wm.adk.error.AdapterException; import com.wm.MyAdapter.MyAdapter; import com.wm.MyAdapter.services.MockDbUpdate; public class SimpleConnection extends WmManagedConnection { String hostName; int port; //Adapter Services variables private String[] mockTableNames ={ "CUSTOMERS","ORDERS","LINE_ITEMS"}; private String[][] mockColumnNames ={ {"name","id", "ssn"}, {"id","date","customer_id"}, {"order_id","item_number","quantity","description"} }; private String [][] mockDataTypes = { {"java.lang.String","java.lang.Integer", "java.lang.String"}, {"java.lang.Integer", "java.util.Date", "java.lang.Integer"}, {"java.lang.Integer", "java.lang.Integer", "java.lang.Integer", "java.lang.String"} }; public SimpleConnection(String hostNameValue, int portValue) { .. .. } public void destroyConnection() { .. .. } // The remaining methods support metadata for related services, etc. // Implement content as needed. public Boolean adapterCheckValue(String serviceName, String resourceDomainName, String[][] values, String testValue) throws AdapterException { Boolean result = new Boolean(false); if(resourceDomainName.equals(MockDbUpdate.OVERRIDE_TYPES_RD)) { try { Object o = Class.forName(testValue).getConstructor( new Class[] {String.class}).newInstance(new Object[]{"0"}); result = new Boolean(true); } catch (Throwable t){} } return result; } public ResourceDomainValues[] adapterResourceDomainLookup(String serviceName, String resourceDomainName, String[][] values) throws AdapterException { ResourceDomainValues[] results = null; //MockDB Group Lookup if(resourceDomainName.equals(MockDbUpdate.COLUMN_NAMES_RD)|| resourceDomainName.equals(MockDbUpdate.COLUMN_TYPES_RD)) { String tableName = values[0][0]; for(int x = 0; x < this.mockTableNames.length;x++) { if(this.mockTableNames[x].equals(tableName)) { ResourceDomainValues columnsRdvs = new ResourceDomainValues( MockDbUpdate.COLUMN_NAMES_RD,this.mockColumnNames[x]); columnsRdvs.setComplete(true); ResourceDomainValues typesRdvs = new ResourceDomainValues( MockDbUpdate.COLUMN_TYPES_RD, this.mockDataTypes[x]); typesRdvs.setComplete(true); results = new ResourceDomainValues[] {columnsRdvs,typesRdvs}; break; } } } return results; } public void registerResourceDomain(WmAdapterAccess access) throws AdapterException { //MockDB Group Registering Resource Domain ResourceDomainValues tableRdvs = new ResourceDomainValues( MockDbUpdate.TABLES_RD,mockTableNames); tableRdvs.setComplete(true); access.addResourceDomain(tableRdvs); access.addResourceDomainLookup(MockDbUpdate.COLUMN_NAMES_RD,this); access.addResourceDomainLookup(MockDbUpdate.COLUMN_TYPES_RD,this); ResourceDomainValues rdvs = new ResourceDomainValues( MockDbUpdate.OVERRIDE_TYPES_RD, new String[] {""}); rdvs.setComplete(false); rdvs.setCanValidate(true); access.addResourceDomain(rdvs); access.addCheckValue(MockDbUpdate.OVERRIDE_TYPES_RD,this); } } -
Update the resource bundle implementation class to add the
display name and description of the adapter service.
In the example, updated MyAdapterResource class:
package com.wm.MyAdapter; .. .. import com.wm.MyAdapter.services.MockDbUpdate; public class MyAdapterResource extends ListResourceBundle implements MyAdapterConstants{ .. .. static final Object[][] _contents = { .. .. //Adapter Services ,{MockDbUpdate.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Mock Update Service"} ,{MockDbUpdate.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Simulates a database update service"} //MockDB Group Resource Domain Values ,{MockDbUpdate.UPD_SETTINGS_GRP + ADKGLOBAL.RESOURCEBUNDLEKEY_GROUP, MockDbUpdate.UPD_SETTINGS_GRP} ,{MockDbUpdate.TABLE_NAME_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Table Name"} ,{MockDbUpdate.TABLE_NAME_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Select Table Name"} ,{MockDbUpdate.COLUMN_NAMES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Column Names"} ,{MockDbUpdate.COLUMN_NAMES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Name of column updated by this service"} ,{MockDbUpdate.COLUMN_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Column Types"} ,{MockDbUpdate.COLUMN_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Default data type for column"} ,{MockDbUpdate.OVERRIDE_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Override Data Types"} ,{MockDbUpdate.OVERRIDE_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Type to override column default"} ,{MockDbUpdate.REPEATING_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Update Multiple Rows?"} ,{MockDbUpdate.REPEATING_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Select if input will include multiple rows to update"} } protected Object[][] getContents() { // TODO Auto-generated method stub return _contents; } } -
Register the adapter service by updating your
fillResourceAdapterMetadataInfo method in your
WmManagedConnectionFactory implementation class.
In the example, MockDbUpdate class is registered using the fillResourceAdapterMetadataInfo method in the SimpleConnectionFactory connection factory class:
package com.wm.MyAdapter.connections; import com.wm.adk.connection.WmManagedConnectionFactory; import com.wm.adk.connection.WmManagedConnection; import com.wm.adk.info.ResourceAdapterMetadataInfo; import com.wm.adk.metadata.WmDescriptor; import com.wm.adk.error.AdapterException; import java.util.Locale; import com.wm.MyAdapter.MyAdapter; import com.wm.MyAdapter.MyAdapterConstants; import com.wm.MyAdapter.services.MockDbUpdate; public class SimpleConnectionFactory extends WmManagedConnectionFactory implements MyAdapterConstants { .. .. .. public void fillResourceAdapterMetadataInfo(ResourceAdapterMetadataInfo info, Locale locale) { info.addServiceTemplate(MockDbUpdate.class.getName()); } } -
Execute the ANT script created in the adapter definition to
compile, and deploy the adapter in
Integration Server.
Use the files build.xml and build.properties.
ant deploy - Restart Integration Server.
- Start Integration Server Administrator.
- In Designer, create the adapter service.
Results
- The labels are descriptive (as described in ListResourceBundle implementation).
- The table names are populated with mock data as described in WmManagedConnection implementation.
- The column names and column types update when the table name changes.
How to display adapter service signature?
Procedure
-
Update the
com.wm.adk.cci.interaction.WmAdapterService
implementation class.
-
Create a class attribute, a set method, a constant, and a
resource domain for each metadata parameter. For example, a class attribute
_fieldNames, a corresponding set method
setFieldNames, a corresponding constant
FIELD_NAMES_PARM, and a corresponding
resource domain
FIELD_NAMES_RD (which needs to lookup) for
the parameter table name.
Class Attribute Name Class Attribute Set Method Name Class Attribute Name Constant Resource Domain Name Constant _fieldNames setFieldNames FIELD_NAMES_PARM FIELD_NAMES_RD _fieldTypes setFieldTypes FIELD_TYPES_PARM FIELD_TYPES_RD None setSigIn SIG_IN_PARM None None setSigOut SIG_OUT_PARM None - In the fillWmTemplateDescriptor method, call WmTemplateDescriptor.createGroup method, WmTemplateDescriptor.createFieldMap method, and WmTemplateDescriptor.createTuple method for the new tab Signature.
- In the fillWmTemplateDescriptor method, call WmTemplateDescriptor.setResourceDomain method, and WmTemplateDescriptor.setDescriptions method.
- Create the private Hashtable[] unpackRequest(WmRecord request) method to process and convert the IBM webMethods's datatype WmRecord to Hashtable[].
- Create the private WmRecord packResonse(Hashtable[] response) method to process and convert the Hashtable[] to IBM webMethods's datatype WmRecord.
- In the execute method, call unpackRequest method, and packResonse method.
For example, MockDbUpdate class:package com.wm.MyAdapter.services; import com.wm.adk.cci.interaction.WmAdapterService; import com.wm.adk.cci.record.WmRecord; import com.wm.adk.cci.record.WmRecordFactory; import com.wm.adk.connection.WmManagedConnection; import com.wm.adk.metadata.WmTemplateDescriptor; import com.wm.data.IData; import com.wm.data.IDataCursor; import com.wm.data.IDataFactory; import com.wm.data.IDataUtil; import java.util.Hashtable; import java.util.Locale; import javax.resource.ResourceException; import com.wm.MyAdapter.MyAdapter;public class MockDbUpdate extends WmAdapterService { //MockDB Group public static final String UPD_SETTINGS_GRP = "Mock Settings"; public static final String TABLE_NAME_PARM = "tableName"; public static final String COLUMN_NAMES_PARM = "columnNames"; public static final String COLUMN_TYPES_PARM = "columnTypes"; public static final String REPEATING_PARM = "repeating"; public static final String OVERRIDE_TYPES_PARM = "overrideTypes"; private String _tableName; private String[] _columnNames; private String[] _columnTypes; private boolean _repeating; private String[] _overrideTypes; public void setTableName(String val){ _tableName = val;} public void setColumnNames(String[] val){ _columnNames = val;} public void setColumnTypes(String[] val){ _columnTypes = val;} public void setRepeating(boolean val){ _repeating = val;} public void setOverrideTypes(String[] val){_overrideTypes = val;} public static final String TABLES_RD = "tablesRD"; public static final String COLUMN_NAMES_RD = "columnNamesRD"; public static final String COLUMN_TYPES_RD = "columnTypesRD"; public static final String OVERRIDE_TYPES_RD = "overrideTypesRD";//MockDB Signature Group public static final String SIG_SETTINGS_GRP = "Signature"; public static final String FIELD_NAMES_PARM = "fieldNames"; public static final String FIELD_TYPES_PARM = "fieldTypes"; public static final String SIG_IN_PARM = "sigIn"; public static final String SIG_OUT_PARM = "sigOut"; private String[] _fieldNames; private String[] _fieldTypes; public void setFieldNames(String[] val){ _fieldNames = val;} public void setFieldTypes(String[] val){ _fieldTypes = val;} public void setSigIn(String[] val){} public void setSigOut(String[] val){} public static final String FIELD_NAMES_RD = "fieldNamesRD"; public static final String FIELD_TYPES_RD = "fieldTypesRD";public void fillWmTemplateDescriptor(WmTemplateDescriptor d,Locale l) throws ResourceException { //MockDB Grouping and resource domain setup d.createGroup(UPD_SETTINGS_GRP, new String [] { TABLE_NAME_PARM, REPEATING_PARM, COLUMN_NAMES_PARM, COLUMN_TYPES_PARM, OVERRIDE_TYPES_PARM} ); d.createFieldMap(new String[] { COLUMN_NAMES_PARM, COLUMN_TYPES_PARM, OVERRIDE_TYPES_PARM}, true); d.createTuple(new String[]{COLUMN_NAMES_PARM,COLUMN_TYPES_PARM}); d.setResourceDomain(TABLE_NAME_PARM,TABLES_RD,null); d.setResourceDomain(COLUMN_NAMES_PARM,COLUMN_NAMES_RD, new String[]{TABLE_NAME_PARM}); d.setResourceDomain(COLUMN_TYPES_PARM,COLUMN_TYPES_RD, new String[]{TABLE_NAME_PARM}); d.setResourceDomain(OVERRIDE_TYPES_PARM,OVERRIDE_TYPES_RD,null); //MockDB Signature Grouping and resource domain setup d.createGroup(SIG_SETTINGS_GRP, new String [] { FIELD_NAMES_PARM, FIELD_TYPES_PARM, SIG_IN_PARM, SIG_OUT_PARM} ); d.createFieldMap(new String [] { FIELD_NAMES_PARM, FIELD_TYPES_PARM, SIG_IN_PARM, SIG_OUT_PARM}, false); d.createTuple(new String[]{FIELD_NAMES_PARM,FIELD_TYPES_PARM}); String [] fieldTupleDependencies = {TABLE_NAME_PARM, REPEATING_PARM, COLUMN_NAMES_PARM, COLUMN_TYPES_PARM, OVERRIDE_TYPES_PARM}; d.setResourceDomain(FIELD_NAMES_PARM,FIELD_NAMES_RD, fieldTupleDependencies); d.setResourceDomain(FIELD_TYPES_PARM,FIELD_TYPES_RD, fieldTupleDependencies); d.setResourceDomain(SIG_IN_PARM,WmTemplateDescriptor.INPUT_FIELD_NAMES, new String[] {FIELD_NAMES_PARM, FIELD_TYPES_PARM}); d.setResourceDomain(SIG_OUT_PARM,WmTemplateDescriptor.OUTPUT_FIELD_NAMES, new String[] {FIELD_NAMES_PARM, FIELD_TYPES_PARM}); //Call to setDescriptions d.setDescriptions(MyAdapter.getInstance(). getAdapterResourceBundleManager(),l); } public WmRecord execute(WmManagedConnection connection, WmRecord input) throws ResourceException { Hashtable[] request = this.unpackRequest(input); return this.packResonse(request); } private Hashtable[] unpackRequest(WmRecord request) throws ResourceException { Hashtable data[] = null; IData mainIData = request.getIData(); IDataCursor mainCursor = mainIData.getCursor(); try { String tableName = this._tableName; String[] columnNames = this._columnNames; if(mainCursor.first(tableName)) { IData[] recordIData; if(this._repeating) { recordIData = IDataUtil.getIDataArray (mainCursor,tableName); data = new Hashtable[recordIData.length]; } else { recordIData = new IData[] {IDataUtil.getIData(mainCursor)}; data = new Hashtable[1]; } for(int rec=0;rec<recordIData.length;rec++) { IDataCursor recordCursor = recordIData[rec].getCursor(); data[rec] = new Hashtable(); for(int c = 0; c < columnNames.length;c++) { if(recordCursor.first(columnNames[c])) { data[rec].put(tableName + "." + columnNames[c], recordCursor.getValue()); } } recordCursor.destroy(); } } else { throw MyAdapter.getInstance().createAdapterException(9999, new String[] {"No Request Data"}); } } catch (Throwable t) { throw MyAdapter.getInstance().createAdapterException(9999, new String[] {"Error unpacking request data"},t); } finally { mainCursor.destroy(); } return data; } private WmRecord packResonse(Hashtable[] response) throws ResourceException { WmRecord data = null; try { IData[] recordIData = new IData[response.length]; String tableName = this._tableName; String[] columnNames = this._columnNames; for(int rec = 0; rec < response.length; rec++) { recordIData[rec] = IDataFactory.create(); IDataCursor recordCursor = recordIData[rec].getCursor(); for(int col = 0; col < columnNames.length;col++) { IDataUtil.put(recordCursor,columnNames[col], response[rec].get(tableName + "." + columnNames[col])); } recordCursor.destroy(); } IData mainIData = IDataFactory.create(); IDataCursor mainCursor = mainIData.getCursor(); if(this._repeating) { IDataUtil.put(mainCursor,tableName,recordIData); } else { IDataUtil.put(mainCursor,tableName,recordIData[0]); } mainCursor.destroy(); data = WmRecordFactory.getFactory().createWmRecord("nameNotUsed"); data.setIData(mainIData); } catch (Throwable t) { throw MyAdapter.getInstance().createAdapterException(9999, new String[] {"Error packing response data"},t); } return data; } } -
Create a class attribute, a set method, a constant, and a
resource domain for each metadata parameter. For example, a class attribute
_fieldNames, a corresponding set method
setFieldNames, a corresponding constant
FIELD_NAMES_PARM, and a corresponding
resource domain
FIELD_NAMES_RD (which needs to lookup) for
the parameter table name.
-
Update the
WmManagedConnection implementation class.
- Add the data for the mock tables in the adapter service.
- Add the methods adapterCheckValue, adapterResourceDomainLookup, and registerResourceDomain
package com.wm.MyAdapter.connections; import com.wm.adk.connection.WmManagedConnection; import com.wm.adk.metadata.*; import com.wm.adk.error.AdapterException; import com.wm.MyAdapter.MyAdapter; import com.wm.MyAdapter.services.MockDbUpdate; public class SimpleConnection extends WmManagedConnection { String hostName; int port; //Adapter Services variables private String[] mockTableNames ={ "CUSTOMERS","ORDERS","LINE_ITEMS"}; private String[][] mockColumnNames ={ {"name","id", "ssn"}, {"id","date","customer_id"}, {"order_id","item_number","quantity","description"} }; private String [][] mockDataTypes = { {"java.lang.String","java.lang.Integer", "java.lang.String"}, {"java.lang.Integer", "java.util.Date", "java.lang.Integer"}, {"java.lang.Integer", "java.lang.Integer", "java.lang.Integer", "java.lang.String"} }; public SimpleConnection(String hostNameValue, int portValue) { super(); hostName = hostNameValue; port = portValue; MyAdapter.getInstance().getLogger().logDebug(9999, "Simple Connection created with hostName = " + hostName + "and port = " + Integer.toString(port)); } public void destroyConnection() { MyAdapter.getInstance().getLogger().logDebug(9999,"Simple Connection Destroyed"); } // The remaining methods support metadata for related services, etc. // Implement content as needed. public Boolean adapterCheckValue(String serviceName, String resourceDomainName, String[][] values, String testValue) throws AdapterException { Boolean result = new Boolean(false); if(resourceDomainName.equals(MockDbUpdate.OVERRIDE_TYPES_RD)) { try { Object o = Class.forName(testValue).getConstructor( new Class[] {String.class}).newInstance(new Object[]{"0"}); result = new Boolean(true); } catch (Throwable t){} } return result; } public ResourceDomainValues[] adapterResourceDomainLookup(String serviceName, String resourceDomainName, String[][] values) throws AdapterException { ResourceDomainValues[] results = null; //MockDB Group Lookup if(resourceDomainName.equals(MockDbUpdate.COLUMN_NAMES_RD)|| resourceDomainName.equals(MockDbUpdate.COLUMN_TYPES_RD)) { String tableName = values[0][0]; for(int x = 0; x < this.mockTableNames.length;x++) { if(this.mockTableNames[x].equals(tableName)) { ResourceDomainValues columnsRdvs = new ResourceDomainValues( MockDbUpdate.COLUMN_NAMES_RD,this.mockColumnNames[x]); columnsRdvs.setComplete(true); ResourceDomainValues typesRdvs = new ResourceDomainValues( MockDbUpdate.COLUMN_TYPES_RD, this.mockDataTypes[x]); typesRdvs.setComplete(true); results = new ResourceDomainValues[] {columnsRdvs,typesRdvs}; break; } } //MockDB Signature Group Lookup else if (resourceDomainName.equals(MockDbUpdate.FIELD_NAMES_RD)|| resourceDomainName.equals(MockDbUpdate.FIELD_TYPES_RD)) { String tableName = values[0][0]; boolean repeating = Boolean.valueOf(values[1][0]).booleanValue(); String[] columnNames = values[2]; String[] columnTypes = values[3]; String[] overrideTypes = values[4]; String[] fieldNames = new String[columnNames.length]; String[] fieldTypes = new String[columnTypes.length]; String optBrackets; if(repeating) optBrackets ="[]"; else optBrackets = ""; for (int i = 0; i< fieldNames.length;i++) { fieldNames[i] = tableName + optBrackets + "." + columnNames[i]; fieldTypes[i] = columnTypes[i] + optBrackets; if(overrideTypes.length > i) { if (!overrideTypes[i].equals("")) { fieldTypes[i] = overrideTypes[i] + optBrackets; } } } results = new ResourceDomainValues[]{ new ResourceDomainValues(MockDbUpdate.FIELD_NAMES_RD,fieldNames), new ResourceDomainValues(MockDbUpdate.FIELD_TYPES_RD,fieldTypes)}; } return results; } public void registerResourceDomain(WmAdapterAccess access) throws AdapterException { //MockDB Group Registering Resource Domain ResourceDomainValues tableRdvs = new ResourceDomainValues( MockDbUpdate.TABLES_RD,mockTableNames); tableRdvs.setComplete(true); access.addResourceDomain(tableRdvs); access.addResourceDomainLookup(MockDbUpdate.COLUMN_NAMES_RD,this); access.addResourceDomainLookup(MockDbUpdate.COLUMN_TYPES_RD,this); ResourceDomainValues rdvs = new ResourceDomainValues( MockDbUpdate.OVERRIDE_TYPES_RD, new String[] {""}); rdvs.setComplete(false); rdvs.setCanValidate(true); access.addResourceDomain(rdvs); access.addCheckValue(MockDbUpdate.OVERRIDE_TYPES_RD,this); //MockDB Signature Group Registering Resource Domain access.addResourceDomainLookup(MockDbUpdate.FIELD_NAMES_RD,this); access.addResourceDomainLookup(MockDbUpdate.FIELD_TYPES_RD,this); } } -
Update the resource bundle implementation class to add the
display name and description of the adapter service.
In the example, update MyAdapterResource class:
package com.wm.MyAdapter; .. .. import com.wm.MyAdapter.services.MockDbUpdate; public class MyAdapterResource extends ListResourceBundle implements MyAdapterConstants{ .. .. static final Object[][] _contents = { .. .. //MockDB Group Resource Domain Values ,{MockDbUpdate.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Mock Update Service"} ,{MockDbUpdate.class.getName() + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Simulates a database update service"} ,{MockDbUpdate.UPD_SETTINGS_GRP + ADKGLOBAL.RESOURCEBUNDLEKEY_GROUP, MockDbUpdate.UPD_SETTINGS_GRP} ,{MockDbUpdate.TABLE_NAME_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Table Name"} ,{MockDbUpdate.TABLE_NAME_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Select Table Name"} ,{MockDbUpdate.COLUMN_NAMES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Column Names"} ,{MockDbUpdate.COLUMN_NAMES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Name of column updated by this service"} ,{MockDbUpdate.COLUMN_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Column Types"} ,{MockDbUpdate.COLUMN_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Default data type for column"} ,{MockDbUpdate.OVERRIDE_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Override Data Types"} ,{MockDbUpdate.OVERRIDE_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Type to override column default"} ,{MockDbUpdate.REPEATING_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Update Multiple Rows?"} ,{MockDbUpdate.REPEATING_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Select if input will include multiple rows to update"} //MockDB Signature Group Resource Domain Values ,{MockDbUpdate.SIG_SETTINGS_GRP + ADKGLOBAL.RESOURCEBUNDLEKEY_GROUP, MockDbUpdate.SIG_SETTINGS_GRP} ,{MockDbUpdate.FIELD_NAMES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Field Names"} ,{MockDbUpdate.FIELD_NAMES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Name of Field"} ,{MockDbUpdate.FIELD_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Field Type"} ,{MockDbUpdate.FIELD_TYPES_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Type of Field"} ,{MockDbUpdate.SIG_IN_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Input Signature"} ,{MockDbUpdate.SIG_IN_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Input Signature"} ,{MockDbUpdate.SIG_OUT_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DISPLAYNAME, "Output Signature"} ,{MockDbUpdate.SIG_OUT_PARM + ADKGLOBAL.RESOURCEBUNDLEKEY_DESCRIPTION, "Output Signature"} } protected Object[][] getContents() { // TODO Auto-generated method stub return _contents; } } -
Register the adapter service by updating your
fillResourceAdapterMetadataInfo method in your
WmManagedConnectionFactory implementation class.
In the example, MockDbUpdate class is registered using the fillResourceAdapterMetadataInfo method in the SimpleConnectionFactoryconnection factory class:
package com.wm.MyAdapter.connections; import com.wm.adk.connection.WmManagedConnectionFactory; import com.wm.adk.connection.WmManagedConnection; import com.wm.adk.info.ResourceAdapterMetadataInfo; import com.wm.adk.metadata.WmDescriptor; import com.wm.adk.error.AdapterException; import java.util.Locale; import com.wm.MyAdapter.MyAdapter; import com.wm.MyAdapter.MyAdapterConstants; import com.wm.MyAdapter.services.MockDbUpdate; public class SimpleConnectionFactory extends WmManagedConnectionFactory implements MyAdapterConstants { .. .. .. public void fillResourceAdapterMetadataInfo(ResourceAdapterMetadataInfo info, Locale locale) { info.addServiceTemplate(MockDbUpdate.class.getName()); } } -
Execute the ANT script created in the adapter definition to
compile, and deploy the adapter in
Integration Server.
Use the files build.xml and build.properties.
ant deploy - Restart Integration Server.
- Start Integration Server Administrator.
-
In
Designer,
create the adapter service.
You will see the Mock Settings, and Signature tab
-
In the
Mock Settings tab,
select a table and then select
Signature tab. For
example: In
Mock Settings tab,
select table
Customer and then select
Signature tab.
You will see the following in the Mock Settings tab, Signature tab, and Input/Output tab.
-
In the
Mock Settings tab, for a table, populate the
rows using
Insert Row or
Fill in all rows to the table and then
select
Signature tab. For example: In the
Mock Settings tab, select the table
Customer, populate the rows using
Insert Row or
Fill in all rows to the table and then
select
Signature tab.
You will see the following in the Mock Settings tab, Signature tab, and Input/Output tab.
Note: The Signature tab shown is for demonstration purposes only. In most cases, the fields in the Signature are hidden. Select the Input/Output tab to view the signature.
-
In the
Mock Settings tab,
select a table and then select
Signature tab. For
example: In
Mock Settings tab,
select table
Customer and then select
Signature tab.