H3TGet H3T | API doc |
If you use Hibernate in a server and are returning entities
to a client in a different process, this framework may be for you.
Hibernate allows associated collections and single entities to be
marked as LAZY
(it's the
default for associated collections). When you attempt to access an
uninitialized lazy element, Hibernate will use the session associated
with the entity to load it for you under the covers. If you attempt to
access an uninitialized lazy element in your client, then you will see an
exception because your entity is no longer associated with a session.
Nor can it be.
H3T will intercept your attempts to access uninitialized lazy elements and load them from the server for you. This will happen as seamlessly as if it were being done by Hibernate on the server.
H3T hooks into JPA entity annotations (e.g., ManyToOne
) to intercept
your attempts to access associated elements. For this reason, you need
to be using Hibernate 3.0 or above and be using JPA annotations. You
do not need to be using EntityManager
. Nor do you need to be using JBoss
Application Server, or any Java EE container for that matter.
JBoss AOP (tested with 1.5), cglib (tested with 2.1.3), and Hibernate (with annotations).
Possibly. This topic even has its own entry in the Hibernate Users FAQ. It's also discussed in the Hibernate forum and mentioned in Hibernate In Action. You should be familiar with the pitfalls of following such a strategy before using H3T.
No. You have to annotate the associations with org.h3t.RemoteLoad
. Sometimes you want
to see LazyInitializationExceptions in your client because
they are highlighting coding errors (e.g., an association should have
been marked EAGER
). If
H3T were to handle all lazy associations for you then you would never,
ever see these exceptions and may miss coding errors.
When you mark an association with the org.h3t.RemoteLoad
annotation, you can specify an optional factory
parameter.
Set it to the class of a custom implementation of the org.h3t.LoadServiceFactory
interface.
Your implementation should return a reference to an org.h3t.LoadService
implementation.
The LoadService
interface
has methods for loading lazy elements. Normally your implementation (or
the implementation that sits on the server, at least) will simply pass
through the call to corresponding helper methods in org.h3t.Loader
.
Note that H3T doesn't care how your implementation of LoadService
makes
requests to the server. It could be an RMI stub, your own
implementation that generates HTTP requests—anything.
If you don't set the factory
parameter, then H3T will fall back on its default behavior.
To acquire a reference to a LoadService
, it will create an InitialContext
and look up an object named
"ejb/H3T/LoadService"
. The H3T distribution includes, in its own zip archive, org.h3t.ejb.LoadServiceBean
.
This is an EJB3 stateless session bean. If you deploy it in your EJB app and provide the client with an appropriate
jndi.properties
, H3T will work out of the box.
Yes. You need these VM arguments:
-Djboss.aop.path=[jboss-aop.xml] -javaagent:[location of JBoss AOP jars]/jboss-aop-jdk50.jar
jboss.aop.path
should point to wherever you place the jboss-aop-xml
file that ships with H3T.
Yes. Download the source archive and run the "runExample"
ant target. It builds and deploys an EAR and then runs a very simple
client application, which pulls back entities from the server. When the
client attempts to access uninitialized lazy associations, H3T kicks in.
To run this application, you'll need JBoss Application Server. If you don't have 4.0.4GA, you'll need to grab your Hibernate/EJB3 jars from JBoss and drop them into the appropriate H3T lib directories. The jars on the client and server need to match.
You'll also need to modify the properties in build.properties
to point to your JBoss installation.