JPA in practice

Discussion in 'Java' started by Lew, Aug 11, 2009.

  1. Lew

    Lew Guest

    JPA (Java Persistence API) makes promises about injection of references and
    behavior through magic annotations like @Entity and @PersistenceContext. To
    keep those promises, JPA apps must deploy into containers that know how to
    inject, like GlassFish or Spring or (supposedly) Java Server Faces (JSF). You
    can still use JPA without injection in a leaner Tomcat environment.

    The key enablers to JPA are EntityManagerFactory and EntityManager. You
    define a bunch of @Entity classes to pull database information into your
    object model as value objects. Logic instances, i.e., business processes that
    use these entities need an EntityManager to bind the objects to their data
    store backing. For non-injected environments like plain Tomcat, you use a
    static method to create the factory:

    public class Util
    {
    private static final String PUNIT = "projectPU";
    private static final EntityManagerFactory EMFCANON =
    Persistence.createEntityManagerFactory( PUNIT );

    public static EntityManagerFactory getEmf()
    {
    return EMFCANON;
    }
    }

    The factory will be heavy but thread safe. Request processors get their
    lightweight, non-thread-safe EntityManagers from the common factory:

    public class BizProcess
    { ...
    public String submit()
    {
    EntityManager emgr = Util.getEmf().createEntityManager();
    try
    {
    Entity e = new Entity();
    fill( e );
    emgr.getTransaction().begin();
    emgr.merge( e );
    emgr.getTransaction().commit();
    }
    finally
    {
    emgr.close();
    }
    }
    }

    Not as sexy as @PersistenceContext() but it works.

    --
    Lew
     
    Lew, Aug 11, 2009
    #1
    1. Advertising

  2. Lew wrote:
    > JPA (Java Persistence API) makes promises about injection of references
    > and behavior through magic annotations like @Entity and
    > @PersistenceContext. To keep those promises, JPA apps must deploy into
    > containers that know how to inject, like GlassFish or Spring or
    > (supposedly) Java Server Faces (JSF). You can still use JPA without
    > injection in a leaner Tomcat environment.
    >
    > The key enablers to JPA are EntityManagerFactory and EntityManager. You
    > define a bunch of @Entity classes to pull database information into your
    > object model as value objects. Logic instances, i.e., business
    > processes that use these entities need an EntityManager to bind the
    > objects to their data store backing. For non-injected environments like
    > plain Tomcat, you use a static method to create the factory:
    >
    > public class Util
    > {
    > private static final String PUNIT = "projectPU";
    > private static final EntityManagerFactory EMFCANON =
    > Persistence.createEntityManagerFactory( PUNIT );
    >
    > public static EntityManagerFactory getEmf()
    > {
    > return EMFCANON;
    > }
    > }
    >
    > The factory will be heavy but thread safe. Request processors get their
    > lightweight, non-thread-safe EntityManagers from the common factory:
    >
    > public class BizProcess
    > { ...
    > public String submit()
    > {
    > EntityManager emgr = Util.getEmf().createEntityManager();
    > try
    > {
    > Entity e = new Entity();
    > fill( e );
    > emgr.getTransaction().begin();
    > emgr.merge( e );
    > emgr.getTransaction().commit();
    > }
    > finally
    > {
    > emgr.close();
    > }
    > }
    > }
    >
    > Not as sexy as @PersistenceContext() but it works.
    >

    If your client happens to still be wedded to OAS 10g (oc4j 10.1.3), with
    EJB 2.5 (the best way to put it), and JSF 1.1, you still have to forgo
    some of those nice annotations, and do things like you describe above. :)

    We're pushing them to switch to Weblogic...it's a hard slog. These are
    people that still use IE 6.

    AHS
     
    Arved Sandstrom, Aug 11, 2009
    #2
    1. Advertising

  3. Lew

    Tom Anderson Guest

    On Tue, 11 Aug 2009, Lew wrote:

    > public class Util
    > {
    > private static final String PUNIT = "projectPU";
    > private static final EntityManagerFactory EMFCANON =
    > Persistence.createEntityManagerFactory( PUNIT );
    >
    > public static EntityManagerFactory getEmf()
    > {
    > return EMFCANON;
    > }
    > }
    >
    > The factory will be heavy but thread safe. Request processors get their
    > lightweight, non-thread-safe EntityManagers from the common factory:
    >
    > public class BizProcess
    > { ...
    > public String submit()
    > {
    > EntityManager emgr = Util.getEmf().createEntityManager();
    > try
    > {
    > Entity e = new Entity();
    > fill( e );
    > emgr.getTransaction().begin();
    > emgr.merge( e );
    > emgr.getTransaction().commit();
    > }
    > finally
    > {
    > emgr.close();
    > }
    > }
    > }
    >
    > Not as sexy as @PersistenceContext() but it works.


    Is there a convenient way to write code that gets an injected
    EntityManager in a managed environment, but arranges its own provision in
    an unmanaged one? Is that a meaningful thing to ask for?

    tom

    --
    I think the Vengaboys compliment his dark visions splendidly well. -- Mark
    Watson, on 'Do you listen to particular music when reading lovecraft?'
     
    Tom Anderson, Aug 11, 2009
    #3
  4. Lew

    Lew Guest

    Tom Anderson wrote:
    > Is there a convenient way to write code that gets an injected
    > EntityManager in a managed environment, but arranges its own provision
    > in an unmanaged one? Is that a meaningful thing to ask for?


    I have a way, but I won't know if it works until I succeed at getting an
    injected one. Then I can compare the two scenarios.

    For the factory:

    public class Persistuff
    {
    public static final String PUNIT = "projectPU";

    @PersistenceUnit( unitName=PUNIT )
    private static EntityManagerFactory emf;

    private static final EntityManagerFactory EMFCANON =
    Persistence.createEntityManagerFactory( PUNIT );

    public static EntityManagerFactory getEmf()
    {
    return (emf == null? EMFCANON : emf);
    }
    }

    For the manager:
    <http://java.sun.com/javaee/5/docs/tutorial/doc/bnbrm.html#bnbrp>

    public class Bizzniss
    {
    @PersistenceContext
    private EntityManager em;

    public void run()
    {
    EntityManager mgr = (em != null? em
    : Persistuff.getEmf().getEntityManager());
    // use 'mgr' here
    }
    }

    Unknown: resource consumption and packratting caused by injected values, if any.

    Learning how to do this, I was running Glassfish 3 with a Postgres back end,
    but my 4 GB RAM server box's power supply just gave up the ghost. Turns out
    the combination of GF and PG with NetBeans was too much for my poor
    single-core 64-bit workstation with only 1 GB RAM. Then I tried the
    non-injective approach with Tomcat, Postgres and NetBeans. Turns out that
    runs just great on the workstation.

    That triggered a major "Hmmm." I may be on to a way to develop, deliver and
    deploy full-blown custom apps very quickly with very low administrative and
    hardware overhead.

    Looks like JSF, JSP, JPA and servlets on Tomcat are a winning combination.
    Once you factor in a few quirks.

    (Bonus - Tomcat plays well with other environments like Apache Web Server and
    many Java EE application servers.)

    --
    Lew
     
    Lew, Aug 12, 2009
    #4
  5. Lew wrote:
    > Tom Anderson wrote:
    >> Is there a convenient way to write code that gets an injected
    >> EntityManager in a managed environment, but arranges its own provision
    >> in an unmanaged one? Is that a meaningful thing to ask for?

    >
    > I have a way, but I won't know if it works until I succeed at getting an
    > injected one. Then I can compare the two scenarios.
    >
    > For the factory:
    >
    > public class Persistuff
    > {
    > public static final String PUNIT = "projectPU";
    >
    > @PersistenceUnit( unitName=PUNIT )
    > private static EntityManagerFactory emf;
    >
    > private static final EntityManagerFactory EMFCANON =
    > Persistence.createEntityManagerFactory( PUNIT );
    >
    > public static EntityManagerFactory getEmf()
    > {
    > return (emf == null? EMFCANON : emf);
    > }
    > }
    >
    > For the manager:
    > <http://java.sun.com/javaee/5/docs/tutorial/doc/bnbrm.html#bnbrp>
    >
    > public class Bizzniss
    > {
    > @PersistenceContext
    > private EntityManager em;
    >
    > public void run()
    > {
    > EntityManager mgr = (em != null? em
    > : Persistuff.getEmf().getEntityManager());
    > // use 'mgr' here
    > }
    > }
    >
    > Unknown: resource consumption and packratting caused by injected values,
    > if any.


    I wouldn't bother to do the above, but in response to Tom's question the
    above is what I would do. If that makes any sense. :)

    After all, there are no classpath issues - Java knows about the
    annotations. All that happens, from observation, is that if in a given
    situation that injection doesn't work then it doesn't work, and you
    proceed and use the other approach(es).

    My gut feeling is that if injection doesn't work then there's not much
    penalty. For example, if your version of JSF doesn't support specific
    annotations then nothing happens when you inadvertently use them.

    I simply haven't bothered doing anything like the above because I never
    write J2EE apps where it's not already known exactly what the
    environment is. And if the environment ever changes there'll be major
    advance notice.

    > Learning how to do this, I was running Glassfish 3 with a Postgres back
    > end, but my 4 GB RAM server box's power supply just gave up the ghost.
    > Turns out the combination of GF and PG with NetBeans was too much for my
    > poor single-core 64-bit workstation with only 1 GB RAM. Then I tried
    > the non-injective approach with Tomcat, Postgres and NetBeans. Turns
    > out that runs just great on the workstation.
    >
    > That triggered a major "Hmmm." I may be on to a way to develop, deliver
    > and deploy full-blown custom apps very quickly with very low
    > administrative and hardware overhead.
    >
    > Looks like JSF, JSP, JPA and servlets on Tomcat are a winning
    > combination. Once you factor in a few quirks.
    >
    > (Bonus - Tomcat plays well with other environments like Apache Web
    > Server and many Java EE application servers.)


    We ourselves (me and the other folks at the small consulting company I
    work for) have internally arrived at much the same conclusion. As in,
    why bother with a full-fledged app server when you don't need it?

    To your list of API's/frameworks I would also add Seam as a
    consideration, for some projects.

    AHS
     
    Arved Sandstrom, Aug 12, 2009
    #5
  6. Lew

    Tom Anderson Guest

    On Tue, 11 Aug 2009, Lew wrote:

    > Tom Anderson wrote:
    >> Is there a convenient way to write code that gets an injected EntityManager
    >> in a managed environment, but arranges its own provision in an unmanaged
    >> one? Is that a meaningful thing to ask for?

    >
    > I have a way, but I won't know if it works until I succeed at getting an
    > injected one. Then I can compare the two scenarios.
    >
    > For the factory:
    >
    > public class Persistuff
    > {
    > public static final String PUNIT = "projectPU";
    >
    > @PersistenceUnit( unitName=PUNIT )
    > private static EntityManagerFactory emf;
    >
    > private static final EntityManagerFactory EMFCANON =
    > Persistence.createEntityManagerFactory( PUNIT );
    >
    > public static EntityManagerFactory getEmf()
    > {
    > return (emf == null? EMFCANON : emf);
    > }
    > }
    >
    > For the manager:
    > <http://java.sun.com/javaee/5/docs/tutorial/doc/bnbrm.html#bnbrp>
    >
    > public class Bizzniss
    > {
    > @PersistenceContext
    > private EntityManager em;
    >
    > public void run()
    > {
    > EntityManager mgr = (em != null? em
    > : Persistuff.getEmf().getEntityManager());
    > // use 'mgr' here
    > }
    > }


    Do you need the injection bits in Persistuff? If injection is working,
    Bizzniss will get an EntityManager of its own, and never have to call
    Persistuff.getEmf(). The only time it will have to call it is when there
    is no injection, in which case the injected in field in Persistuff will be
    null anyway. I suppose this approach means you take advantage of the case
    where a EntityManagerFactory is injected but a PersistenceContext isn't.
    That seems like a bit of an unlikely case to me, but i am far from an
    expert on this.

    > Unknown: resource consumption and packratting caused by injected values, if
    > any.


    True that.

    > Learning how to do this, I was running Glassfish 3 with a Postgres back end,
    > but my 4 GB RAM server box's power supply just gave up the ghost. Turns out
    > the combination of GF and PG with NetBeans was too much for my poor
    > single-core 64-bit workstation with only 1 GB RAM. Then I tried the
    > non-injective approach with Tomcat, Postgres and NetBeans. Turns out that
    > runs just great on the workstation.
    >
    > That triggered a major "Hmmm." I may be on to a way to develop, deliver and
    > deploy full-blown custom apps very quickly with very low administrative and
    > hardware overhead.


    I'm surprised GF took *so* much extra memory (and CPU?). What's it doing?

    Are there any lightweight app servers that wouldn't be a big overhead over
    Tomcat (or perhaps even better, Jetty)?

    tom

    --
    SAWING CHASING CRUNCHING ROBOTIC DEMOLITION
     
    Tom Anderson, Aug 12, 2009
    #6
  7. Lew

    Lew Guest

    Lew wrote:
    >> Learning how to do this, I was running Glassfish 3 with a Postgres
    >> back end, but my 4 GB RAM server box's power supply just gave up the
    >> ghost. Turns out the combination of GF and PG with NetBeans was too
    >> much for my poor single-core 64-bit workstation with only 1 GB RAM.
    >> Then I tried the non-injective approach with Tomcat, Postgres and
    >> NetBeans. Turns out that runs just great on the workstation.
    >>
    >> That triggered a major "Hmmm." I may be on to a way to develop,
    >> deliver and deploy full-blown custom apps very quickly with very low
    >> administrative and hardware overhead.


    Tom Anderson wrote:
    > I'm surprised GF took *so* much extra memory (and CPU?). What's it doing?
    >
    > Are there any lightweight app servers that wouldn't be a big overhead
    > over Tomcat (or perhaps even better, Jetty)?


    In part the answer depends on how much app server you need. Tomcat already is
    an app server for web apps and web services. Arved's suggestion of Seam
    <http://www.jboss.com/products/seam/>
    seems promising.

    Do you need EJBs? Tomcat with Apache OpenEJB might do the trick. Seam does
    that, too. One day I'll test to find out, if I can figure out why I ever need
    EJBs.

    Do you just need dependency injection? Maybe Spring is enough (or too much -
    I'm still deciding).

    Do you need message queues? BPEL? Integrated JNDI? Multiple cooperating
    apps or quasi-independent components? Common services for multiple enterprise
    applications? Clustering or other scalability strategies?

    My untested hypothesis is that there's a threshold of system complexity or
    performance where the overhead of a full-blown app server like JBoss or
    Glassfish is less than the difficulty of managing or scaling piecemeal solutions.

    If nothing else, there's the fact that the job market requires practitioner
    skill in all of that, so it behooves me to buy a new power supply for my
    multi-core PC and keep practicing with full-bore Java EE.

    --
    Lew
     
    Lew, Aug 12, 2009
    #7
  8. On 12.08.2009 16:06, Lew wrote:

    > My untested hypothesis is that there's a threshold of system complexity
    > or performance where the overhead of a full-blown app server like JBoss
    > or Glassfish is less than the difficulty of managing or scaling
    > piecemeal solutions.


    I second that. That bad news is

    1. it's difficult to determine that level of complexity

    2. from my experience real world software tends to start out simple and
    ends up complex

    So it's probably worthwhile to consider going full JEE earlier than you
    really need it.

    Unfortunately those JEE containers do also have issues of their own.
    The fact that JBoss introduces the third transaction manager in a
    relatively short period of time gives you hints as to where they might
    lie. A pity TX management is so fundamental...

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Aug 14, 2009
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Vincent Cantin

    A implicit @Id for JPA for pure POJO ?

    Vincent Cantin, Dec 24, 2006, in forum: Java
    Replies:
    0
    Views:
    460
    Vincent Cantin
    Dec 24, 2006
  2. josh
    Replies:
    0
    Views:
    2,355
  3. Curtis
    Replies:
    4
    Views:
    14,827
    steve
    Jun 26, 2007
  4. JPA Implementations

    , May 13, 2007, in forum: Java
    Replies:
    0
    Views:
    415
  5. Harry
    Replies:
    0
    Views:
    352
    Harry
    May 16, 2007
Loading...

Share This Page