简体   繁体   中英

Getting Cast Exception while testing web service

I'm new to Java Web services, and I'm stuck with this for the past 4 days. Here s the problem , I intend to create web services to be used by other applications.The requirement is that the web service has to return multiple records from a table, so I created a sample web service and here is the code

Interface

@WebService 
@SOAPBinding(style = Style.DOCUMENT)
public interface TestClassInt {

/**
 * @param args
 */

@WebMethod
SampleClass[] getCaseId (String country);
}

A custom class with two string objects

public class SampleClass {
protected String caseid;
protected String dummy;

public SampleClass(){
    super();
}
public SampleClass(String caseid,String dummy){
    this.caseid=caseid;
    this.dummy=dummy;
}
public String getDummy() {
    return dummy;
}

public void setDummy(String dummy) {
    this.dummy = dummy;
}

public String getCaseid() {
    return caseid;
}

public void setCaseid(String caseid) {
    this.caseid = caseid;
}
}

and here s the implementation

@WebService(endpointInterface = "com.org.ccb.test.TestClassInt")
public class TestClassImpl implements TestClassInt {

public SampleClass[] getCaseId(String country) {
    // TODO Auto-generated method stub
    System.out.println("Console " + country);
    SampleClass tempSc[] = new SampleClass[2];
    tempSc[0]=new SampleClass();
    tempSc[1]=new SampleClass();
    tempSc[0].setCaseid(country);
    tempSc[0].setDummy(country);
    tempSc[1].setCaseid(country);
    tempSc[1].setDummy(country);
    return tempSc;
}

}

The WSDL generated using JBoss Developer Studio is

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="TestClassImplService targetNamespace="http://test.ccb.org.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://test.ccb.org.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://test.ccb.org.com/" targetNamespace="http://test.ccb.org.com/" version="1.0">
<xs:element name="getCaseId" type="tns:getCaseId"/>
<xs:element name="getCaseIdResponse" type="tns:getCaseIdResponse"/>
<xs:complexType name="getCaseId">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="getCaseIdResponse">
<xs:sequence>
<xs:element maxOccurs="unbounded" name="sampleClass" type="tns:sampleClass"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="sampleClass">
<xs:sequence>
<xs:element maxOccurs="1" name="caseid" type="xs:string"/>
<xs:element maxOccurs="1" name="dummy" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="getCaseIdResponse">
<wsdl:part name="parameters" element="tns:getCaseIdResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getCaseId">
<wsdl:part name="parameters" element="tns:getCaseId">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="TestClassInt">
<wsdl:operation name="getCaseId">
  <wsdl:input name="getCaseId" message="tns:getCaseId">
</wsdl:input>
  <wsdl:output name="getCaseIdResponse" message="tns:getCaseIdResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="TestClassImplServiceSoapBinding" type="tns:TestClassInt">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getCaseId">
  <soap:operation soapAction="" style="document"/>
  <wsdl:input name="getCaseId">
    <soap:body use="literal"/>
  </wsdl:input>
  <wsdl:output name="getCaseIdResponse">
    <soap:body use="literal"/>
  </wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="TestClassImplService">
<wsdl:port name="TestClassImplPort" binding="tns:TestClassImplServiceSoapBinding">
  <soap:address location="http://localhost:8080/rc_ccb/TestClass"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

When given a SOAP request I'm getting the cast exception [Lcom.org.ccb.test.SampleClass; cannot be cast to com.org.ccb.test.SampleClass

For getting an array of object from a web service, the following is the WSDL definition right?

<xs:complexType name="getCaseIdResponse">  
<xs:sequence>  
<xs:element maxOccurs="unbounded" name="sampleClass" type="tns:sampleClass"/>  
</xs:sequence>  
</xs:complexType>  
<xs:complexType name="sampleClass">  
<xs:sequence>  
<xs:element maxOccurs="1" name="caseid" type="xs:string"/>  
<xs:element maxOccurs="1" name="dummy" type="xs:string"/>  
</xs:sequence>  
</xs:complexType>

Server : JBoss eap 5.1

Any idea?

Stack Trace

14:31:46,743 WARNING [PhaseInterceptorChain] Interceptor for {http://test.ccb.org.com  /}TestClassImplService#{http://test.ccb.org.com/}getCaseId has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: [Lcom.org.ccb.test.SampleClass; cannot be cast to   com.org.ccb.test.SampleClass
at   org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor.handleMessage(WrapperClassOutInterceptor.java:119)
at  org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:243)
at org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:76)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:243)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:109)
at org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestination.java:98)
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:406)
at org.jboss.wsf.stack.cxf.ServletControllerExt.invoke(ServletControllerExt.java:173)
at org.jboss.wsf.stack.cxf.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:61)
at org.jboss.wsf.stack.cxf.CXFServletExt.invoke(CXFServletExt.java:163)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:179)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:103)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:159)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:183)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:95)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:451)
at java.lang.Thread.run(Thread.java:662)
  Caused by: java.lang.ClassCastException: [Lcom.org.ccb.test.SampleClass; cannot be cast to com.org.ccb.test.SampleClass
at   com.org.ccb.test.jaxws.GetCaseIdResponse_WrapperTypeHelper1.createWrapperObject(Unknown Source)
at  org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor.handleMessage(WrapperClassOutInterceptor.java:103)
... 33 more

** A major EDIT ** The Create Web Service wizard generated the esdl file but it did not contain maxOccurs="unbounded" , so i manually added , saved and restarted thought that it would ve changed, but found that wsdl isn't changing and it's retaining the old one, so it should be the problem! Couldn't find why the wsdl file isn't changing!

I think that WSDL file generated by JBoss is wrong and following code

<xs:complexType name="getCaseId">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>

should look like this

<xs:complexType name="getCaseId">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>

Default maxOccurs attribute value is 1 and your array of SimpleClass becomes just a single instance of SingleClass which lead to class cast error (trying to cast array to instance).

I have no experience with JBoss studio but I can propose you to use some collection instead of array - maybe JBoss can handle collections better then arrays. Also you can try JAX-WS.

You need to understand a bit advance concepts.

http://weblogs.java.net/blog/kohsuke/archive/2005/04/xmladapter_in_j.html

http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html

http://docs.oracle.com/javaee/5/tutorial/doc/bnazf.html

How I do this, is to get a class that will represent my table/entity. Then I have a wrapper class for the list_of_entities; which is the return from the web service. So, in total:

  1. Entity class with the required annotations
  2. Wrapper class with the required annotations
  3. Web service with the required annotations

I have provided a sample for each of these below, which MIGHT NOT RUN . They are just to give you an understanding.

//*********************** 1. your Object/Structure/table record you want to return

//since you'll like to send the object across thus it should be serializable
import java.io.Serializable;

//The following two imports are specific to your case. Read about them
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

//The code related to the following classes is just to give you a taster of the JPA side of it
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Entity;


/**
 *  The class that will be the Type of your list, I have used it as an entity too for the JPA Layer
 *
 */
@XmlType(namespace = "myNamespace")

@Entity
@Table(name="MY_TABLE"
    ,schema="MY_DB_SCHEMA"
)

public class SampleClass implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;
protected String caseid;
protected String dummy;
/**
 * @return the dummy
 */
@XmlElement(namespace = "myNamespace")
@Column(name="TYPE", nullable=true, length=225) 
public String getDummy() {
    return dummy;
}
/**
 * @return the caseid
 */
@Id
@Column(name="TYPE", nullable=false, length=225)


@XmlElement(namespace = "myNamespace")

public String getCaseid() {
    return caseid;
}
/**
 * @param caseid the caseid to set
 */
public void setCaseid(String caseid) {
    this.caseid = caseid;
}
/**
 * @param dummy the dummy to set
 */
public void setDummy(String dummy) {
    this.dummy = dummy;
}

}

// * ** * ** * ** * *** 2. The object wrapper class ** * ** * ** * ** * ****

// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.1-b02-fcs 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2009.02.12 at 12:55:08 PM GMT 
//
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

import YOURPACKAGE.SampleClass;

/**
 * Wrapper class for List, makes it possible for JAXB to marshal/unmarshal java.util.List.
 * 
 * @param <T>
 *          Generic List
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "myListType", propOrder = { "listReturn" })
public class ExampleList {

  /**
   * instructing JAXB about the xml element and the name to use in the resulting xml structure.
   */
  @XmlElement(name = "sampleClass")
  protected List<SampleClass> listReturn;

  public ExampleList() {
    listReturn = new ArrayList<SampleClass>();
  }

  /**
   * @param local_list
   *          a generic list
   */
  public ExampleList(final List<SampleClass> local_list) {
    listReturn = local_list;
  }

  public List<SampleClass> getList() {
    return listReturn;
  }

}

// * ** * ** * ** * ** * ** * *

// * ** * ** * *** 3. The web service ** * ** * ** * ** *

import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;



@Stateless(name = "myEJB")
@WebService(serviceName = "myService", targetNamespace = "mynamespace", name = "myServicePT", portName = "myServicePort")
public class ServiceImpl implements ServiceLocal {

  @SuppressWarnings("unused")
  private final Log log = LogFactory.getLog(ServiceImpl.class);

  @PersistenceContext(name = "MyContext")
  private EntityManager em;


  @WebMethod(operationName = "listAll")
  @WebResult(name = "myList", targetNamespace = "mynamespace")
  public ExampleList listAll() throws EastException {
    try {
      Query query = em.createNamedQuery("myQueryToGetMyListFromDB");
      return new ExampleList(query.getResultList());
    }
    catch (Exception e) {
      log.error("Error in retrieving  list", e);

    }
  }



}

// * ** * *** 3.1 web service local interface * ** * ****

import javax.ejb.Local;

@Local
public interface ServiceLocal {
    ExampleList listAll();
}

// * ** * ** * ** * ** * ** * ** * ** * ****

Since its a bottom up service editing the wsdl was futile, hence I generated java skeleton classes from the wsdl (using JBoss Studio) and wrote my business in the implementation class. Now the service is working fine. Anyways I've no idea why maxOccurs="unbounded" wasn't generated automatically when the wsdl was generated from java classes at first. Thanks for the replies guys @gkzmin @mhan @dan

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