简体   繁体   中英

Java CXF restful webservices

My webservice class is as following:

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;
    }
}

and the web.xml as follows:

<?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>

While deploying it in tomcat 6.0, iam getting the following exception:

SEVERE: Servlet /jaxws-rest-converter threw load() exception java.lang.ClassCastException: com.siemens.rest.ConverterService cannot be cast to javax.servlet.Servlet at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1116) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4420) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4733) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053) at org.apache.catalina.core.StandardHost.start(StandardHost.java:840) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053) at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463) at org.apache.catalina.core.StandardService.start(StandardService.java:525) at org.apache.catalina.core.StandardServer.start(StandardServer.java:754) at org.apache.catalina.startup.Catalina.start(Catalina.java:595) at sun.ref lect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)

I think the web.xml is wrong, can anyone pls help me in this. Iam trying to implement restful webservices in CXF .

I think that you have several things wrong in your implementation.

First of all your web.xml is indeed wrong. This file is meant to declare servlets, filters, etc, but never webservices providers. You are getting the ClassCastException because you are telling that your ConverterService is a servlet.

So, what you need to do is to declare the Apache CXF servlet in you web.xml to let him anwser some request. Check this example:

   <!-- 
       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>

After this, you need to declare correctly each one of your webservices. I use Spring to config my Apache CXF services, so here you can check an example.

    <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>

With this configuration, you any request to /ctx/authbasic/ws/DataService will be handled by the web services implementation. Here the example of a web service declaration (SEI) and its implementation (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
}

NOTE: This is an example of a SOAP web services, but this might help you to understand the framework

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM