Often times you have Spring services that you want to expose as web-services. In this small tutorial I’ll just show a few configuration files and code that demonstrate how a service and its implementation can accommodate both REST and SOAP access to the same backbone.
Thanks Justin for the REST part.
This tutorial is available for download with svn:
svn checkout http://raulrajatutorials.googlecode.com/svn/trunk/ raulrajatutorials-read-only
Comments in the code itself should be self-explanatory if you already have some java + spring experience.
I have not included the dependencies on CXF for simplicity but you can take a look at them and some for the other tutorials here.
And now to the point.
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd" default-autowire="byName"> <!-- Load CXF modules from cxf.jar --> <import resource="classpath:META-INF/cxf/cxf.xml"/> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/> <cxf:bus> <cxf:features> <cxf:logging/> </cxf:features> </cxf:bus> <!-- The hello world service --> <bean id="helloWorldService" class="com.raulraja.ws.impl.HelloWorldServiceImpl" autowire="autodetect"/> <!-- Exposing the Helloworld service as a rest service --> <jaxrs:server id="restServer" address="/rest/"> <jaxrs:serviceBeans> <ref bean="helloWorldService"/> </jaxrs:serviceBeans> <jaxrs:extensionMappings> <entry key="feed" value="application/atom+xml"/> <entry key="json" value="application/json"/> <entry key="xml" value="application/xml"/> <entry key="html" value="text/html"/> </jaxrs:extensionMappings> </jaxrs:server> <!-- Exposing the HelloWorld service as a SOAP service --> <bean id="jaxbBean" class="org.apache.cxf.jaxb.JAXBDataBinding" scope="prototype"/> <bean id="jaxws-and-aegis-service-factory" class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean" scope="prototype"> <property name="dataBinding" ref="jaxbBean"/> <property name="serviceConfigurations"> <list> <bean class="org.apache.cxf.jaxws.support.JaxWsServiceConfiguration"/> <bean class="org.apache.cxf.aegis.databinding.AegisServiceConfiguration"/> <bean class="org.apache.cxf.service.factory.DefaultServiceConfiguration"/> </list> </property> </bean> <jaxws:endpoint id="helloWorldServiceEndpoint" serviceName="HelloWorld" implementorClass="com.raulraja.ws.HelloWorldService" implementor="#helloWorldService" address="/helloWorldService"> <jaxws:serviceFactory> <ref bean="jaxws-and-aegis-service-factory"/> </jaxws:serviceFactory> </jaxws:endpoint> </beans>
HelloWorldService.java
package com.raulraja.ws; import javax.ws.rs.Path; import javax.ws.rs.GET; import javax.jws.WebService; import javax.jws.WebMethod; /** * The hello world service interface exposed as soap and rest * * @ WebService is for soap * @ Path is for the rest top path */ @Path("/helloWorldService/") @WebService(serviceName = "HelloWorld", name = "HelloWorldService", targetNamespace = "http://ws.raulraja.com") public interface HelloWorldService { /** * Simple methods that says hello * * @return hello world rest and soap!!! * @ WebMethod is for soap * @ GET is for REST * @ Path is for the REST service path */ @WebMethod @GET @Path("/") HelloWorld sayHello(); }
HelloWorldServiceImpl.java
package com.raulraja.ws.impl; import com.raulraja.ws.HelloWorld; import com.raulraja.ws.HelloWorldService; /** * Implementation of the hello world web service. */ public class HelloWorldServiceImpl implements HelloWorldService { /** * Simple methods that says hello * * @return hello world rest and soap!!! */ public HelloWorld sayHello() { HelloWorld helloWorld = new HelloWorld(); helloWorld.setMessage("Hello world rest and soap!!!"); return helloWorld; } }
HelloWorld.java
package com.raulraja.ws; import javax.xml.bind.annotation.XmlRootElement; /** * Hello world object that demonstrates the service */ @XmlRootElement public class HelloWorld { /** * the message */ private String message; /** * @return the message */ public String getMessage() { return message; } /** * @param message sets the message */ public void setMessage(String message) { this.message = message; } }
And here is some screen captures for the results…
Soap Services list
Hello World Service WSDL (autogenerated)
Hello World Service REST XML Result (add .json or .xml, … at the end of the service path to get results in the different format exposed)














I´ve got an error on applicationContext.xml in first line saying: Referenced file contains errors (http://www.springframework.org/schema/beans/spring-beans.xsd). For more
information, right click on the message in the Problems View and select “Show Details…”
What should i do?
Bruno, sorry for the late approve of your comment and response, somehow it got lost on my inbox. As for your error it’s most likely a problem with your validator. That xsd validates fine on my IDE (IntelliJ IDEA) .
Do you have an example which takes an object as a parameter ?
Dave, this post is a bit old and there are new ways to do this in Spring. I recommend you take a look at http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch18s02.html for RESTfull services in Spring. To accept an object as parameter you simply pass the object in the POST BODY and annotate your service param with @RequestBody which marshalls the JSON or XML to your bean.
great and thanks
Hi Raul,
I tried your example as had similar requirements to expose a service as both ReST and SOAP, but spring is complaining that it cant create the main bean class.Can u suggest something.
I am using spring 2.5.5, CXf 2.2.9 JBOSS4.0.5..
07:02:21,632 ERROR [ContextLoader] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘ProvisionPaygNetworkProducts’: Cannot resolve reference to bean ‘fulfillPAYGMultim
nstructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘fulfillPAYGMultimediaProducts’ defined in
INF/provisionPAYGMultimedia-beans.xml]: Initialization of bean failed; nested exception is java.lang.ClassCastException: $Proxy99
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:275)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:104)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:479)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:162)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:925)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:835)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:440)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3763)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4211)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:759)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:739)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:524)
@Shamama, looks like your exception is unrelated. Maybe you are referencing ‘fulfillPAYGMultim’ as a bean dependency but you don’t have a bean with that name. Double check your id references are correct.
Thanks Raul, all that looks good to me, upgraded JDK to 6 now and atleast I am not getting this proxy error.
But I have! to use JDK1.5.10, I will try to upgrade cxf to 2.4.3 with JDK1.5.10 and try again.
@Shamana Also make sure that all methods that are being proxied are declared on a interface. Depending on your spring config you may be using JDK dynamic proxies or cglib class based proxies. Your AOP auto proxy config may also affect this and I’ve seen similar exceptions in the past similar to yours due to lack of interfaces or use/lack of use of Spring AOP’ autoproxying capabilities.
I am new to webservice world. The requirement of project is to use REST framework in order to expose Legacy services as web services. I am confused about ‘REST with cxf’ OR simply ‘REST’ will do the work for me. Also existing legacy services return response in XML format but we want these new webservices to return JSON . Kindly guide and assist.
@JavaDev REST is not a framework but a style of consuming and exposing WebServices. http://en.wikipedia.org/wiki/Representational_state_transfer
CXF is just a project that aids in building web services. There are multiple other projects and framework for building web services. The fact that a service returns XML or JSON has nothing to do with REST. REST services can also return XML even though they are most commonly found in JSON format. Legacy services usually are found as SOAP services http://en.wikipedia.org/wiki/SOAP
REST style services such as the one shown in this article can use SOAP and still be consider REST. Unfortunately REST, SOAP, JSON, … have become buzz words that non developer roles (sales, project managers…) in this industry misuse and butcher or just simply confuse. My advice is that you choose the right solution for the problem you’re trying to solve, and shy away from turning your legacy WS to a REST style just for the sake of it.
Thanks Raja that helps for basic understanding, may post more questions down the line.
Iam getting an error during server start up: CREATE_LISTENER_FAILED_4 vmcid: 0×49421000
com.ibm.ws.exception.RuntimeError: com.ibm.ws.exception.RuntimeError: org.omg.CORBA.INTERNAL: CREATE_LISTENER_FAILED_4 vmcid: 0×49421000 minor code: 56 completed: No
[12/19/11 12:17:30:294 IST] 0000000a WsServerImpl E WSVR0009E: Error occurred during startup
META-INF/ws-server-components.xml
[12/19/11 12:17:30:309 IST] 0000000a WsServerImpl E WSVR0009E: Error occurred during startup
com.ibm.ws.exception.RuntimeError: com.ibm.ws.exception.RuntimeError: org.omg.CORBA.INTERNAL: CREATE_LISTENER_FAILED_4 vmcid: 0×49421000 minor code: 56 completed: No
at com.ibm.ws.runtime.WsServerImpl.bootServerContainer(WsServerImpl.java:199)
at com.ibm.ws.runtime.WsServerImpl.start(WsServerImpl.java:140)
at com.ibm.ws.runtime.WsServerImpl.main(WsServerImpl.java:461)
at com.ibm.ws.runtime.WsServer.main(WsServer.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:615)
at com.ibm.wsspi.bootstrap.WSLauncher.launchMain(WSLauncher.java:183)
at com.ibm.wsspi.bootstrap.WSLauncher.main(WSLauncher.java:90)
at com.ibm.wsspi.bootstrap.WSLauncher.run(WSLauncher.java:72)
at org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:78)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:92)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:68)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:400)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:615)
at org.eclipse.core.launcher.Main.invokeFramework(Main.java:340)
at org.eclipse.core.launcher.Main.basicRun(Main.java:282)
at org.eclipse.core.launcher.Main.run(Main.java:981)
at com.ibm.wsspi.bootstrap.WSPreLauncher.launchEclipse(WSPreLauncher.java:339)
at com.ibm.wsspi.bootstrap.WSPreLauncher.main(WSPreLauncher.java:94)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:615)
at com.citigroup.cdcla.eclipse.launch.ServerLauncher.run(ServerLauncher.java:130)
at com.citigroup.cdcla.eclipse.launch.ServerLauncher.main(ServerLauncher.java:189)
Caused by: com.ibm.ws.exception.RuntimeError: org.omg.CORBA.INTERNAL: CREATE_LISTENER_FAILED_4 vmcid: 0×49421000 minor code: 56 completed: No
at com.ibm.ws.runtime.component.ORBImpl.start(ORBImpl.java:424)
at com.ibm.ws.runtime.component.ContainerImpl.startComponents(ContainerImpl.java:977)
at com.ibm.ws.runtime.component.ContainerImpl.start(ContainerImpl.java:673)
at com.ibm.ws.runtime.component.ServerImpl.start(ServerImpl.java:526)
at com.ibm.ws.runtime.WsServerImpl.bootServerContainer(WsServerImpl.java:192)
… 30 more
Caused by: org.omg.CORBA.INTERNAL: CREATE_LISTENER_FAILED_4 vmcid: 0×49421000 minor code: 56 completed: No
at com.ibm.ws.orbimpl.transport.WSTransport.createListener(WSTransport.java:859)
at com.ibm.ws.orbimpl.transport.WSTransport.initTransports(WSTransport.java:597)
at com.ibm.rmi.iiop.TransportManager.initTransports(TransportManager.java:155)
at com.ibm.rmi.corba.ORB.set_parameters(ORB.java:1212)
at com.ibm.CORBA.iiop.ORB.set_parameters(ORB.java:1662)
at org.omg.CORBA.ORB.init(ORB.java:364)
at com.ibm.ws.orb.GlobalORBFactory.init(GlobalORBFactory.java:86)
at com.ibm.ejs.oa.EJSORBImpl.initializeORB(EJSORBImpl.java:179)
at com.ibm.ejs.oa.EJSServerORBImpl.(EJSServerORBImpl.java:102)
at com.ibm.ejs.oa.EJSORB.init(EJSORB.java:55)
at com.ibm.ws.runtime.component.ORBImpl.start(ORBImpl.java:417)
… 34 more
@VTS I have no idea what your error is about. I neither use IBM WS nor there is a META-INF/ws-server-components.xml file in this example.
Which is the cxf jar version are you using? Iam getting cvc-complex-type.2.4.c no declaration error for jaxrs:server, cxf:bus and jaxws:endpoint….
@VTS I recommend you follow some other example for getting RESTful services working with Spring as this post is a bit almost 3 years old. Look into something like http://bit.ly/u9JbyD . I had already mentioned where the dependencies are as part of this post http://raulrajatutorials.googlecode.com/svn/trunk/raulraja.com.tutorials/pom.xml , you can get the CXF list of dependencies there.