1

I'm not much familiar with JPA, but I have this scenario: I would like to use the same classes (read "code") on both the server and the client (Java SE) for KISS/DRY reasons. It seems to me that one possible way to do this would be to have a (special?) EntityManager on the client that passes requests for entities to the server and at the end passes all entities back to the server for a "batch persist action" where classes can (re-)validate their data, apply some transactional operations (updating and stuff) and be all persisted nicely by the JPA implementation.

The question is: Is that possible? How? (is there already a solution for this? is it simple, of sorts, to solve this with "some" code?)


Edit: Ok, let me clarify a couple of things for everyone. My background is with an in-house grown application framework that uses what could be called generic persistence services; i.e. services for performing CRUD actions (one service per action for any table) within a single transaction but are backed by classes (within the service) that intercept these actions and offer validation and (often) complicated business rules (with updates to other tables, etc.). That was implemented with older Microsoft products. Now there is a shift to .NET where there have recently appeared similarly-working but more advanced frameworks like DevForce and CSLA. DevForce in particular offers what I'd like to also do in Java (see the "Executing on the client" paragraphs on this page and then visit this page for a better overview).

An older question of mine on this general subject: Java "equivalent" to CSLA

Community
  • 1
  • 1
Doc
  • 343
  • 3
  • 13
  • 1
    And how is this different from sending detached entities to the client, modify them, and then send them back to the server for re-attachment and persistence? – Edwin Dalorzo Aug 13 '11 at 00:15
  • @edalorzo That's what I'm saying, but... "management" is the key word. Since my classes are JPA-enabled, wouldn't it be "swell" to have an EntityManager on the client that has the added (?) ability to "pack-up" all those entities I've been working with and send them to an EntityManager on some server that can properly take care of persistence in one transactional swoop? – Doc Aug 13 '11 at 21:48
  • I do not think I am understanding your scenario yet. From my standpoint the client should not even know that such thing as an entity manager exists. Correctly exposed through a business interface, the server could carry out all the work you suggest in a single transaction swoop when asked by the client and the entities would not even abandon the safety of the server. Having a persistence context per client must be a nightmare when it comes to concurrency. Depending on the level of concurrency every client is likely to become a stale cache in a very short time. Don't you think? – Edwin Dalorzo Aug 16 '11 at 15:16

2 Answers2

1

I have tried to do similar things before and maybe just share a bit on my findings (I was using Hibernate + XFire for WS that time)

I believe what you are thinking works theoretically. What you need to do is simply serialize your managed entities and send it to client. Client deserialize and update the object (of course, on client's end, it is simply normal POJO, not managed entities) and send it back to server. At this point, the object recieved by Server is simply a detached object. You can reattach to session (JPA/Hibernate will do those optimistic concurrency check for you), and do your persistence.

However it only works fine for very simply POJO. One of the major problem is, in JPA (or mostly all ORM framework) you are having relationships between different entities. For example, an Order will have relationships to Product and Account, an Account will have relatinships to Client, Client will have list of Addresses.... etc. It is mostly fine if you are manipulating in server side because of lazy fetching, relationships are not actually fetched until you access it. However when you perform serialization, it become a difficult problem to solve: most serialization solution like JAXB will simply navigate all properties recursively. The result is, you expect to send only the Order object to client side, but finally you are sending a huge piece of data to Client. Simply telling the serializer not to serialize some properties is not going to work, coz when the object is sent back and reattach the detached obj to session, JPA/Hibernate have no way to know that if you are simply ignoring the relationship or you are actually removing the relationship. Of course there are still some tricks you can do but all these makes such approach painful to adopt and it is no longer elegant.

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
0

Your idea is smart.

But it is not possible to do what you suggest. Why isn't it? Well, to answer this, we have to first understand "what is a managed entity".

A managed entity is nothing else than "cached" instance. An instance that resides inside the entity manager. If you send this instance throught the network to another machine, you are serializing it, thus copying it: creating another instance on the remote server that, of course, is not managed (because the entity manager doesn't even know about its existence).

In the other side there could exist something "smart enough" to simulate an entity manager and trasparently "manage" this copied entity, but this is out of the JPA specification, and you would have to implement it yourself (which doesn't seem to be easy). I don't think that there exists anything reliable out there for this.

Your solution would be to persist, update, etc, explicitly from your client (through methods exposed from the server).

Mr.Eddart
  • 10,050
  • 13
  • 49
  • 77
  • You mean, I should expose the EntityManager's vital methods on the server to my client? What about the transaction? I've been seeing in examples that I have to control the transaction myself: start a transaction, do my stuff, and then commit the transaction. I'd like to do my stuff, and then tell the EntityManager to do whatever is required for persistence in a transaction automatically. – Doc Aug 13 '11 at 21:56
  • The way to do the thing would be to expose "business services" (for example: placeBid) from the server that executes in 1 transaction, and you invoke it when the "screen flow" of your user has finished. To maintain a transaction opened from the client (thus possible) is not usually a good idea. It is possible to maintain a transaction opened from the client spanning several service calls, but the entities will always be detached when sent through the network without remedy. – Mr.Eddart Aug 14 '11 at 13:25