views:

269

answers:

5

Hi,

I am developing a stand-alone java client application that connects to a Glassfish v3 application for JPA/EJB facade style transactions. In other words, my client application do not connect directly to the database to CRUD, but it transfers JPA objets using EJB stateless sessions.

I have scenarios where this client application will be used in an external network connected with a VPN over Internet with a client connection of 512kbp/DSL, and a simple query takes so much time, I'm seeing the traffic graph and when I merge a entity in the client application I see megabytes of traffic (I couldn't believe how a purchase order entity could weight more than 1 mb).

I have LAZY fetch in almost every many-to-many relationship, but I have a lot of many-to-one relationships between entities (but this is the great advantage of JPA!).

Could I do something to accelerate the the speed of transactions between JPA/EJB server and the remote java client?

Thank you in advance.

+1  A: 

How much data do you really transfer? Maybe the purchase order you're sending has a product, which has a model, which has a supplier, which has a set of models... and so on...

You could try serializing the object you're sending to the server into a file (using the standard ObjectOutputStrem) and check how big the file is.

Guillaume
+1  A: 

I'm seeing the traffic graph and when I merge a entity in the client application I see megabytes of traffic (I couldn't believe how a purchase order entity could weight more than 1 mb).

RMI-IIOP is a bit more verbose than plain RMI. In my experience, it doesn't work well when transferring large graphs.

So far I remember (but maybe things changed in the meantime), when you transfer an lazy loaded entity, the parts that haven't been loaded yet are sent as-is (the proxy is serialized), which means you can not access them on the client because lazy loading won't work if there is no session anymore. Are you eagerly loading the entity before sending it back to the client?

Could I do something to accelerate the the speed of transactions between JPA/EJB server and the remote java client?

But the crux of the problem is that you are in a scenario where you need to think about a strategy to transfer data. You must design you application is a way that you don't send large graphs; this concern must be addressed in the design of your app. Then you can decide to still send JPA entities or rely on Data Transfer Object (DTO).

You might also consider using an extended persistence context with a stateful session bean, this way I think an entity on the client side can still be loaded lazy. But I never used this personally and don't know if it works well or not.

ewernli
A: 

If I understand your architecture correctly you have:

 Client(works with disconnected Entities)  
            ----RMI/IIOP--->
 Server(SLSB, using entitiy manager, JPA persistence) 
            ----JDBC------->
 Database

In effect your SLSBs are expressing their interface in terms of the JPA Objects, your DTOs are the JPA objects. I see two possible scenarios:

  1. your client needs only a subset of the data in your JPA objects, and you are transfering more than you acually need. For example you might only need an employee's name and you send his entire life history.
  2. you are traversing more of the relationship treee than you intend

My feeling is that you should first determine exactly what you are getting in the client. Should be pretty easy to add some trace statements to see exactly what data you have.

Possibly by tweaking the lazy loading etc, you can then control the behaviour.

My expectation is that you may need to define client-specific "subset" DTOs and have your SLSB act more as a facade, sending only the subset data. It's more work, but you have fine control over what's in the interface.

Architecturally, fine tuning a remote interface is quite a reasonable thing to need to do.

djna
A: 

Could I do something to accelerate the the speed of transactions between JPA/EJB server and the remote java client?

You can't accelerate things. However, you can transfer less (only the required part or lighter objects).

Pascal Thivent
A: 

Thank you all.

I guess using JPA entities as DTOs is not so good idea, right?

Maybe I could design for the client a combined JPA entities and DTOs client data model (and not just use JPA), but it is a lot of more painful work.

JPA entites are designed just for server side use (including Web clients in the same server)???

Xavier.

Using JPA entities as DTOs is far from ideal as the client needs to know which parts of the object graph have been initialized on the server side so the client doesn't trigger LazyInitExceptions. On the other hand, when implementing e.g. CRUD interfaces, JPA entities are (structurally) a perfect fit to what you want to transfer so I find the alternative - creating an almost identical DTO - even less appealing. Is there a 3rd way?
Tomislav Nakic-Alfirevic