Java EE 7 - #Decorator, #Stateless and #PersistenceContext = nullpointerException - java

I'm using decorator pattern in java ee 7 (glassfish 4).
I've this decorator
#Decorator
public class FooIndexer implements FooService {
#Inject
#Delegate
FooService fooService;
private Logger logger = Logger.getLogger(FooIndexer.class.getName());
//#Inject
//Indexer indexer;
#Override
public Foo create(Foo foo, boolean index) {
fooService.create(foo, index);
if (index) {
System.out.println("Im in");
}
return foo;
}
}
And this ejb class
#Stateless(name = "fooService")
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
#DeclareRoles({"ADMINISTRATOR", "USER"})
public class FooServiceImpl implements FooService {
#PersistenceContext(unitName = "foo")
private EntityManager em;
#Resource(lookup="java:comp/EJBContext")
private SessionContext ctx;
/** CRUD **/
#RolesAllowed("ADMINISTRATOR")
public Foo create(Foo foo, boolean index) {
Principal cp = ctx.getCallerPrincipal();
System.out.println(cp.getName());
em.persist(foo);
return foo;
}
}
When I use this decorator pattern, EntityManager in EJB is null (without decorator, everything goes fine). I supose is because of decorator use #Inject instead of #EJB annotation (#EJB annotation can't be used in #Decorator), and EntityManager is not being injected.
But, what can I do to get entitymanager will be injected using #decorator?
Thank you

Try adding an empty beans.xml in your META-INF, this will activate CDI bean discovery. I had a similar issue with my project.
See oracle doc here : http://docs.oracle.com/javaee/6/tutorial/doc/gjbnz.html
You must create an empty beans.xml file to indicate to GlassFish Server that your application is a CDI application. This file can have content in some situations, but not in simple applications like this one.
http://docs.oracle.com/javaee/6/tutorial/doc/gjbju.html#gjcvh
Good luck !
Alexander Kirilov

Related

When I use dependecy injection like #Inject in my entity class it throw an error

#Stateless
public class MyAccountsBean {
#Inject SomeEntityClass someOtherBean;
#Resource UserTransaction jtaTx;
#PersistenceContext(unitName="AccountsPU") EntityManager em;
#Resource QueueConnectionFactory accountsJMSfactory;
#Resource Queue accountPaymentDestinationQueue;
public List<Account> processAccounts(DepartmentId id) {
// Use all of above instance variables with no additional setup.
// They automatically partake in a (server coordinated) JTA transaction
}
}
There are likely multiple issues, but one that sticks out is that all of the fields should be marked with the private modifier.
In addition, can you post the rest of your codebase and the error you are getting?

Proliferation of EntityManager in EJB 3

Consider this scenario:
#Stateless
public class A{
#PersistenceContext
private EntityManager em;
#EJB
B b;
#EJB
C c;
public void doSomeWork(){
b.doSomeWork();
c.doSomeWork();
em.persist(someStuff);
}
}
#Stateless
public class B{
#PersistenceContext
private EntityManager em;
public void doSomeWork(){
//Do stuff
em.persist(stuff)
}
}
#Stateless
public class C{
#PersistenceContext
private EntityManager em;
public void doSomeWork(){
//Do stuff
em.persist(stuff)
}
}
In this scenario I'm using three different EntityManagers for the same transaction (started in method doSomeWork() from class A
Now, the same transaction but with only one EntityManager:
#Stateless
public class A{
#PersistenceContext
private EntityManager em;
#EJB
B b;
#EJB
C c;
public void doSomeWork(){
b.setTheEntityManager(em);
b.doSomeWork();
c.setTheEntityManager(em);
c.doSomeWork();
em.persist(someStuff);
}
}
#Stateless
public class B{
private EntityManager em;
public void setTheEntityManager(EntityManager em){
this.em = em;
}
public void doSomeWork(){
//Do stuff
em.persist(stuff)
}
}
#Stateless
public class C{
private EntityManager em;
public void setTheEntityManager(EntityManager em){
this.em = em;
}
public void doSomeWork(){
//Do stuff
em.persist(stuff)
}
}
I've been reading about the EntityManager lifecycle but I just can't get if there's any advantage (in terms of performance, database connections,..) in the second scenario. My first answer would be yes because there's only one EntityManager but on the other hand I don't see any code examples using this approach (passing the EntityManager from EJB to EJB). Also, the Oracle Docs say "By automatically propagating the persistence context, application components don’t need to pass references to EntityManager instances to each other in order to make changes within a single transaction. The Java EE container manages the lifecycle of container-managed entity managers."
Anything you #Inject or #Resource from the container should never ever be passed somewhere else. That's a surefire way to create a memory leak and/or undefined behavior. There also is no advantage to doing the second, as the container automatically injects the correct EntityManager for you every time :)
So in short, never ever do the second scenario, always do the first scenario. The container is actually inject a Proxy that routes you to the correct (the same in your case since you haven't exited your transaction boundary) entity manager.
What's happening is the call into a.doSomeWork() has an implied TransactionAttribute.Required. If a transaction has not already been started, the container starts one for you. Subsequent calls to B and C now participate in that transaction. When you exit a.doSomeWork(), assuming that's where the transaction started, that's where the transaction commits. Anything done by A, B, and C all occur in the same transaction.

Can I use CDI to inject a resource into a JAX-RS Application/ResourceConfig?

I'd like for my ResourceConfig to have access to a database for its configuration. I've tried this:
#ApplicationPath("/api")
public class ApplicationConfig extends ResourceConfig {
#PersistenceContext(unitName = "myPU")
private EntityManager em;
#Inject
private MyEjb myEjb;
#PostConstruct
public void init() {
// em and myEjb are both null
...
}
But neither the EntityManager, not the EJB, are injected (both are null)
Is there a special way to do this in JAX-RS?
NOTE: I'm able to inject resources into a Path-annotated class just fine. I'm having trouble doing it in the actual ApplicationPath-annotated class.

How use analog #Autowired annotation in JavaEE (#Inject)?

In Spring project I can use #Autowired annotation.
#Service
public class DefaultUserService implements UserService {
...
#Autowired
private UserDao userDao;
But I don't understand how do it in JavaEE project. I found:
#Inject
private AvayaDao avayaDao;
But my avayaDao is NULL. I tried add annotation
#Default
public class AvayaService {
...
#Inject
private AvayaDao avayaDao;
but not helped. It id my Dao:
public interface AvayaDao extends BaseDao<AvayaSdr> {
List<AvayaSdr> getAll();
void insertCdr(AvayaSdr avayaSdr);
}
It is My Service:
#Default
public class AvayaService {
private static AvayaService instance;
#Inject
private AvayaDao avayaDao;
public synchronized static AvayaService me() {
if (instance == null) {
instance = new AvayaService();
}
return instance;
}
public Set<String> selectAllLoadedAVAYAcmCDRFiles() {
Set<String> result = new HashSet<>();
List<AvayaSdr> resultList = avayaDao.getAll();
for (AvayaSdr avayaSdr : resultList) {
result.add(avayaSdr.getHashValue());
}
return result;
}
public void insertCdr(String fileHash) {
AvayaSdr avayaCmCdr = new AvayaSdr("", fileHash, 0);
avayaDao.insertCdr(avayaCmCdr);
}
java.lang.NullPointerException
Either the AvayaDao must be an EJB and annotated with #Stateless or #Singleton or you use CDI injection and an empty beans.xml file is needed (http://docs.oracle.com/javaee/6/tutorial/doc/gjbnz.html) if you are using Java EE 6. In Java EE 7 the attribute bean-discovery-mode="all" must be set (https://docs.oracle.com/javaee/7/tutorial/cdi-adv001.htm).
UPDATE 1:
Enterprise Java Beans are POJOS annotated with #Stateless, #Statefull or #Singleton, that are managed by the EJB container inside the application server. They are able to access container specific services like the TimerService, the security context and aspects like transaction support and monitoring. Stateless enterprise java beans are also pooled by the application server.
UPDATE 2:
#Tiny Your right, but if AvayaDao is no EJB and your application contains a beans.xml file, where interceptors or other CDI specific POJOS are registered the default bean-discovery-mode is 'annotated' and the injection will not work with not annotated POJOS and explicitly setting the 'all' value is needed (http://www.adam-bien.com/roller/abien/entry/when_your_di_breaks_bean). Another option would be using no beans.xml if you explicitly know, that your application is only deployed in JAVA EE 7 environments.

EJB injection returns a null exception

I have a .ear that imports a .jar and a .war modules. I'm trying to inject a EJB on my war that exists in jar, and I'm getting a null pointer exception when I call it. Here's the code.
WAR PACKAGE
Controller
This property "private AutenticacaoBean authBean;" is getting a null pointer exception. I don't really know if I need to use #remote in any place, because I'm using different packages, but in the same ear.
public class LoginController extends AbstractController {
#EJB
private AutenticacaoBean authBean;
public void execute() {
//code
}
}
JAR PACKAGE
Bean
#Stateless
#LocalBean
public class AutenticacaoBean {
#EJB
private UsuarioDAO usuarioDao;
//code
}
Implementation
#Stateless
public class UsuarioDAOImpl implements UsuarioDAO {
public UsuarioDAOImpl() {
//code
}
//code
}
Interface
#Local
public interface UsuarioDAO {
//code
}
Any help would be great. Thank you for your time!
EJB 3.1 dropped the requirement for local interfaces and you are using AutenticacaoBean without the interface, but probably your Application Server is not compliant about EJB 3.1 and you cannot perform the injection in this way:
#EJB
private AutenticacaoBean authBean;
You could try to create an interface (AutenticacaoLocal for example) for your AutenticacaoBean with the needed methods and then inject this one in your LoginController:
#EJB
private AutenticacaoLocal authBean;
Exactly as you did for UsuarioDAOImpl.

Categories

Resources