Adapter Development Kit 9.12 | webMethods Adapter Development Kit Documentation | webMethods Adapter Development Kit Installation and User’s Documentation | Usage Scenarios | How to create an adapter service implementation? | How to group elements, display data in tables and perform lookups in an adapter service?
 
How to group elements, display data in tables and perform lookups in an adapter service?
1. Update the com.wm.adk.cci.interaction.WmAdapterService implementation class.
a. 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
b. In the fillWmTemplateDescriptor method, call WmTemplateDescriptor.createGroup method, WmTemplateDescriptor.createFieldMap method, and WmTemplateDescriptor.createTuple method.
c. In the fillWmTemplateDescriptor method, call WmTemplateDescriptor.setResourceDomain method, and WmTemplateDescriptor.setDescriptions method.
d. Create the private Hashtable[] unpackRequest(WmRecord request) method to process and convert the webMethods's datatype WmRecord to Hashtable[].
e. Create the private WmRecord packResonse(Hashtable[] response) method to process and convert the Hashtable[] to webMethods's datatype WmRecord.
f. 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;
}
}
2. Update the WmManagedConnection implementation class.
*Add the data for the mock tables in the adapter service.
*Add the methods adapterCheckValue, adapterResourceDomainLookup, and registerResourceDomain
For example, SimpleConnection class:
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);
}
}
3. 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;
}
}
4. 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());
}
}
5. 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
6. Restart Integration Server.
7. Start Integration Server Administrator.
8. In Designer, create the adapter service.
A new adapter service of type MyAdapter is created. You can see the following in the MockDBUpdate tab:
*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.