In the previous post we saw how JAX-WS 's RI implementation could be used to build and interact with web services. I decided to work with one of the other implementations - Apache CXF. I decided to create and run a code first webservice using CXF implementation.
The CXF applications are deployed in a web context. So the first step was to create a web application.
The next step is the same as we did in the last application. We created the webservice interface and implementation:
The implementation is as below:
The last annotations are the WebParam and WebResult. WebParam will map the method parameter to a Web Service message part and XML element. WebResult is used to set the name for the returned result. The User class referred in the above code is a simple POJO.
Now to configure CXF:
First the web.xml:
The CXF-Servlet is like a front controller to which all the webservice calls are routed. It then accordingly redirects the calls to appropriate webservice endpoints.
This will seem similar to the implementation of spring's -mvc framework – though the important point is CXF is not using spring-mvc. The architecture while similar to spring-mvc at no point uses anything beyond spring's core jars.
Here we have configured all urls of the form /services/* to be routed to the cxf servlet. Our webservice endpoints are treated as Spring beans and are wired here through the spring-cxf-services.xml file.
The URL for the webservice is now <application-context>/services/echo.
What of the libraries ?
The application can now be deployed on an application server. I used Apache Tomcat 7.
On starting the server:
This completes the web service implementation. In the next post we shall create a client for the service and test it.
The CXF applications are deployed in a web context. So the first step was to create a web application.
The next step is the same as we did in the last application. We created the webservice interface and implementation:
package com.code.first.ws.server; import javax.jws.WebService; @WebService public interface IEcho { String echoHi(String text); String echoHiToUser(User user); }All the annotations used are standard JAX-WS annotations. The WebService annotation indicates that the Java class is implementing a Web Service, or (as in this case) a Java interface is defining a Web Service interface.
The implementation is as below:
package com.code.first.ws.server.impl; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebParam.Mode; import javax.jws.WebResult; import javax.jws.WebService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.code.first.ws.server.IEcho; import com.code.first.ws.server.User; @WebService(endpointInterface = "com.code.first.ws.server.IEcho", name = "EchoWebService", portName = "EchoImplPort", serviceName = "EchoImplService", targetNamespace = "http://www.cfx.ws/") public class EchoImpl implements IEcho { private static final Logger logger = LoggerFactory .getLogger(EchoImpl.class); @Override @WebMethod(action = "hiEchoAction", operationName = "sayHi") public @WebResult(partName = "result", name = "rslt") String echoHi( @WebParam(mode = Mode.IN, partName = "message", name = "msg") String text) { logger.info("echoHi called with msg as {}", text); return "Hi " + text; } @Override @WebMethod(/* exclude = true, */ action = "echoHiToUserAction", operationName = "echoHiToUser") public @WebResult(partName = "result") String echoHiToUser(@WebParam(mode = Mode.IN, partName = "user") User user) { logger.info("echoHiToUser called with user id {}", user.getId()); return "Hi " + user.getName() + " - id " + user.getId() + ", weight " + user.getWeight(); } }Here more detailed information has been provided. Most of it is optional. The endpointInterface attribute of WebService indicates the Service endpoint Interface . Rest of the details are for use in the generated wsdl. The WebMethod annotation indicates that this method is exposed as a Web Service operation. The action attribute indicates the value for SoapAction header. If we set exclude attribute to true, then the method will not be exposed as a operation. Remaining attribute is for use in wsdl.
The last annotations are the WebParam and WebResult. WebParam will map the method parameter to a Web Service message part and XML element. WebResult is used to set the name for the returned result. The User class referred in the above code is a simple POJO.
public class User { private Long id; private String name; private BigDecimal weight; // setter getters }This completes the code.
Now to configure CXF:
First the web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- This file includes information of the services - needed by Spring to create the beans and add them to the container --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:spring-cxf-services.xml </param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>cxf</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cxf</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> </web-app>As seen a single servlet was added to the web.xml – The CXFServlet is the start up point for the CFX system.
The CXF-Servlet is like a front controller to which all the webservice calls are routed. It then accordingly redirects the calls to appropriate webservice endpoints.
This will seem similar to the implementation of spring's -mvc framework – though the important point is CXF is not using spring-mvc. The architecture while similar to spring-mvc at no point uses anything beyond spring's core jars.
Here we have configured all urls of the form /services/* to be routed to the cxf servlet. Our webservice endpoints are treated as Spring beans and are wired here through the spring-cxf-services.xml file.
<?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:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- name of all the services exposed as beans. The path is added from here ahead --> <jaxws:endpoint id="echoEndpointImpl" implementor="com.code.first.ws.server.impl.EchoImpl" address="echo" /> </beans>The endpoint element from the http://cxf.apache.org/jaxws namespace configures a JAX-WS Web service endpoint. Here we have configured our implementation to the address “echo”.
The URL for the webservice is now <application-context>/services/echo.
What of the libraries ?
The application can now be deployed on an application server. I used Apache Tomcat 7.
On starting the server:
2125 [pool-2-thread-1] DEBUG org.springframework.beans.factory.xml.XmlBeanDefini tionReader - Loaded 1 bean definitions from location pattern [classpath:spring- cxf-services.xml] ... 5531 [pool-2-thread-1] INFO org.apache.cxf.service.factory.ReflectionServiceFac toryBean - Creating Service {http://www.cfx.ws/}EchoImplService from class com. code.first.ws.server.IEcho ... 8406 [pool-2-thread-1] DEBUG org.apache.cxf.jaxb.JAXBDataBinding - Created JAXB Context "jar:file:/C:/Program%20Files/Java/jdk1.6.0/jre/lib/rt.jar!/com/sun/xml/ internal/bind/v2/runtime/JAXBContextImpl.class Build-Id: 1.6.0-rc Classes known to this context: [B boolean byte char com.code.first.ws.server.User com.code.first.ws.server.jaxws_asm.EchoHi com.code.first.ws.server.jaxws_asm.EchoHiResponse com.code.first.ws.server.jaxws_asm.EchoHiToUser com.code.first.ws.server.jaxws_asm.EchoHiToUserResponse com.sun.xml.internal.bind.api.CompositeStructure ... 11000 [pool-2-thread-1] INFO org.apache.cxf.endpoint.ServerImpl - Setting the server's publish address to be echo ... 11125 [pool-2-thread-1] DEBUG org.apache.cxf.endpoint.ServerImpl - Server is st arting. ... 11266 [pool-2-thread-1] INFO org.springframework.web.context.ContextLoader - R oot WebApplicationContext: initialization completed in 11250 msAs seen, the request and response wrappers were automatically generated. The service was also created with QName {http://www.cfx.ws/}EchoImplService
This completes the web service implementation. In the next post we shall create a client for the service and test it.
This is post very good, and useful for me, thank you very much..
ReplyDelete