Decoupling XML parser from classes - java

I'm writing an Android application and I want to provide the ability for the end user to create collections of objects from a class hierarchy with XML. For example: I'd like the user to be able to provide something like this arbitrary example:
<animals>
<dogs>
<bulldog name="Frank" />
<mastif name="George" />
</dogs>
<cats>
<mainecoon name="Alex" age="3" />
</cats>
</animals>
I'd like to validate this user-provided XML against a schema I create, and then create instances of these classes based on the XML. The question I have is that if I add a subclass.. say reptile, I have to change the implementation for the XML parser as well as the schema to validate the XML. This seems like bad practice because a change in the class hierarchy mandates a change in other places. Is there anyway to minimize the impact of adding a type to my Android app with regard to the XML the user can provide and the Schema that validates it?

I found a solution. Using annotations and a framework like JAXB or Simple will let you serialize/deserialize objects to/from xml. JAXB can be run on Android which could be a solution. link
But JAXB is pretty heavy weight so I'm favoring Simple because it is more lightweight.

Related

Generate POJO from .yaml

I'm looking for a solution which automatically generates POJO classfiles from a given .yaml-Files but have not found anything like this yet.
I can not imagine that it should be the only way to write these classes yourself.
The problem is that YAML describes objects, not classes. In general, you cannot automatically derive a POJO structure from a given YAML file. Take, for example, this YAML:
one: foo
two: bar
In YAML, this is a mapping with scalar keys and values. However, there are multiple possibilities to map it to Java. Here are two:
HashMap<String, String>
class Root {
String one;
String bar;
}
To know which one is the right mapping, you would need a schema definition like those for XML. Sadly, YAML currently does not provide a standard way of defining a schema. Therefore, you define the schema by writing the class hierarchy your YAML should be deserialised into.
So, in contrary to what you may think, writing the POJOs is not a superfluous action that could be automated, but instead is a vital step for including YAML in your application.
Note: In the case that you actually want to use YAML to define some data layout and then generate Java source code from it, that is of course possible. However, you'd need to be much more precise in your description to get help on that.
As pointed out in the comments by Jack Flamp, you can use an online tool (jsonschema2pojo) to convert a sample yaml file to its equivalent POJO classes. This tool can convert json or yaml data to corresponding POJO classes and I have used it successfully in the past.
That being said, the tool is forced to make certain "assumptions" when you are using a yaml file(instead of yaml schema). So, it would be a good idea to look at the generated classes carefully before you start using them.
You can find more information about how to use this online tool from its wiki page.
The Accepted Answer is incomplete.
You can try to use https://editor.swagger.io/
After importing yaml file You can generate Java REST Client project through menu with correspondent POJO classes.

Importing XML to Java - What advantages are there to use JAXB over custom-reading the file?

I easily found JAXB for importing XML into Java code, however, after looking at it a bit more, I started wondering if it were more than I really needed.
It should be rather simple XML that I or other users would create.
For example:
<Type>Armor Material</Type> //could be various types of parent objects
<Name>Steel</Name> //object properties
<Toughness>10</Toughness>
<Type>Armor Material</Type>
<Name>Iron</Name>
<Toughness>7</Toughness>
For the background on my problem: I have a game written in Java, and aim to have many Objects of certain types defined in the XML. I'm hoping to keep the XML as simple as possible for easy user-modding.
I know how to read from a file for creating my own custom solution - but I have never dealt with marshalling/unmarshalling and JAXB in general. I won't lie - something about it intimidates me, maybe because it seems like this "black box" which I don't quite understand.
Are there clear advantages to argue for learning how to get it work, as opposed to implementing a solution I already know I can get to work?
You definitely want to use JAXB.
Whether your XML is simple or complex, write an XML schema (xsd) file. You want the schema file anyway, so you can validate the files you are reading. Use xjc (part of JAXB) to generate Java classes for all the element of your XML schema (complete with setters/getters). Then, it is a one-liner to read or write an XML file.
Because the XML file is mapped to/from Java objects, it is very easy to manipulate these data structures (to create or consume them) in Java.
JAXB is a plugin architecture and there are quite a few open source plugins that you can utilize to enhance the generated classes. By default, JAXB generates all your setters/getters automatically, but there are plugins that will generate equals/hashcode, fluent-style methods, clone, etc. There is even a plugin (hyperjaxb3) that will put JPA annotations on the generated classes, so you can go XML->Java->database->Java->XML all based on the XML schema.
I have worked on projects that used JAXB to generate POJOs even though we didn't need XML - it was quicker to write and easier to maintain the XML schema than all the Java code for the POJOs.
If you're using Java 8, perhaps a dynamic style would be a good fit
XmlDynamic xml = new XmlDynamic(
"<items>" +
"<item>" +
"<type>Armor Material</type>" +
"<name>Steel</name>" +
"<toughness>10</toughness>" +
"</item>" +
"<item>" +
"<type>Armor Material</type>" +
"<name>Iron</name>" +
"<toughness>7</toughness>" +
"</item>" +
"</items>"
);
xml.get("items|item|name").asString(); // "Steel"
xml.get("items|item[1]|toughness").convert().intoInteger(); // 7
see https://github.com/alexheretic/dynamics#xml-dynamics

How to create custom common JSON message format for Java JAX-RS services?

I am creating a web application in Java and I want to completely divide the frontend from the server part. Therefore everything is going to be implemented via services, particularly JSON Rest services. I want to have a common message format, something like this (for convenience I write it as XML, but am going to use JSON - should be a matter of configuration anyway):
<response>
<time>...</time>
<status>
<code></code>
<message></message>
</status>
<data>
...my entities resulting from the operations...
</data>
</response>
My question is how to implement and use this custom format in my methods universally? That means, that in case of everything ran fine, I just want to write something like response.setData(data) and return the object. Otherwise the error handler would take care. Thanks for help.
Take a look at the JAX-RS spec or Jersey User Guide especially section devoted to JSON (JAXB based JSON support).
The simplest way of doing this is to use JAXB to create the tooled version of the structure (with something like Jackson as the serialization engine) and then to create a factory method somewhere that will make the structure for you without you having to specify anything extra yourself.

Is there a way of handling multiple xsd versions with xmlBeans?

I know that I can compile multiple xsd files in a single jar. I've tried using different namespaces which only takes me half way through my goal. This way I can parse the correct schema but I want this to be transparent to my users which will receive the xmlBeans object that I've parsed.
They don't have to know which version of xml file is currently present on the system. I would need a super class for every xsd version to achieve this.
Could this be done with xmlBeans?
My understanding is, if you have a com namespace and a com.v1 and com.v2 namespace and you have an xsd element called EmployeeV1 in com.v1 and EmployeeV2 in com.v2.
You want to a super class called Employee in the com namespace which you want to return to your caller?
Do you think EmployeeV1 and EmployeeV2 could extend from Employee in your xsd? Then maybe when you generate you will get the class hierarchy that represents your xsd.
If that doesn't work, (i haven't used xmlbeans in years now), you might have to create your own domain object and make your callers consume that. That might be worth the effort, since to me it looks like you handle the parsing of an XML that other people rely on, you could abstract all other users from the structure of the XML (which is in flux) by having an intermediary domain object.

Play Model Objects from External API

I'm new in Play 2 Framework v. 2.1.1 with Java and I'm looking for the best way to do the following without duplicating code.
To simplify, I have a Play 2 backoffice that uses an external API. I don't manage this API, but I call REST Services to perform operations over the api.
This API's objects are exactly the same as Play 2 Model Objects. But I don't want to duplicate the api objects to add Play validations and other annotations.
Is there any way to add this type of behavior using configuration files? I'm thinking about something like Hibernate hbm's for example.
For example:
Object in the unmanaged api: (I omit getters and setters for simplicity)
public class Entity{
public String field1;
public String field2;
}
Object that I want to avoid: (I omit getters and setters for simplicity)
public class Entity1{
#Required
#NonEmpty
#MinLength(3)
public String field1;
#Required
#NonEmpty
public String field2;
}
Config example: (I need something like this)
<class name="Entity1">
<property name="field1" >
<required/>
<nonEmpty/>
<minLength value="3"/>
</property>
<property name="field2" >
<required/>
<nonEmpty/>
</property>
</class>
Using annotations seems better than using xmls or any other configuration file, so I don't necessarily want to use configuration files, I'm open to any suggestions to solve this problem.
Thanks
I can't see how duplicating the API model in a non typesafe descriptor like XML is better than using a typesafe language. Moreover, I would not want to couple my model and application to a model from the API under my control.
I think it is far better to duplicate the model in Java/Scala and use a simple bean copier like dozer to move between the two.
One problem is ebean as the persistence provider - in ebean there is no way to externalize the bean persistence configuration as it is possible in hibernate (except for sql queries). Is a switch of the persistence provider possible? Play seems to allow that.
Since you wrote that you are unable to modify the entities source code and you don't want to copy the source, the only other possibility I see is bytecode enhancement.
What you need is a library that would allow you to externalize annotations in a xml file. This library would use the instrumentation api, read the xml file at jvm statup and modify the bytecode of each listed class in order to add annotations to the class and fields at runtime.
There are two problems with this approach:
There is no such library (at least I couldn't find it)
Play and EBean use their own agent / classloader in order to allow hot deployment and persistence
The first problem is the easy and fun part, see for example https://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html. With javaassist it is easy to add annotations to classes and fields. The mapping from xml to annotations is straight foreward. And it would be a nice open source project.
The second problem looks much harder, because you must install your annotation agent so that it executes before play and ebean start to parse the annotations.
It is not clear to me why can't add annotations in your own app, but if you have such constraints why don't you just extend the class, override the variables, add the annotations, and use that as an EBean model?
Play has dynamic forms, which let you validate against a map of key,value pairs. If validation is what you want you could copy an entity's data to a map and validate that.
Simple answer: There is not always code duplication also if the code lines are the same.
Robert C. Martin shows this in one of his talks: the single responsible principle. There are two ways to break this principle: On the one hand two responsibilities in one code fragment on the other hand one responsibility handled independently bei two code fragments.
Code duplication is a matter responsibility and semantics not of code lines that are the same (which may be at most an indicator for having code duplication).
In your case the responsibilities are clearly separated: You have an external API and your code. So there is no code duplication.

Categories

Resources