Custom Inbound Webservices using WebServices Router

OverView

Websphere commerce inbound webservices can be developed either by using the webservices router project which is available out of the box or by making use of SOI / BOD architecture to develop services module
http://publib.boulder.ibm.com/infocenter/wchelp/v7r0m0/topic/com.ibm.commerce.component-services.doc/tasks/twvcreatecomponent.htm

In this article I would like to explore the webservices router project and how this can be extended to develop custom inbound services, the webservice created by this approach supports JAX-RPC style of webservice and hence it can only support protocol level or SOAP header level security configuration, if you are interested in Digitally signing the SOAP envelop you should look for JAX-WS based webservices.

Reference to developing custom inbound webservices using webservices router has been deleted from V7 infocenter as the future direction is to develop services as BOD or SOI Module.
Developing Inbound Webservices using WebService router is still available on V6 Infocenter link.
http://publib.boulder.ibm.com/infocenter/wchelp/v6r0m0/index.jsp?topic=/com.ibm.commerce.webservices.doc/tutorial/twvinboundws.htm

I have tried this technique with Commerce V7 FEP 1 and works just fine with few tweaks :)

The procedure to create a JAX-RPC style webservice is quite common in J2EE application, Websphere commerce additionally supports a common servlet which handles all inbound requests and then delicates the calls to appropriate template which will be used to compose the response XML.

One last differentiator before we jump into this article, WebServices router based inbound webservice can support OAGIS/non OAGIS style of webservices, this is much more simpler to develop and maintain as compared to WCS services module, WCS services module are based on SOI architecture which is based on OAGIS style BOD messages, you can read more about defining a services module from following link.

I don’t want to make this article complicated, for simplicity, we will use a simple Ping WebService as an Example.


Flow of Action

  1. WebSphere application server will intercept the SOAP request first.
  2. WCS defines a generic interception point to handle all incoming webservice requests, com.ibm.commerce.webservices.OpenWebServicePortType is the common service endpoint interface.
  3. SOAP security details from the header section is retrieved and validated.
  4. SOAP message is then converted to name/value pair and packaged as command property, this is supported by message mapper which can be found in wc-server.xml file.
  5. Identify the command to execute, this information is configured in Message mapper file located in /WC/xml/messaging/webservice_SOABOD_template.extension.xml, all custom services should have message mapping entry in this file.
  6. Upon completion of the command, use JSP composition service to compose a response XML. WCS takes care of marshalling the XML response to SOAP message before sending it back to the caller.

Step 1

Defined the WSDL for HelloWorld Service

Step 2

Generate the Java skeleton code using the option as shown in the screenshot
Right click on wsdl file and select
web services -> Generate Java bean skeleton
Make the selection as shown in the screenshot, as you can see we are generating JAX-RPC code. By default JAX-WC is the default option, you will have to ensure you change the selection as per the screenshot below.


Step 3

Next we make couple of changes to the generated files from the previous step, the key is to plug in the generated code to WebSphere commerce webservices inbound framework.

Make following changes to HelloWorld_mapping.xml which is generated by Step 2 in /WebServicesRouter/WebContent/WEB-INF/HelloWorld_mapping.xml

Change 1:
        <port-mapping>
            <port-name>PingServicePort</port-name>
            <!-- java-port-name>HelloWorldSOAP</java-port-name -->
            <java-port-name>com.ibm.commerce.webservices.OpenWebServicePortType</java-port-name>

        </port-mapping>
  
Change 2:

        <!-- service-endpoint-interface>org.example.www.HelloWorld_PortType</service-endpoint-interface -->
        <service-endpoint-interface>com.ibm.commerce.webservices.OpenWebServicePortType</service-endpoint-interface>

Change 3:

            <!-- java-method-name>echoMessage</java-method-name -->
            <java-method-name>executeService</java-method-name>
Change 4:

NOTE: This step is not documented in infocenter, surprising this is an important step else your custom inbound service will throw an exception, let’s hope that IBM will fix it in the tutorial. Valid parameter for executeService is javax.xml.soap.SOAPElement

Edit HelloWorld_mapping.xml file to replace all occurrence of param-type as follows

<param-type>javax.xml.soap.SOAPElement</param-type>

The side effect of not doing this step results in following exception

[12/2/10 11:57:35:828 CST] 00000025 InternalExcep E com.ibm.ws.webservices.engine.InternalException <init> WSWS3227E:  Error: Exception:
                                 java.lang.Exception: WSWS3034E: Error: The OperationDesc for executeService was not matched to a method of com.ibm.commerce.webservices.OpenWebServiceBindingImpl. Debug:name:            services/HelloWorldSOAP
implClass:       class com.ibm.commerce.webservices.OpenWebServiceBindingImpl

Step 4

Made following changes to webservices.xml located in /WebServicesRouter/WebContent/WEB-INF/webservices.xml

Screen show below shows the changes in “Web Services” tab of webservices.xml file



Screen show below shows the changes in “Port Components” tab of webservices.xml file


Screen shown below shows the changes in “Handlers” tab of webservices.xml file



Step 5

Validate that following files have been updated with the binding entries for the new HelloWorld service.

/WebServicesRouter/WebContent/WEB-INF/ibm-webservices-bnd.xmi
/WebServicesRouter/WebContent/WEB-INF/ibm-webservices-ext.xmi

You may have to do a manually edit following files to remove “scope” entry in case you get following exception while starting the server

E WSWS1013E: Error: Found illegal scope: binding file=, portComponentName=HelloWorld, scope=.

The updated file appears as follows on my toolkit setup

/WebServicesRouter/WebContent/WEB-INF/ibm-webservices-bnd.xmi

  <wsdescBindings xmi:id="WSDescBinding_1292347236703" wsDescNameLink="PingService">
    <pcBindings xmi:id="PCBinding_1292347236703" pcNameLink="PingServicePort"/>
  </wsdescBindings>



/WebServicesRouter/WebContent/WEB-INF/ibm-webservices-ext.xmi

  <wsDescExt xmi:id="WsDescExt_1292347236828" wsDescNameLink="PingService">
    <pcBinding xmi:id="PcBinding_1292347236828" pcNameLink="PingServicePort"/>
  </wsDescExt>


Step 6

In the previous step we have mapped the WSDL document to the WebSphere commerce webservice framework, next we need to configure the message mapping file to handle the response.


/WC/xml/messaging/webservice_SOABOD_template.extension.xml needs to be updated to include the View name for response XML, you can either use the XML editor of make changes manually.

Following are the changes I made to the mapping file.

<ECTemplate>
      <TemplateDocument>
            <DocumentType>EchoMessage</DocumentType>
            <StartElement>EchoMessage</StartElement>
            <TemplateTagName>EchoMessageMap</TemplateTagName>
            <CommandMapping>
                  <Command CommandName="EchoMessageView">
                        <Constant Field="ibm.wc.responseOnly">true</Constant>
                  </Command>
            </CommandMapping>
      </TemplateDocument>
      <TemplateTag name="EchoMessageMap">
            <Tag XPath="Name" Field="Name" />
      </TemplateTag>
</ECTemplate>

Step 7

/Stores/WebContent/WEB-INF/struts-config-ext.xml

<forward name="EchoMessageView/0/-10" path="/webservices/custom/HelloWorld.jsp" className="com.ibm.commerce.struts.ECActionForward">
<set-property property="properties" value="storeDir=no"/>
<set-property property="interfaceName" value="com.ibm.commerce.messaging.viewcommands.MessagingViewCommand"/>
<set-property property="implClassName" value="com.ibm.commerce.messaging.viewcommands.MessagingViewCommandImpl"/>
<set-property property="direct" value="true"/>
</forward>


Right click on the test server and select “Publish”, this is a very important step, restarting the server alone will not enable the new service, since we have modified quite a few deployment descriptor files we will have to re-publish the WC EAR file.

During server publish process you should be able to see following logs which indicates that the web service has been deployed successfully.

[2/13/11 20:36:10:671 CST] 00000012 SystemOut     O WSWS3185I: Info: Parsing XML file:  C:\IBM\WCDE_ENT70\workspace\WebServicesRouter\WebContent\WEB-INF\wsdl\HelloWorld.wsdl
[2/13/11 20:36:10:671 CST] 00000012 SystemOut     O Retrieving document at 'file:/C:/IBM/WCDE_ENT70/workspace/WebServicesRouter/WebContent/WEB-INF/wsdl/HelloWorld.wsdl'.
[2/13/11 20:36:10:687 CST] 00000012 SystemOut     O WSWS3576I: Info: Changed java name pingOperation to executeService for xml construct pingOperation due to mapping file reference.
[2/13/11 20:36:10:687 CST] 00000012 SystemOut     O WSWS3576I: Info: Changed java name PingServicePort to com.ibm.commerce.webservices.OpenWebServicePortType for xml construct {http://commands.sample.commerce.ibm.com}PingServicePort due to mapping file reference.
[2/13/11 20:36:10:703 CST] 00000012 webapp        I com.ibm.ws.webcontainer.webapp.WebGroupImpl WebGroup SRVE0169I: Loading Web Module: WebServicesRouter.







Step 8

Create a sample response JSP and place it in Stores folder at following location
/Stores/WebContent/webservices/custom/HelloWorld.jsp

You should be able to access the response JSP directly by using following URL
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://commerce.ibm.com/base" prefix="wcbase" %>
<% response.setContentType("text/xml"); %>
<% response.setCharacterEncoding("UTF-8"); %>
<pingStringOutput>
    <pingOutput><c:out value="Hello ${name}"/></pingOutput>
</pingStringOutput>



 Step 9

Test the Webservice from SOAP UI or with RAD webservices explorer as follows.



Additional Reference Links
----------------------------

Pituluik Media Blogger | Freelancer |Operations Manager | Marketing and Sales Manager | Lancer Evo 4 Community. Indonesian Bloggers Who Become Bloggers Because of Hobby. Feel free to connect with me on Social Media Instagram @alberandesko

0 Response to "Custom Inbound Webservices using WebServices Router"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel