Programming Web Services

     Previous  Next    Open TOC in new window    View as PDF - New Window  Get Adobe Reader - New Window
Content starts here

Using Plug-ins with BEA SALT

This chapter contains the following topics:

 


Overview

BEA SALT GWWS server is a configuration-driven process which, for most basic Web service applications, does not require any programming tasks. However, BEA SALT functionality can be enhanced by developing plug-in interfaces which utilize custom typed buffer data and customized shared libraries to extend the GWWS server.

 


Understanding BEA SALT Plug-ins

A plug-in interface is a set of functions exported by a shared library that can be loaded and invoked by GWWS processes to achieve special functionality. BEA SALT provides a plug-in framework as a common interface for defining and implementing a plug-in interface. Plug-in implementation is carried out by a shared library which contains the actual functions. The plug-in implementation library is configured in the SALT configuration file and is loaded dynamically during GWWS server startup.

Plug-in Elements

Four plug-in elements are required to define a plug-in interface:

Plug-in ID

The plug-in ID element is a string used to identify a particular plug-in interface function. Multiple plug-in interfaces can be grouped with the same Plug-in ID for a similar function. Plug-in ID values are predefined by BEA SALT. Arbitrary string values are not permitted.

BEA SALT 1.1 only supports the P_CUSTOM_TYPE plug-in ID, which is used to define plug-in interfaces for custom typed buffer data handling.

Plug-in Name

The plug-in Name differentiates one plug-in implementation from another within the same Plug-in ID category.

For the P_CUSTOM_TYPE Plug-in ID, the plug-in name is used to indicate the actual custom buffer type name. When the GWWS server, attempts to convert data between Tuxedo custom typed buffers and an XML document, the plug-in name is the key element that searches for the proper plug-in interface.

Plug-In Implementation Functions

Actual business logic should reflect the necessary functions defined in a plug-in vtable structure. Necessary functions may be different for different plug-in ID categories. For the P_CUSTOM_TYPE ID category, two functions need to be implemented:

For more information, see Programming Plug-ins for Custom Typed Buffer Data on page 2-7.

Plug-in Register Functions

Plug-in Register functions are a set of common functions (or rules) that a plug-in interface must implement so that the GWWS server can invoke the plug-in implementation. Each plug-in interface must implement three register function These functions are:

Initiating Function

The initiating function is immediately invoked after the plug-in shared library is loaded during GWWS server startup. Developers can initialize data structures and set up global environments that can be used by the plug-ins.

Returning a 0 value indicates the initiating function has executed successfully. Returning a value other than 0 indicates initiation has failed. If plug-in interface initiation fails, the GWWS server will not start.

The initiating function uses the following syntax:

int _ws_pi_init_@ID@_@Name@(char * params, void **priv_ptr);

@ID@ indicates the actual plug-in ID value. @Name@ indicates the actual plug-in name value. For example, the initiating function of a plug-in with P_CUSTOM_TYPE as a plug-in ID and MyType as a plug-in name is: _ws_pi_init_P_CUSTOM_TYPE_MyType (char * params, void **priv_ptr).

Exiting Function

The exiting function is called before closing the plug-in shared library when the GWWS server shuts down. You should release all reserved plug-in resources.

The exiting function uses the following syntax:

int _ws_pi_exit_@ID@_@Name@(void * priv);

@ID@ indicates the actual plug-in ID value. @Name@ indicates the actual plug-in name value. For example, the initiating exiting function name of a plug-in with P_CUSTOM_TYPE as a plug-in ID and MyType as a plug-in name is: _ws_pi_exit_P_CUSTOM_TYPE_MyType(void * priv).

vtable Setting Function

vtable is a particular C structure that stores the necessary function pointers for the actual businesss logic of a plug-in interface. In other words, a valid plug-in interface must implement all the functions defined by the corresponding vtable.

The vtable setting function uses the following syntax:

int _ws_pi_set_vtbl_@ID@_@Name@(void * priv);

@ID@ indicates the actual plug-in ID value. @Name@ indicates the actual plug-in name value. For example, the vtable setting function of a plug-in with P_CUSTOM_TYPE as a plug-in ID and MyType as a plug-in name is: _ws_pi_set_vtbl_P_CUSTOM_TYPE_MyType(void * priv).

The vtable structures may be different for different plug-in ID categories. For the BEA SALT 1.1 release, P_CUSTOM_TYPE is the only valid plug-in ID.

The vtable structure for P_CUSTOM_TYPE plug-in interfaces is shown in Listing 2-1.

Listing 2-1 custtype_vtable Structure
struct custtype_vtable {
CustomerBuffer *(*soap_in_tuxedo__CUSTBUF)(char *, CustomerBuffer *, char *);
int (*soap_out_tuxedo__CUSTBUF)(char **, CustomerBuffer *, char *);
};

struct custtype_vtable indicates that two functions need to be implemented for a P_CUSTOM_TYPE plug-in interface. For more information, see Programming Plug-ins for Custom Typed Buffer Data on page 2-7.

The function input parameter void * priv points to a concrete vtable instance. You should set the vtable structure with the actual functions within the vtable setting function.

An example of setting the vtable structure with the actual functions within the vtable setting function is shown in Listing 2-2.

Listing 2-2 Setting the vtable Structure with Actual functions within the vtable Setting Function
int _DLLEXPORT_ _ws_pi_set_vtbl_P_CUSTOM_TYPE_MyType (void * vtbl)
{
struct custtype_vtable * vtable;
if ( ! vtbl )
return -1;

vtable = (struct custtype_vtable *) vtbl;

vtable->soap_in_tuxedo__CUSTBUF = ConvertXML_2_MyType;
vtable->soap_out_tuxedo__CUSTBUF = ConvertMyType_2_XML;

userlog(" setup vtable for custom type %s", type_name);

return 0;}

Developing a Plug-in Interface

To develop a comprehensive plug-in interface, do the following steps:

  1. Develop a shared library to implement the plug-in interface
  2. Define the plug-in interface in SALT configuration file
Developing a Plug-in Shared Library

To develop a plug-in shared library, do the following steps:

  1. Write C language plug-in implementation functions for the actual business logic. These functions are not required to be exposed from the shared library. For more information, see Plug-In Implementation Functions on page 2-2.
  2. Write C language plug-in register functions that include: the initiating function, the exiting function and the vtable setting function. These register functions need to be exported so that they can be invoked from the GWWS server. For more information, see Plug-in Register Functions on page 2-3.
  3. Compile all the above functions into one shared library.
Defining a Plug-in interface in SALT configuration file

To define a plug-in shared library that is loaded by the GWWS server, the corresponding plug-in interface information must be configured in the BEA SALT configuration file. For more information, see Configuring BEA SALT in the BEA Salt Administration Guide.

An example of how to define plug-in information in the BEA SALT configuration file is shown in Listing 2-3.

Listing 2-3 Defined Plug-In in the BEA SALT Configuration File
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://www.bea.com/Tuxedo/Salt/200606">
<Servicelist id="sample">
<Service name="custom_type_svc1"/>
</Servicelist>
<Policy/>
<System>
<Plugin>
<Interface>
<ID>P_CUSTOM_TYPE</ID>
<Name>MYTYPE</Name>
<Library>mytype_plugin.so</Library>
</Interface>
</Plugin>
</System>
<WSGateway>
<GWInstance id="GWWS1">
<HTTP address="//my host"/>
</GWInstance>
</WSGateway>
</Configuration>
Notes: To define multiple plug-in interfaces, multiple <Interface> elements must be specified. Each <Interface> element indicates one plug-in interface.
Note: Multiple plug-in interfaces can be built into one shared library file.

 


Programming Plug-ins for Custom Typed Buffer Data

Tuxedo allows developers to customize their own typed buffers. If you are already using your own custom typed buffers, the BEA SALT plug-in mechanism provides a way to convert SOAP XML payloads to and from custom typed buffers.

For more information, see Customizing a Buffer in Programming a Tuxedo ATMI Application Using C.

How Tuxedo Custom Typed Buffer Plug-ins Work

Figure 2-1 depicts custom typed buffer data streaming between a Web service client program and a Tuxedo domain.

Figure 2-1 Web Service Client Program and Tuxedo Domain Custom Typed Buffer Data Streaming

Web Service Client Program and Tuxedo Domain Custom Typed Buffer Data Streaming

When a Tuxedo service requires an input custom typed buffer, the GWWS server automatically looks for the proper custom type name vtable structure:

Developing a BEA SALT Plug-in Interface for Tuxedo Custom Typed Buffers

Using the following scenario:

Perform the following steps to develop a BEA SALT plug-in interface:

  1. Write two functions to convert the SOAP XML payload and mytype
  1. Write three plug-in register functions for mytype
  1. Compile the previous five functions into one shared library, mytype_plugin.so.
  2. Configure the plug-in interface in the SALT configuration file

Configure the plug-in interface as shown in Listing 2-4.

Listing 2-4 Custom Typed Buffer Plug-in Interface
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://www.bea.com/Tuxedo/Salt/200606">
<Servicelist id="sample">
<Service name="myservice"/>
</Servicelist>
<Policy/>
<System>
<Plugin>
<Interface>
<ID>P_CUSTOM_TYPE</ID>
<Name>mytype</Name>
<Library>mytype_plugin.so</Library>
</Interface>
</Plugin>
</System>
<WSGateway>
<GWInstance id="GW1">
<HTTP address="//host:5001"/>
</GWInstance>
</WSGateway>
</Configuration>

Tuxedo Custom Typed Buffer XML Data Representation

In the BEA SALT generated WSDL document, the XML Schema built-in type xsd:anyType is used to represent a Tuxedo custom typed buffer. This allows arbitrary content to be encapsulated within the SOAP message, except for the following format restrictions:

  1. Since xsd:anyType is the schema type for the SOAP body tuxtype:inbuf or tuxtype:outbuf element, the effected XML payload for custom typed buffers must be the content encapsulated in the <inbuf> or <outbuf> SOAP elements.
  2. The effective content encapsulated in the SOAP message for Tuxedo custom typed buffers must be a single root XML buffer.
  3. The effective content encapsulated in the SOAP message for Tuxedo custom typed buffers must not include an XML prolog.
  4. Listing 2-5 A Valid SOAP Message Carrying Custom Typed Buffer Data (XML)
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
       <soapenv:Header/>
       <soapenv:Body>
          <m:CALC24 xmlns:m="urn:pack.custtypeapp_typedef.salt11">
             <m:inbuf>
                <poin:point24 xmlns:poin="http://www.example.org/Point24">
                   <poin:p>3</poin:p>
                   <poin:p>5</poin:p>
                   <poin:p>7</poin:p>
                   <poin:p>2</poin:p>
                </poin:point24>
             </m:inbuf>
          </m:CALC24>
       </soapenv:Body>
    </soapenv:Envelope>
    Listing 2-6 An Invalid SOAP Message Carrying Custom Typed Buffer Data
    (Payload is Not a Single Root XML Document)
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
       <soapenv:Header/>
       <soapenv:Body>
          <m:CALC24 xmlns:m="urn:pack.custtypeapp_typedef.salt11">
             <m:inbuf>
                <poin:point24 xmlns:poin="http://www.example.org/Point24">
                   <poin:p>1</poin:p>
                   <poin:p>1</poin:p>
                   <poin:p>2</poin:p>
                   <poin:p>3</poin:p>
                </poin:point24>
                <poin:point24 xmlns:poin="http://www.example.org/Point24">
                   <poin:p>2</poin:p>
                   <poin:p>3</poin:p>
                   <poin:p>5</poin:p>
                   <poin:p>8</poin:p>
                </poin:point24>
             </m:inbuf>
          </m:CALC24>
       </soapenv:Body>
    </soapenv:Envelope>

Converting an XML Effective Payload to a Tuxedo Custom Typed Buffer

The following function should be implemented in order to convert a SOAP XML payload to a custom typed buffer:

CustomerBuffer * (* soap_in_tuxedo__CUSTBUF) (char *xml, CustomerBuffer *a, char *type);

Synopsis

#include <custtype_pi_ex.h>

CustomerBuffer * myxml2buffer (char * xmlbuf, CustomerBuffer *a, char * type);

myxml2buffer is the function name of any user-created valid string.

Description

The implemented function should have the capability to parse the given XML buffer and convert concrete data items to a Tuxedo custom typed buffer instance.

The input parameter, char * xmlbuf, indicates a NULL terminated string with the XML format data stream. Please note that the XML data is the actual XML payload for the custom typed buffer, not the whole SOAP envelop document or the whole SOAP body document.

The input parameter, char * type, indicates the custom typed buffer type name, this parameter is used to verify that the GWWS server expected custom typed buffer handler matches the current plug-in function.

The output parameter, CustomerBuffer *a, is used to store the allocated custom typed buffer instance. A Tuxedo custom typed buffer must be allocated by this plug-in function via the ATMI function tpalloc(). Plug-in code is not responsible to free the allocated custom typed buffer, it is automatically destroyed by the GWWS server if it is not used.

Diagnostics

If successful, this function must return the pointer value of input parameter CustomerBuffer * a.

If it fails, this function returns NULL.

Listing 2-7 Converting XML Effective Payload to Tuxedo Custom Typed Buffer Pseudo Code
CustomerBuffer * myxml2buffer (char * xmlbuf, CustomerBuffer *a, char * type)
{
// Use DOM implementation to parse the xml payload
//SAX can be used as an alternative.
DOMTree = ParseXML( xmlbuf );

if ( error )
return NULL;

// allocate custom typed buffer via tpalloc
a->buf = tpalloc("MYTYPE", "MYSUBTYPE", 1024);
a->len = 1024;

// fetch data from DOMTree and set it into custom typed buffer
DOMTree ==> a->buf;
if ( error ) {
release ( DOMTree );
tpfree(a->buf);
a->buf = NULL;
a->len = 0;
return NULL;
}

release ( DOMTree );

return a;
}
Tip: Tuxedo bundled Xerces library can be used for XML parsing. Tuxedo 8.1 bundles Xerces 1.7 and Tuxedo 9.1 bundles Xerces 2.5

Converting a Tuxedo Custom Typed Buffer to a SOAP XML Payload

The following function should be implemented in order to convert a custom typed buffer to SOAP XML payload:

int (*soap_out_tuxedo__CUSTBUF)(char ** xmlbuf, CustomerBuffer * a, char * type);

Synopsis

#include <custtype_pi_ex.h>

int * mybuffer2xml (char ** xmlbuf, CustomerBuffer *a, char * type);

"mybuffer2xml" is the function name can be specified with any valid string upon your need.

Description

The implemented function has the capability to convert the given custom typed buffer instance to the single root XML document used by the SOAP message.

The input parameter, CustomerBuffer *a, is used to store the custom typed buffer response instance. Plug-in code is not responsible to free the allocated custom typed buffer, it is automatically destroyed by the GWWS server if it is not used.

The input parameter, char * type, indicates the custom typed buffer type name, this parameter can be used to verify if the SALT GWWS server expected custom typed buffer handler matches the current plug-in function.

The output parameter, char ** xmlbuf, is a pointer that indicates the newly converted XML payload. The XML payload buffer must be allocated by this function and use the malloc () system API. Plug-in code is not responsible to free the allocated XML payload buffer, it is automatically destroyed by the GWWS server if it is not used.

Diagnostics

If successful, this function must returns 0.

If it fails, this function must return -1.

Listing 2-8 Converting Tuxedo Custom Typed Buffer to SOAP XML Pseudo Code
int mybuffer2xml (char ** xmlbuf, CustomerBuffer *a, char * type)
{
// Use DOM implementation to create the xml payload
DOMTree = CreateDOMTree( );

if ( error )
return -1;

// fetch data from custom typed buffer instance,
// and add data to DOMTree according to the client side needed
// XML format

a->buf ==> DOMTree;

// allocate xmlbuf buffer via malloc
* xmlbuf = malloc( expected_len(DOMTree) );
if ( error ) {
release ( DOMTree );
return -1;
}

// serialize DOMTree as xml string
DOMTree >> (* xmlbuf);
if ( error ) {
release ( DOMTree );
free ( (* xmlbuf) );
return -1;
}

release ( DOMTree );
return 0;
}
Tip: The Tuxedo bundled Xerces library can be used to create DOM tree and transform to XML data stream.

Tuxedo 8.1 bundles Xerces 1.7 and Tuxedo 9.1 bundles Xerces 2.5.

Using Customized XML Schema to Extend Default SALT WSDL

The default SALT WSDL document uses xsd:anyType to represent custom typed buffer XML data. xsd:anyType is not well supported by some Web service client-side toolkits. Even for those Web service toolkits that support xsd:anyType, client-side programming is still a complex programming task.

Extending the default SALT WSDL document by replacing xsd:anyType with a customized XML Schema is highly recommended.

To extend the default SALT WSDL document with a customized XML Schema, do the following:

  1. Construct your customized XML Schema file
  2. Use Document/literal encoded style to generate the SALT WSDL document.
  3. Note: BEA SALT only supports extending a Document/literal encoded style WSDL document.
  4. Modify the BEA SALT WSDL document by importing the customized XML Schema and replacing xsd:anyType with the customized XML Schema type.

Listing 2-9 and Listing 2-10 depict samples of an original SALT WSDL document and an extended WSDL document with a customized XML Schema respectively.

Listing 2-9 Original Default SALT WSDL Document
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions ......>
......
<wsdl:types>
<xsd:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
targetNamespace="urn:pack.custtypeapp_typedef.salt11">
<xsd:element name="CALC24">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="inbuf" type="xsd:anyType"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
			<xsd:element name="CALC24Response">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="outbuf" type="xsd:anyType"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>

<wsdl:message name="CALC24Input">
<wsdl:part element="tuxtype:CALC24" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="CALC24Output">
<wsdl:part element="tuxtype:CALC24Response" name="parameters"></wsdl:part>
</wsdl:message>

<wsdl:portType ...>
......
</wsdl:portType>
......
</wsdl:definitions>
Listing 2-10 Extended WSDL Document
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions ......>
......
<wsdl:import namespace= "http://www.example.org/Point24"
location="file:///home/user/bea/tuxedo8.1/samples/salt/custtypeapp/Point24.xsd">
</wsdl:import>
<wsdl:types>
<xsd:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
targetNamespace="urn:pack.custtypeapp_typedef.salt11">
<xsd:element name="CALC24">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="inbuf" type="m:Point24"
xmlns:m="http://www.example.org/Point24">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="CALC24Response">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="outbuf" type="m:Point24"
xmlns:m="http://www.example.org/Point24">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="CALC24Input">
<wsdl:part element="tuxtype:CALC24" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="CALC24Output">
<wsdl:part element="tuxtype:CALC24Response" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:portType ......>
......
</wsdl:portType>
......
</wsdl:definitions>

BEA SALT Custom Typed Buffer Sample

BEA SALT product distribution bundles a sample application that demonstrates how to write plug-in shared library for custom typed buffer data conversion. This sample also demonstrates how to use a customized XML Schema to extend the WSDL document in order to make client/server-side programming more convenient. For more information, see BEA SALT Sample Applications.


  Back to Top       Previous  Next