Implementation of CXF Dynamic Webservices

Introduction

This documentation explains how to embed WebServices into the B2B.

This documentation assumes there is a WSDL file for the WebService. From this WSDL java classes are generated using the Apache CXF framework. In this documentation the installation of sending and receiving webservices are described.

WSDL Transformation To B2B Content

The classes needed for the webservice are deployed as B2B content.

To use the webservice, annotated service classes are needed. These can be generated from the wsdl or written by hand.

The first step is to transform the wsdl into the corresponding Java class. This class has the needed annotations for publishing the webservice.

The alternative is to create directly the classes which implement the necessary interfaces. But this is not described in this documentation.

Create WSDL, if none exists

The first step is to create a wsdl. We use in this documentation the following example.wsdl. The details of the wsdl are not important and it is only displayed for completion of the documentation. We assume the example.wsdl is in the directory C:\WSDL\

<?xml version="1.0"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://b2bbypractice.org/b2bbp-engine/exampleAdapter" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://b2bbypractice.org/b2bbp-engine/exampleAdapter" name="EdifactMessageService">
  <types>
    <xsd:schema xmlns:tns="http://b2bbypractice.org/b2bbp-engine/exampleAdapter" targetNamespace="http://b2bbypractice.org/b2bbp-engine/exampleAdapter" attributeFormDefault="unqualified" elementFormDefault="qualified" version="1.0">
      <xsd:element name="MessageList" type="tns:MessageListType"/>
      <xsd:element name="Message" type="tns:MessageType"/>
      <xsd:complexType name="MessageListType">
        <xsd:sequence maxOccurs="unbounded">
          <xsd:element name="edifactMessage" type="tns:MessageType"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="MessageType">
        <xsd:sequence>
          <xsd:element name="messageId" type="xsd:string"/>
          <xsd:element name="status" type="xsd:string"/>
          <xsd:element name="type" type="xsd:string"/>
          <xsd:element name="idocNumber" type="xsd:string"/>
          <xsd:element name="referenzUNB" type="xsd:string"/>
          <xsd:element name="referenzUNH" type="xsd:string"/>
          <xsd:element name="senderILN" type="xsd:string"/>
          <xsd:element name="receiverILN" type="xsd:string"/>
        </xsd:sequence>
      </xsd:complexType>
    </xsd:schema>
  </types>
  <message name="getInboundMessagesForTimeRangeRequest">
    <part name="startTime" type="xsd:dateTime"/>
    <part name="endTime" type="xsd:dateTime"/>
    <part name="destinationSystem" type="xsd:string"/>
  </message>
  <message name="getInboundMessagesForTimeRangeResponse">
    <part name="edifactMessageList" element="tns:MessageList"/>
  </message>
  <portType name="EdifactMessageService">
    <operation name="getInboundMessagesForTimeRange">
      <input message="tns:getInboundMessagesForTimeRangeRequest"/>
      <output message="tns:getInboundMessagesForTimeRangeResponse"/>
    </operation>
  </portType>
  <binding name="EdifactMessageServicePortBinding" type="tns:EdifactMessageService">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="getInboundMessagesForTimeRange">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>
  <service name="EdifactMessageService">
    <documentation>EdifactMessageService</documentation>
    <port name="EdifactMessageServicePort" binding="tns:EdifactMessageServicePortBinding">
      <soap:address location="http://localhost:80"/>
    </port>
  </service>
</definitions>

Generating the Source Code manually

Download wsdl2java from the apache.org. We use the wsdl2java of apache-cxf-2.6.2 in this documentation. Open the commandline and switch to the downloadlocation into the bin folder.

And enter the following command for creating the files:

wsdl2java -frontend jaxws21 -d C:\WSDL\ C:\WSDL\example.wsdl

In the WSDL folder should a new folder appear or some errors are displayed if the wsdl is not valid. At this point also soapUi is a good compiler for wrong wsdl files.

Source Code to Java Project

Now crate a new Project in Exclipse (or other Java IDE). Maven or not is not important for the result. Copy the generated source code into the project. If the File should be transformed into xml then the tag @XmlRootElement need to be added to the Request and response objects.

Implement Server Side

If the server side needs to be implemented need to create the concrete implementation and add it into the source code. To continue the above example the implementation could look like:

Very important is that the @WebService anotation with the service name and port name need to be added!

After this we can export the java projekt to a jar file.

Java Projekt to B2B Content

Before we can upload the java project we have to specify which classes are implementation, interface and service. Therefore we have to create a file with name “content.properties”. In our example the file has the following content:

ServiceClass=org.b2bbypractice.b2bbp_engine.exampleadapter.EdifactMessageService
ServiceServiceClass=org.b2bbypractice.b2bbp_engine.exampleadapter.EdifactMessageService_Service
ServiceImplClass=org.b2bbypractice.b2bbp_engine.exampleadapter.ServerSideImpl

WithServiceClass is set to the class path of the generated interface of the web service. ServiceServiceClass is set to the generated class which extends javax.xml.ws.Service. Last but not least ServiceImplClass is set to the client side implementation of the previous chapter.

This file needs to be copied into the jar file. For this rename the file from .jar to .zip and copy the content.properties into the META-INF folder.

Uploading the Jar File to the Content

The jar needs to be added into the content of the B2B.

The fields Type, Format and Zielformat has a special functionality:

  • Typ: Need to set to “CXF” such that the services will detect this content
  • Format: If this is set to “WebService” the receiving service will automaticall create this as endpoint and publish the service after start up. (only for receiving webservices)
  • Zielformat: This will be the last part of the address where the endpoint is published
    • http://localhost:8080/b2bbp-engine/cxf/example-service

Create Receiving Web Service

This step is only necessary if the server side part is needed. A B2B service needs to be created for publish the web services from the content. This service will publish all contents with Type CXF and Format WebService. The field Klasse needs to be set to org.b2bbp.webservices.CXFDynamicReceiverServlet.

For publishing the service a restart of the B2B is necessary. For testing the publishing was successful check the wsdl with http://localhost:8080/b2bbp-engine/cxf/example-service?wsdl (addapt ip and port).

Create Sending Web Service

This step is only necessary if the client side part is needed. Add the service org.b2bbp.webservices.CXFDynamicSenderServlet. This service can send messages to extern webservices.

In this example we will send a request to the web service we have published in the previous chapter. Create the extension B3P_CXF_SENDERS. This extension contains the information about the called web service. In our example:

ExampleService.SERVICE_NAME=http://exampleadpter.b2bbp_engine.b2bbypractice.org/,EdifactMessageService
ExampleService.PORT_NAME=http://exampleadapter.b2bbp_engine.b2bbypractice.org/,EdifactMessageServicePort
ExampleService.WSDL_LOCATION=http://localhost:8080/b2bbp-engine/cxf/example-service?wsdl
ExampleService.B3P_CONTENT_PROVIDER=NLI
ExampleService.B3P_CONTENT_VERSION=1.0
ExampleService.B3P_CONTENT_TYP=CXF
ExampleService.B3P_CONTENT_FORMAT=WebService
ExampleService.B3P_CONTENT_FORMAT_VERSION=Example
ExampleService.B3P_CONTENT_DEST=example-service

The key ExampleService is used to identify the used sender configuration and will be set in the next chapter. This is necessary, because more than one service could be defined.

Call the Sending Web Service

The request is controlled over the messagecontext. Means the following three entries need to be available in the messagecontext if the service is called.

  • Fill CURRENT_PAYLOAD_TYPE with name of the called function in the service (in our example “getInboundMessagesForTimeRange”
  • Fill CURRENT_PAYLOAD with an Object[] containing the parameters. (E.g in our example two times a date and on time a String. This can be omitted, if BASE_MESSAGE is an xml Message, which represents a request object for the given webservice, and the entry WEBSERVICE_FUNCTION_PARAMETER contains the class name of the RequestObject.
  • Fill B3P_TARGET_SERVICE with key in the extension (E.g. ExampleService)

The result is after the execution is written to CURRENT_PAYLOAD and overwrites the request parameter.

Example

A possible execution could be an action in the B2B which fills the CURRENT_PAYLOAD with the import parameter.

The other information for calling the web service can be set in the action properties.

The sent and received message is logged in MESSAGE_SEND and MESSAGE_RECEIVED attributes.

Bear in mind that to actually use the newly created Action, it must reside on the class path, i.e. it must be loaded in the wars classloader. (e.g WEB-INF/lib) - > this may create a specific distribution! Only if the Request Payload can be constructed from BASE_MESSAGE, the Service can be called without a specific Action (e.g via SetPropertyAction or NLCAction2)

Error Handling

If sending the message fails the error message is persisted in the attribute STACK_TRACE.

View Me   Edit Me