JAXB unmarshalling - missing referenced objects

N

news

Hi

I've come upon a problem which I just can't figure out.

So, here's a little about the context. An enterprise-application is
running on a Java EE-server. Some POJOs are annotated as Java
Persistence entities aswell as JAXB-annotations to create wanted XML-
representation for them. All annotations are added manually (meaning
no auto-generated classes/factory). A Servlet acts as an interface
against an Ajax-enabled webpage. The script in the web-page retrieves
xml-representation from the servlet and should also send xml back on
the same form for persisting on the server. The script returns the xml
in string-representation.

And here's the problem. Marshalling to xml works just as it should.
The script returns an xml in the exact same form, but the
unmarshalling of it does not produce what is expected. An object for
the main class is created, however any referenced objects are not
created. Primitive fields are generated correctly. No error is thrown.

Simplified, this is how it looks:

---List.java---

@XmlRootElement(name="list")
@XmlType(name="ListType")
@Enitity //JPA
public class List implements Serializable {

private Long id;
private weekNumber;
private Set<Element> elements;

@XmlAttribute(name="weeknumber", required=true)
public void getWeekNumber() {
//...
}

@XmlAttribute(name="id", required=true)
public void getId() {
//...
}

@XmlElementWrapper(name="elements", nillable=false)
@XmlElementRef
@ManyToMany( //JPA
//...
)
public void getElements() {
//...
}
}

---Element.java---

@XmlRootElement(name="element")
@XmlType(name="ElementType")
public class Element implements Serializable {

//...
private Long id;

@XmlAttribute(name="id", required=true)
public void getId() {
//...
}

//...

}

---xml---

<?xml .....>
<ns2:list ..... weeknumber="3" id="21">
<elements>
<ns2:element ... id="42">
...
</ns2:element>
<ns2:element ... id="43">
...
</ns2:element>
...
</elements>
</ns2:list>

In this example, a List-object would be created by the unmarshaller,
however the referenced elements of class Element will not. And I have
no idea why! The package contains a jaxb.index with all class names,
and I also added an ObjectFactory, but the result was the same. Here's
the unmarshalling:

private <T> T recieve(Class<T> classType, String xml) {

JAXBElement<T> obj = null;

try {

JAXBContext jc =
JAXBContext.newInstance(classType.getPackage().getName());

Unmarshaller um = jc.createUnmarshaller();

obj = (JAXBElement<T>)um.unmarshal(new StreamSource(new
StringReader(xml)));

} catch(JAXBException jex) {
jex.printStackTrace();
}

return obj.getValue();
}

I hope someone has something wise to say about this. I've really
twisted my brain to try to figure it out!

Thanks.
 
N

news

*snip*

Appearently I missed something not checking out the XmlJavaTypeAdapter-
annotation. In the Javadocs on the XmlAdapter-class I found this
sentence: "Some Java types do not map naturally to a XML
representation, for example HashMap or other non JavaBean classes". If
this could be the reasons for my problem, why did marshalling work
just fine? Am I on the right track here? :)
 
N

news

*snip*

Appearently I missed something not checking out the XmlJavaTypeAdapter-
annotation. In the Javadocs on the XmlAdapter-class I found this
sentence: "Some Java types do not map naturally to a XML
representation, for example HashMap or other non JavaBean classes". If
this could be the reasons for my problem, why did marshalling work
just fine? Am I on the right track here? :)

Yep, this did the trick! Collections of type Set, among other things,
doesn't work off the bat with JAXB. An adapter has to be made and it
is annotated with XmlJavaTypeAdapter.

//Removed: @XmlElementWrapper(name="elements", nillable=false)
@XmlElementRef
@XmlJavaTypeAdapter(value=ElementXmlAdapter.class)
@ManyToMany( //JPA
//...
)
public void getElements() {
//...
}

---ElementXmlAdapter---

public class ElementXmlAdapter extends
javax.xml.bind.annotation.adapters.XmlAdapter<ElementXmlContainer,Set<Element>>{

@Override
public Set<Element> unmarshal(ElementXmlContainer list) throws
Exception {
return new HashSet<Element>(list.getElements());
}

@Override
public ElementXmlContainer marshal(Set<Element> set) throws
Exception {
return new ElementXmlContainer(new ArrayList<Element>(set));
}

}

---ElementXmlContainer---

@XmlRootElement(name="elements")
public class ElementXmlContainer {

private List<Element> elements;

public ElementXmlContainer() {
}

public ElementXmlContainer(List<Element> elements) {
this.elements = elements;
}

@XmlElementRef
public List<Element> getElements() {
return elements;
}

public void setElements(List<Element> elements) {
this.elements = elements;
}

}

I have several Sets around in my classes so I thought I'd try to make
generic classes for the two above. This didn't work, though, and I
believe it has to do with the fact that with Generics the type is set
at run-time, meaning there's no way of saying
ElementXmlAdapter<Element>.class and ElementXmlAdapter.class != new
ElementXmlAdapter<Element>().class. As far as I can see anyway,
correct me if I'm wrong. If anyone has a solution to this, I'd really
appriciate it! :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top