Calling Web Services with Apache Camel

Web Services are very important components of most (if not all) of the integration projects these days. The Web Services architecture make them extremely useful for distributed applications and they are often associated with Service-Oriented Architecture (SOA).

Calling Web Services from Apache Camel is pretty simple yet powerful and Camel uses Apache CXF (http://cxf.apache.org).

Apache CXF provides you many options to build Web Services (JAX-WS Annotated Services from Java, JAX-WS Annotated Services from WSDL, JAX-WS Providers, Simple Frontend and JavaScript).
Additionally, there are three major types of services (SOAP, REST and CORBA). For more information, check this web page http://cxf.apache.org/docs/how-do-i-develop-a-service.html.

JAX-WS (Java API for XML Web Services) specification defines annotations that allow you to tell CXF how your POJOs should be represented on the web.

Basically, there two types of web services development with Apache CXF:

Contract-first development - Recall that WSDLs define what operation and types a web service provides. This is often referred to as web services contract, and in order to communicate with a web service, you must satisfy the contract. Contract-first development means that you develop a WSDL file and then generate stub Java class implementations using a tool like Apache CXF.

Code-first development - The other way to develop web services is by starting out with a Java class and then letting the web service framework handle the job of generating a WSDL contract for you. In this case, Apache CXF will be in control of what the contract will be.

To configure the CXF component URI in Camel there are two main ways that you can do that:

Configuring Using the URI Options - The most simple way (and the one will be using for demo purposes) where you pass inline parameters to the component. Here is the format you have to specify:

cxf://<service_address>[?options]

The options available for the CXF component are available here: http://camel.apache.org/cxf.html

Referencing a Bean - Using this approach, you have to specify a bean containing the configuration. You have much more power and flexibility than configuring CXF via URI options but it also requires more work on your side. You can configure things like CXF interceptors, JAX-WS handlers and the CXF bus but we're going to cover that on a different blog post. To configure the CXF component referencing a bean the URI is something like this:

cxf:bean:beanName where the beanName specifies the ID of the CXF endpoint bean defined in your Spring XML file.

So, to give you a taste of what's going to be a simple project calling Web Services with Apache Camel here is the step-by-step procedure:

I'll be using the FuseIDE for that but the artifacts generated are pretty much the same if you choose the Maven approach.

Here is what you need:

- Eclipse IDE (Eclipse Helios 3.6.2)
- Apache Maven (3.0.3)
- FuseSource Camel IDE (http://fusesource.com/products/fuse-ide-camel/)


Then, create a new Fuse IDE project and select the Camel Archetype and type the Group Id, Artifact Id and Package name for your project then click Finish.


As I've explained before on my previous post (http://marcelojabali.blogspot.com/2011/06/file-batch-splitter-with-apache-camel.html) the default Fuse IDE project comes with a sample configuration that you can remove for the purpose of this demonstration.


Create a new Camel XML File (camelContext.xml) and then create a new route. 


Drag and drop an endpoint from the palette and also a log component. Connect them and make sure you save your project. You should see something like the picture below:




Edit the URI property of the Endpoint to be: file:src/data?noop=true


Edit the Message property of the Log component to be: ${body} and the Logging Level to INFO


You should be able to run this route now which is going to display the content of files under the src/data directory in your project in the Camel log. It's always a good practice to make sure every step in your route runs consistently and without any problems.


To run the Camel route (if you're using the FuseIDE) just right click int the Camel XML file and then select Run As... Local Camel Context.


If everything executed correctly you should see the content of the files in the Eclipse console and you're ready for the next step.


Add another Endpoint to your route. Connect the Log component to the new created Endpoint.

The recently added Endpoint is going to be our CXF component. We're going to use a sample Stock Quote Web Service available at http://www.webservicex.net/WS/WSDetails.aspx?CATID=2&WSID=9

Click on the Endpoint and then add the following to the URI:

cxf://http://www.webservicex.net/stockquote.asmx?wsdlURL=src/main/resources/META-INF/stockquote.wsdl&serviceName={http://www.webserviceX.NET/}StockQuote&portName={http://www.webserviceX.NET/}StockQuoteSoap&dataFormat=MESSAGE

Here are the options being used on this simple call:

cxf://http://www.webservicex.net/stockquote.asmx - Endpoint definition (cxf) and then the required service address

wsdlURL=src/main/resources/META-INF/stockquote.wsdl - The location of the WSDL file

serviceName={http://www.webserviceX.NET/}StockQuote - The service name this service is implementing, it maps to wsdl:service@name

portName={http://www.webserviceX.NET/}StockQuoteSoap - The port name this service is implementing, it maps to wsdl:port@name

dataFormat=MESSAGE - The data type messages supported by the CXF endpoint (default is POJO)


The last step in the route to be implemented is a Log component to display the Web Service response. To do that, just add another Log and connect the CXF component to it.


Edit the Message property of the Log component to be: ${body} and the Logging Level to INFO


Your route should be similar to the following:




Save the project.


For reference, here is the whole route:




<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:cxf="http://camel.apache.org/schema/cxf" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://camel.apache.org/schema/spring
    http://camel.apache.org/schema/spring/camel-spring.xsd">

  <camelContext xmlns="http://camel.apache.org/schema/spring" trace="false">
    <route id="my_Sample_Camel_Route_with_CXF">
        <from uri="file:src/data?noop=true"/>
        <log loggingLevel="INFO" message="&gt;&gt;&gt; ${body}"/>
        <to uri="cxf://http://www.webservicex.net/stockquote.asmx?
        wsdlURL=src/main/resources/META-INF/stockquote.wsdl&amp;
        serviceName={http://www.webserviceX.NET/}StockQuote&amp;
        portName={http://www.webserviceX.NET/}StockQuoteSoap&amp;
        dataFormat=MESSAGE"/>
        <log loggingLevel="INFO" message="&gt;&gt;&gt; ${body}"/>
    </route>
</camelContext>

</beans>




Before you test it make sure you change the values of the sample messages (under src/data) to the following:


message1.xml:


<?xml version="1.0" encoding="utf-8"?>


<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <GetQuote xmlns="http://www.webserviceX.NET/">
      <symbol>AAPL</symbol>
    </GetQuote>
  </soap12:Body>
</soap12:Envelope>

message2.xml:

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <GetQuote xmlns="http://www.webserviceX.NET/">
      <symbol>GOOG</symbol>
    </GetQuote>
  </soap12:Body>
</soap12:Envelope>

This is the SOAP format that the web service is expecting and we're not doing any message transformation here so far.
At this point, you're ready to go and you just need to run the Camel route as explained before.
After you run the route, you should see two messages being displayed in the Eclipse console with the content of the files you just edited and then two responses from the Web Service showing the stock value of AAPL and GOOG.

The sample code is available at https://github.com/mjabali/CXF-Sample

Enjoy the ride!






Comments

  1. This is a very nice article. I have added a link to it from the Apache Camel articles link collection.

    ReplyDelete
  2. Hi,
    why does it throw an exception when I set dataFormat=PAYLOAD?
    Also can you please give en example on how to access the soap elements in a camel processor? I have been trying to do this but exchange.getIn().getBody always returns null.

    ReplyDelete
    Replies
    1. Su, have a look at the following page to understand the dataFormat options (http://camel.apache.org/cxf.html). I think that on the same page there is an example about how to handle messages with the CXF component. Look for "How to deal with the message for a camel-cxf endpoint in PAYLOAD data format". As far as I know SOAP message headers are not available in the MESSAGE mode. Good luck!

      Delete
  3. If the dataFormat=PAYLOAD, I can use the CxfPayload class to access the internals of the soap message. However, the problem is i cannot set dataFormat to PAYLOAD in the endpoint you have defined above. It runs to an exception. Is this a problem in the way you have defined the endpoint?

    In the MESSAGE mode, there is no way to access the individual elements of the soap message using xpath or xquery and get the element values into variables. xpath and xquery work ONLY if you want to set a header, or in a filter condition. A feature request is now filed in camel now to get this missing functionality. At the meantime, I convert this raw soap message into an xml document explicitly and access the soap message. The other option is to create a temporary header to extract the soap elements using xpath or xquery, and later copy it to a variable as needed.

    ReplyDelete
    Replies
    1. It's hard to tell you without seeing the exception. The tutorial was created to educate and help developers to get started with Apache Camel and the CXF component. It works as described in the tutorial. For any further questions, please continue to use the Apache Camel forum and we'll help you there.

      Delete
  4. In Web Development Services there are multiple ways you can deal with the Web services Apache camels. Either use Spring Web services or the use of Apache CXF. Spring Web Services is really easy to start with, compared CXF. Although CXF web service more complete stack.

    ReplyDelete
  5. Hello,
    I am facing the below issue while executing this sample. Could you please help

    Caused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: cxf://http://www.webservicex.n
    et/stockquote.asmx?++++dataFormat=MESSAGE&++++portName=%7Bhttp%3A%2F%2Fwww.webserviceX.NET%2F%7DStockQuoteSoap&++++ser
    I am facing the following error when trying to execute this sampleCaused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: cxf://http://www.webservicex.n
    et/stockquote.asmx?++++dataFormat=MESSAGE&++++portName=%7Bhttp%3A%2F%2Fwww.webserviceX.NET%2F%7DStockQuoteSoap&++++ser
    viceName=%7Bhttp%3A%2F%2Fwww.webserviceX.NET%2F%7DStockQuote&++++wsdlURL=src%2Fmain%2Fresources%2FMETA-INF%2Fstockquot
    e.wsdl due to: There are 4 parameters that couldn't be set on the endpoint. Check the uri if the parameters are spelt
    correctly and that they are properties of the endpoint. Unknown parameters=[{ dataFormat=MESSAGE, portName={htt
    p://www.webserviceX.NET/}StockQuoteSoap, serviceName={http://www.webserviceX.NET/}StockQuote, wsdlURL=src/main
    /resources/META-INF/stockquote.wsdl}]

    ReplyDelete
  6. There are 4 parameters that couldn't be set on the endpoint. Check the uri if the parameters are spelt correctly and that they are properties of the
    endpoint. Unknown parameters=[{ dataFormat=MESSAGE, portName={http://www.webserviceX.NET/}StockQuoteSoap}.

    This is the exact exception.

    ReplyDelete
    Replies
    1. Just out of curiosity, did you clone the project from the github repo, build it and then ran mvn camel:run ? I'm able to run it without any problems by doing that and I'm wondering if you can do that too.

      Delete
  7. This comment has been removed by the author.

    ReplyDelete
  8. Hi,

    great article. Thanks for the work you have put into it!

    Do I understand your sample correct, that if I want to pass on the message to the webservice, that it is up to me to put it into a soap structure?

    If so, is there a recommended way to do so?

    Thanks

    Patrick

    ReplyDelete
    Replies
    1. Hi Patrick,
      In the context of this sample, the SOAP is coming from the XML files under CXF-Sample/src/data. You're also correct that if you want to pass on the message then you'll have to put the SOAP structure together. However, there are other approaches (better than what I've used on this sample here) available at http://camel.apache.org/cxf.html

      Delete
  9. Hi,
    great article. Thanks for the work you have put into it!

    I need small help on this. I have configured same configuration in my camel-config.xml.

    I am facing below exception while accessing the route.

    Exchange
    ---------------------------------------------------------------------------------------------------------------------------------------
    Exchange[
    Id ID-CSCINDAE748383-61559-1395308823045-0-12580
    ExchangePattern InOnly
    Headers {breadcrumbId=ID-CSCINDAE748383-61559-1395308823045-0-12579, CamelHttpMethod=POST, CamelRedelivered=false, CamelRedeliveryCounter=0, Content-Type=text/xml, User-Agent=Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)}
    BodyType null
    Body [Body is null]
    ]

    Stacktrace
    ---------------------------------------------------------------------------------------------------------------------------------------
    org.apache.camel.component.http.HttpOperationFailedException: HTTP operation failed invoking http://www.webservicex.net/stockquote.asmx?wsdlURL= with statusCode: 403
    at org.apache.camel.component.http.HttpProducer.populateHttpOperationFailedException(HttpProducer.java:228)[camel-http-2.12.2.jar:2.12.2]
    at org.apache.camel.component.http.HttpProducer.process(HttpProducer.java:156)[camel-http-2.12.2.jar:2.12.2]


    Below is the camel configuration





    text/xml


    POST







    Java changes.

    I am calling my ProducerTemplate.send() method.

    integrationService.send("direct:soap/test", null, null, String.class);


    Please help me on this.

    ReplyDelete
  10. I have used same configuration which you have given in this example

    ReplyDelete
    Replies
    1. I just tested the Web Service implementation (http://www.webservicex.net/ws/WSDetails.aspx?CATID=2&WSID=9) outside of the Camel route and it fails for no apparent reason (just returning "exception" as the result). I'm sorry there is not much I can help with if the service is not working. My suggestion is to try a different web service (your own or another one on available on the web).

      Delete
  11. Hi Team,

    In our project we are using camel file component to read the files.

    We have created spring mvc project. Under resource folder, i have created metamodel/grids folder.
    In this folder i have pasted all my files.

    below is the camel endpoint configuration.

    <camel:endpoint id="homeMetaModel"
    uri="file:${MetaModelScreenEndPointURI}&fileName=home.json" />

    Here MetaModelScreenEndPointURI=medamodel/grids/?noop=true&idempotent=false

    When i am trying to access this endpoint using cosumber, i am getting file not found error message.

    Could you please help me on this?

    Thanks,
    Sada.B

    ReplyDelete
  12. Well, this made my day. Very comprehensive tutorial indeed. Thanks for sharing!
    Web Development Islamabad

    ReplyDelete
  13. web development services
    : Muxions Technologies is about simple but yet elegant and effective web, mobile and data solutions. Our areas of expertise includes Mobile Application Development (Android, iOS and Blackberry), Web Design and Development, Content Management Systems, eCommerce Solutions, Data Modeling and Analysis, and Bioinformatics. Our mission is to transform our skill and knowledge into competitive capabilities of our clients. We carefully analyze our clients' requirements, and design and develop solutions that fill their technological gaps with respect to emerging trends web, mobile and data industry.

    ReplyDelete
  14. Hi When I run the application it hangs after creating the service. This is the last message I get in the eclipse console.

    INFO: Creating Service {http://www.webserviceX.NET/}StockQuote from WSDL: src/main/resources/META-INF/stockquote.wsdl

    The code hangs and I don't see anything happening in console as well.
    Kindly help... Thanks in advance

    ReplyDelete
    Replies
    1. I just executed the project without any problems. This is really old stuff and might need an update. You can send me a pull request on GitHub with the fixes and I will incorporate them into the branch.

      Delete
    2. Hi now I am able to run the code successfully. Previously I cloned the code and ran mvn clean:install, which gave me a maven plugin exception(could not find goal 'install' in plugin org.apache.maven.plugins:maven-clean-plugin:2.5) so I googled and changed contents of pom. I think this might have made the application to hang. Now I did a new clone of the project and ran the mvn install command which made it work. Thanks :)

      Delete
    3. Awesome! Thanks for the feedback.

      Delete
  15. Hello Sir, I was able to run your tutorial and code successfully with my setup. Great tutorial, thank you for that. But whn i am trying to integrate the same with the webservice that i have deployed i get message Exchange Exception.
    I have deployed my Webservice at http://localhost:8080/OrderManagementFuseWebService/OrderImpl?Wsdl
    and I am able to access the wsdl as well..

    Here's the error log..

    1) thread #0 - file://src/data] DefaultErrorHandler ERROR Failed delivery for (MessageId: ID-Aman-36020-1428526617355-0-1 on ExchangeId: ID-Aman-36020-1428526617355-0-2). Exhausted after delivery attempt: 1 caught: org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[message3.xml]

    Message History
    ---------------------------------------------------------------------------------------------------------------------------------------
    RouteId ProcessorId Processor Elapsed (ms)
    [route1 ] [route1 ] [file://src/data?noop=true ] [ 20]
    [route1 ] [log1 ] [log ] [ 12]
    [route1 ] [to1 ] [cxf://http://localhost:8080/OrderManagementFuseWebService/OrderImpl?serviceNam] [ 4]

    Exchange
    ---------------------------------------------------------------------------------------------------------------------------------------
    Exchange[
    Id ID-Aman-36020-1428526617355-0-2
    ExchangePattern InOnly
    Headers {breadcrumbId=ID-Aman-36020-1428526617355-0-1, CamelFileAbsolute=false, CamelFileAbsolutePath=C:\Users\Aman Verma\JBossworkspace\orderManagement\src\data\message3.xml, CamelFileLastModified=1428526603589, CamelFileLength=395, CamelFileName=message3.xml, CamelFileNameConsumed=message3.xml, CamelFileNameOnly=message3.xml, CamelFileParent=src\data, CamelFilePath=src\data\message3.xml, CamelFileRelativePath=message3.xml, CamelRedelivered=false, CamelRedeliveryCounter=0}
    BodyType org.apache.camel.component.file.GenericFile
    Body [Body is file based: GenericFile[message3.xml]]
    ]

    Stacktrace
    ---------------------------------------------------------------------------------------------------------------------------------------
    org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[message3.xml]
    at org.apache.camel.util.ObjectHelper.wrapCamelExecutionException(ObjectHelper.java:1379)
    at org.apache.camel.impl.DefaultExchange.setException(DefaultExchange.java:283)


    I had no problems executing your code, but i get similar error when i try following another similar tutorial from http://javahabit.com/2013/12/16/apache-camel-how-to-call-an-external-webservice/

    here's my route..















    what's wrong I am doing..??any direction you can tell me to process..?

    ReplyDelete
    Replies
    1. Not able to comment my route...
      route>
      from uri="file:src/data?noop=true"/>
      log message="${body}" loggingLevel="INFO"/>
      to uri="cxf://http://localhost:8080/OrderManagementFuseWebService/OrderImpl?serviceName={http://orderFeatures/}OrderImplService&portName={http://orderFeatures/}OrderImplPort&DataFormat=MESSAGE"/>
      log message="${body}" loggingLevel="INFO"/>
      </route

      Delete
    2. Not really sure what kind of issue you're hitting there since you're combining two tutorials together but have a look at the full exception and you might be able to figure that out.

      Delete
    3. According to what you've shown it looks like there is a problem when you process message3.xml. Make sure the payload is the one expected by the service you're invoking.

      Delete
  16. Yes, i actually copied it directly while testing it from SOAPUI.. So, atleast i am sure, that there is no issue with the payload file.. its 3:38AM in the clock and still no on Bed....:(






    34

    23


    ReplyDelete
  17. Best SEO Services Affordable Packages and Prices - SEO Experts in coimbatore, chennai Tamil Nadu, India Search engine Optimization Company in india

    ReplyDelete
  18. Many more designing process available for website creation such as graphic design,flash design,UX and UI design.Website Designing Company Bangalore | Web Designing Company Bangalore

    ReplyDelete
  19. Bangalore Web Design Company, a complete web solutions company in Bangalore brings you the most innovative, economical and search engine friendly website design and development services.
    Website Development Company Bangalore|SEO Services in Bangalore

    ReplyDelete
  20. Website is an interactive marketing tool,as all the products will be displayed and advertised on all over the world and possible to communicate with customers.
    Web Design Company India|SEO Company India

    ReplyDelete
  21. Web design and development always keep a personal recommendation to clients and increase the popularity of a company.
    Web Development Company Bangalore|SEO Experts Bangalore

    ReplyDelete
  22. very good article ... and if I need to pass through a proxy server, do you have some hints ?

    ReplyDelete
  23. good one. Thank you
    https://ultimez.com/web-designer-accepts-bitcoin.html

    ReplyDelete

  24. "best data collection and responsive blogs. Like it, thanks for sharing."!!

    Dubai Social Media Agency

    ReplyDelete
  25. Informative article, thanks for sharing with us
    https://ultimez.com

    ReplyDelete
  26. Very informative ..i suggest this blog to my friends..Thank you for sharing
    http://www.bestandroidtrainingchennai.in

    ReplyDelete
  27. This information is impressive; I am inspired with your post writing style & how continuously you describe this topic. After reading your post, thanks for taking the time to discuss this, I feel happy about it and I love learning more about this topic.
    http://www.credosystemz.com/training-in-chennai/best-android-training-in-chennai

    ReplyDelete
  28. Apache is actually the most commonly used Web servers currently. This is because it provides a very good support for the web services and also has simplified functionality. In addition to that, it is also inbuilt in a number of database software and that makes it easily accessible. I know that the Apache camel will be useful to the web developers.
    Edit my business school admission essay

    ReplyDelete
  29. Thanks for the very informative blog, extremely grateful that you perform this piece of writing very simply, I mean to say that it's quite simple to read and understand.
    Branding Dubai

    ReplyDelete
  30. These ways are very simple and very much useful, as a beginner level these helped me a lot thanks fore sharing these kinds of useful and knowledgeable information.
    Digital Marketing SMS
    Digital Marketing Text
    Digital Mobile Marketing
    Text Whitelabel Solutions
    sms Whitelabel Solutions

    ReplyDelete

Post a Comment

Popular posts from this blog

How to Declare Variables in MS-SQL Server Management Studio

Using HTTP-based endpoints with Apache Camel