JAXBException:类java.util.ArrayList或其任何超类都是此上下文已知的

时间:2014-06-26 06:12:08

标签: spring

我是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>
    
  2. 我使用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(多个记录)的List并使用spring integration marshaller Jaxb2Marshaller,我希望这会将java对象编组为soap响应,并且应该在SOAPUI中为MyUserResponse显示此列表名单。但我在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:类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)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     at 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对象文件中的相应更改,但是在尝试获取多个记录响应时面临问题,我再次收到正确的响应(一条记录)。

    请帮助我找到我在做错误或遗失的地方。

4 个答案:

答案 0 :(得分:3)

从我得到的链接中引用:

  

发生上述异常是因为JAXB总是期望实体上有@XmlRootElement注释,它会被编组。这是强制性的,不能跳过。需要此@XmlRootElement注释才能从XML对象编组的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注释。

答案 1 :(得分:1)

这对我有用:

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

答案 2 :(得分:1)

我遇到了同样的问题,你可以检查这样的代码行:
jaxbMarshaller.marshal(obj,sw);
- 确保obj不是收藏品 - obj是反映XML root的父类 希望这有帮助!

答案 3 :(得分:0)

我有类似的问题,我使用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
            });