Mule 3.3 RC3 – Building and Consuming Web Services

So, this is my first blog and I hope you can like it.

Let’s start to talk about how build and consume Web Services in Mule enviroment.

More references are available from official Mule web site here

Building Web Services

<mule xmlns="http://www.mulesoft.org/schema/mule/core"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:spring="http://www.springframework.org/schema/beans"
  xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
  xmlns:http="http://www.mulesoft.org/schema/mule/http"
  xsi:schemaLocation="
               http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
               http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.1/mule.xsd
               http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/3.1/mule-cxf.xsd
               http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/3.1/mule-http.xsd">

  <flow name="helloService">
    <http:inbound-endpoint address="http://localhost:63081/hello" exchange-pattern="request-response">
        <cxf:jaxws-service serviceClass="org.example.HelloWorld">
        	<cxf:inInterceptors>
        		<spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
        </cxf:inInterceptors>
       	<cxf:outInterceptors>
	    	<spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
	    </cxf:outInterceptors>
        </cxf:jaxws-service>
    </http:inbound-endpoint>
    <component class="org.example.HelloWorldImpl" />
  </flow>
</mule>

Take a look from the above code .

At line 13 it’s defined a service interface (you can see it later) with its implementation at line 23. Also, on line 15 and 18 there are the definitions to logging the Soap Message incoming and outcoming (I think it’s very usefull).

HelloWorld.class

 
package org.example;
import javax.jws.WebService;
import org.example.client.Order;
@WebService
public interface HelloWorld {
       Order sayHi(Order order);
}

HelloWorldImpl.class

 
package org.example;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.ws.WebServiceContext;
import org.example.client.Order;
@WebService(endpointInterface = "org.example.HelloWorld",serviceName = "HelloWorld")
public class HelloWorldImpl implements HelloWorld {
@Resource
private WebServiceContext context;
public Order sayHi(Order order) { 
try {
return order.getReceipt();
}
catch (DatatypeConfigurationException e) {
e.printStackTrace();
return null;
}
}
}

And now the Order class used for the body of the message.

package org.example.client;
import java.util.GregorianCalendar;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
/**
 * <p>Java class for order complex type.
 *
 * <p>The following schema fragment specifies the expected content contained within this class.
 *
 * <pre>
 * &lt;complexType name="order">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="itemNumber" type="{http://www.w3.org/2001/XMLSchema}int"/>
 *         &lt;element name="orderId" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         &lt;element name="shippingDate" type="{http://www.w3.org/2001/XMLSchema}dateTime" minOccurs="0"/>
 *         &lt;element name="sum" type="{http://www.w3.org/2001/XMLSchema}double"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 *
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "order", propOrder = {
    "itemNumber",
    "orderId",
    "shippingDate",
    "sum"
})
public class Order {
    protected int itemNumber;
    protected String orderId;
    @XmlSchemaType(name = "dateTime")
    protected XMLGregorianCalendar shippingDate;
    protected double sum;
    /**
     * Gets the value of the itemNumber property.
     *
     */
    public int getItemNumber() {
        return itemNumber;
    }
    /**
     * Sets the value of the itemNumber property.
     *
     */
    public void setItemNumber(int value) {
        this.itemNumber = value;
    }
    /**
     * Gets the value of the orderId property.
     *
     * @return
     *     possible object is
     *     <a href="mailto:%7B@link">{@link</a> String }
     *    
     */
    public String getOrderId() {
        return orderId;
    }
    /**
     * Sets the value of the orderId property.
     *
     * @param value
     *     allowed object is
     *     <a href="mailto:%7B@link">{@link</a> String }
     *    
     */
    public void setOrderId(String value) {
        this.orderId = value;
    }
    /**
     * Gets the value of the shippingDate property.
     *
     * @return
     *     possible object is
     *     <a href="mailto:%7B@link">{@link</a> XMLGregorianCalendar }
     *    
     */
    public XMLGregorianCalendar getShippingDate() {
        return shippingDate;
    }
    /**
     * Sets the value of the shippingDate property.
     *
     * @param value
     *     allowed object is
     *     <a href="mailto:%7B@link">{@link</a> XMLGregorianCalendar }
     *    
     */
    public void setShippingDate(XMLGregorianCalendar value) {
        this.shippingDate = value;
    }
    /**
     * Gets the value of the sum property.
     *
     */
    public double getSum() {
        return sum;
    }
    /**
     * Sets the value of the sum property.
     *
     */
    public void setSum(double value) {
        this.sum = value;
    }
    public Order getReceipt() throws DatatypeConfigurationException
 {
     GregorianCalendar c = new GregorianCalendar(); 
     XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);      
  setShippingDate(date2);
  return this;
 }
    @Override
   public String toString()
   {
    return "orderId:" + orderId + " - " +
      "itemNumber:" + itemNumber + " - " +
      "sum:" + sum + " - " +
      "shippingDate:" + shippingDate;
   }

This class has been generated using a wsimport tool from Jdk. The same class will be used for consume web service process later.

It’s time to run the mule engine and browse to http://localhost:63081/hello?wsdl and watch the auto-generated Wsdl definition.

Consume Web Services

First we need to generate class from wsdl definition. We use a wsimport tool to execute this task.

wsimport.exe -p org.example.client -s C:\src http://localhost:63081/hello?wsdl

This tool generated the follow classes.

HelloWorld
HelloWorldService
ObjectFactory
Order
package-info
SayHi
SayHiResponse

Now, we defined the client mule config file.

<mule xmlns="http://www.mulesoft.org/schema/mule/core"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:spring="http://www.springframework.org/schema/beans"
  xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
  xmlns:stdio="http://www.mulesoft.org/schema/mule/stdio"
  xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.1/mule.xsd
  http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/3.1/mule-cxf.xsd
  http://www.mulesoft.org/schema/mule/stdio http://www.mulesoft.org/schema/mule/stdio/3.2/mule-stdio.xsd">

  <custom-transformer class="org.example.transformer.OrderWsClient" name="OrderWs" />

  <flow name="csvPublisher">
    <stdio:inbound-endpoint system="IN" />
    <transformer ref="OrderWs" />

    <outbound-endpoint address="http://localhost:63081/hello" exchange-pattern="request-response">

      <cxf:jaxws-client clientClass="org.example.client.HelloWorldService" port="HelloWorldPort" wsdlLocation="http://localhost:63081/hello?wsdl" operation="sayHi">
          <cxf:inInterceptors>
        <spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
        </cxf:inInterceptors>
        <cxf:outInterceptors>
          <spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
        </cxf:outInterceptors>
      </cxf:jaxws-client>

    </outbound-endpoint>

    <stdio:outbound-endpoint system="OUT" />

  </flow>
</mule>

It’s used a readline for start the process.  Next it’s called a custom transformer “OrderWs” to generate a sample Order to send to Web service (line 18).  The “sayHi” operation add the process’s time to order and return the String rappresentation of that Order.

We can see a Soap request:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
  <ns2:sayHi xmlns:ns2="http://example.org/">
  <arg0>
    <itemNumber>2</itemNumber>
    <orderId>1234</orderId>
    <sum>12.0</sum>
  </arg0>
  </ns2:sayHi>
</soap:Body>
</soap:Envelope>

And this is the Soap response:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
  <ns2:sayHiResponse xmlns:ns2="http://example.org/">
  <return>
    <itemNumber>2</itemNumber>
    <orderId>1234</orderId>
    <shippingDate>2012-05-18T12:23:14.249+02:00</shippingDate>
    <sum>12.0</sum>
  </return>
  </ns2:sayHiResponse>
</soap:Body>
</soap:Envelope>

That’s all. I must apologize for the classes name of above example because that are not very corrects (what means “sayHi” method with order process??) and also for my poor english.

I’m working at both sides…

UPDATE

I forgot the OrderWsClient class. Here the code

package org.example.transformer;

import org.example.client.Order;
import org.mule.api.MuleMessage;
import org.mule.api.transformer.TransformerException;
import org.mule.transformer.AbstractMessageAwareTransformer;
import org.mule.transformer.AbstractTransformer;

public class OrderWsClient extends AbstractTransformer{

 @Override
 protected Object doTransform(Object src, String enc)
   throws TransformerException {
  Order order = new Order();
  order.setOrderId("1234");
  order.setItemNumber(2);
  order.setSum(12.00);
  
  return order;
 }

}
Advertisements

14 thoughts on “Mule 3.3 RC3 – Building and Consuming Web Services

    • Hi,
      I’m not sure to have understood your question.
      In your client application you need a wsdl definition and then you can invoke a method by using “operation” property of jaxws-client node.

      So, the payload becomes the web service invocation parameter and it returns the web services response.

      Give me an example so I can give you a better answer.

    • You have two options: the first is through implementing the next session of the article named “Consume Web Service”, the second is through implementing only the server part and using tools like SoapUI for calling that.

  1. In the previous comment, i forget for notifying on reply, and i am unable to delete previous comment, so i comment again, so if some answer my comment, i will notifying.
    I am trying to access SOAP external service using mule. Following is my mule code :

    <!– –>

    When i run my example as a mule application, it will generate an exception :

    ERROR 2014-05-20 13:04:21,988 [main] org.mule.module.launcher.application.DefaultMuleApplication: null
    org.apache.cxf.service.factory.ServiceConstructionException: Could not find definition for service {http://soapclient.insonix.com/}UserLoginImplServiceService.
    at org.apache.cxf.wsdl11.WSDLServiceFactory.create(WSDLServiceFactory.java:168)

    How i resolve this Issue ?

    • Hi Jai,
      In order to elaborate the response from the WS, you should put a object after the and keep in mind that the message payload of your object is already a POJO object.

      It works even putting a custom transformer.
      The Soap Response is already an Order object.

      • Hi Jai,
        It’s easier than it seems.
        Put the transformer node before the last stdio node.

        </outbound-endpoint>

        <transformer ref=”OrderWs” />

        <stdio:outbound-endpoint system=”OUT” />

        Now, in the class OrderWsClient at the method doTransform(Object src, String enc) you can see that the src is of type Order (I used the debug to watch it).

        It’s enough for you to create a new class like the OrderWsClient, defines it as global endopoint
        <custom-transformer class=”org.example.transformer.MyClass” name=”OrderWsMyClass” />

        I hope this solve your problem.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s