spring Web 服务中根元素解组的 SAXException

SAXException on root element unmarshalling in spring web service

我有 restful 网络服务 spring 具有以下映射:

<?xml version="1.0"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Object Mapping DTD Version 1.0//EN"
                         "http://Castor.exolab.org/mapping.dtd">


<mapping>
    <class name="com.example.web.Contacts">
        <field name="contacts" type="com.example.web.model.Contact"
            collection="arraylist">
            <bind-xml name="contact" />
        </field>
    </class>
    <class name="com.example.web.model.Contact" identity="id">
        <map-to xml="contact" />
        <field name="id" type="long">
            <bind-xml name="id" node="element" />
        </field>
        <field name="firstName" type="string">
            <bind-xml name="firstName" node="element" />
        </field>
        <field name="lastName" type="string">
            <bind-xml name="lastName" node="element" />
        </field>
        <field name="birthDate" type="string" handler="dateHandler">
            <bind-xml name="birthDate" node="element" />
        </field>
        <field name="version" type="integer">
            <bind-xml name="version" node="element" />
        </field>
    </class>
    <field-handler name="dateHandler"
        class="com.example.web.DateTimeFieldHandler">
        <param name="date-format" value="yyyy-MM-dd" />
    </field-handler>
</mapping>

联系人class:

public class Contacts implements Serializable {
    private List<Contact> contacts;

    public Contacts() {
    }

    public Contacts(List<Contact> contacts) {
        this.contacts = contacts;
    }

    public List<Contact> getContacts() {
        return contacts;
    }

    public void setContacts(List<Contact> contacts) {
        this.contacts = contacts;
    }
}

联系人class:

@Entity
@Table(name = "contact")
public class Contact implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Long id;
    private int version;
    private String firstName;
    private String lastName;
    private DateTime birthDate;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    public Long getId() {
        return id;
    }

    @Version
    @Column(name = "VERSION")
    public int getVersion() {
        return version;
    }

    @Column(name = "FIRST_NAME")
    public String getFirstName() {
        return firstName;
    }

    @Column(name = "LAST_NAME")
    public String getLastName() {
        return lastName;
    }

    @Column(name = "BIRTH_DATE")
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    public DateTime getBirthDate() {
        return birthDate;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public void setVersion(int version) {
        this.version = version;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public void setBirthDate(DateTime birthDate) {
        this.birthDate = birthDate;
    }

    @Override
    public String toString() {
        return "Contact - Id: " + id + ", First name: " + firstName + ", Last name: " + lastName + ", Birthday: "
                + birthDate;
    }
}

当我从 curl 以 xml 格式处理 GET 时,我收到以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<Contacts>
   <contacts>
      <contacts>
         <id>1</id>
         <version>0</version>
         <firstName>Chris</firstName>
         <lastName>Schaefer</lastName>
         <birthDate>
            <dayOfMonth>3</dayOfMonth>
            <dayOfWeek>7</dayOfWeek>
            <era>1</era>
            <year>1981</year>
            <dayOfYear>123</dayOfYear>
            <millisOfDay>3600000</millisOfDay>
            <monthOfYear>5</monthOfYear>
            <hourOfDay>1</hourOfDay>
            <minuteOfHour>0</minuteOfHour>
            <weekyear>1981</weekyear>
            <yearOfEra>1981</yearOfEra>
            <yearOfCentury>81</yearOfCentury>
            <centuryOfEra>19</centuryOfEra>
            <secondOfDay>3600</secondOfDay>
            <minuteOfDay>60</minuteOfDay>
            <secondOfMinute>0</secondOfMinute>
            <millisOfSecond>0</millisOfSecond>
            <weekOfWeekyear>18</weekOfWeekyear>
            <millis>357696000000</millis>
            <zone>
               <uncachedZone>
                  <fixed>false</fixed>
                  <cachable>true</cachable>
                  <id>Europe/Belgrade</id>
               </uncachedZone>
               <fixed>false</fixed>
               <id>Europe/Belgrade</id>
            </zone>
            <chronology>
               <zone>
                  <uncachedZone>
                     <fixed>false</fixed>
                     <cachable>true</cachable>
                     <id>Europe/Belgrade</id>
                  </uncachedZone>
                  <fixed>false</fixed>
                  <id>Europe/Belgrade</id>
               </zone>
            </chronology>
            <afterNow>false</afterNow>
            <beforeNow>true</beforeNow>
            <equalNow>false</equalNow>
         </birthDate>
      </contacts>
   ...

   </contacts>
</Contacts>

Maven 依赖项(Web 和客户端应用程序相同):

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.9.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.3.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>1.0.0.Final</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.190</version>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.8.1</version>
        </dependency>
        <dependency>
            <groupId> org.jadira.usertype </groupId>
            <artifactId>usertype.core</artifactId>
            <version> 3.0.0.CR3 </version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>4.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>4.0.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>4.0.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-lgpl</artifactId>
            <version>1.8.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.6.3</version>
        </dependency>

        <dependency>
            <groupId>org.codehaus.castor</groupId>
            <artifactId>castor-xml</artifactId>
            <version>1.3.3</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.castor</groupId>
            <artifactId>castor-core</artifactId>
            <version>1.3.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
            <version>2.6.3</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.3.10.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>1.0.0.Final</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.190</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-servlet-api</artifactId>
            <version>7.0.30</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>jstl-api</artifactId>
            <version>1.2</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>jstl-impl</artifactId>
            <version>1.2</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

然后,当我尝试通过 org.springframework.web.client.RestTemplate 获取 java 对象(在客户端应用程序中)时,出现以下异常:

Exception in thread "main" 
org.springframework.http.converter.HttpMessageNotReadableException: 
Could not read [class com.example.web.Contacts]; nested exception is 
org.springframework.oxm.UnmarshallingFailureException: SAX reader 
exception; nested exception is org.xml.sax.SAXException: The class for 
the root element 'Contacts' could not be found. at 
org.springframework.http.converter.xml.MarshallingHttpMessageConverter.re
adFromSource(MarshallingHttpMessageConverter.java:134)
    ...

我认为我的映射文件有问题。如您所见,即使在映射文件中我也有三重联系人标签我有其他名字..有谁知道使用这种 exception/wrong xml 格式的原因是什么?

发生的事情是,当 unmarshaller 正在寻找 class 时,他正在寻找 "Contacts" 中的别名 XML。他在缓存中的是 "contacts" 映射,它与 "Contacts" 不同。问题是 marshaller 库与 unmarshaller 不同。应该是配置有问题吧。。 我所做的是将实现更改为 jaxb,我将 @XMLRootElement 和 @XMLElement 放在模型 classes 上,并完全删除了 mvc:annotation-driven 中 messageConverters 的配置(也映射 xml 个文件)。在客户端应用程序上,我将 messageConverter 更改为:

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
        <property name="messageConverters">
            <list>
                <bean
                    class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                    <property name="marshaller" ref="jaxb2Marshaller" />
                    <property name="unmarshaller" ref="jaxb2Marshaller" />

                </bean>
            </list>
        </property>
    </bean>
    <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="classesToBeBound">
            <list>
                <value>com.example.web.model.Contact</value>
                <value>com.example.web.Contacts</value>
            </list>
        </property>
    </bean>

一切正常。