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>
一切正常。
我有 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>
一切正常。