Gerard,
I thought of that, my concern was having to have the EJB annotations in my shared objects that would also be used on the client side. Unless I am mistaken, with the EJB annotations it requires the dependency on at least one JEE jar file to be on the client side in order to use the pojos there as well. Also, maybe it's me being picky, but in many of our session beans we had to detach the entity beans before sending them back to the rest resource class.. for example, an entity with the getSocialSecurity method, in order to avoid the social security being passed back, I would have to do a setSocialSecurity(null) in the resource class. That would prevent it from going back as part of the response, but then it would also update the database because the bean was still attached. The @XmlTransient may have worked in that case, but still the import of ejb classes and using them on the client side bugs me.
>________________________________
>From: Gerard Davison <gerard.davison_at_oracle.com>
>To: users_at_jersey.java.net
>Sent: Monday, September 19, 2011 6:13 AM
>Subject: [Jersey] Re: Entity Manipulation Prior to REST Implementation Call
>
>
>
>Kevin,
>
>Out of interest did you consider just have one object that was both
@Entity and @XmlRootElement and just using @XmlTransient to knock
out those values which you don't want on the client side? This seems
like a simpler solution to the problem; but it might not have worked
in practice.
>
>I am a little biased towards generating a client set of beans on the
client side, if only to prove that other non java client can do the
same,
>
>Gerard
>
>On 19/09/2011 01:43, Kevin Duffey wrote:
>I don't know if anyone else has done this the way I have... I like probably many have a similar need as yours. We have some sort of domain entity that contains more than what we want to expose via the REST API.
>>
>>
>>The first thing I realized is I want to build a Java SDK that client side Java developers can use to use my REST API. What I didn't want to do was have EJB entity beans, then copy them to a 2nd set of objects that had "less" properties in them (to expose them via the API), and also, I needed to bundle up the same set of objects in the SDK so that they could be used between the jersey client SDK and the jersey REST API server. Instead of using an XSD file, I wrote my own Representation classes that expose via getXxx() methods only what I want to allow exposed.
>>
>>
>>
>>One issue I found when using entity beans, and then copying them to pojo models of almost identical properties (for example, a User entity bean had getSocialSecurityNumber(), but I didn't want to make that available in the REST API, so the intermediary user object I copied entity properties to did not have a setSocialSecurityNumber() or getSocialSecurityNumber() methods in it). The problem I cam across is that I am basically doubling my objects in memory for almost the same data.
>>
>>
>>
>>So knowing that EJB entity beans can use either property or method annotations, I thought, why not use a single pojo that is shared, passed around all tiers, and use method delegation in the entity and representation classes. In this way the entity beans use get/set methods to read/write to the database, and the REST representation classes use the delegation to the same pojo to expose only what I want. I have something like this:
>>
>>
>>public class User {
>> private String username;
>> private String name;
>> private String socialSecurity;
>>
>>
>> ... // get/set methods ...
>>}
>>
>>
>>@Entity
>>@Table(name="user")
>>
>>public class UserEntity {
>> private User model = null;
>> public UserEntity(User model){
>> this.model = model;
>> }
>> public UserEntity(){
>> this.model = new User();
>> }
>> public User fetchModel(){
>> return this.model;
>> }
>>
>>
>> public String getUserName(){
>> return (null != model ? model.getUserName() : null);
>> }
>> public void setUserName(String userName){
>> if (null != model){
>> model.setUserName(userName);
>> }
>> }
>> ../ rest of methods ../
>>}
>>
>>
>>@Stateless
>>public class UserBean {
@PersistenceContext(name = "someConfiguredPU")
>> EntityManager em;
>>
>> public int createUser(User user){
>> UserEntity ue = new UserEntity(user);
>> em.persiste(ue);
>> em.flush();
>> em.refresh(ue);
>> return ue.getId();
>> }
>>}
>>
>>
>>
>>@XmlRootElement(name = "user")
>>public class UserRepresentation {
>> private User = null;
>> public UserRepresentation(User model){
>> this.model = model;
>> }
>> public UserRepresentation(){
>> this.model = new User();
>> }
>> public User fetchModel(){
>> return thise.model;
>> }
>> .. / same as above in entity.. method delegation to model methods ../
>>}
>>
>>
>>
>>
>>
>>The above bit of code allows me to do a few things. First, in the Representation classes, since the Jersey/JAxB stuff uses get/set signature methods via reflection, by using fetchModel to get the model, it is NOT exposed in the API. The same is true for EJB entity beans.. the fetchModel() does not result in a table column called user (the result type of fetchModel).. it's thusly ignored.
>>
>>
>>Now, a jersey rest method that makes use of this would be like this:
>>
>>
>>@Path("user")
>>@Stateless
>>public class UserResource {
>> @EJB
>> UserBean userBean;
>>
>>
@Post
>> public Response createUser(UserRepresentation newUser){
>> int id userBean.createUser(newUser.fetchModel());
>> return Response.created(new URI(... + id).build();
>> }
>>}
>>
>>
>>So, the point of all this is to use a single pojo model object within the incoming REST call, pass the underlying model (via fetchModel()) to the session bean, that then creates a new entity bean passing the same object into the constructor that is set as the entity beans model. In other words, a single object, completely pojo, passed from the front to the back, and even can come back after the persist() call and used in the response Representation.
>>
>>
>>
>>Even nicer is that I can bundle up these pojos into my client side SDK, and now it is very easy for a JAva client side to use the exact same pojo objects to make REST calls that work perfectly. No worries about a StringBuilder and building up the right XML and getting any xml parse issues.. or in the case of REST, if you have invalid XML no method is called at all and you can't easily track down why this happens.
>>
>>
>>
>>This is working for me nicely. Before I did this, I used separate entitiy beans, a intermedialy object and a representation object.. 3.. and couldn't easily build the client side SDK either. This has cut my memory consumption by 2/3s with regards to the objects used, and thus with less object creation has increased my performance as well.
>>
>>
>>
>>Not sure if this addresses any of your questions though.. I thought I'd share at lest how I handle the part of what methods you expose via your REST API compared to what your entity bean may actually have with it.
>>
>>
>>I also like this because it allows me to modularize my code a bit more.. there is the representation and resource classes, the session and entity beans, the SDK classes, and then the pojos that are shared by all three. I've actually broken my pojos out into a separate project because I have another deployed app project that uses them.. I used REST to communicate between a couple of web apps deployed in different locations as opposed to dealing with JMS and configuration issues. It works very nicely and with the shared pojos and also shared representation classes, my work is minimal on adding communication between distributed deployed web apps.
>>
>>
>>
>>
>>
>>
>>
>>>________________________________
>>>From: "webron_at_gmail.com" <webron_at_gmail.com>
>>>To: users_at_jersey.java.net
>>>Sent: Saturday, September 17, 2011 5:56 AM
>>>Subject: [Jersey] Entity Manipulation Prior to REST Implementation Call
>>>
>>>Hi everyone,
>>>
>>>I hope this haven't been asked and answered before - I
wasn't sure
>>>exactly what to look for.
>>>
>>>Brief description of our architecture:
>>>We have an entity-management Spring-based system. The
system consisted
>>>of several entities - all JAXB annotated. Those entities
are used both
>>>with our DB ORM framework and by our REST API
implementation. The
>>>entities are sent to the REST API in JSON format.
>>>
>>>Currently, when the client invoke an API call, it needs
to send the
>>>whole JSON/entity.
>>>For example, assume the following API declaration:
>>>
>>>@PUT
>>>@Path("/entity")
>>>@Consumes({MediaType.APPLICATION_JSON})
>>>public void updateEntity(FooEntity fooEntity) { ... }
>>>
>>>What I'd like to do is allow the client to send only
parts of the
>>>entity, and somehow add a hook before the actual
updateEntity(...)
>>>invocation. In that hook, I would read the actual entity
from the
>>>database (or whichever source), and modify only the
fields received
>>>from the client, and only then invoke the
updateEntity(...) with the
>>>newly created entity. I would probably want to put some
extra
>>>security-checks logic in that hook.
>>>
>>>Is there any way to do it? If there's more than one way,
I'd like to
>>>hear the options out there (with pros and cons if
willing).
>>>
>>>Thanks,
>>>Ron
>>>
>>>
>>>
>
>--
Gerard Davison | Senior Principal Software Engineer | +44 118 924 5095
Oracle JDeveloper Web Service, Spring, Weblogic SCA Tooling Development
Oracle Corporation UK Ltd is a company incorporated in England & Wales.
Company Reg. No. 1782505.
Reg. office: Oracle Parkway, Thames Valley Park, Reading RG6 1RA. Blog
http://kingsfleet.blogspot.com Twitter kingsfleet
>
>