In [step1], we have configured CXF Eclipse Plugin to use CXF 2.4.2 and created an empty Dynamic Web project with Tomcat 7.
In this article we will create a sample Java class HelloServiceImpl and publish it as WebService by using CXF Eclipse wizard. Basicly, this wizard will :
- modify the HelloServiceImpl to add well JAX-WS annotation.
- modify or create the Spring beans.xml file which declares the WebServices (in our case HelloServiceImpl) to publish.
- modify the web.xml to declare the Spring CXF Servlet used to dispatch to the well WebService declared in the beans.xml.
Download
You can download jaxwswithcxf_step2.zip which is a zip which contains the the Dynamic Web Project jaxwswithcxf with the HelloWorldImpl WebServices explained in this article.
Create Class HelloServiceImpl
Create in the jaxwswithcxf Dynamic Web Project the class org.sample.ws.HelloServiceImpl like this :
package org.sample.ws;
public class HelloServiceImpl {
public String getVersion() {
return "1.0";
}
public String hello(String user) {
return "Hello " + user + "!";
}
}Create WebService HelloServiceImpl
Web services can be created using two methods:
- top-down development : Top-down Web services development involves creating a Web service from a WSDL file. WSDL file describe the services (methods, parameters) and defines the contract for WebService. This WSDL file can be used to generate too the consumer of the WebService (which can be different technolgy (PHP, .Net, etc) than the WebService).
- bottom-up development : Bottom-up Web services development involves creating a Web service from a Java bean or enterprise bean.
In our case we will use bottom-up development : we will use HelloServiceImpl Java class to create the Web Service.
step1 : select Java class
Select HelloServiceImpl and click on right mouse button to click on the Web Services/Create Web Service menu item :
step2 : select CXF runtime
This action opens the generic Wizard Web Service to generate WebService with Axis, Axis2, CXF, etc :
In our case we wish generate CXF code. To do that, click on Web service runtime: Apache Axis, the Service Deployment Configuration opens. Select Apache CXF 2.x for Web service runtime :
Click on OK button to close the Service Deployment Configuration dialog :
You can check that Web service runtime is Apache CXF 2.x. By default the Start service is selected which means as soon as wizard is finished, the server will start. I prefer start my server at hand, so I use Install Service to avoid launching the server at end of the wizard :
step3 : Starting Point Configuration
Click on Next button, the Starting Point Configuration wizard page displays. This page is used to generate an interface (for the HelloServiceImpl) annoted with JAX-WS annotation. In our case we do nothing and HelloServiceImpl will contains the JAX-WS annotation :
step4 : Web Service JAX-WS Annotations Configuration
Click on Next button, the Web Service JAX-WS Annotations Configuration wizard page displays. This page provides several checkbox that you can select/unselect to generate JAX-WS annotation. You can preview the generated code on the bottom of this page. In our case we don’t change the pre-defined values. We will play with those checkbox in a next article :
step5 : Web Service Java2WS Configuration
Click on Next button, the Web Service Java2WS Configuration wizard page displays. This wizard page provides some checkbox to select that you wish generate :
- Generate client generate simple client with JAX-WS Service.create()
- Generate server generate simple client of the WebService. This code starts a server (with Embedding Jetty) and publish the WebService by using JAX-WS Endpoint#publish.
- Generate Wrapper and Fault Beans generate Java class with JAXB annotation. Those classes are generated in the *.jaxws package (in our case org.sample.ws.jaxws). We will see the using of those class in next articles.
- Generate WSDL generate WSDL of the WebService.
- WSDL file : name of the WSDL file to generate.
- Default SOAP binding.
- Generate seperate XSD for the types : if this option is selected, the generated WSDL file will not contains the XML Schema which declares type of the structure used in the method parameters.
step6 : Web Service Publication
Click on Next button, the Web Service Publication wizard page displays :
Click on Finish button to generate JAX-WS WebService and CXF component (Spring beans and web.xml).
Result of CXF Wizard
After finishing the generation of the CXF wizard, your workspace looks like this :
The wizard generate several things :
- [1] HelloServiceImpl : modify the Java class HelloServiceImpl with JAX-WS annotation :
package org.sample.ws;
import javax.jws.WebService;
@WebService(targetNamespace = "http://ws.sample.org/", portName = "HelloServiceImplPort", serviceName = "HelloServiceImplService")
public class HelloServiceImpl {
public String getVersion() {
return "1.0";
}
public String hello(String user) {
return "Hello " + user + "!";
}
}The JAX-WS javax.jws.WebService annotation is used to indicate that this class is a WebService.
- [2] generate some classes in the org.sample.ws.jaxws package. Those classes are generated because the Generate Wrapper and Fault Beans of the page Web Service Java2WS Configuration was checked. At this step, those class are not used.
- [3] CXF librarires. If you opens this item you will see that the wizard use the whole JAR of the CXF distribution :
Don’t be afraid with the lof of JARs, CXF needs few JARs.
- [4] beans.xml : this Spring file is used to declare with Spring bean the Java class HelloServiceImpl which must be published as WebService :
<?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-2.5.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<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" />
<jaxws:endpoint xmlns:tns="http://ws.sample.org/" id="helloservice"
implementor="org.sample.ws.HelloServiceImpl" wsdlLocation="wsdl/helloserviceimpl.wsdl"
endpointName="tns:HelloServiceImplPort" serviceName="tns:HelloServiceImplService"
address="/HelloServiceImplPort">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
</jaxws:endpoint>
</beans>
- the following declaration :
<jaxws:endpoint ... implementor="org.sample.ws.HelloServiceImpl"
is used to publish the HelloServiceImpl class.
- the following declaration :
<jaxws:endpoint ... address="/HelloServiceImplPort"
is used to set the path for the URL of HelloServiceImpl. In our case our service will be available at http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort.
- the following declaration :
<jaxws:endpoint ... wsdlLocation="wsdl/helloserviceimpl.wsdl"
set the location of the WSDL. If you remove this wsdlLocation attribute, WSDL will be generated if you access it by the URL http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort?wsdl.
- [5] web.xml is modified to declare the CXF servlet based on Spring
<servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
available at http://localhost:8080/jaxwswithcxf/services/ :
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
This servlet is used to dispatch to the well WebServices. To know WebServices deployed, this servlet use the Spring ApplicationContext loaded from the beans.xml :
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Here the full code of the web.xml :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>jaxwswithcxf</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<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>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app> - [6] helloserviceimpl_schema1.xsd : this XML Schema describes the structure used in the WebService. This file is generated because the Generate seperate XSD for the types checkbox of the page Web Service Java2WS Configuration was checked. Here the content of this file :
<?xml version="1.0" encoding="utf-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://ws.sample.org/" elementFormDefault="unqualified" targetNamespace="http://ws.sample.org/" version="1.0">
<xs:element name="getVersion" type="tns:getVersion"/>
<xs:element name="getVersionResponse" type="tns:getVersionResponse"/>
<xs:element name="hello" type="tns:hello"/>
<xs:element name="helloResponse" type="tns:helloResponse"/>
<xs:complexType name="getVersion">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="getVersionResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="hello">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="helloResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema> - [7] helloserviceimpl.wsdl : is the generated WSDL. This file is generated because the Generate WSDL checkbox of the page Web Service Java2WS Configuration was checked. Here the content of this file :
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="HelloServiceImplService" targetNamespace="http://ws.sample.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws.sample.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://ws.sample.org/" schemaLocation="helloserviceimpl_schema1.xsd"/>
</schema>
</wsdl:types>
<wsdl:message name="hello">
<wsdl:part name="parameters" element="tns:hello">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getVersion">
<wsdl:part name="parameters" element="tns:getVersion">
</wsdl:part>
</wsdl:message>
<wsdl:message name="helloResponse">
<wsdl:part name="parameters" element="tns:helloResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getVersionResponse">
<wsdl:part name="parameters" element="tns:getVersionResponse">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="HelloServiceImpl">
<wsdl:operation name="getVersion">
<wsdl:input name="getVersion" message="tns:getVersion">
</wsdl:input>
<wsdl:output name="getVersionResponse" message="tns:getVersionResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="hello">
<wsdl:input name="hello" message="tns:hello">
</wsdl:input>
<wsdl:output name="helloResponse" message="tns:helloResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloServiceImplServiceSoapBinding" type="tns:HelloServiceImpl">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getVersion">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="getVersion">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getVersionResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="hello">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="hello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="helloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloServiceImplService">
<wsdl:port name="HelloServiceImplPort" binding="tns:HelloServiceImplServiceSoapBinding">
<soap:address location="http://localhost:9090/HelloServiceImplPort"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
You can notice that you have JAX-WS Web Services menu item which show you information about Java classes which are annotated with JAX-WS :
Launch WEB Application
At this step we have not a client (consumer of the HelloServiceImpl) but we can test it.
An important information is that our WebService is declared with the org.apache.cxf.feature.LoggingFeature :
<jaxws:endpoint id="helloservice"
...>
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
</jaxws:endpoint>
This feature is very usefull because it gives you the capability to trace for instance the received SOAP message (IN) and the sent SOAP message (OUT). We will check that in the Eclipse Console View.
Launch jaxwswithcxf to publish our WebService. After the start of the Web Application, you can notice some interesting logs in the Eclipse Console View :
- you can notice that WEB-INF/beans.xml is loaded :
...
INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/beans.xml]
...
And check that HelloServiceImpl is published :
...
INFO: Creating Service {http://ws.sample.org/}HelloServiceImplService from WSDL: wsdl/helloserviceimpl.wsdl
22 août 2011 17:16:13 org.apache.cxf.endpoint.ServerImpl initDestination
INFO: Setting the server's publish address to be /HelloServiceImplPort
...URLs
At this step we can play with different URLs
CXF Services listIf you go at http://localhost:8080/jaxwswithcxf/services, you can see list of WebServices (and REST services) :
WSDLIf you click on the link
WSDL : {http://ws.sample.org/}HelloServiceImplService
you will see the WSDL :
URL of the WSDL is http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort?wsdl
If you go to the Eclipse Console View, you will see some logs (because we have LoggingFeatures) :
getVersion methodIt’s possible to call our getVersion method with the following URL http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort/getVersion which returns the SOAP message :
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:getVersionResponse xmlns:ns2="http://ws.sample.org/">
<return>1.0</return>
</ns2:getVersionResponse>
</soap:Body>
</soap:Envelope>
If you go to the Eclipse Console View, you will see some logs (because we have LoggingFeatures)
With this log you can see for instance the sent SOAP Message :
hello methodIt’s possible to call method with parameter. If you call hello like this, you will that :
http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort/hello
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:helloResponse xmlns:ns2="http://ws.sample.org/">
<return>Hello null!</return>
</ns2:helloResponse>
</soap:Body>
</soap:Envelope>
Hello null!
is returned because we have not filled the parameter.
To set a parameter, you must access to this URL :
http://localhost:8080/jaxwswithcxf/services/HelloServiceImplPort/hello?arg0=world
This URL will returns the following SOAP message :
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:helloResponse xmlns:ns2="http://ws.sample.org/">
<return>Hello world!</return>
</ns2:helloResponse>
</soap:Body>
</soap:Envelope>
Why arg0? Because if you check the XML Schema you have :
<xs:complexType name="hello">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>Conclusion
In this article we have generated with CXF Eclipse wizard a WebService with JAX-WS. This wizard initialize CXF by creating beans.xml wich declare Java classes which must be published and CXF Servlet. You can notice that HelloServiceImpl is not linked to CXF and could be used with another JAX-WS implementation.
In next article [step3] we will create and generate a client with JAX-WS (and CXF) which will consume our WebService.