Any tools to document Java POJO transformer code? - java

I've inherited a project which essentially maps large documents from one structure to another. The source and target documents are POJOs, and there are a number of transformer classes that map the source POJO to the target by using the getters/setters of each field.
For example, say we have:
public void transform(SourceDocument source, TargetDocument target) {
target.setField1(source.getField1());
target.setField2(source.getField5());
target.setField3(source.getField2());
target.setField4(source.getField4());
target.setField5(source.getField3());
}
We're looking to refactor large parts of this project and as part of it, our customer has requested that we document these mappings before we look to refactor with a better implementation.
There are several hundred of these mappings and before we get one of team to go through them all by hand, does anyone know of any tools that could analyse this code and produce a simple mapping document. All mapping have been strictly performed using getters/setters with no direct property access.
We can't give the actual code to our customer due to IP restrictions, and also it's the (non-technical) business who need this information, so ideally we need a very simple output, describing the mapping from source to target.
These transformers are still occasionally updated while we work on a new version, so I'd really prefer something that could generate the documentation we're after directly from the code rather than comments/annotations that would have to be manually updated by developers.

Related

Is it possible to cache XML documents in Saxon to avoid re-parsing and re-indexing?

I am currently assessing whether XSLT3 with Saxon could be useful for our purposes. Please hear me out.
We are developing a REST API which provides credentials given an input request XML. Basically, there are 3 files in play:
site.xml:
This file holds the data representing the complete organisation: users, roles, credentials, settings, ...
It could easily contain 10.000 lines.
It could be considered as static/immutable.
You could compare it as XML representation of a database, so to say.
request.xml:
This file holds the request as provided to the REST API.
It is rather small, usually around 10 to 50 lines.
It is different for each request.
request.xslt:
This file holds the stylesheet to convert the given request.xml to an output XML.
It loads site.xml via the XSLT document() function, as it needs that data to fulfill the request.
The problem here is that loading site.xml in request.xslt takes a long time. In addition, for each request, indexes as introduced by the XSLT <xsl:key .../> directive must be rebuilt. This adds up.
So it would make sense to somehow cache site.xml, to avoid having to parse and index that file for every request.
It's important to note that multiple API requests can happen concurrently, thus it should be safe to share this cached site.xml between several ongoing XSLT transformations.
Is this possible with Saxon (Java)? How would that work?
Update 1
After some additional reflecting, I realize that maybe I should not attempt to just cache the site.xml XML file, but the request.xslt instead? This assumes that site.xml, which is loaded in request.xslt via document(), is part of that cache.
It would help if you show/tell us which API you use to run XSLT with Saxon.
As for caching the XSLT, with JAXP I think you can do that with a Templates created with newTemplates from the TransformerFactoryImpl (http://saxonica.com/html/documentation/using-xsl/embedding/jaxp-transformation.html), each time you want to run the XSLT you will to create a Transformer with newTransformer().
With the s9api API you can compile once to get an XsltExecutable (http://saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/XsltExecutable.html) that "is immutable, and therefore thread-safe", you then have to us load() or load30() to create an XsltTransformer or Xslt30Transformer each time you need to run the code.
As for sharing a document, see http://saxonica.com/html/documentation/sourcedocs/preloading.html:
An option is available (Feature.PRE_EVALUATE_DOC_FUNCTION) to indicate
that calls to the doc() or document() functions with constant string
arguments should be evaluated when a query or stylesheet is compiled,
rather than at run-time. This option is intended for use when a
reference or lookup document is used by all queries and
transformations
The section on that configuration option, however, states:
In XSLT 3.0 a better way of having external documents pre-loaded at
stylesheet compile time is to use the new facility of static global
variables.
So in that case you could declare
<xsl:variable name="site-doc" static="yes" select="doc('site.xml')"/>
You will need to wait on Michael Kay's response as to whether that suffices to share the document.
Well, it is certainly possible, but the best way of doing it depends a little on the circumstances, e.g. what happens when site.xml changes.
I would be inclined to create a single s9api Processor at application startup, and immediately (that is, during application initialization) load site.xml into an XdmNode using Processor.DocumentBuilder.build(); this can then be passed as a parameter value (an <xsl:param>) into each transformation that uses it. Or if you prefer to access it using document(), you could register a URIResolver that responds to the document() call by returning the relevant XdmNode.
As for indexing and the key() function, so long as the xsl:key definition is "sharable", then if two transformations based on the same compiled stylesheet (s9api XsltExecutable) access the same document, the index will not be rebuilt. An xsl:key definition is shareable if its match and use attributes do not depend on anything that can vary from one transformation to another, such as the content of global variables or parameters.
Saxon's native tree implementations (unlike the DOM) are thread-safe: if you build a document once, you can access it in multiple threads. The building of indexes to support the key() function is synchronized so concurrent transformations will not interfere with each other.
Martin's suggestion of allowing compile-time evaluation of the document() call would also work. You could also put the document into a global variable defined with static="yes". This doesn't play well, however, with exporting compiled stylesheets into persistent files: there are some restrictions that apply when exporting a stylesheet that contains node-valued static variables.

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.

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.

regenerate ecore after schema changes

I have a schema in xsd file. once in a while a new version of the schema is created, and I need to update my .ecore (and .genmodel).
How do I update them, without deleting them and re-generate them. I have made some manual modification to the ecore, and i want to keep this modifications.
Ido.
Use the Reload... action on the *.genmodel to update the *.ecore based on the new version of the *.xsd.
And don't change the .ecore directly. Using ecore: annotations in the schema. http://www.eclipse.org/modeling/emf/docs/overviews/XMLSchemaToEcoreMapping.pdf
I've never tried this, but the XSD FAQ says this:
JAXB produces a simple Java API given
an XML Schema and it does so using
essentially a black box design. EMF
produces an Ecore model given an XML
Schema and then uses template-based
generator technology to generate a
rich Java API (of hand written
quality). The XML Schema to Ecore
conversion can be tailored, the
templates used to generate the Java
API can be tailored, and the resulting
Java API can be tailored. The
generator supports merging
regeneration so that it will preserve
your hand written changes. In other
words, EMF is far richer and more
flexible, and supports a broader
subset of XML Schema (especially in
2.0, where wildcards and mixed content will be supported).
If I were you, I'd try some experiments to see how well this process works, and what the practical limitations are.
You can regenerate using the context menu options. To preserve your modifications:
If there is a method that has "Gen" added to the name -- e.g. setWhateverGen in addition to setWhatever -- new code will be generated to the "Gen" method. So leave the "Gen" method alone so that it can be overwritten, and then call it from the non-Gen method, which you can modify.
All the generated methods are annotated with #generated. If you add "NOT" -- #generated NOT -- it will not be overwritten.
All other content should be merged. Go ahead and experiment -- that's what version control is for....

Dynamically create table and Java classes at runtime

I have a requirement in my application. My tables won't be defined beforehand.
For example, if a user creates a form by name Student, and adds its attributes like name, roll no, subject, class etc, then on runtime, there should be a table created by name student with columns name, roll no, subject, class etc. And also its related class and its Hibernate mapping file.
Is there any way of doing so?
Thanks in advance,
Rima Desai
Hibernate supports dynamic models, that is, entities that are defined at run-time, but you have to write out a mapping file. You should note a couple things about dynamic models:
You may be restricted in how you define these at run-time (viz. you will have to use the Session directly instead of using a helper method from HibernateTemplate or something like that).
Dynamic models are supported using Maps as the container for the fields of an entity, so you will lose typing and a POJO-style API at run-time (without doing something beyond the baked-in dynamic model support).
All of that said, you didn't mention whether it was a requirement that the dynamically defined tables be persistent across application sessions. That could complicate things, potentially.
It's possible, but it's not clear why would you want to do something like that, so it's hard to suggest any specific solution.
But generally, yes, you can generate database tables, hibernate classes and mappings dynamically based on some input. The easiest approach is to use some template engine. I've used Velocity in the past and it was very good for this task, but there are others too if you want to try them.
EDIT:
Following OP clarification the better approach is to use XML to store user defined data.
The above solution is good but it requires recompiling the application whether forms are changed. If you don't want to stop and recompile after each user edit, XML is much better answer.
To give you some head start:
#Entity
public class UserDefinedFormData {
#Id
private long id;
#ManyToOne
private FormMetadata formMetadata;
#Lob
private String xmlUserData;
}
Given a definition of the form it would trivial to save and load data saved as XML.
Add a comment if you would like some more clarifications.
last week I was looking for same solution and then I got idea from com.sun.tools.javac.Main.compile class, you create the Entity class using java IO and compile using java tools, for this you need tools.jar to locate on CLASS_PATH, now I am looking for run time hibernate mapping without restart.
some one was saying in the post regarding to this type of requirement that "but it's not clear why would you want to do something like that" answer is this requirement is for CMS(Content Management System). and I am doing the same. code is as below.
public static void createClass()
{
String methodName=“execute”;
String parameterName=“strParam”;
try{
//Creates DynamicTestClass.java file
FileWriter fileWriter=new FileWriter(fileName,false);
fileWriter.write(“public class “+ className +” {\n”);
fileWriter.write(“public String “+methodName +“(String “+parameterName+“) {\n”);
fileWriter.write(“System.out.println(\” Testing\”);\n”);
fileWriter.write(“return “+parameterName +“+ \” is dumb\”;\n }\n}”);
fileWriter.flush();
fileWriter.close();
String[] source = { new String(fileName) };
com.sun.tools.javac.Main.compile(source);
}

Categories

Resources