2014-12-16 4 views
3

В настоящее время я использую PersistenceContext для ввода EntityManager. ЭМ впрыскивается отлично.Inject PersistenceContext с CDI

@Stateless 
public StatelessSessionBean implements StatelessSessionBeanLocal { 

    @PersistenceContext(unitName = "MyPersistenceUnit") 
    private EntityManager em; 

    @Override 
    public Collection<MyObject> getAllObjects(){ 
     CriteriaBuilder cb = em.getCriteriaBuilder(); 
     CriteriqQuery<MyObject> query = cb.createQuery(MyObject.class); 
     query.from(MyObject); 
     return em.createQuery(query).getResultList(); 
    } 
} 

Теперь я пытаюсь украсить бобов, и внезапно им не вводят. Я получаю исключение NullPointerException.

@Decorator 
public StatelessSessionBeanDecorator implements StatelessSessionBeanLocal { 

    @Inject 
    @Delegate 
    @Any 
    StatelessSessionBeanLocal sb 

    @Override 
    public Collection<MyObject> getAllObjects(){ 
     System.out.println("Decorated method!"); 
     return sb.getAllObjects(); 
    } 
} 

Я знаю, что EJB и CDI являются 2 совершенно разными менеджерами, поэтому никто не знает о другом. Я ожидаю, что @PersistenceContext является точкой инъекции EJB, а @Inject - CDI. Что я должен сделать, чтобы решить эту проблему и получить EntityManager для инъекций, как и следовало бы?

+0

Почему вы используете '@ Delegate' и' @ Any' на вашей точке впрыска? Соответствует ли конфиг вашему 'beans.xml'? Можете ли вы опубликовать его? Также, пожалуйста, укажите, какую версию используют стеклянную рыбку. –

ответ

9

Наилучшая практика для контекста постоянства и CDI заключается в том, чтобы сделать их CDI bean, чтобы избежать такого рода проблем.

public class MyProducers { 
    @Produces 
    @PersistenceContext(unitName = "MyPersistenceUnit") 
    private EntityManager em; 
} 

После того, что вы будете иметь возможность вводить EntityManager в КДИ пути. Берет EJB это будет:

@Stateless 
public StatelessSessionBean implements StatelessSessionBeanLocal { 

    @Inject 
    private EntityManager em; 

    @Override 
    public Collection<MyObject> getAllObjects(){ 
     CriteriaBuilder cb = em.getCriteriaBuilder(); 
     CriteriqQuery<MyObject> query = cb.createQuery(MyObject.class); 
     query.from(MyObject); 
     return em.createQuery(query).getResultList(); 
    } 
} 

Таким образом, вы будете иметь возможность украсить свой CDI боб без каких-либо проблем.

Если у вас есть несколько EntityManagers вы можете использовать классификаторы CDI, чтобы отличить их

+0

Если вы уже используете EJB, предположительно для вашего уровня контроллера, почему вы хотите использовать '@ CDI' для вставки в него« EntityManager ». Просто придерживайтесь '@ PersistenceContext' в своих EJB. Настолько проще и держит логику контроллера в EJB для более четкого/чистого разделения и всех других тонкостей, таких как CMT и т. Д. – NBW

+0

Потому что, если вы используете Java EE 6 и более, ваш уровень контроллера CDI. Используя EJB в качестве CDI bean, вы получаете лучшее из обеих спецификаций. –

+0

Я использовал только EJB, но теперь мне нужно украсить некоторые бобы. Поскольку @Decorated - это CDI, мне также нужно использовать CDI в других местах. Проблема заключалась в том, что CDI не был уверен, какой EntityManager должен вводить. Теперь с классом MyProducers, который решается. Спасибо! – Erates

2

@PersistenceContext является точкой инъекции EJB, в то время как @Inject является одним CDI

На самом деле, нет. @PersistenceContext аннотация может использоваться в CDI и не связана с EJB. Вы можете сделать что-то вроде этого:

@Named 
public class EntityDAO { 
    @PersistenceContext 
    private EntityManager manager; 

    ... 

} 

EJB использует @EJB аннотацию, чтобы ввести другую EJB, но он может придать любой боб или сохраняемость контекста CDI с одинаковыми аннотациями.