users@jersey.java.net

[Jersey] Re: Entity Manipulation Prior to REST Implementation Call

From: Gerard Davison <gerard.davison_at_oracle.com>
Date: Mon, 19 Sep 2011 14:13:23 +0100

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