I'm designing a client/server application that uses JPA and RMI.
On the server I bind in the rmiregistry a DAOFactory remote object used by clients to obtain remote references to dao objects that manage entity beans.
I came across is the old remote lazy loading problem and thought of a workarround to get over it: each entity bean has a transient remote reference to the DAOFactory ( I'm overriding readObject so that I get the remote reference when to entity is deserialised on the client side ) so that when a call to a method that uses an uninitialised atribute is made I use the dao to initialise that attribute.
Example:
Code:@Entity @Table(name = "users") public class User implements Serializable { private static final long serialVersionUID = 7125941441868989498L; /** User's id in the corresponding table */ @Id @GeneratedValue @Column(name = "user_id") private Long id = null; @ManyToMany( cascade={CascadeType.PERSIST}, fetch = FetchType.LAZY) @JoinTable(name = "user_phone", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "phone_id")) Set<Phone> associatedPhones= new HashSet<Phone>(); @Transient private transient IDaoFactory daoFactory = DaoFactory.getInstance(); private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); try { daoFactory = (IDaoFactory) Naming.lookup("//localhost:12345/JpaTest"); } catch (NotBoundException e) { e.printStackTrace(); } } public Set<Phone> getAssociatedPhones() throws RemoteException{ try{ associatedPhones.size(); }catch( LazyInitializationException e){ //is detached entity with associatedMachines not loaded IUserLazyLoader loader = daoFactory.createUserLazyLoader(); User usr = loader.loadAssociatedPhones(this); this.associatedPhones = usr.associatedPhones; } return associatedPhones; }Each dao call has it's own transaction, so this is safe from data integrity point of view. The downside is that I have to couple my entities to the RMI implementation of the server...Code:public User loadAssociatedPhones(User usr) throws RemoteException{ EntityManager em = EMFactory.createEntityManager(); try { usr = em.merge(usr); usr.getAssociatedPhones().size(); return usr; } finally { em.close(); } }
Thx, looking forward to your opinion ...


Reply With Quote