1

I have restful webservice with spring which has following mapping:

<?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>

Contacts 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;
    }
}

Contact 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;
    }
}

When I process GET with xml format from curl, I am receiving following output:

<?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 dependencies (same for web and client app):

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

Then when I am trying to get java objects (in client application) via org.springframework.web.client.RestTemplate I have following exception:

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

I belive that something wrong is with my mapping file. As You can see I have triple contacts tag even in mapping file I have other names.. Do anyone know what can be a reason of having this exception/wrong xml format?

Software Engineer
  • 15,457
  • 7
  • 74
  • 102
Gazeciarz
  • 516
  • 1
  • 8
  • 22
  • You have a number of problems here, but the specific one you're talking about may well be caused by the rest controller not having a dependency on your entity model. The error is telling you, explicitly, that it can't find the class definition for Contacts -- it has the mapping file, which is why it's trying to bind to contacts, but it can't find Contacts.class on the classpath. – Software Engineer Nov 11 '15 at 21:47
  • Problem is that I have this class in client application. The same package as in WebService. What I am thinking that the xml output should be: ... As You can see I have triple which is not clear for me - even I have this mapping file.. – Gazeciarz Nov 11 '15 at 21:51
  • Then bind the outer contacts to a ContactsHolder, or something similar, or preprocess the xml using a filter of some sort before passing it to the unmarshaller. Adding the extra binding is easiest I think. Also, there may be a typo in your binding, in the collction's bind-xml tag -- shouldn't that be 'contacts' plural? – Software Engineer Nov 11 '15 at 21:55
  • I changed the outer class to ContactsHolder. I checked bind-xml tag and for me it is ok. Both files are same so It can't be a typo. Whole project is sample from ProSpring4 book but it is not working with unmarshaller.. I am thinking if this is not problem with Castor.. Anyway, after those changes xml looks like: 10Chris.....anotherDataFromContact... I am still confused that there is contacts instead of contact... Maybe this is a problem? – Gazeciarz Nov 12 '15 at 17:25
  • What is happening is that when unmarshaller is looking for class he's looking for alias "Contacts" as in XML. What he has in cache is "contacts" mapping.. It seems like marshaller is doing something wrong.. Instead of Contacts main tag should be contacts. – Gazeciarz Nov 12 '15 at 19:30

1 Answers1

0

What is happening is that when unmarshaller is looking for class he's looking for alias "Contacts" as in XML. What he has in cache is "contacts" mapping and its not the same as "Contacts". Problem was that marshaller library was not the same as unmarshaller. Probably something wrong in configuration.. What I did is change of implementation to jaxb I put @XMLRootElement and @XMLElement on model classes and completely removed configuration of messageConverters in mvc:annotation-driven (also mapping xml files). On client application I changed messageConverter to:

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

And everything works fine.

Gazeciarz
  • 516
  • 1
  • 8
  • 22