users@glassfish.java.net

Re: General question about detachable EJB 3.1 entities

From: Bobby Bissett <Robert.Bissett_at_Sun.COM>
Date: Thu, 28 Jan 2010 10:09:35 -0500

Like Marina, I'm confused about your example (the "outsourcing the
method" part) so it looks like you're mixing session beans and
entities in the same class. But your question is still good I think.
See below:

> When talking about detaching an entity, I will be thinking of
> something like this:
>
> Client Code:
> BankAccountFactoryRemote bacf = (BankAccountFactoryRemote)
> initialCtx.lookup(...);
> BankAccount b = bacf.newBankAccount();
>
> Code in the Session Bean:
> public BankAccount newBankAccount() {
> return new BankAccountEntity();
> }
>
> Of course, BankAccountEntity is implementing the BankAccount
> interface, which is used at the client.
>
> If the entity now gets detached (transferred to the client by using
> serialization) and the client works with the object by only knowing
> the interface, what actually happens to the isValid() method call...
> will it be executed locally at the client (as all the bytecode
> required will also be transferred to the client at time of
> detachment) or will calling isValid() at the client result in an RPC
> call and the isValid() method is executed at the application server?
>

If BankAccountEntity is the entity, and it's serializable, then the
client will get a copy of the object that is detached from the entity
manager's scope. Every method in the class will work just like you'd
expect it to (with one big exception). For instance, if you have
something like this very dumb example:

@Entity
public class BankAccountEntity {
   private String name;
   // public getter/setter for name not shown
   public boolean isValid() { return (name != null); }
}

Then calling isValid() on the remote instance of the object will
return true if the name isn't null. And the name field will have been
populated by the entity manager when the object was created, for
instance through a query.

The big exception is a field that is loaded lazily. By default,
collections are loaded lazily -- anything marked @OneToMany or
@ManyToMany (I think). Those fields won't be set until someone calls
the associated getter, and that will fail if the object is no longer
in scope (aka attached, aka managed).

Make sense? :)

It's a good idea to keep isValid() in the JPA entity if you can since
it's better encapsulation. A good short blog about whether or not you
want to send the JPA entity to a remote client is here:

http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to

For instance, you may have a bunch of lazily loaded fields and only
want to load them all eagerly in the case of a remote request. In that
case, you could create a DTO in the server and return it, and the DTO
constructor could call the getters on the entity, thus forcing the
desired fields to be loaded.

Cheers,
Bobby