adam bien's blog

JPA Injection Shortcomings and Possible Workaround 📎

I got a really interesting question/suggestion as a feedback for p4j5 and the PDO pattern. If you are going to realize rich domain objects, sometimes it's necessary to access the resources like EntityManager from inside a JPA-Entity. Eg. sometimes it is useful to search for entites, access other Session Beans/Services etc. The problem here - dependency injection in JPA is not supported by the EJB-Container (now).
However simple Strategy algorithms, can be injected in e.g. the Service Facade, or Persitent Domain Object Facade (checkout p4j5)
Sample:

/** SessionBean Discount Strategy */
@Stateless
public class DiscountStrategyImpl implements DiscountStrategy { ... }

/** ShoppingCart uses a DiscountStrategy to calculate discount */
@Entity
public class ShoppingCart
{
  @Transient
  private DiscountStrategy strategy;
  ..
  void setDiscountStrategy(DiscountStrategy discountStrategy) { this.strategy = discountStrategy; }
}

/** Facade for ShoopingCart */
@Stateless
public class ShoppingCartService
{
  @EJB
   private DiscountStrategy strategy;

  public ShoppingCart findById(Object id)
  {
    final ShoppingCart cart = em.find(ShoppingCart.class, id);
    cart.setDiscountStrategy(strategy);
    return cart;
  }
}
The solution only works for the "master", and not dependent entities, however the master-entity could propagate the strategy to the children as well. This could change in Java EE 6 with the "Singleton Beans".
Thanks to Thomas Bauer for the suggestion of this pattern. He suggested the name "Service Injection". However "Strategy Injection" could be a better name for this specific case above.
Btw. there are now 24 approved observers in p4j5.