1

I noticed that when I invoke

    SomeProxy proxyNew = someRequestContext.edit(proxyOld);
    proxyNew.setSomething(somethingNew);
    someRequestContext.mySaveMethod(proxyNew).fire();

The entity returned from

    @Override //from Locator<SomeEntity ,IdClass>
    public SomeEntity find(Class<? extends SomeProxy > clazz, IdClass id) {
    ...
    }

is used in server when saving method is invoked and only those property/istance variable values of proxyNew are transfered to server implementation mySaveMethod(SomeEntity entity)which are new in comparison with the returned entity.

Now. I understand that there is some comparison in order to provide server side only with deltas so there is efficiency in communication but I think it is somehow offset by additional processing/transfer time needed by implementation of public SomeEntity find(Class<? extends SomeProxy > clazz, IdClass id) which retrieves the entity objects from database.

My question now is, how should this be correctly implemented in system with persistence services exposed via stateless session bean which provide services to GWT server side servlets/DAO objects. Correctly implemented in a way that the highest efficiency and lowest waiting time is achieved. Also could someone explain to me this RequestFactory aspect/process in greater detail?

My example: I retrieve OrganizerEntry entities from persistence layer for a certain day span - a week.

So the method like retrieveOrganizerEntries(Date from, Date to) is invoked in persistence layer.

Then I see that for each OrganizerEntry entity object obtained which is to be sent to the client layer, another query is made, like retrieveOrganizerEntry(int id).

So not only are the same objects queried twice, but the second time they are queried one by one in a very inefficient manner.

How can this be improved? Should I cache in DAO/servlet objects somehow the results from first query and let public SomeEntity find(Class<? extends SomeProxy > clazz, IdClass id) search the cache? Is it way to go to implement this method returning null or newly created empty entity (new OrganizerEntity()) and before invoking the persist/save method from the client just setting every single property/instance variable value?

Where can I find more examples and explanation about this stuff? Because http://www.gwtproject.org/doc/latest/DevGuideRequestFactory.html seems to me not very exhausting .

ps-aux
  • 11,627
  • 25
  • 81
  • 128

1 Answers1

1

1.) Regarding the rf internals, you can refer to this document. But I guess Thomas Broyer is going to respond to this in more detail.

The basic flow is following:

  • properties that are modifed through the setter are transmitted to the server.
  • server uses find() to retrieve the entity and calls the corresponding setters (whatever you also called on the client).
  • Validation rules are processed
  • The entity is passed to your service method.

2.) With RF you need one session per http request aka OpenSessioninview pattern. . The first level cache of your persistence layer (i.e. Hibernate) should make multiple redundant calls to find() really efficient so you usually will only hit the database once during the session`s lifetime.

3.) If you don't care about EntityProxyChange events on the client you could override the isLive() method of your Locator and just return true (see here for more details). That's also probably the reason why the find() method is called when you retrieve a list of OrganizerEntry instances because for each OrganizerEntry RF checks if it's still alive by calling 'isLive()' which itself calls find().

Community
  • 1
  • 1
Ümit
  • 17,379
  • 7
  • 55
  • 74
  • Thanks for nice explanation Uemit. So there are two ways to go: A) to have one session with persistance layer / `EntityManager` per http request - this would involve some interceptors or stateful session beans? Right now the calls to JPA are via stateless session beans for CRUD operations. B) "Turning off" invocation of `find()` by overriding `isLive()` to return always `true`. I wonder, what I am losing here with this approach? What is the catch? What exactly are 'EntityProxyChange' events? – ps-aux Aug 07 '13 at 17:14
  • A.) Yes the `OpenSessionview` pattern is the right approach. Unfortunately I have no experience with JavaEE but with `Spring` you just need to add a servlet filter. – Ümit Aug 08 '13 at 08:59
  • B.) `EntityProxyChange` events are useful when you want to notify the client that an entity has been changed/deleted. (see [here](http://stackoverflow.com/questions/9476341/requestfactory-theory-why-is-locator-find-being-called-so-often) for more details). If you override `isLive()` and return `true` you won't get those events on the client. Most people probably don't care about those `Events`. – Ümit Aug 08 '13 at 09:07
  • So I am sacrificing events received from server side to client when the entity has changed so I can have simpler architecture and faster loading (even with `OpenSessionView` there must be some increased overhead, oder?). What are the advantages of having `Events` anyway? If data are edited by more users at the same time? I must say that overriding `isLive()` helped, but I am still confused and don`t understand how RT works. Now I don`t see `find()` called at all even when persisting `Entity`. – ps-aux Aug 08 '13 at 11:17
  • Properly reacting to Events (i.e. an entiy was deleted by another user) and keeping the system und UX simple is quite difficult. That's probably the reason why most people don't rely on the `EntityProxyChange` events. The last user who saves the entiy "wins" is a common approach. Even if you override the `isLive()` method `find()` should be called when you persist the entity. if it's not called then I guess nothing has changed (no setter was called). – Ümit Aug 08 '13 at 11:59
  • You are right. The `find()` method is called. So even when I have overriden `isLive()`, thus effectively turning off the 'Events feature', I still need the server code to have invocation of `find()` and custom `saveEntity()` in one session with persistence provider. Am I right? – ps-aux Aug 10 '13 at 17:16
  • Yes you need the `find()` method otherwise you the object that is passed to your service method `saveEntity()` will be null. – Ümit Aug 12 '13 at 08:23
  • I know this. I meant, that having two separate persistence sessions for find() and saveEntity() is just a bad design in general or is this acceptable? – ps-aux Aug 12 '13 at 09:03
  • you should have on session and possibly actually one transaction which wraps all the calls to the persistence layer. You can do this by extending the `RequestFactoryServlet` and starting a transaction and commiting it at the end. – Ümit Aug 12 '13 at 12:11