Joined: 03 Sep 2008
|Posted: Mon Nov 30, 2009 8:55 pm Post subject: Generated JAX-RS server and client code-generation - feedback, plus guidance required
As per my last post, I'm playing with the JAX-RS code-generation from within Netbeans and I have some questions / concerns about the code it generates.
One entity results in 3 classes - 1) a POJO to match the database entity with JPA annotations, I'll call this the domain object. 2) a Resource class that is basically the JAX-RS service definition using JAX-RS annotations (I'll refer to this as the controller) and 3) A converter class that uses JAXB annotations to define how to marshall/un-marshall the data.
Part of me likes what's generated, but, another part of me doesn't understand why so much code has to be generated _if_ we are going to program by convention instead, i.e. if the entity is called User and one field is userName, then it makes sense that the domain object is called User, has one field called getUsername and this same class could be annotated with the JAXB annotations? It makes sense that the services are in a separate class - but if it's a straight pass-through of data for CRUD operations, then an annotation could be added to the POJO and then one class has all the annotations (admittedly this is for prototyping or simple solutions)?
On the opposite side of the coin, I like the separation, however, I'd almost like it separated even more! I'm thinking about the fact that the UserResource (I see this as a controller) should delegate through to some sort of re-usable manager, the manager returns back the data for the controller to do what it sees fit. Lets say I add an RMI server, I want the controllers in that to call my re-usable / common manager code, but thats not possible with the code that has been generated by Netbeans.
The other reason why I want the resources to delegate to a manager is that I might add 5 new fields to an entity and as a result re-generate the entity classes, restful classes and client-side stubs. Currently the controllers will be overwritten with the new version and any custom code is replaced. One solution would be to enable the programmer to mark blocks as protected, so that generated code preserves what's entered? Does anyone have a workaround for this?
Service parameters - I don't know whether I like the fact that each resource is given the start, max, expand level and query parameters. For example, I might want to return data specific to the user that's logged in, but if the client can influence the query run, that sounds dangerous? I certainly want the default to be customisable, i.e. 100 results for some entities.
Auto serialisation - Are the Converters really necessary? I previously experimented with Spring and used the XStream API to take an object graph and marshall/un-marshall it to XML. Can't the framework do this generically rather than a converter class per entity. The marshaller could explode or collapse the references, i.e. if I return an XML object graph of a JAVA object graph, it returns an element / attribute for each field, but if the field points to another entity, it can either collapse it include the URL reference, or serialise the child object inline in the XML for convenience (or a hybrid of both).
An entity with two references to the same entity - generates bad code - I noticed that my Profile has two Address, named homeAddress and businessAddress, but in the Profile.js file it does not have two variables as homeAddress and businessAddress, instead it has two attributes of the same name 'address'. This causes hiding of values and means one of the values will not be stored correctly.
As JSON or as XML - Although the domain objects in the client have methods to get attributes, it appears that it always defaults to JSON, but sometimes it's actually nice to say I want the verbose XML version instead, especially when some of the GUI frameworks might only have XML support.
Why an object - It would be nice if there was an alternative option to generating object versions of the domain objects, i.e. EXT-JS doesn't know about the domain objects and will just use the JSON or XML results, so using the generated domain objects is very nice for auto-loading child objects, but if I could ask for the raw XML/JSON instead and the server exploding references out to the actual objects, it would be simpler (but not pure REST I agree!).
A DAO interface - The client generated code appears to really help rapidly get some data from the server without writing any code (always a good thing), but I think it needs the ability to have the equivallent of a Java Interface, with CRUD style operations exposed and a JAX-RS implementation as default. Then I can easily add a switch before that to go to Google Gears for example if installed, whereas at the moment I would have to insert the code inside each entity.
So my suggestions, in the wizard
- Ask whether a simple CRUD solution is required, if yes, annotate the POJO instead of creating a Resource class for each entity
- Ask whether to introduce a manager / interface to delegate to
- Enable what parameters are used per entity (and these settings to be remembered across code-generations), plus default values (i.e. max results to return).
- An option to serialise using convention rather than code
- Explode references to resources to inline resource (i.e. <user='http://....user/44'> becomes <user id='33'><name>xxx</name> etc.
- Generate client DAO pattern to help with Google Gears / other client integrations.
I'd love to hear feedback on my initial thoughts, particularly any architectural suggestions to assist with making these things even more reusable.
For your information, I plan to add JAX-RS and EXT-JS related information to my blog if you wish to follow my progress (http://spikyorange.blogspot.com/)?