Java CXF宁静的Web服务

时间:2011-11-29 06:58:46

标签: java web-services rest cxf

我的webservice类如下:

package com.siemens.rest;
import java.io.ByteArrayInputStream;
import java.math.BigDecimal;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.BindingType;
import javax.xml.ws.Provider;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;
import javax.xml.ws.http.HTTPException;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

@WebServiceProvider
@BindingType(value = HTTPBinding.HTTP_BINDING)
public class ConverterService implements Provider<Source> {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    @Resource
    protected WebServiceContext wsContext;

    private BigDecimal rupeeRate = new BigDecimal("40.58");
    private BigDecimal euroRate = new BigDecimal("0.018368");

    public Source invoke(Source source) {
        try {
            String amount = null;

            if (source == null) {
                System.out.println("Getting input from query string");
                MessageContext mc = wsContext.getMessageContext();
                String query = (String) mc.get(MessageContext.QUERY_STRING);
                System.out.println("Query String = " + query);
                ServletRequest req = (ServletRequest) mc
                        .get(MessageContext.SERVLET_REQUEST);
                amount = req.getParameter("amount");
            } else {
                System.out.println("Getting input from input message");
                Node n = null;
                if (source instanceof DOMSource) {
                    n = ((DOMSource) source).getNode();
                } else if (source instanceof StreamSource) {
                    StreamSource streamSource = (StreamSource) source;
                    DocumentBuilderFactory dbf = DocumentBuilderFactory
                            .newInstance();
                    DocumentBuilder db = dbf.newDocumentBuilder();
                    InputSource inputSource = null;
                    if (streamSource.getInputStream() != null) {
                        inputSource = new InputSource(
                                streamSource.getInputStream());
                    } else if (streamSource.getReader() != null) {
                        inputSource = new InputSource(streamSource.getReader());
                    }
                    n = db.parse(inputSource);
                } else {
                    throw new RuntimeException("Unsupported source: " + source);
                }
                NodeList children = n.getChildNodes();
                for (int i = 0; i < children.getLength(); i++) {
                    Node child = children.item(i);
                    if (child.getNodeName().equals("dollars")) {
                        amount = child.getAttributes().getNamedItem("amount")
                                .getNodeValue();
                        break;
                    }
                }
            }
            BigDecimal dollars = new BigDecimal(amount);
            BigDecimal rupees = dollarToRupees(dollars);
            BigDecimal euros = rupeesToEuro(rupees);
            return createResultSource(rupees, euros);
        } catch (Exception e) {
            e.printStackTrace();
            throw new HTTPException(500);
        }
    }

    public BigDecimal dollarToRupees(BigDecimal dollars) {
        BigDecimal result = dollars.multiply(rupeeRate);
        return result.setScale(2, BigDecimal.ROUND_UP);
    }

    public BigDecimal rupeesToEuro(BigDecimal rupees) {
        BigDecimal result = rupees.multiply(euroRate);
        return result.setScale(2, BigDecimal.ROUND_UP);
    }

    private Source createResultSource(BigDecimal rupees, BigDecimal euros) {
        String body = "<ns:return xmlns:ns=\"http://rest.jaxws.samples.geronimo.apache.org\">"
                + "<ns:dollarToRupeesResponse>"
                + rupees
                + "</ns:dollarToRupeesResponse><ns:rupeesToEurosResponse>"
                + euros + "</ns:rupeesToEurosResponse></ns:return>";
        Source source = new StreamSource(new ByteArrayInputStream(
                body.getBytes()));
        return source;
    }
}

和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_2_5.xsd"
  id="WebApp_ID" version="2.5">
  <display-name>jaxws-rest-converter</display-name>
  <servlet>
    <servlet-name>ConverterService</servlet-name>
    <servlet-class> com.siemens.rest.ConverterService </servlet-class>
    <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>ConverterService</servlet-name>
    <url-pattern>/converter</url-pattern>
  </servlet-mapping>
</web-app>

在tomcat 6.0中部署它时,我得到以下异常:

  

严重:Servlet / jaxws-rest-converter引发了load()异常   java.lang.ClassCastException:com.siemens.rest.ConverterService不能   被转换为javax.servlet.Servlet at   org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1116)     在   org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993)     在   org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4420)     在   org.apache.catalina.core.StandardContext.start(StandardContext.java:4733)     在   org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)     在org.apache.catalina.core.StandardHost.start(StandardHost.java:840)     在   org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)     在   org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)     在   org.apache.catalina.core.StandardService.start(StandardService.java:525)     在   org.apache.catalina.core.StandardServer.start(StandardServer.java:754)     在org.apache.catalina.startup.Catalina.start(Catalina.java:595)at   sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(未知来源)at   sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)at   java.lang.reflect.Method.invoke(未知来源)at   org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)at at   org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)

我认为web.xml是错误的,任何人都可以帮助我。我试图在CXF中实现restful webservices。

1 个答案:

答案 0 :(得分:0)

我认为您的实施中存在一些问题。

首先,你的web.xml确实是错误的。此文件用于声明servlet,过滤器等,但从不声明webservices提供程序。您收到ClassCastException,因为您告诉您ConverterService是一个servlet。

因此,您需要做的是在web.xml中声明Apache CXF servlet,让他回答一些请求。检查此示例:

   <!-- 
       Web service Front Controller. It will receive all the web service request and then it 
       delegates the request to the web services configured in the CXF config file
    -->
    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- 
       Every request that start with this will be handled by the CXF servlet 
    -->
    <servlet-mapping>
      <servlet-name>CXFServlet</servlet-name>
      <url-pattern>/ctx/authbasic/ws/*</url-pattern>
    </servlet-mapping>

在此之后,您需要正确声明每个Web服务。我使用Spring来配置我的Apache CXF服务,所以在这里你可以查看一个例子。

    <jaxws:endpoint id="dataService"
        implementor="some.package.DataSIB"
        address="/DataService" wsdlLocation="classpath:wsdls/DataService.wsdl">
        <jaxws:properties>
            <!-- jaxws properties binding config -->
        </jaxws:properties>
        <jaxws:dataBinding>
          <!-- data binding config -->
        </jaxws:dataBinding>
    </jaxws:endpoint>

使用此配置,您对/ctx/authbasic/ws/DataService的任何请求都将由Web服务实现处理。这里是Web服务声明(SEI)及其实现(SIB)的示例:

@WebService(name = "dataService", targetNamespace = "http://some-domain/dataservice/definition")
@SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL, parameterStyle = ParameterStyle.WRAPPED)
public interface DataSEI {
    // You methods here
}

@WebService(endpointInterface = "some.package.DataSEI",
serviceName = "dataServiceService",
portName = "dataServicePort",
targetNamespace = "http://some-domain/dataservice/definition")
public class DataSIB implements DataSEI {
   // Your methods here
}

注意:这是SOAP Web服务的示例,但这可能有助于您理解框架