Design pattern to use to populate multiple class fields - java

I have a use case where I have to parse an XML document and fill details in a corresponding fields of an internal model POJO Details.
Let's say, the XML look like following -
<?xml version="1.0" encoding="UTF-8"?>
...
<TagA>
<Child1>
...
</Child1>
<Child2>
...
</Child2>
</TagA>
...
<TagB>
<Child1>
...
</Child1>
<Child2>
...
</Child2>
</TagB>
....
And the internal model POJO looks like following -
public class Details {
...
Set<TagAInfo> tagAInformation;
Set<TagBInfo> tagBInformation;
...
}
The XML has multiple fields like TagAs, TagBs etc.
Current implementation: So currently there is a mapper/parser class(let's say Mapper.java) that calls multiple methods like mapTagAInfo(details, xmlRootElement), mapTagBInfo(details, xmlRootElement) etc. on details(i.e. instance of Details.java) something like following -
public class Mapper {
....
public Details mapInfo(XmlElement xmlRootElement) {
Details details = new Details();
mapTagAInfo(details, xmlRootElement)
mapTagBInfo(details, xmlRootElement)
mapTagCInfo(details, xmlRootElement)
....
return details;
}
private void mapTagAInfo(details, xmlRootElement) {
stp1: Extract <TagA> tag element info using a utility which reads the xml document
stp2: use the stp1 info and convert to internal model POJO TagAInfo and
add to details (details.addTagAInfo(tagAInfo))
}
Question: The current implementation makes the code look very ugly(as in a single class Mapper.java multiple things are happening), so wanted to know if I can use some design pattern to improve the code ? If so, please suggest what design pattern to use and an example explaining the design pattern usage would help a lot.
Update: The project uses Dom4j to read XML. Also, the question was more around handling the responsibilities of the mapper class. As one can see, it has lot of functions like mapTagAInfo, mapTagBInfo etc. Wanted to know if I should delegate the responsibilities to different classes - eg. TagAInfoEnricher, TagBInfoEnricher etc. If yes, then how to do it, what design pattern to use etc. ?

Try Unmarshalling with JAXB.
Examples:
https://howtodoinjava.com/jaxb/jaxb-unmarshaller-example/
https://howtodoinjava.com/jaxb/read-xml-to-java-object/

I usually like using the builder pattern, Lombok #Builder annotation, to create my objects.
#Builder
#Getter
class Details implements Serializable {
Set<TagAInfo> tagAInformation;
Set<TagBInfo> tagBInformation;
public static void mapTagAInfo(details, xmlRootElement) {
...
}
}
The other design pattern I like to use is creating Static method inside the class to construct my objects especially DTOs
Don't know if this helps

Related

Alternative Entity-Conversion with XStream

We are using XStream to serialize and deserialize entities. If the entities are persisted, they have an ID and the serialized form of the object is the ID only which could look like:
<Person>4</Person>
"Deserialization" is simply the read operation from the database.
This works pretty good implementing a SingleValueConverter which uses a DAO to load the entity:
public class TestSerializer implements SingleValueConverter {
public Object fromString(String str) {
return dao.readById(str);
}
public String toString(Object obj) {
return ((Entity) obj).getId();
}
}
But in some cases the entities which have to be serialized are not persisted. So they do not have an ID and I have to do a "real" serialization. Since XStream knows how to serialize many objects on it's own and I do not care about the structure of the XML outcome, it would be fine if i could get something like this:
<Person>
<name>Jon Doe</name>
</Person>
So is it possible in a custom Converter-implementation to do this serialization and deserialization?
In a converter you are free to do conversion in any way you like. So basically you can decide in your custom converter how you want to (de-)serialize the object. However, AFAIK you cannot switch between single-value-conversion/normal conversion. But your example XML implies this.
If you just want to delegate to another converter like XStream's ReflectionConverter, you could do this with the convertAnother(Object, Converter)-method (see also this question/answer). For this, you have to implement the Converter interface instead of SingleValueConverter, to get access to the (un-)marshalling context.
Does this answer your question?
hth,
- martin
Underscore-java can read and write xml files. I am the maintainer of the project.

XML produce by RESTful webservice

I have a RESTful web services , up and running and it produces XML output upon a call by the client.
So I have a class to represent the data and I have annotated with #XMLRootElemnt and so it produces the data accordingly as XML. My question is - what is the best way to represent the XML , when there is an inner class in the class that I have annotated with #XMLRootElement? Pardon me if the question is not clear, and if you ask me more detail, I can explain. But if someone already got what I am asking, please advise.
I think that you want to explain that you want to produce an XML like this:
<programmer>
<name>Marcelo Tataje</name>
<pl>Java</pl>
<id>1</id>
</programmer>
And you have used something like this to produce it:
#XmlRootElement
public class Programmer
{
private String name;
private String pl;
private int id;
public Programmer()
{
}
//here your getters and setters
}
And your web services looks like this:
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("/getProgrammer")
public Programmer getProgrammer()
{
Programmer p = new Programmer();
p.setName("Marcelo Tataje");
p.setPl("Java");
p.setId(1);
return p;
}
Ant then you invoke your client and so on... I think that's the simpliest way to do it and it's not bad, if you want the best way or a better method it is by using Spring3 which supports Rest and XML, you will have a structure for your requirements in a flash, is a faster framework. Recommended, well I'm answering to you of what I understand to your question.
http://blog.springsource.com/2009/03/08/rest-in-spring-3-mvc/
Got it worked. basically need to use the #XmlElementWrapper and #XmlElement and the field property will be a list of string.

Patterns: Populate instance from Parameters and export it to XML

I'm building a simple RESTFul Service; and for achieve that I need two tasks:
Get an instance of my resource (i.e Book) from request parameters, so I can get that instance to be persisted
Build an XML document from that instance to send the representation to the clients
Right now, I'm doing both things in my POJO class:
public class Book implements Serializable {
private Long id;
public Book(Form form) {
//Initializing attributes
id = Long.parseLong(form.getFirstValue(Book.CODE_ELEMENT));
}
public Element toXml(Document document) {
// Getting an XML Representation of the Book
Element bookElement = document.createElement(BOOK_ELEMENT);
}
I've remembered an OO principle that said that behavior should be where the data is, but now my POJO depends from Request and XML API's and that doesn't feels right (also, that class has persistence anotations)
Is there any standard approach/pattern to solve that issue?
EDIT:
The libraries i'm using are Restlets and Objectify.
I agree with you when you say that the behavior should be where the data is. But at the same time, as you say I just don't feel confortable polluting a POJO interface with specific methods used for serialization means (which can grow considerably depending on the way you want to do it - JSON, XML, etc.).
1) Build an XML document from that instance to send the representation to the clients
In order to decouple the object from serialization logic, I would adopt the Strategy Pattern:
interface BookSerializerStrategy {
String serialize(Book book);
}
public class XmlBookSerializerStrategy implements BookSerializerStrategy {
public String serialize(Book book) {
// Do something to serialize your book.
}
}
public class JsonBookSerializerStrategy implements BookSerializerStrategy {
public String serialize(Book book) {
// Do something to serialize your book.
}
}
You POJO interface would become:
public class Book implements Serializable {
private Long id;
private BookSerializerStrategy serializer
public String serialize() {
return serializer.serialize(this);
}
public void setSerializer(BookSerializerStrategy serializer) {
this.serializer = serializer;
}
}
Using this approach you will be able to isolate the serialization logic in just one place and wouldn't pollute your POJO with that. Additionally, returning a String I won't need to couple you POJO with classes Document and Element.
2) Get an instance of my resource (i.e Book) from request parameters, so I can get that instance to be persisted
To find a pattern to handle the deserialization is more complex in my opinion. I really don't see a better way than to create a Factory with static methods in order to remove this logic from your POJO.
Another approach to answer your two questions would be something like JAXB uses: two different objects, an Unmarshaller in charge of deserialization and a Marshaller for serialization. Since Java 1.6, JAXB comes by default with JDK.
Finally, those are just suggestions. I've become really interested in your question actually and curious about other possible solutions.
Are you using Spring, or any other framework, in your project? If you used Spring, it would take care of serialization for you, as well as assigning request params to method params (parsing as needed).

Adding behaviour to JAXB generated class

I have to add little bussiness logic in my jaxb generated classes. For example, I have following XMLs:
<vehicle>
<car id="20" make="ABC"/>
</vehicle>
<vehicle>
<motorcycle id="05" make="XYZ"/>
<vehicle>
<vehicle>
<truck id="34" make="UVW"/>
</vehicle>
And I generate XSD for these.
Now what I have to achieve is during unmarshalling of any XML of these type (that is whenever setters of car, motorcycle or truck is envoked, it should also set the vehicle type which I don't want to add as an attribute in the XML).
Or after unmarshalling (any way by which I can know the QName of sub element).
I have tried How can I extend Java code generated by JAXP-cxf or Hibernate tools?, but the overriden setters were never called.
JAXB has a "post construct" facility (see javadoc). Just add something like this to your annotated class:
void afterUnmarshal(Unmarshaller, Object parent) {
vehicle.setType(..); // your logic here
}
You can create a JAXB extension. But that sounds like an overhead to me - you could simple invoke an initializer whenever you unmarshal a JAXB object. Something like:
public class Initializer {
public static void initialize(Vehicle vehicle) {
vehicle.setType(..); // your logic here
}
}
And call Initializer.initialize(unmarshalledObject)

How to easily load a XML-based Config File into a Java Class?

I've got a simple java class that looks something like this:
public class Skin implements Serializable {
public String scoreFontName = "TahomaBold";
...
public int scoreFontHeight = 20;
...
public int blockSize = 16;
...
public int[] nextBlockX = {205, 205, 205, 205};
...
public String backgroundFile = "back.bmp";
...
}
I'd like to read this information from a simple XML file that looks something like this:
<xml>
<skin>
<scoreFontName>"Tahoma Bold"</scoreFontName>
...
<scoreFontHeight>20</scoreFontHeight>
...
<blockSize>16</blockSize>
...
<nextBlockX>
<0>205</0>
<1>205</1>
<2>205</2>
<3>205</3>
<nextBlockX>
....
<backgroundFile>"back.bmp"</backgroundFile>
...
<skin>
</xml>
Is there an easy way to inject the information from the xml file directly into the variable names rather than having to parse it manually? I don't mind using an external library.
Any help is appreciated.
XStream is really great library for just this.
http://x-stream.github.io/
You can set up aliases for your class and even custom data formats to make the XML file more readable.
Alternatives to the already mentioned solutions (XStream and Apache Commons Digester) would be Java's own JAXB for a comparable general approach, or solutions more tailored towards configuration like Apache Commons Configuration or Java's Preferences API.
I would actually recommend Apache Digester, since if your classes are beans, it will just handle reading the XML into them.
You can also use Spring - although it may be a bit of overkill for one class if its for a mobile game!
I've recently started using Simple http://simple.sourceforge.net/ for XML to object mapping. It uses annotations within the class similarly to method I use in C# and is nice and clean.
You can also break up the file into multiple classes and loading saving is a simple one liner.
In your case the Class structure would look like.
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
#Root (Name="skin")
public class Skin {
#Element(name="scoreFontName") // name param not needed if class field is the same as the xml (element) value
private String scoreFontName
#Element
private int scoreFontHeight
#Element
private int blockSize
#ElementArray
private int[] nextBlockX
#Element
private String backgroundFile
// getters
} 
Note one difference is that your array will be saved like this
<nextBlockX>
<int>205</int>
<int>205</int>
<int>205</int>
<int>205</int>
<nextBlockX>
But you you have the option of adding (entry="myName") to the annotation in which came the XML will be saved down like this
<nextBlockX>
<myName>205</myName>
<myName>205</myName>
<myName>205</myName>
<myName>205</myName>
<nextBlockX>
But the end result is the same once it's loaded into the array.
Use JAXB. It is included in the JDK starting with Java 1.6.

Categories