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.
Related
I am working on a struts2 project that has interdependent forms.
I found struts2-conversation, stepped through their simple-example
and understood the conversation mechanism this far (please correct me if I got something wrong):
The Controller is mapped in the struts.xml
It holds the serializable ConversationContext and the Storing-Service
The ConversationContext holds POJOs mapped on forms by naming convention
Now my question is where to put the validation?
In this structure the controller is only one extending ConversationSupport and thereby ActionSupport supplying the validate, prepare and addField- & ActionError methods.
But validating within the controller would mean to validate the whole context, which does not really serve the issue.
I tried validation through annotation within the POJOs, within the context as described above which gives me some NullPointerException as if the context wasn't flushed and I think the xml-validation approach of struts2 is just too stiff. (btw how to let the generated javascripts be minified before being served? And why is there so many options?)
Mark's conversation-interceptor approach had similar problems coming up which's workarounds I didn't really get. Maybe you can help me there.
If you would like to use annotations on your model classes, it works fine with the plugin (as do the other validation approaches).
To validate your model, add #VisitorFieldValidator to the getModel() method in your controller. In the example app, you would then also add #VisitorFieldValidator to the getContact() and getPreferences() methods. Then you can use the validation annotations on the fields you wish to validate.
The service in the example is just there as a simple example of using an injected service in a Struts2 controller and how that can integrate easily with the conversation framework, but it is not directly related or needed (and I would recommend using either Spring, Guice, or CDI for dependency injection in the real world).
The ConversationContext class is intended mostly for internal use by the framework. You should be able to avoid interacting with it by using the annotations and conventions. Unless you simply wish to be adventurous.
To use XML validation in the example app, you would have to change the package name to remove the "struts2" word in order for the Struts2 resource loading tool to load the XML.
I was wondering if I can easily annotate Acceleo templates and then get these annotations when working with TraceabilityModel.
Acceleo is now using an annotation to determine entry points for generation:
[comment #main]
So I am asking, if I can use this mechanism to annotate my templates for other purposes, for example:
[comment #org.project.SimpleStatement]
[template public generateSimpleStatement(...)]
...
[/template]
Then, I could be able to get the annotation programmatically when working with traceability model (probably using the org.eclipse.acceleo.traceability.ModuleElement interface).
Acceleo's traceability does not support either annotations or comments : we only record traceability information for the actually generated text bits, not for any of the "extra" information (comments of the module, main annotation, metamodels ...).
That being answered, and though not possible through the means of an annotation, maybe your use case would be worth an enhancement request? Can you describe what you were expecting to achieve through this? (preferrably through the Eclipse M2T forum since stack overflow does not seem to be appropriate for such discussions ;)).
(Note : I am an active developper on Acceleo)
I have a class that needs to be sortable in a couple of different ways, many of which break the equals() contract, so I need to have a bunch of different Comparator classes. The question I have is where should those classes live?
So that there is something concrete to use as an example namespace structure and to limit the question to package structure rather than file structure, lets assume the following namespaces:
app
domain
exception
hibernatemapping
mvc
propertyeditor
tags
persistence
hibernate
Domain classes live in the domain namespace, and related exceptions and hibernate mapping files in exception and hibernatemapping respectively. persistence holds DAO interfaces, with hibernate-based implementations in hibernate. All of the MVC controllers live in mvc, with specialized property editors (this is Spring MVC) in propertyeditor and classes that back custom tags in tags.
My gut says that Comparators should live under the domain namespace, perhaps in domain.comparator, but I'm not sure.
Where would you put them and why?
Update: A number of people have suggested using a general Util package. When going that route, would you separate out the Util classes by UI helpers vs. domain helpers? For example, if the domain needed to sort things for business logic reasons, but the UI needed additional sortings that the domain doesn't care about? Basically, would you tend to have a helper package per-layer?
As suggested, something like a util or a commons package would seem to make the most sense, though be sure you don't end up using that as a "goto" package if you don't know where to put something.
I'd also suggest looking into package by feature. In this cause, your compartor would just go with whatever corresponding feature its used with. Again, this is only a suggestion - you'll have to make the call for the best layout of your project.
I made a package called comparators which is where I store mine.
I usually go with the following structure:
company
appname
model
util
dao
service
controller
In this type of structure a comparator would probably get dumped into the util package (if there were really a lot of comparators).
However, usually I find that comparators are used in exactly one place, and so I declare them inline where they're actually used, e.g.
public class SomeService {
public void someMethod(String id) {
List<ListType> list = dao.getSomeListById(id);
Collections.sort(list, new Comparator<ListType>() {
public compare(ListType a, ListType b) {
// ...
}
});
}
}
I suggest to create a package called "app.util" or "app.helper".
Conceptionally speaking, in Domain Driven Design this belongs in the infrastructure layer (http://www.infoq.com/articles/ddd-in-practice).
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
How and where are Annotations used in Java?
Java beans, annotations: What do they do? How do they help me?
Over and over, I read about Java 5's annotations being an 'advanced feature' of the language. Until recently, I haven't much used annotations (other than the usual #Override, &c), but work on a number of webservice-related projects has forced my hand. Since I learned Java pre-5, I never really took the time to sit down and grok the annotation system.
My question- do you guys actually use annotations? How helpful are they to you, day-to-day? How many StackOverflow-ers have had to write a custom annotation?
Perhaps the most useful and used case of Java Annotations is to use POJO + Annotation instead of xml configuration files
I use it a lot since (as you already stated) if you use a web framework (like spring or seam) they usually have plenty of annotations to help you.
I have recently wrote some annotations to build a custom statemachine, validations purpose and annotations of annotations (using the metadata aspect of it). And IMO they help a lot making the code cleaner, easier to understand and manage.
Current project (200KLOC), annotations I use all the time are:
#NotNull / #Nullabe
#Override
#Test
#Ignore
#ThreadSafe
#Immutable
But I haven't written yet my own annotation... Yet!
I have used annotations for:
Hibernate, so I don't need to keep those huge XML files;
XML Serialization, so I describe how the object should be rendered in the object itself;
Warning removal for warnings that I don't want to disable (and for which the particular case cannot be properly solved).
I have created annotations for:
Describe the state required in order for my method to be executed (for example, that a user must be logged in);
Mark my method as executable from a specific platform with additional properties for that platform;
And probably some other similar operations.
The annotations that I have created are read with Reflection when I need to get more information about the object I am working with. It works and it works great.
Annotations are just for frameworks and they do work great in hibernate/jpa. until you write a framework that needs some extra information from passed to it objects you wont write your own annotations.
however there is new and cool junit feature that let you write your own annotations in tests - http://blog.mycila.com/2009/11/writing-your-own-junit-extensions-using.html
I use annotations daily and they are wonderful. I use them with jsf and jpa and find them much easier to manage and work with than the alternative XML configurations.
I use annotations for describing in my state synchronisation system what classes are specialisations of the annotated classes, and the environment in which they should be used (when an object is created, it will work out for its entity lists which are the best entity classes to create for the nodes on the network; i.e., a Player entity for a server node is instead a ServerPlayer entity). Additionally, the attributes inside the classes are described and how they should be synchronised across machines.
We just used annotations to create a simple way to validate our POJO's:
#NotEmpty
#Pattern(regex = "I")
private String value;
Then we run this through the Hibernate validator which will do all our validation for us:
import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
public void validate(T validateMe) {
ClassValidator<T> validator = new ClassValidator<T>((Class<T>) validateMe.getClass());
InvalidValue[] errors = validator.getInvalidValues(validateMe);
}
Works great. Nice clean code.
We use custom annotations as a part of our integration testing system:
#Artifact: Associates an integration test with an issue ID. Trace matrices are then automatically generated for our testing and regulatory departments.
#Exclude: Ignores an integration test based on the browser platform / version. Keeps the IE 6 bugs from clogging up our nightly test runs :)
#SeleniumSession: Defines test specific selenium settings for each integration test.
They are a very powerful tool, but you gotta use them carefully. Just have a look at those early .NET Enterprise class files to see what a nightmare mandatory annotations can be :)
We have a report builder as part of our webapp. A user can add a large number of widgets that are all small variations on the same set of themes (graphs, tables, etc).
The UI builds itself based on custom annotations in the widget classes. (e.g. an annotation might contain default value and valid values that would render as a dropdown. Or a flag indicating if the field is mandatory).
It has turned out be be a good way to allow devs to crank out widgets without having to touch the UI.
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);
}