Java Reference
In-Depth Information
bytecode of the class (unlike source retained annotations). If the
JPA
container,
JPA
provider,
EJB
container, Spring, or anyone else, looks at the raw class bytes to deter-
mine which classes need to be managed, then the annotations can be found easily.
This is a common way to locate annotated classes, and so most containers will locate
your annotated classes, even if you don't import the annotation package. Up to this
point there isn't a problem; annotated classes will be found correctly, the problem is
with what happens next...
Having identified an annotated class for processing, it's common practice to load
it, and then use the Java reflection
API
to find the rest of the annotations present on
the class. There are two main reasons for this. First, it's much easier to use the reflec-
tion
API
than bytecode scanning to find all the annotations on a given class, and the
annotations are returned in a more easily used form. Second, by loading the class it's
much easier to find any annotations it has inherited from its type hierarchy. Those of
you who are particularly on the ball may now have noticed the problem. If the type is
loaded but the annotation package isn't available, then none of the annotations will
be visible! If you're lucky, this will cause an immediate failure, but usually containers
have sensible defaults for cases where there are no annotations. This can lead to part-
configured objects being used by the container, almost always with spectacularly
unpleasant results.
javax.persistence
isn't the only package that can potentially cause this problem,
and because some packages contain
only
annotations, it's entirely possible that you
might run into this problem elsewhere. If you do use annotations, then consider using
a manifest generation/validation tool like bnd to make sure that you don't acciden-
tally end up in this situation.
JPA CLIENTS IN OSGI
Building a working manifest for a persistence bundle isn't a particularly difficult task,
but this is only part of the story. The other difference between
OSG
i and Java
SE
is the
way in which clients obtain an
EntityManagerFactory
. Unfortunately, this often
requires changes to the client code. In Java
SE
, the
API
for obtaining an
EntityManager-
Factory
is the
Persistence
bootstrap class, as follows:
Persistence.createEntityManagerFactory("myPUnit");
This model has a number of problems in
OSG
i. We've already mentioned the visibility
of the persistence descriptor, but there are also general problems with static factories
in
OSG
i that we'll discuss further in section 12.3.1. To avoid these problems in
OSG
i,
the
JPA
runtime registers the
EntityManagerFactory
as a service in the Service Regis-
try. After a client has looked up this service, it can use it in the same way that it did
before. In the case where there are multiple persistence units defined in the system,
then clients can filter on the persistence unit's name using the
osgi.unit.name
ser-
vice property.
This code change may seem like a big problem, but it's almost never pervasive.
Because
EntityManagerFactory
objects are designed to be created once and reused,