【问题标题】:JAXBException: class java.util.ArrayList nor any of its super class is known to this contextJAXBException:此上下文已知类 java.util.ArrayList 或其任何超类
【发布时间】:2014-08-16 21:26:25
【问题描述】:

我是 Spring 集成的新手,并且正在为我的项目需求工作。我面临以下问题将 Pojo(java 对象)编组到 SOAP 响应(使用 Spring 集成 ws):请查找以下详细信息:

  1. 我有如下示例 xsd 文件:

      </xsd:element>
        <xsd:element name="MyUserResponses">
        <xsd:complexType>
          <xsd:sequence>
             <xsd:element minOccurs="0" maxOccurs="unbounded" name="MyUserResponse"
           type="tns:MyUserResponse" />
          </xsd:sequence>
        </xsd:complexType>
        </xsd:element>
    
      <xsd:complexType name="MyUserResponse">
       <xsd:sequence>
            <xsd:element minOccurs="0" maxOccurs="1" name="SomeNumber" type="xsd:string"/>
            <xsd:element minOccurs="0" maxOccurs="1" name="ReferenceID" type="xsd:string" />
        </xsd:sequence>
      </xsd:complexType>
    </xsd:schema>
    

我使用 xjc 编译器创建了以下 java 目标文件:

package com.myuser.echannel;

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


/**
 * <p>Java class for anonymous complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="SomeNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         &lt;element name="ReferenceID" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "someNumber",
    "referenceID"
})
@XmlRootElement(name = "MyUserRequest")
public class MyUserRequest {

    @XmlElement(name = "SomeNumber")
    protected String someNumber;
    @XmlElement(name = "ReferenceID")
    protected String referenceID;

    /**
     * Gets the value of the someNumber property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getSomeNumber() {
        return someNumber;
    }

    /**
     * Sets the value of the someNumber property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setSomeNumber(String value) {
        this.someNumber = value;
    }

    /**
     * Gets the value of the referenceID property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getReferenceID() {
        return referenceID;
    }

    /**
     * Sets the value of the referenceID property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setReferenceID(String value) {
        this.referenceID = value;
    }

}

另一个 Java 对象:

package com.myuser.echannel;

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


/**
 * <p>Java class for MyUserResponse complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="MyUserResponse">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="SomeNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *         &lt;element name="ReferenceID" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MyUserResponse", propOrder = {
    "someNumber",
    "referenceID"
})
public class MyUserResponse {

    @XmlElement(name = "SomeNumber")
    protected String someNumber;
    @XmlElement(name = "ReferenceID")
    protected String referenceID;

    /**
     * Gets the value of the someNumber property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getSomeNumber() {
        return someNumber;
    }

    /**
     * Sets the value of the someNumber property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setSomeNumber(String value) {
        this.someNumber = value;
    }

    /**
     * Gets the value of the referenceID property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getReferenceID() {
        return referenceID;
    }

    /**
     * Sets the value of the referenceID property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setReferenceID(String value) {
        this.referenceID = value;
    }

}

MyUserResponses.java 文件如下:

package com.myuser.echannel;

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.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


/**
 * <p>Java class for anonymous complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="MyUserResponse" type="{http://tempuri.org/}MyUserResponse" maxOccurs="unbounded" minOccurs="0"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "myUserResponse"
})
@XmlRootElement(name = "MyUserResponses")
public class MyUserResponses {

    @XmlElement(name = "MyUserResponse")
    protected List<MyUserResponse> myUserResponse;

    /**
     * Gets the value of the myUserResponse property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the myUserResponse property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getMyUserResponse().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link MyUserResponse }
     * 
     * 
     */
    public List<MyUserResponse> getMyUserResponse() {
        if (myUserResponse == null) {
            myUserResponse = new ArrayList<MyUserResponse>();
        }
        return this.myUserResponse;
    }

}

对象工厂:

package com.myuser.echannel;

import javax.xml.bind.annotation.XmlRegistry;


/**
 * This object contains factory methods for each 
 * Java content interface and Java element interface 
 * generated in the com.myuser.echannel package. 
 * <p>An ObjectFactory allows you to programatically 
 * construct new instances of the Java representation 
 * for XML content. The Java representation of XML 
 * content can consist of schema derived interfaces 
 * and classes representing the binding of schema 
 * type definitions, element declarations and model 
 * groups.  Factory methods for each of these are 
 * provided in this class.
 * 
 */
@XmlRegistry
public class ObjectFactory {


    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.myuser.echannel
     * 
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link MyUserResponses }
     * 
     */
    public MyUserResponses createMyUserResponses() {
        return new MyUserResponses();
    }

    /**
     * Create an instance of {@link MyUserResponse }
     * 
     */
    public MyUserResponse createMyUserResponse() {
        return new MyUserResponse();
    }

    /**
     * Create an instance of {@link MyUserRequest }
     * 
     */
    public MyUserRequest createMyUserRequest() {
        return new MyUserRequest();
    }

}

package-info.java 文件:

@javax.xml.bind.annotation.XmlSchema(namespace = "http://tempuri.org/", elementFormDefault =     javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.myuser.echannel;

我正在处理带有请求正文的 SOAP 请求,如下所示到我的 spring 集成层(即下面的 web.xml 和 spring 上下文文件):

web.xml:

<servlet>
        <servlet-name>spring-ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF/spring-ws-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring-ws</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

spring-ws-config.xml 文件:

<context:component-scan base-package="com.nbad.eChannel"/>

    <import resource="classpath:/WEB-INF/inbound-gateway-config.xml"/>

    <!-- Ensures that all incoming requests will be routed to the ws:inbound-gateway -->
    <!-- <bean class="org.springframework.ws.server.endpoint.mapping.UriEndpointMapping">
        <property name="defaultEndpoint" ref="ws-inbound-gateway"/>
    </bean> -->

    <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
     <property name="mappings">            
     <props>                

     <prop key="{http://tempuri.org/}MyUserRequest">ws-myuser-gateway</prop>    
     </props>  
     </property>
    </bean>

</beans>

<context:component-scan base-package="com.mypackage"/>

<import resource="classpath:/com/mypackage/si/jdbc/config/spring-integration-context.xml"/>

    <int:channel id="FFUserRequestChannel"/>


    <int-ws:inbound-gateway id="ws-ffuser-gateway" request-channel="FFUserRequestChannel" marshaller="marshaller" unmarshaller="marshaller"/>

    <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    <property name="contextPath" value="com.mypackage.model" />
    </bean>

    <int:service-activator input-channel="MyUserRequestChannel">
    <bean class="com.mypackage.serviceImpl.MyUserImpl">
    <constructor-arg ref = "MyUserRequest"></constructor-arg>
    </bean>
    </int:service-activator> 

    <bean id="MyUserRequest" class="com.mypackage.model.MyUserRequest"></bean>
    <bean id="MyUserResponse" class="com.mypackage.model.MyUserResponse"></bean>

</beans>

如上所述,我使用 Jaxb2Marshaller 进行编组和解组。现在 serviceImpl 文件如下:

package com.mypackage.serviceImpl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;

import com.mypackage.model.*;
import com.mypackage.service.MyUser;
import com.mypackage.si.jdbc.service.MyUserJdbc;
/**
 * @author Vinay Agrawal
 */
public class MyUserImpl implements MyUser{

    @Autowired
    MyUserRequest request;
    @Autowired
    MyUserJdbc MyUserJdbc;
    public MyUserImpl() {
    }

    public MyUserImpl(MyUserRequest request) {
        super();
        this.request = request;
    }

    @Override
    @PayloadRoot(localPart = "issueResponseFor" , namespace = "http://tempuri.org/")
    @ResponsePayload
    public List<MyUserResponse>issueResponseFor(@RequestPayload MyUserRequest request) {
        List<MyUserResponse> MyUserResponse = new ArrayList<MyUserResponse>();

        MyUserResponse = (List<MyUserResponse>)MyUserJdbc.getMyUserResponse(request);

        return MyUserResponse;
        }
}

在这里,我正在调用 DB 层并从 DB 获取 MyUserResponse(多条记录)的列表,并使用 spring 集成编组器 Jaxb2Marshaller,我希望这会将 java 对象编组为soap响应,并且应该在 MyUserResponse 的 SOAPUI 中显示此列表列表。但我在 SOAP UI 和 Junit 上收到以下错误:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <SOAP-ENV:Fault>
         <faultcode>SOAP-ENV:Server</faultcode>
         <faultstring xml:lang="en">Unknown JAXB exception; nested exception is javax.xml.bind.JAXBException: class java.util.ArrayList nor any of its super class is known to this context.</faultstring>
      </SOAP-ENV:Fault>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

从 Junit 生成的错误:

org.springframework.ws.soap.client.SoapFaultClientException:未知的 JAXB 异常;嵌套异常是 javax.xml.bind.JAXBException: class java.util.ArrayList 或其任何超类在此上下文中都不知道。 在 org.springframework.ws.soap.client.core.SoapFaultMessageResolver.resolveFault(SoapFaultMessageResolver.java:37) 在 org.springframework.ws.client.core.WebServiceTemplate.handleFault(WebServiceTemplate.java:776) 在 org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:602) 在 org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:539) 在 org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:494) 在 org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:438) 在 org.springframework.ws.client.core.WebServiceTemplate.sendSourceAndReceiveToResult(WebServiceTemplate.java:423) 在 com.nbad.eChannel.Common.InContainerTests.testWebServiceRequestAndResponse(InContainerTests.java:44) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:606) 在 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在 org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:309) 在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 在 org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

我的 SOAP 请求如下:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sch="http://tempuri.org/"> 
<soapenv:Header/>
<soapenv:Body>

     <sch:MyUserRequest>
        <sch:SomeNumber>8009618916</sch:SomeNumber>
        <sch:ReferenceID>ReferenceIDReferenceID</sch:ReferenceID>
     </sch:MyUserRequest>

</soapenv:Body>
</soapenv:Envelope>

如果我在 xsd 文件中进行更改以获取单个记录并在创建的 java 对象文件中进行相应更改,但在尝试获取多个记录响应时遇到问题,我再次收到正确的响应(一条记录)。

请帮我找出我在哪里做错或遗漏了什么。

【问题讨论】:

    标签: spring


    【解决方案1】:

    只是引用我得到的链接:

    发生上述异常是因为 JAXB 总是期望实体上有一个 @XmlRootElement 注释,它会被封送。这是强制性的,不能跳过。这个@XmlRootElement 注释是从Java 对象编组的XML 根元素中获取元数据所必需的。 ArrayList 类或任何 java 集合类上都没有任何 JAXB 注释。由于这个 JAXB 无法解析任何此类 java 对象并引发此错误。

    [Solved]: javax.xml.bind.JAXBException: class java.util.ArrayList nor any of its super class is known to this context

    您的MyUserResponse 似乎没有@XMLRootElement 注释。

    【讨论】:

    • 谢谢。但是我也很早就尝试了这个选项,今天又尝试了一次,但没有帮助。我仍然遇到同样的异常。 :(
    • 请有任何建议。我仍然面临这个问题。
    • 你是如何生成你的 POJO 的,你能重新生成它们吗?
    • 我使用 JAXB2Marshaller xjc 编译器生成了 POJO 文件,但是当我从服务层发送项目列表时出现异常“JAXBException: class java.util.ArrayList 及其任何超类都不知道这个上下文。” .我生成了 2-3 次 pojo,但没有帮助。如果我将 xsd 文件更改为仅接收一条记录并使用 xjc 编译器相应地生成 Pojo,然后从我的服务层仅发送一条记录,那么 Jaxb2marshaller 工作正常,我收到结果但在多条记录时抛出异常。
    【解决方案2】:

    我也遇到了同样的问题,你可以这样检查代码行:
    jaxbMarshaller.marshal(obj, sw);
    - 确保 obj 不是集合
    - obj 是反映 XML 根的父类。
    希望对您有所帮助!

    【讨论】:

      【解决方案3】:

      这对我有用:

      javax.xml.bind.JAXBException: Class *** nor any of its super class is known to this context

      只需将XmlSeeAlso 注释添加到您的响应类:

      @XmlAccessorType(XmlAccessType.FIELD)
      @XmlType(name = "", propOrder = {"myUserResponse"})
      @XmlRootElement(name = "MyUserResponses")
      @XmlSeeAlso(ArrayList.class)
      public class MyUserResponses {
      
          @XmlElement(name = "MyUserResponse")
          protected List<MyUserResponse> myUserResponse;
          ...
      

      【讨论】:

      • 实施此解决方案给了我这个异常 - “无法将类型“java.util.ArrayList”编组为元素,因为它缺少 @XmlRootElement 注释”
      • 当您在 web 方法中返回一个事物列表时,这似乎会发生。尝试返回一个包含事物列表的对象。
      【解决方案4】:

      我遇到了类似的问题,我使用 CXF 生成了存根。我遇到了类似的错误,在分析中我发现我正在创建的列表有一些 null 值导致了它。我用空字符串替换了空值。我的代码如下使用 Java 8。如果我启用注释的代码行,我会得到 java.util.ArrayList 或其任何超类都不知道此上下文 异常。

      希望这会对某人有所帮助。

          model.keySet().forEach( val ->{
                      TestRequest.Param param = new Param();
                      param.setKey(val);
                      param.setValue(model.get(val) != null ?model.get(val).toString():""); //works fine   
                          //below line has caused the issue
                          //param.setValue(model.get(val));
                      request.getParam().add(param);// this is the list on my request
                  });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-27
        • 1970-01-01
        • 1970-01-01
        • 2011-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-01
        相关资源
        最近更新 更多