Get existing object by reading out of XML using Java (JAXB) - java

I have some problems describing my problem.
I have an XML-File with names of existing classes in my project.
E.g.:
<?xml version="1.0" encoding="UTF-8"?>
<MetaClasses>
<MetaClass ID="1">
<Meta>ExistingClassName</Meta>
</MetaClass>
<MetaClass ID="2">
...
</MetaClass>
</MetaClasses>
And i need the corresponding existing class, because i need to work with this class.
I don't want to create a new object, like MetaClass meta = new MetaClass();, i want the real class with its real attributes, properties and methods, since the XML ClassName is just simple text.
I need the properties of that class to proceed my project.
I hope you were able to get my problem correctly or rather i explained it correctly :P
Thank you

I did it by myself.
Maybe someone has the same problem and I could help you with my answer.
I had to take the String inside the <Meta>-Tag and did this:
Class classMeta = Class.forName(string);
Bean beanMeta = (Bean) classMeta.newInstance();
Then I was able to work with this Meta-Class.

Related

Changing single parameters in XML file wrapped as Java Object

I am getting a config.xml file via a REST API which has a specific structure. I am adapting this config.xml via Java and pushing it again via PUT command to the REST endpoint to update it.
This XML structure contains the same amount of properties (let's say 'name' and 'description') but might be enhanced by some more properties (e.g. 'category'), which I am not aware of.
<config>
<name>myName</name>
<description>myDescription<description>
<category>myCategory<category>
</config>
My goal is to adapt this config file via Java Code while wrapping it into an Object. So I built a Class 'Config' containing 'String name' and 'String description'.
I can easily parse the config.xml to my Config object with JAXB and adapt name and description, but when marshalling it to XML the category would be missing, although it was returned by the REST API. Is there a way (maybe ValueChangeListener?) to adapt only the changed values in an existing xml file?
public class Config { String name; String description; }
So I don't event want to be able to change 'category' at all, I just don't want to lose the data.
Info: In my scenario the Config class is very complex and has alot of subclasses (it's a representing a Jenkins Job). So the example above is very simplified.
I got the idea to create a second config file, only having the changed parameters. Afterwards merging the to config files. But I had no idea how to be aware what exactly has changed and how to implement it.
Example:
I want to change description to "newDescription", so my expected XML would be:
<config>
<name>myName</name>
<description>newDescription<description>
<category>myCategory<category>
</config>
unfortuntately it is:
<config>
<name>myName</name>
<description>newDescription<description>
</config>
Means category parameter is lost, as I am not aware of it and therefore didnt add it to the Config class. Summarized, there might be parameters in the XML file which I am not aware, which I also do not want to change - but don't want to lose when pushing an updated config.

JAXB XML Unmarshalling creates xml classes's fields as well

I have an xml and and at that XML I have too many child fields such like . From the documentation that I read, I see that JAXB auto generated xml to pojo classes but there is a remark there , JAXB can create fields as well ? I meant do i have to create Employee class and its methods such like String job, String id myself or JAXB will create it themselves ? If my question is not clear, I can provide sample codes.
Cheers
Alper
<code>
<Employee>
<id>121</id>
<name>Alper</name>
</Employee>
</code>
Do I have to create String id; String name; as well ?
You have 2 options:
To create necessary Java classes (e.g. Employee) manually
To use XML schema to generate classes
But XML sample itself is not enough surely.
More information here:
https://docs.oracle.com/javase/tutorial/jaxb/intro/examples.html
you can generate POJO or java class from JAXB in eclipse, command line or maven.
you can file below several tutorials to learn this:
create POJO Class from XSD in Eclipse here
create POJO class from XSD using command line here
create POJO Class from XSD using XJC Maven Plugin here

xstream: only parsing child element

I have following xml
<root>
<child-1>
</child-1>
<child-2>
<subchild-21>
</subchild-22>
</child-2>
</root>
My requirement is such that I only want to parse child-2. I am unaware of root and child-1.
Is it possible with xstream because I couldn't find a way to ignore root.
There are several ways to go, depending on your requirements.
If you know the name of the class to parse (child-2 here), you could look for the <child-2> and </child-2> entry in the XML, copy them along with the content in-between to a new temporary XML file (you can create temporary files using createTempFile() from the standard File class). This is the way I would suggest.
If you want to take out the child-2 instance without knowing its name, but you know the names of the surrounding classes, you could mock their classes, that is create classes of the same name, but without their specific content. In your example there is no content (might have been ignored at export time), but it's important to have the same member data in the mock classes for the import to succeed. (unless you use ignoreUnknownElements() as stated by Philipi Willemann)
Of course, if you're the one creating the XML, you should be able to export only the child-2 instance in the first place.
If you know the root name you can create a simple class has an attribute of the class you have mapped to child-2:
#XStreamAlias("root")
class Root {
#XStreamAlias("child-2")
private Child2 child;
//get and set
}
Then when you are processing the XML you can set XStream to ignore unknown elements with xstream.ignoreUnknownElements();

Add Freemarker support to customized JSP tag

I have a customized JSP tag library with a Java class (extending TagSupport) that generates the output for my web application. It has some parameters that are formed into HTML code using a StringBuilder.
Now the generated HTML is becoming more complex and hard to handle with calls of StringBuilder.append, so I'd like to replace the code generation with a Freemarker template.
I already found out that I could use a generic Struts component tag instead, because the Struts tags already use Freemarker template files, so I could write a tag like:
<s:component template="/components/myStruct.ftl">
<s:param name="myParam" value="%{'myParam'}" />
</s:component>
Then writing the specified template file myStruct.ftl would probably solve my problem. I actually did not try if Struts really finds and uses that file correctly, but I optimistically expect it to work.
My question is, if it's also possible to retain the current code with the customized tag
<my:struct param="myParam" />
and only change the Java class linked to that tag.
I've found code that reads a Freemarker template:
Configuration config = FreemarkerManager.getInstance().getConfiguration(pageContext.getServletContext());
config.setServletContextForTemplateLoading(pageContext.getServletContext(), "/components");
Template templ = config.getTemplate("myStruct.ftl");
templ.process(params, pageContext.getOut());
but it seems very circuitously to me and I wondered what would be the "standard" way to do it. Additionally it seemed that you cannot use tags from the Struts tag library in a template used like this. (I ran into an ArrayIndexOutOfBoundException, caused by Sitemesh... I did not analyze it yet.)
My intention was to keep the Java class as some kind of wrapper around the Struts component tag. Maybe somthing like:
OgnlValueStack stack = TagUtils.getStack(pageContext);
Component c = new Component(stack);
c.addParameter("param", param);
But I don't know how to continue this code stub. It may be crap anyway.
Is there an easy/"standard" way to do this or do I simply have to get rid of the customized tag?
Thanks in advance.
A friend of mine sent me this link:
http://cppoon.wordpress.com/2013/02/27/how-to-create-a-struts-2-component-with-freemarker/
This is what I was looking for. The gist is to change the customized tag to not extend TagSupportbut AbstractUITag which makes it a Struts tag instead of a JSP tag, roughly speaking.
This enables the automatic linkage (by name and path conventions) to my Freemarker template. I basically followed the instructions on that page. I only added the methods that are abstract in the super class, so they had to be implemented.
IMO the site lacks of a description of how the UI bean class is linked to the tag class. But as the IDE forces you to implement the getBean method inside the tag class, you quickly get to this code (using the classes described on that site):
#Override
public Component getBean(OgnlValueStack stack, HttpServletRequest request, HttpServletResponse response)
{
Pagination pagination = new Pagination(stack, request, response);
pagination.setList(list);
return pagination;
}
This might not be completely correct for the recent Struts, but it worked for the ancient version I've got to use.
Thanks again to the guy who sent me the link :)

JAXB Factory for JPA entities

In most of my previous projects I have two domain models, one with JAXB annotations and the other one with JPA annotations. I know they can combined into one model with both annotations in the same class, but in my experiences the tradeoffs with this approach always came to the conclusion to separate them. Another advantage of a separate approach is the ability to create the JAXB classes with a XSD and easily link in XSDs from other projects.
In most cases I need factory classes being able for flexible creation of JAXB representations of my entities, e.g.
public class UserFactory
{
public UserFactory(User queryUser, String lang)
{
this.queryUser=queryUser;
this.lang=lang;
}
public JaxbUser getUser(JpaUser jpaUser)
{
JaxbUser jaxbUser = new JaxbUser();
if(queryUser.isSetId()){jaxbUser.setId(jpaUser.getId());}
if(queryUser.isSetEmail()){jaxbUser.setEmail(jpaUser.getEmail());}
if(queryUser.isSetRoles())
{
RolesFactory f = new RolesFactory(queryUser.getRoles(),lang);
jaxbUser.setRoles(f.getRoles(jpaUser.getRoles()));
}
return jaxbUser;
}
}
I create a UserFactory with an individual template queryUser and the desired lang for entities supporting different languages. The template is checked during creation of the result for specific fields or additional factories and the resulting object is created. The query is defined in a XML file like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<query lang="en">
<user id="1">
<roles>
<role code="code"/>
</roles>
</user>
</query>
With this methodology I have a powerful and flexible tool to create customized XML, despite all drawback of maintaining two domain models and the factory classes. I know there are many frameworks or libraries available which I never have heard about, so here my question:
Is there something available similar to my approach?
There are basically two options:
JPA and JAXB annotations on the same classes (see Hyperjaxb3 or DataNucleus)
Or you keepm the separated and write code to map one onto another
I personally do not see much added value in the cross-model mapping code. Usage of factories also does not seem too innovative, it is just a question of programming technique which you use to map one onto another.

Categories