Complex Un-Marshalling with Jersey JAX-RS (List of Lists) - java

I'm trying to figure out the best way to unmarshal some data from a public API (meaning I have no control over how it is serialized into XML).
<Show>
<name>Buffy the Vampire Slayer</name>
<totalseasons>7</totalseasons>
<Episodelist>
<Season no="1">
<episode>...</episode>
<episode>...</episode>
<episode>...</episode>
<episode>...</episode>
</Season>
<Season no="2">...</Season>
<Season no="3">...</Season>
</Episodelist>
</Show>
Above is a sample of the XML returned from a ReSTful query. Ideally, I'd like to figure out how to do two things; 1) merge all the season lists into one list of episodes and 2) is it possible to access only child elements and ignore parent elements when unmarshalling XML (ex. Access EpisodeList only, ignoring Show)?
Thank you for any help! This is my first SO post (still fairly new to programming).

I ended up creating some "helper" classes to extract the data I needed. I wrote a getEpisodeList method in EpisodeListHelper which rolls all the episodes up into a single list.
EpisodeListHelper class
#XmlRootElement(name="Show")
#XmlAccessorType(XmlAccessType.FIELD)
public class EpisodeListHelper {
#XmlElementWrapper(name="Episodelist")
#XmlElement(name="Season")
private List<SeasonHelper> seasonList;
...
}
SeasonHelper class
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class SeasonHelper {
#XmlElement(name="episode")
private List<Episode> list;
...
}

Related

JAXB ordering multiple properties

In my project, I would like to achieve specific order of properties in XML. In java object is represented as:
public class Plan {
private List<Act> act;
private List<Leg> leg;
...
An output object should look similar to this one:
<plan>
<act x="-25000" y="0"/>
<leg mode="car">
...
</leg>
<act x="10000" y="0"/>
<leg mode="car">
...
</leg>
</plan>
Is JAXB able to set up specific order for such case where I need to put items in order:
act.get(0)
leg.get(0)
act.get(1)
leg.get(1)
...
..
.
I know JAXB is able to save specific order of parameters like firstly act, then all legs, using #XmlType (propOrder={"prop1","prop2",..."propN"}) but it is not the case of this project as the 3rd party application which reads this xml's read them in pairs and propOrder would print them one by another.
Ok, I approach the problem from a different side and I solved it... Previously I thought it was a sorting problem - in fact, it is a problem with Java POJO class construction and JAXB annotations.
The solution for that is to use
#XmlElements({
#XmlElement(name="leg", type=Leg.class),
#XmlElement(name="act", type=Act.class)
})
#XmlElementWrapper(name="plan")
public List<Plan> getPlan() {
return plan;
}
and then items must be put one by another.
more details can be found in this answer:
Marshalling a List of objects implementing a common interface, with JaxB

JAXB add grouping element to a list, .NET like

I'm working with a xml file that is generated and used in a .NET application.
I need to deserialize this file in Java and chose to use JAXB.
However, after trying to create the matching class I figured out one major difference.
When having a
#XmlRootElement
public class SomeClass{
List<NestedClass> classes;
}
I get the following structure:
<SomeClass>
...
<NestedClasses>
...
</NestedClasses>
<NestedClasses>
...
</NestedClasses>
</SomeClass>
As oppesed to the required existing structure:
<SomeClass>
...
<NestedClasses>
<NestedClass>
...
</NestedClass>
<NestedClass>
...
</NestedClass>
</NestedClasses>
</SomeClass>
Is there is a way to get my required structure without adding a class that will only contain the list of the nested class?
You will need to have a class that wraps the collection. To get the desired mapping, you can use the #XmlElementWrapper annotation to specify that a grouping element should be used. Then you can use the #XmlElement annotation to specify the name of the element that represents the items in the collection:
#XmlRootElement
public class SomeClass{
#XmlElementWrapper
#XmlElement(name="NestedClass")
List<NestedClass> classes;
}
For More Information
http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html

Is it possible to write web-service that returns a collection of generic type? Spring 3

In my db I have a number of entity classes and I run standart CRUD operations on them via Hibernate. Its not a problem to create generic dao class to make all main operations with classes. For example, in dao I have methods which look like this:
<T> List<T> loadAll(Class clazz)
Now I want to expose these methods to web-service client via Spring 3 operated web-service.
The only way I see is to implement web-methods for all entities i.e. write a class that looks like...
class BookResponse { List<BookEntity> books; }
... and return this in corresponding web-method "BookResponse getAllBooks()". This will ruin my attemts to make a code simplier by using dao with generics.
Is there are any other ways?
How can I do this without implementing web-methods for ALL my entities?
If generic web-service is not possible may be there are some other ways to resolve this task in a simple way?
UPDATE:
At the moment I am trying to implement a response class which should look like
public class ServiceResponse<T>{
#XmlElementWrapper( name = "data" )
#XmlElements( #XmlElement(name = "a", type = EntityA.class), #XmlElement(name = "b", type = EntityB.class) )
private List<T> data = new ArrayList<T>( );
//getters,setters
}
So I want to be able to insert a list of any entities mapped with annotations to this response. This produces no erros, but the response given me by web-service is empty.
I think you'll need a new POJO "GenericEntity" which can hold the information of any domain entity class instance.
It would hold a type string and an arbitrary/generic list of named attributes.
It can then be used to represent any of your real domain entities
e.g.
type = Book
attributes = (title=Order of the Phoenix, author=J K Rowling)
e.g.
type = Car
attributes = (make=Renault, model=Clio)
These examples show String attributes so you'll have to sort out if this is good enough or if you need strong typing - it's possible but harder.
You can then expose your "GenericEntity" via web services, allowing clients to make calls in and specify which domain entity they wish to search for, and even allow them to specify search criteria too.
Adds and deletes could be done in a similar way.
HTH,
David

How to make Jersey/Jackson serialize empty list; single element list as an array

Using Jersey and Jackson to create a REST interface, how do I get List fields to be serialized as a list when there are 0 or 1 elements in them. For example:
#XmlRootElement(name="foo")
public class Foo {
#XmlElement
public List<Bar> getBars() {
return this.bars;
}
}
#Path("foo")
public FooResource {
#GET
public Foo getFoo() {
return theFoo;
}
}
When bars has no elements, the result serializes as null and when it contains a single element, it serializes as that element, not an array containing a single element. Is there a way to get these to always serialize as an array?
For reference, I'm using Jersey 1.10 and Jackson 1.9.2.
I am pretty sure that you are not actually using Jackson ("POJO" variant of JSON serialization), since Jackson would not convert single-element arrays or lists to anything else. So you are probably using one of legacy output methods (like jettison); meaning that if you configure system to use POJO mapping it should just work.
I wrote a blog post ages ago about forcing Jersey to serialize single element arrays correctly, not sure if it's out-dated now (its from mid-2010!), but it might be of use.
Note the blog comment from Brill Pappin on the blog demonstrating a different approach which means upgrading the Jettison library that you are using.
In short you can write a custom JaxbContextResolver that looks a little like:
#Provider
#Component
public class JAXBContextResolver implements ContextResolver {
private JAXBContext context;
public JAXBContextResolver() throws Exception {
MappedBuilder builder = JSONConfiguration.mapped();
builder.arrays("invite");
builder.rootUnwrapping(true);
this.context = new JSONJAXBContext(builder.build(), Payload.class);
}
public JAXBContext getContext(Class objectType) {
return (Payload.class.equals(objectType)) ? context : null;
}
}
For clarity, my payload class looked a little like
#XmlRootElement(name = "response")
#XmlAccessorType(XmlAccessType.FIELD)
public class Payload {
#XmlElement(name = "invite")
List invites;
... etc.
Regarding stopping Jackson serializing bean properties as null, see my previous answer here, about using annotations to change that behaviour.
I managed to solve JSON array "bug" in recent Jersey json library (v1.14 Sep 2012). Secret ingredient is JSONConfiguration and ContextResolver magic. See my following post it has a full code example, customized ContextResolver and rest Application class might be somewhat fuzzy logic in first look.
How to serialize Java primitives using Jersey REST
Primitives and zero or single-element List array are properly serialized to JSON document.
Yes, we also faced the same issue. Jackson cannot serialize list with 0 or single element to json array. So we tried to use Json's ObjectMapper to convert POJO object to String. It will serialize java List to json array irrespective of number of elements in List (0 or 1 or > 0). The code would look like :
request = new ObjectMapper().writeValueAsString(pojo);
where request is of type Object. This will not affect response. You can give a try.

Handling nested elements in JAXB

I am wondering if it is possible to have JAXB not to create Java object for XML elements that serve as wrappers. For example, for XML of the following structure
<root>
<wrapper>
<entity/>
</wrapper>
</root>
I do not want an object for <wrapper> to be created at all. So for a class like
class Root {
private Entity entity;
}
the <entity> element should be unmarshalled directly into the entity field.
Is it possible to achieve with JAXB?
Although it requires extra coding, the desired unmarshalling is accomplished in the following way using a transient wrapper object:
#XmlRootElement(name = "root")
public class Root {
private Entity entity;
static class Entity {
}
static class EntityWrapper {
#XmlElement(name = "entity")
private Entity entity;
public Entity getEntity() {
return entity;
}
}
#XmlElement(name = "wrapper")
private void setEntity(EntityWrapper entityWrapper) {
entity = entityWrapper.getEntity();
}
}
EclipseLink MOXy offers a JAXB 2.2 implementation with extensions. One of the extended capabilities is to use XPath to navigate through layers of the XML you don't want in you domain model.
If you look at:
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/MOXyExtensions
you will notice that the Customer's name is stored within but that the name is a String attribute of Customer. This is accomplished using:
#XmlPath("personal-info/name/text()")
public String getName() {
return name;
}
I hope this helps,
Doug
Worth mentioning, if the content is a list of <entity/> instead of a single instance:
<root>
<wrapper>
<entity/>
<entity/>
...
</wrapper>
</root>
then you can use the #XmlElementWrapper annotation:
#XmlRootElement(name = "root")
public class Root {
#XmlElementWrapper(name = "wrapper")
#XmlElement(name = "entity")
private List<Entity> entity;
static class Entity { }
}
The whole point of JAXB or other mapping systems is to map the elements and their hierarchy to classes. In your example, you seem to want JAXB to somehow know that it can marshal entity into wrapper/entity and vice-versa without actually creating the class used for the wrapper mapping and the connection between root and entity. Which, as presented, is roughly equivalent to asking how to connect a car engine to the wheels without a driveshaft.
So, unless I am missing the point, the answer is no - neither JAXB or any other mapping program can do this. You can avoid creating classes by using something that does mapping purely dynamically (see Groovy, GPath for an example), but that avoids creating all classes, not just skipping one intermediate level in a hierarchy.

Categories

Resources