[Tutorial] Create a Web Service with Apache CXF and JBoss 6

转自:http://www.celinio.net/techblog/?p=531

I have recently started studying Apache CXF, the open source web service framework. I am familiar with developing Web Services using EJB 3, Axis or Glue. But not with CXF. Until now.
CXF is a mix of two projects : Celtix and XFire, which explains the name CXF.
It provides support for the JAX-WS, JAX-RS and JAX-RPC specifications.
Developing Web Services using CXF and JBoss is quite easy. The only annoying part is to figure out which JARs libraries
to include in the classpath and which JARs libraries to exclude.

So i am developing a simple web service that calculates the BMI (Body Mass Index). The formula is :
BMI = weight / (height x height)

[b]1)[/b] First create a dynamic web project in Eclipse Helios.
[img]http://dl.iteye.com/upload/attachment/447501/fb224319-4f33-37df-b070-eacf81918353.png[/img]

[b]2)[/b] Download the CXF framework apache-cxf-2.3.1.zip at [url]http://cxf.apache.org/download.html[/url]

[b]3)[/b] After unzipping the archive, I added to WEB-INF/lib all the libraries that are inside the apache-cxf-2.3.1\lib
folder. It is of course not a good habit to have since adding all sorts of libraries can produces conflicts.
I had to remove a few jars such as :
jaxb-xjc-2.2.1.1.jar, xalan-2.7.1.jar and serializer-2.7.1.jar
[img]http://dl.iteye.com/upload/attachment/447504/a2260501-81a6-3c7c-91f0-be7764e8497a.png[/img]

Anyways here is the list of jars that i have added to WEB-INF/lib :

aopalliance-1.0.jar
commons-collections-3.2.1.jar
commons-lang-2.5.jar
commons-logging-1.1.1.jar
commons-pool-1.5.5.jar
cxf-2.3.1.jar
cxf-manifest.jar
cxf-xjc-boolean-2.3.0.jar
cxf-xjc-bug671-2.3.0.jar
cxf-xjc-dv-2.3.0.jar
cxf-xjc-ts-2.3.0.jar
FastInfoset-1.2.8.jar
geronimo-activation_1.1_spec-1.1.jar
geronimo-annotation_1.0_spec-1.1.1.jar
geronimo-javamail_1.4_spec-1.7.1.jar
geronimo-jaxws_2.2_spec-1.0.jar
geronimo-jms_1.1_spec-1.1.1.jar
geronimo-servlet_3.0_spec-1.0.jar
geronimo-stax-api_1.0_spec-1.0.1.jar
geronimo-ws-metadata_2.0_spec-1.1.3.jar
jaxb-api-2.2.1.jar
jaxb-impl-2.2.1.1.jar
jettison-1.2.jar
jetty-continuation-7.2.0.v20101020.jar
jetty-http-7.2.0.v20101020.jar
jetty-io-7.2.0.v20101020.jar
jetty-server-7.2.0.v20101020.jar
jetty-util-7.2.0.v20101020.jar
jra-1.0-alpha-4.jar
js-1.7R2.jar
jsr311-api-1.1.1.jar
neethi-2.0.4.jar
saaj-api-1.3.jar
saaj-impl-1.3.2.jar
slf4j-api-1.6.1.jar
slf4j-jdk14-1.6.1.jar
spring-aop-3.0.5.RELEASE.jar
spring-asm-3.0.5.RELEASE.jar
spring-beans-3.0.5.RELEASE.jar
spring-context-3.0.5.RELEASE.jar
spring-core-3.0.5.RELEASE.jar
spring-expression-3.0.5.RELEASE.jar
spring-jms-3.0.5.RELEASE.jar
spring-tx-3.0.5.RELEASE.jar
spring-web-3.0.5.RELEASE.jar
stax2-api-3.0.2.jar
stringtemplate-3.2.jar
velocity-1.6.4.jar
woodstox-core-asl-4.0.8.jar
wsdl4j-1.6.2.jar
wss4j-1.5.10.jar
xml-resolver-1.2.jar
xmlbeans-2.4.0.jar
XmlSchema-1.4.7.jar
xmlsec-1.4.4.jar

There are probably a few extras jars that are not needed but at least they do not produce any error for that simple web service.

[b]4)[/b] Create the Service Endpoint Interface (SEI). Here I use the bottom-up approach (code first) : that is first create a Java class that will be converted into a web service. The other approach is Top-Down (contract first, based on an existing WSDL file).
package com.company.bmi.services;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService
public interface IBMICalculator {
public double computeBMI(@WebParam(name="weight") double weight, @WebParam(name="height") double height) ;
}



[b]5)[/b] Create the class that implements this interface. It will implement the operations defined by the service :
package com.company.bmi.services;

public class IBMICalculatorImpl implements IBMICalculator{
@Override
public double computeBMI(double weight, double height) {
return weight / (height * height);
}
}

[b]6)[/b] Add the Spring-based configuration file, cxf.xml, under the package directory, for instance :
<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">

<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 id="calcBMI"
implementor="com.company.bmi.services.IBMICalculatorImpl"
address="/cxfBmi"/>
</beans>


[b]7)[/b] You need to update the deployment descriptor file WEB-INF/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>BMI</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:com/company/bmi/services/cxf.xml</param-value>
</context-param>

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>


I specify the path where to find the cxf.xml file and also the CXFServlet.

[b]8)[/b] Finally create a client that uses this web service. This is a standalone Java class that invokes the IBMICalculator web service :
package com.company.bmi.client;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import com.company.bmi.beans.Person;
import com.company.bmi.services.IBMICalculator;

public final class Client {
private Client() {
}

public static void main(String args[]) throws Exception {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

factory.getInInterceptors().add(new LoggingInInterceptor());
factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setServiceClass(IBMICalculator.class);
factory.setAddress("http://localhost:8085/BMI/services/cxfBmi");
IBMICalculator client = (IBMICalculator) factory.create();
Double bmi = client.computeBMI(75, 170);
System.out.println("BMI : " + bmi);
}
}


[b]9)[/b] The available SOAP services are listed at the following URL :
http://localhost:8085/BMI/services/
[img]http://dl.iteye.com/upload/attachment/447506/c00d1091-c354-390f-900a-8094c4ad659c.png[/img]

[b]10)[/b] WSDL :

http://localhost:8085/BMI/services/cxfBmi?wsdl
<wsdl:definitions name="IBMICalculatorImplService" targetNamespace="http://services.bmi.company.com/">
<wsdl:types>
<xs:schema elementFormDefault="unqualified" targetNamespace="http://services.bmi.company.com/" version="1.0">
<xs:element name="computeBMI" type="tns:computeBMI"/>
<xs:element name="computeBMIResponse" type="tns:computeBMIResponse"/>
<xs:complexType name="computeBMI">
<xs:sequence>
<xs:element name="weight" type="xs:double"/>
<xs:element name="height" type="xs:double"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="computeBMIResponse">
<xs:sequence>
<xs:element name="return" type="xs:double"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="computeBMIResponse">
<wsdl:part element="tns:computeBMIResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="computeBMI">
<wsdl:part element="tns:computeBMI" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="IBMICalculator">
<wsdl:operation name="computeBMI">
<wsdl:input message="tns:computeBMI" name="computeBMI">
</wsdl:input>
<wsdl:output message="tns:computeBMIResponse" name="computeBMIResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="IBMICalculatorImplServiceSoapBinding" type="tns:IBMICalculator">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="computeBMI">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="computeBMI">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="computeBMIResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="IBMICalculatorImplService">
<wsdl:port binding="tns:IBMICalculatorImplServiceSoapBinding" name="IBMICalculatorImplPort">
<soap:address location="http://localhost:8085/BMI/services/cxfBmi"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>


There is one operation : computeBMI. The input is computeBMI and the output is computeBMIResponse.

[b]11)[/b] The response, displayed when running the client (java code) :

---------------------------
ID: 1
Address: http://localhost:8085/BMI/services/cxfBmi
Encoding: UTF-8
Content-Type: text/xml
Headers: {SOAPAction=[""], Accept=[*/*]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns1:computeBMI xmlns:ns1="http://services.bmi.company.com/"><weight>75.0</weight><height>170.0</height></ns1:computeBMI></soap:Body></soap:Envelope>
--------------------------------------
30 janv. 2011 17:56:14 org.apache.cxf.interceptor.AbstractLoggingInterceptor log
INFO: Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {content-type=[text language="/xml;charset=UTF-8"][/text][/text], Date=[Sun, 30 Jan 2011 16:56:14 GMT], Content-Length=[241], X-Powered-By=[Servlet/3.0; JBossAS-6], Server=[Apache-Coyote/1.1]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:computeBMIResponse xmlns:ns2="http://services.bmi.company.com/"><return>0.0025951557093425604</return></ns2:computeBMIResponse></soap:Body></soap:Envelope>
--------------------------------------
BMI : 0.0025951557093425604


Another way to test the Web Service is by using soapUI. First create a new SoapUi project (Ctrl+n), give
the project a name and add the WSDL file or URL :

[img]http://dl.iteye.com/upload/attachment/447510/8bc2acc2-5381-3c29-bd50-114f69cbd7e8.png[/img]

Then you need to call the service that you want to test. Double-click the created request “Request 1″ below the computeBMI method. The request editor pops up :

[img]http://dl.iteye.com/upload/attachment/447512/785811d2-66fd-38b9-9d95-b4d8122c8fff.png[/img]

What you need to do next is add values to the parameters of the method. For instance :

<weight>75</weight>



Then submit the request (green arrow on the top left corner) and validate the response :

<return>0.0025951557093425604</return>


[img]http://dl.iteye.com/upload/attachment/447514/fe13748d-f589-3760-aa97-d6567194259f.png[/img]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值