Photo by elleren - http://www.flickr.com/photos/80415664@N00/121150246/
del.icio.us Digg DZone Reddit StumbleUpon
1 | 2 | 3 | 4 | Next »
Software Development

Web Services with Spring 2.5 and Apache CXF 2.0

Quickly create web services in Spring 2.5 using Apache CXF 2.0, a.k.a. XFire 2.0.

In this tutorial I explain how to get a web service up and running using Spring 2.5 and Apache CXF 2.0, which is the combination of Celtix and XFire and is considered XFire 2.0. (I don't know what the Celtix team would say about that, but that's what the XFire site says.) Here I just treat the web service itself; to learn about consuming the web service using Spring and CXF, please see the article Make Web Services Transparent with Spring 2.5 and Apache CXF 2.0.

CXF supports both WSDL-first and Java-first web service development. This article takes the Java-first approach.

Project Setup

The first thing you'll need to do is download CXF from the Apache CXF site. At the time of this writing the project is in incubator status and the latest version is 2.0.4. That's the version I'm using.

You'll also find it useful to know about the section of the CXF user documentation that deals with writing a service with Spring, but currently the docs describe how to integrate with Spring 2.0, and since I want to integrate with Spring 2.5, there are some differences worth highlighting along the way.

Also, the docs describe a "Hello, World" web service that just returns a string, and in this tutorial we want to go a little further than that and actually do a class databinding.

Here are the service-side dependencies you'll need. Inside the distribution there is a file called WHICH_JARS that describes in a little more detail what the JARs are for and which ones you'll really need, if you're interested in that. But the following is essentially the list given in the user docs.

CXF itself

  • cxf-2.0.4-incubator.jar

CXF dependencies

Note that for CXF 2.0.4 the documented dependencies are almost but not quite the same as the JARs that are actually included in the distribution, once again, at the time of this writing (February 2008). Specifically the stax, neethi and XMLSchema JARs are not the ones listed. Here's the corrected list for CXF 2.0.4:

  • commons-logging-1.1.jar
  • geronimo-activation_1.1_spec-1.0-M1.jar (or Sun's Activation jar)
  • geronimo-annotation_1.0_spec-1.1.jar (JSR 250)
  • geronimo-javamail_1.4_spec-1.0-M1.jar (or Sun's JavaMail jar)
  • geronimo-servlet_2.5_spec-1.1-M1.jar (or Sun's Servlet jar)
  • geronimo-stax-api_1.0_spec-1.0.jar
  • geronimo-ws-metadata_2.0_spec-1.1.1.jar (JSR 181)
  • jaxb-api-2.0.jar
  • jaxb-impl-2.0.5.jar
  • jaxws-api-2.0.jar
  • neethi-2.0.2.jar
  • saaj-api-1.3.jar
  • saaj-impl-1.3.jar
  • wsdl4j-1.6.1.jar
  • wstx-asl-3.2.1.jar
  • XmlSchema-1.3.2.jar
  • xml-resolver-1.2.jar

Aegis dependencies

In addition to the above, you will need to add jdom-1.0.jar since Aegis databinding uses it.

Spring dependencies

In this case ignore what's in the CXF documentation, because we're integrating with Spring 2.5 instead of Spring 2.0. I'm going to assume that you have Spring 2.5 already set up on your web services project, including Hibernate or anything else that your web services will need on the implementation side.

Just in case you were wondering, you don't need the Spring MVC module's DispatcherServlet as CXF comes with its own servlet, org.apache.cxf.transport.servlet.CXFServlet.

OK, that should be good for basic project setup. Let's write a simple service.

Social bookmarks: del.icio.us Digg DZone Reddit StumbleUpon
1 | 2 | 3 | 4 | Next »

Comments (26)

Great tutorial -- Used NB 6.0.1 and deployed into Glassfish V2 aok

Thank you
By Roger on Mar 12, 2008 at 11:55 AM PDT
Tutorial is ok but quite shallow information. Besides, it does not run with cfx-2.0.4 and spring-2.5.2 (known issue in cxf, solved in 2.0.5 snapshots).

Thank you.
By Cristian Caprar on Mar 21, 2008 at 7:29 AM PDT
Thanks for the feedback guys, and @Cristian, thanks for the heads-up about Spring 2.5.2.
By Willie Wheeler on Mar 22, 2008 at 10:49 AM PDT
Awesome tutorial, had it working and debugging with Eclipse3.3, CXF2.0.5,Spring 2.5.2 with Tomcat5.5

Thank you
By Makarand on Apr 4, 2008 at 12:13 PM PDT
This is great stuff/Good article.
Thank You
By Rajesh Pollepalli on Apr 18, 2008 at 11:32 AM PDT
The attribute default-autowire="byName" caused this example to fail for me.
By Richard on Apr 23, 2008 at 1:13 AM PDT
Hi!

Note: I am a beginner for CXF and Spring.

What I would like to know how one should start the webservice?

If using just CXF, there is a class with main method (e. g. here: http://svn.apache.org/repos/asf/incubator/cxf/trunk/distribution/src/main/release/samples/java_first_jaxws/src/demo/hw/server/Server.java)

What is the case here?
What choices do I have?

thanks
By Gergely Kontra on Apr 24, 2008 at 8:21 AM PDT
Hi Willie,
this is my first web service application example in Java & I like the way you have put the tutorial in simple terms so that a beginner like me can understand it clearly as well.

I have a doubt though, can I pass parameters to postMessage method & if so how?
Please provide me the way to pass parameters in the URL.
Thanks
Cheers
prasannarupan
By Prasannarupan on Apr 24, 2008 at 8:21 AM PDT
Hi Willie,
I also noticed the use of @overide annotation.
What is the purpose of it?.Is it a typo?
I also got a warning from Eclipse & I couldnt access the getMessages method when @override annotation was used when I deployed the application on JBoss AS 4.2.2GA.
I removed the annoation & the application is working fine now.


Thanks
prasanna
By Prasannarupan on Apr 24, 2008 at 8:30 AM PDT
@Makarand and Rajesh: Thanks!

@Richard: Not sure why that is happening for you. If you provide more information I might be able to help. At any rate the autowiring part is optional. If you are having problems with that you can always manually wire the beans.

@Gergely: In my article, the web service is just part of a web application, so you would start it in your web container (e.g. Tomcat). As to the example you reference, that uses the JAX-WS Endpoint API to publish the web service. The idea is that it starts up a lightweight web server to host your web service. Here is a link for you:

http://weblogs.java.net/blog/jitu/archive/2006/01/web_service_end.html

@Prasannarupan: Glad you found the tutorial useful. As far as passing parameters to postMessage(), I'm not sure I'm following your meaning. We are in fact passing an argument to postMessage--namely, the Message object itself. The client doesn't know that ContactUsService is backed by a web service and in particular it doesn't know that HTTP parameters are involved at all (if that's what you're asking). Can you describe more generally what you are trying to do?

As far as @Override goes, it wasn't a typo, but you are right to remove it. @Override tells the compiler that the method is supposed to override a method in an interface or a base class. (So if the compiler doesn't find the overridden method, it complains. This helps avoid cases where you think you overrode a method but you really didn't, like if you implement hashcode() instead of hashCode(), etc.) In Java 5 you can't use @Override when the method in question is an interface method; it works only for methods defined in a base class. In Java 6 you can use @Override in either situation. I am using Java 6 in the article and I neglected to say anything about that. Thanks for highlighting this.
By Willie Wheeler on Apr 24, 2008 at 1:11 PM PDT
Hi Willie!

Thanks for the quick reply.

Ok, the article shows how to do a web server, but spring is still not involved...
Since it may take up just a few lines of code, is it possible to complete the tutorial to a fully working example, or I'm just the only one who needs this extra.
By Gergely Kontra on Apr 25, 2008 at 1:44 AM PDT
Hi Gergely. The tutorial's example should be a fully working example :-) though the downloads are in my other Spring/CXF article (the second in the series) at

http://wheelersoftware.com/articles/spring-cxf-consuming-web-services-4.html

One of the links under Resources is the web service (i.e. the example in this article) and the other is the client code. You'll need to grab the dependencies yourself but those are listed in the article itself. Let me know if you aren't able to get the example to run.
By Willie Wheeler on Apr 25, 2008 at 1:49 AM PDT
By the way, Gergely, I may be misunderstanding you when you say "spring is still not involved", but in my article, Spring is very much involved. We're using Spring to wire up the beans and (importantly) to abstract the service implementation, among other things. Then we're taking the resulting web app (well, web services in this case, but bundled in a WAR) and dropping that into Tomcat or whatever servlet container you like.

The nice thing about Spring + CXF here is that as far as your application is concerned, it's just working with service beans. It has no knowledge that the service beans are actually web service proxies. You can very easily replace web service remoting with some other remoting mechanism (e.g. RMI, Hessian, Burlap, HttpInvoker) and you don't have to change the app at all--just the Spring config.

The app doesn't even know that the service beans are making remote calls, so you can replace the web service proxies with the actual web service implementation bean and the app doesn't know. In fact I did exactly that when I wrote the code for the comment service on this very web site. Originally I was making web service calls to a CommentService I wrote, and then I decided that there was no point and simply replaced the web service calls with a local service bean. Worked perfectly. :-)
By Willie Wheeler on Apr 25, 2008 at 2:02 AM PDT
Hi!

Well, the problem for me is (maybe just for me...): who will know web.xml must be read and parsed, and where is this piece of information in the code?

ui: I said I'm a beginner in this area.

By the way, with using a Server.java, which is here:
[http://pastebin.com/m5204fe28]

The output of the program looks like this (exception at startup):
[http://pastebin.com/m6366ff96]
By Gergely Kontra on Apr 25, 2008 at 5:33 AM PDT
Hi Gergely. It looks like you are trying to use the approach at

http://cwiki.apache.org/CXF20DOC/a-simple-jax-ws-service.html

which does not involve Spring or even a WAR. (So there is no web.xml involved with that.) That approach is not directly related to my article.

You might take a look at

http://cwiki.apache.org/CXF20DOC/writing-a-service-with-spring.html

instead, which is one of the other CXF 2.0 howtos (and it happens the one on which my article is based).
By Willie Wheeler on Apr 25, 2008 at 10:59 AM PDT
Hi,

it seems very usefull tutorial but when i try to do what you did, i got following exception

14:16:30.292 INFO [main] org.apache.cxf.aegis.type.XMLTypeCreator.<clinit>(XMLTypeCreator.java:125) >46> Parser doesn't support setSchema. Not validating.
java.lang.UnsupportedOperationException: This parser does not support specification "null" version "null"
at javax.xml.parsers.DocumentBuilderFactory.setSchema(DocumentBuilderFactory.java:489)

i could not get rid of this problem.
By alperen on May 6, 2008 at 4:46 AM PDT
When using Spring 2.4, Tomcat 6 and CXF 2.1 you need to add jaxen library to you classpath ortherwise AegisDatabinding bean won't be created.
By Alex Khvatov on May 9, 2008 at 12:36 PM PDT
Man you saved my life... at least my work life. I've been working with CXF for a month without getting any test running well but simple services which return basic data types. When I've read your post I've realized about the JAXB problem with complex types and then I've took all necessary beans and Aegis configurations from your tutorial and my little service has worked!
Thanks a lot. Greetings from Argentina

PS: sorry about my english, it's quite poor yet ;)
By Federico A. Ocampo on May 14, 2008 at 11:45 AM PDT
@Federico: Really happy to hear that the article helped you. And your English is fine. A lot better than my Spanish. :-D
By Willie Wheeler on May 15, 2008 at 12:08 AM PDT
Thanks for putting this tutorial together. Was very helpful.
By Scott on May 24, 2008 at 6:27 AM PDT
I was just reading through the article and the bottom of page 3 mentions a validation annoyance in Eclipse. I checked to see whether the CXF team had yet posted the core and jaxws schemas to the specified schema locations and the answer is yes. So the validation annoyance I mentioned should not be a problem anymore. (Maybe it will still come up if you aren't on the Internet but other than that...)
By Willie Wheeler on May 24, 2008 at 6:28 AM PDT
Willie, although CXF have posted those schemas to the sites, it still causes an issue if the machine that CXF + Spring 2.5 is behind a proxy with no access to the outside world. I do have a solution that I have used for Spring 2.5 in the past for other Schemas, and once I have tested that it works with this, I will post the answer here and on my blog.
By Willie on Jun 5, 2008 at 1:28 AM PDT
I am using netbeans 6.0.1 added the jar files in the libraray and also using glassfish V2 server , and got the following errors while running the application .

Deployment error:
The module has not been deployed.
See the server log for details.
at org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment.deploy(Deployment.java:163)
at org.netbeans.modules.j2ee.ant.Deploy.execute(Deploy.java:104)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor106.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:105)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
By yelena on Jul 28, 2008 at 3:23 AM PDT
nice doc .. thanks ..
running into a problem after deploying app on tomcat.

Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'cxf:bus'

The declarations inside my spring-beans.xml are 100% correct.

Error occurs on both, the ctx suffix as well as the jaxw suffix.

Using spring 2.5.5 and cxf 2.1 (tried older versions as well).
Manually added jdom 1.0 to maven build.

Was wondering if anyone stepped into same problems before .. thanks
By tmaus on Jul 29, 2008 at 2:19 AM PDT
Hi Willie,
Can you provide a specific example of the following?:

[path to CXFServlet]/contactus/postMessage?message=... - postMessage operation
By Alex on Aug 4, 2008 at 8:50 AM PDT
@Alex: The specific examples are listed at the top of page 4. Basically you just need to include the URL up to and including the servlet name, so that would include your servlet context and the servlet name just like with any servlet.
By Willie Wheeler on Aug 4, 2008 at 7:48 PM PDT
Post a comment
Home | Consulting | Articles | Blog | About | Contact
Copyright © 2008 Wheeler Software, LLC.