Web Services Invocation Framework:
J2C Sample

The sample for the J2C WSIF provider consists of two elements, a sample Resource Adapter, MyEIS, and the Customer Info Service, a sample service implemented by the EIS system, access through MyEIS Resource Adapter, described in WSDL and executable via J2C WSIF. 

Customer Info Service

The Customer Info service sample illustrates the invocation of the service implemented by the back end system (MyEIS). The service is described in wsdl and invoked using WSIF J2C provider and MyEIS Resource Adapter. The sample shows how the customer retrieval business function of the back end can be described in WSDL, including complex types schama,  the format handling mechanism and the dynamic invocation. To run the the sample set the classpath to include wsdl4j, wsif.jar, wsif-j2c.jar, j2ee.jar, myeis.jar and run "com.myeis.customer.J2C_MyEIS_CustomerInfoProxy". You should see the following result:

Customer number: 33333
Customer name: Alan Turing

The Customer Info Sample consists of the following files:

MyEIS Resource Adapter

The connector provided as a sample contains the minimal set of classes necessary to execute the interaction with the MyEIS back-end system. The back end is implemented as a Java class (MyEIS) and therefore all services it provides can be accessed without any additional setup. It is not meant to provide a sample implementation of the J2C Resource Adapter but only shows the skeleton classes necessary to support Resource Adapter's pluggability into the tools, import and sample services. Because of the minimal implementation, the Resource Adapter cannot be deployed in the managed environment of the J2EE Application Server, only the non-managed use is supported.  The Connector consists of the following classes, implementing J2EE Connector Architecture interfaces (in the com.myeis.j2c  package):

Class Description
MyEISConnection Client view of the managed connection (connection handle)
MyEISConnectionFactory Factory of connection handles
MyEISInteraction Object providing methods to execute interactions with EIS
MyEISInteractionSpec Object encapsulating properties of a specific interaction
MyEISManagedConnection Physical connection to the backend system. The implementation of this class illustrates two different possibilities of retrieving the list of PortTypes and Definition by the Resource Adapter. The first method is to ship the service (wsdl) files representing available services and definitions with the Resource Adapter. This method would be appropriate for the connector to the EIS with the infrequently changing (for example only between EIS releases) services available. In the sample implementation, the shipped wsdl files are accessed in the com.myeis.repository.Repository class implementation. The second method to get the services available is by querying the EIS (com.myeis.MyEIS class in the sample). In that case the Resource Adapter would connect to and query the EIS for available services.  The tooling does not make any assumptions about which method is used.  The sample connector illustrates support for both methods, switchable through the property on the Managed Connection Factory.
MyEISManagedConnectionFactory Factory of physical connections to the EIS system
Create the MyEIS specific Connector Binding

To enable capturing of the meta information characterizing the details of the interactions with the EIS in the wsdl model, the Resource Adapter provides Connector Bindings. These bindings consist of the following:

The sample connector implements Connector Bindings in the com.myeis.wsdl.extensions.j2c.myeis package. The Binding extensibility element is used as a tag (has no properties) and defines the binding type. The extensibility element for the Operation captures the meta information describing a single interaction with the EIS system. The properties of this extensibility element correspond to the properties of the Resource Adapter's InteractionSpec. The Port extensibility element represents the endpoint (address) where the service is available. It contains properties corresponding to the properties of the ManagedConnectionFactory.   To implement Extensibility Element, create class implementing the javax.wsdl.extensions.ExtensibilityElement and java.io.Serializable interfaces and add appropriate properties from InteractionSpec to the Operation extensibility element and from Managed Connection Factory to Port extensibility element. Next, you need to select the namespace for your bindings. The sample connector uses the following namespace URI: http://schemas.xmlsoap.org/wsdl/myeis/ with the standard prefix, followed by the connector specific last segment. The element names are left to the implementor, however the ones used in the sample connector (MyEISBinding, MyEISAddress, MyEISOperation) make the wsdl files easier to read. The next step is to provide a serializer and deserializer for your bindings. This is necessary since the wsdl file reader and writer cannot handle arbitrary extensibility elements. The serializer writes the XML format of your extensibility elements, for example Operation, the deserializer reads in and parses the XML, creating from it instances of these elements. For example to serialize MyEISOperation object from the sample connector, you need to create the following XML fragment:

<myeis:operation functionName="CUSTOMERINFO_getAddress" />

with the following code:

  if (extension instanceof MyEISOperation) {                      
                  MyEISOperation operation = (MyEISOperation) extension;                      
                  pw.print( "      <"  +  TPrefix +  ":operation" );  
                      
                  if (operation.getFunctionName() !=  null ) {                             
                          DOMUtils.printAttribute( "functionName" ,
                          operation.getFunctionName(), pw);                      
                  } pw.println("/>"); }
  

To deserialize the XML fragment, use the following:

  if (MyEISBindingConstants.Q_ELEM_OPERATION.equals(elementType)) {                     
                  MyEISOperation operation =  new  MyEISOperation();  
                      
                  String functionName = DOMUtils.getAttribute(el, "functionName" );                      
                  if (functionName !=  null ) {                             
                          operation.setFunctionName(functionName);                      
                  }                      
                  return operation;

The last component that you need to provide with your bindings is the Extension Registry. Its purpose is to provide convenient way to register serializer and deserializer for your extensibility elements with tools and run time. The class implements the javax.wsdl.extensions.ExtensionRegistry interface and registers serializer/deserializer for each element in its constructor using the following code:

  MyEISBindingSerializer ser =  new  MyEISBindingSerializer();
  // operation
  this.registerSerializer(javax.wsdl.BindingOperation.class, 
     MyEISOperation. class , ser);
  this.registerDeserializer(javax.wsdl.BindingOperation.class,
     MyEISBindingConstants.Q_ELEM_OPERATION, ser);
Create the WSIF extensions for MyEIS Connector

The WSIF requires that every binding to be executed has to provide the set of supporting classes implementing binding run time. J2C Plugin provides elements of the run time and delegates to the specific connector only these elements that cannot be handled in a generic manner for example,  corresponding to the extensibility elements provided by the connector, Address and Operation.

The J2C Plugin implements  WSIFMessage_JCA, WSIFPort_JCA and WSIFOperation_JCA and requires the resource adapter to provide WSIFProvider and WSIFProviderJCAExtensions implementations.

The WSIF uses WSIFService to create a dynamic port corresponding to the endpoint at which the service is accessible. This, in turn, corresponds to the creation of the Connection to the EIS. The resource adapter implements the WSIFProvider and WSIFProviderJCAExtensions interfaces. In its createDynamicWSIFPort method, it creates the WSIFPort_JCA (part of the J2C Plugin run time) initialized with the active javax.resource.cci.Connection. The resource adapter creates the connection either using JNDI lookup or directly using Managed Connection Factory. The name used for the lookup is either built from the service namespace URI, service name and port name or specified explicitly in the Address extensibility element. The provided org.apache.wsif.util.WSIFUtils class contains a set of utility methods that should be used to construct names (for example, JNDI lookup name, Format Handler class name etc.).  In the required implementation of the createOperation method the resource adapter creates WSIFOperation_JCA and initializes is with the instance of Connection and InteractionSpec as shown below:

	BindingOperation bindingOperationModel = aPort.getBinding().getBindingOperation(aOperationName, aInputName, aOutputName);
	ExtensibilityElement bindingOperationModelExtension = (ExtensibilityElement)bindingOperationModel.getExtensibilityElements().get(0);
	if (bindingOperationModelExtension == null) {
		throw new WSIFException("missing bindingOperation extension");
	}
	if (!(bindingOperationModelExtension instanceof MyEISOperation)) {
		throw new WSIFException("invalid extensibility element");
	}
	MyEISOperation operationModelExtension = (MyEISOperation) bindingOperationModelExtension;
	MyEISInteractionSpec interactionSpec = new MyEISInteractionSpec();
	interactionSpec.setFunctionName(operationModelExtension.getFunctionName());
	operation = new WSIFOperation_JCA(aDefinition, aService, aPort, aOperationName, aInputName, aOutputName, typeMap, jcaPort, this, aConnection, interactionSpec);

Optionally, the Resource Adapter can provide implementation of the Message creation methods to be able to create customized messages. The default implementation uses the Streamable interface to exchange input and output data with the Connector.

Create the FormatHandler Generator for MyEIS

The connector provides the format handler generator by implementing com.ibm.jca.formathandler.FormatHandlerGenerator interface. During connector  deployment into the tools, the format handler generator is registered, based on the encoding and style it specifies in the XML file. When the service definition is deployed and the helper classes need to be generated, the encoding and style are used to lookup the format handler generator and invoke it from the tooling. The generate method is passed with the following arguments:

Argument Description
generationPackage the fully qualified package that the generator should use to generate its classes in. This name follows the naming convention described earlier in the document.
beanClass the fully qualified name of the Java bean class that represents the XSD type (or element) for which a format handler is being generated.
aDefinition the WSDL definition from which the XSD type is derived.
aBinding the WSDL binding element that contains the type mapping for the XSD type that is being used.
anEncoding the encoding attribute off the TypeMapping element associated with the format handler to be generated.
aStyle the style attribute off the TypeMapping element associated with the format handler to be generated
xsdQname the QName of the XSD element (or type) for which the format handler is being generated.
elementType the type of element represented by the xsdQname parameter. This is either CustomFormatHandlerGenerator.XSD_TYPE or CustomFormatHandlerGenerator.XSD_ELEMENT
generationContext The context is an optional object that can be used by a FormatHandlerGenerator to assist in code generation, or in keeping track of
artifacts generated. The details, and implementation, of the object are specific to each FormatHandlerGenerator.
Tooling environments must create context, before invoking the FormatHandlerGenerator to generate code.

The format handler generator returns a Hashtable that contains a set of  java.io.InputStreams. Each input stream contains the generated code for a particular class generated by the format handler generator. The number of input streams returned depends on the number of classes that are generated by the format handler generator.  The keys of the Hashtable must be the name of each class (unqualified) that is represented by its corresponding InputStream value. The class name keys are unqualified because they must all be in the generationPackage that is passed in as an input parameter.

The arguments to the generate method may contain sufficient information to generate the specific format handler for example, the xsd type of the part and assumed encoding and style since these were used to locate and invoke the generator.  In some cases, additional information may be required. In this case, the TypeMappings from the passed bindings can be used:

             
  TypeMapping typeMapping =  null ;                
  Iterator iterator = aBinding.getExtensibilityElements().iterator();                
  while (iterator.hasNext()){                       
           Object element = iterator.next();                       
           if (element instanceof TypeMapping){                             
                    typeMapping = (TypeMapping)element;                             
                     break ;                      
           }               
  } 

When the type mappings are used, the generator should verify that type mapping has an encoding, and optionally a style it supports for example

  if (!typeMapping.getEncoding().equals( "myeis" ))                      
          return null ; 

Finally, the generator could retrieve from the format binding the formatType string corresponding to the xsd (type or element) for which the format handler is being generated:

        
  String formatType = null ;              
  iterator = typeMapping.getMaps().iterator();              
  while (iterator.hasNext()){
           TypeMap typeMap = (TypeMap)iterator.next();                     
           if (typeMap.getTypeName().equals(xsdQname)){                           
                    formatType = typeMap.getFormatType();
                    break ;
           }             
  }   

The formatType is a string and tools do not make any assumption about it contents. It is a specific value understood by the generator. In the sample generator, the native format for all types is Java serialization and therefore the formatType string is empty.

The sample generator: com.myeis.j2c.formathandler. MyEISFormatHandlerGenerator does not use typeMaps since the native format it generates is a simple Java serialization and therefore formatTypes in the wsdl files are empty.

In addition to handling the associated part as a Java bean, the format handler should have a capability to read and write the native format to and from the SAXSource and DOMSource. This allows the invoker of the service to pass or retrieve the data as XML. The sample format handler generator shows one of the possible methods to convert a native format, in its case a Java bean, to the "javax.xml.transform.sax.SAXSource" format.

Create the Import Service for MyEIS

The resource adapter supporting the import service is required to provide, in addition to the implementation described in the section above, the following: a service file with the bindings for the Import interface from the J2C Plugin and a set of format handlers for the conversion to native format during execution of the import service. The sample connector binding file is as follows:

 	<binding name="ImportMyEISBinding" type="interface:Import">
		<myeis:binding/>
		<format:typeMapping encoding="myeis">
		</format:typeMapping>
		<operation name="getDefinition">
		<myeis:operation functionName="IMPORT_DEFINITION"/>
			<input name="getDefinitionRequest"/>
			<output name="getDefinitionResponse"/>
		</operation>
		<operation name="getPortTypes">
		<myeis:operation functionName="IMPORT_PORTTYPES"/>
			<input name="getPortTypesRequest"/>
			<output name="getPortTypesResponse"/>
		</operation>
		<operation name="getRawEISMetaData">
		<myeis:operation functionName="IMPORT_RAWMETADATA"/>
			<input name="getRawEISMetaDataRequest"/>
			<output name="getRawEISMetaDataResponse"/>
		</operation>
	</binding>
	<service name="ImportService">
		<port binding="tns:ImportMyEISBinding" name="ImportMyEISPort">
		<myeis:address repositoryLocation="remote"/>
		</port>
	</service>

It contains all the information needed to execute import service, for example function names (in the operation binding) and the repository location (in the port binding). The user will be able to edit these values if necessary, for example if the port binding contains the location of the target EIS system.

The format handlers necessary to execute the import service are no different than any other format handlers generated by the Resource Adapter and the format handler generator can be used to create them. The sample connector provides all the elements needed for the import service.

Packaging the MyEIS Connector together with the Tool Extensions

The sample MyEIS Connector is packaged into myeis.rar, a resource adapter archive file. It contains the "META-INF/j2c_plugin.xml" file, "ra.xml" and one jar with the connector run time and tool extensions. The rar file can contain more than one jar file so for example when the tool extensions are added to the existing connector, they could be packaged in the separate jar.