I'm having problems with CDI on tomcat. That's some relevant part of my code:
public class JPAUtil {
private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("unit");
#Produces #RequestScoped
public static EntityManager getEntityManager() {
return emf.createEntityManager();
}
public void close(#Disposes EntityManager em) {
em.close();
}
}
My DAO Class:
public class DAO<T> implements Serializable{
private final Class<T> classe;
#Inject
protected EntityManager em;
public DAO(Class<T> classe) {
this.classe = classe;
}
}
and a child class:
public class UserDao extends DAO<User> implements Serializable{
public UserDao() {
super(User.class);
}
}
Because of the Generics, I used a producer for the DAO class:
public class DAOFactory {
#Produces
#SuppressWarnings({ "rawtypes", "unchecked" })
public DAO createDAO(InjectionPoint injectionPoint) {
ParameterizedType type = (ParameterizedType) injectionPoint.getType();
Class classe = (Class) type.getActualTypeArguments()[0];
return new DAO(classe);
}
}
In this example:
public class Test {
#Inject UserDAO userDAO;
#Inject DAO<User> dao;
}
When I try to use the UserDAO class, everything works fine, but when I use the DAO, the EntityManager remains null. Anyone have any idea?
In DAOFactory you instantiate the DAO with new operator, if you do so, CDI has no chance to inject dependencies in the DAO instance.
While in UserDAO CDI manages the entity manager injection.
So in DAOFactory you should set manually the entity manager in the newly created DAO instance.
Related
I've coded this aspect:
#Aspect
public class LoggingCacheAspect {
#Pointcut("call * javax.cache.integration.CacheLoader.load(*)")
void cacheLoadCalls() {};
#Before("cacheLoadCalls")
public void beforeCacheCalls() {}
}
Also, I'm using CDI, and I'm looking forward to figure out how to inject a bean into this aspect.
I guess that adding #Inject annotation will not be enought.
Is it possible?
How could I get it?
You need to use an interceptor instead of the aspect
Here is an example:
#InterceptorBinding
#Target({TYPE, METHOD })
#Retention(RUNTIME)
public #interface CacheLog{
}
#Interceptor
#CacheLog
public class CacheLogInterceptor implements Serializable {
private static final long serialVersionUID = 1L;
#Inject
private YourBean yourBean;
#AroundInvoke
public Object cacheLogMethodCall(InvocationContext ctx) throws Exception {
//#Before
yourBean.method();
...
return ctx.proceed();
}
}
#CacheLog
public void cacheLoadCalls() {
...
...
}
I'm pretty new to the general procedure of bean injection. I've googled a lot but haven't found a solution to my problem.
Additional Information
Running Wildfly 9.0.1 final
EJB Vers. : 3.1
CDI Vers. : 2.2.16 (SP1)
JSF Vers. : 2.2
import javax.annotation.PostConstruct;
import javax.ejb.Stateless;
import javax.inject.Named;
#Named
#ViewScoped
public class UserEmailSettingsBean extends UserModuleSettingsBean {
private List<String> store;
private List<String> selectedStore;
//getters and setters, some fancy stuff...
#Override
public boolean saveProperties() {
LOG.info("Save called");
LOG.info(selectedStore.toString());
LOG.info(store.toString());
for(String prop : store) {
getProperties().setProperty(prop, String.valueOf(false));
}
for(String selectedProp : selectedStore){
LOG.info("selected: " + selectedProp + ":" + getProperties().getProperty(selectedProp) + " -> true");
getProperties().setProperty(selectedProp, String.valueOf(true));
}
super.saveProperties();
return true;
}
}
2nd Class:
public abstract class UserModuleSettingsBean implements ModuleSettings {
private static final long serialVersionUID = 459417872482285085L;
protected abstract List<String> getPropertiesName();
#Inject
private SettingsRepository settingsRepository;
#Inject
private SettingsService settingsService;
private Properties properties = new Properties();
#Override
public boolean saveProperties() {
String username = SecurityContextHolder.getContext().getAuthentication().getName();
settingsService.store(getProperties(), username);
return (true);
}
}
The problem is, that the settingsService is constructed, however its field "settingsRepository" is null in my child class.
On the call of my save method from UserEmailSettings, getProperties().setProperty() is called with the right values, however its never stored, as the settingsRepository is null. I believe that is due to a wrong Injection for some reason.
Let me know if I need to provide more information ☺
Here is the needed part of SettingsRepository:
#Stateless
#TransactionAttribute(TransactionAttributeType.SUPPORTS)
public class SettingsService implements Serializable {
private static final long serialVersionUID = 1695882717866085259L;
#Inject
SettingsRepository settingsRepository;
//...
}
And here the information SettingsRepository
#Stateless
public class SettingsRepository extends AbstractBaseRepository<Settings, Long> {
/**
* Instantiates a new settings repository.
*/
public SettingsRepository() {
super(Settings.class);
}
}
wanted to say my problem was that I didn't called an init() function on the settingsService to create the propertys, so getProperties was empty
I'm trying to set a value to my ManagedProperty but I'm getting the null result when I try to print this.
I'd like to set the Bean Class to use it in my query.
I've been tryin' set String, Class, but all the times it returned a null value.
Can anyone help me?
#ManagedBean
public class FilialBean extends BaseBean implements Serializable{
private Filial filial;
private List<Filial> filiais;
#ManagedProperty("#{entidadeService}")
private EntidadeService service;
#PostConstruct
public void init(){
service.setFaces(Filial.class);
filial = new Filial();
filiais = (List<Filial>) (List) service.getbasesEntidades();
}
//GETTERS AND SETTERS
}
#ManagedBean(name="entidadeService", eager=true)
#ApplicationScoped
public class EntidadeService implements Serializable{
private List<EntidadeBase> basesEntidades;
private Class faces;
#PostConstruct
public void init(){
System.out.println(faces.getSimpleName());
try{
EntityManager manager = JPAUtil.getEntityManager();
Query query = manager.createQuery("SELECT e FROM Filial e WHERE e.ativo = :ativo");
query.setParameter("ativo", true);
this.basesEntidades = query.getResultList();
}
catch(Exception e){
e.printStackTrace();
}
}
public List<EntidadeBase> getbasesEntidades() {
return basesEntidades;
}
public Class getFaces() {
return faces;
}
public void setFaces(Class faces) {
this.faces = faces;
}
}
Have you check that #ManagedBean has same package in both classes?
I ran into same problem, a property with null value executing Post Construct method and this is the problem, one class had javax.annotation.ManagedBean (CDI) annotation and the other had javax.faces.bean.ManagedBean (JSF) annotation.
In my case I needed both classes with JSF annotations...
I've the below managed bean
#ManagedBean
#RequestScoped
public class customerBean {
private Customer customer;
private CustomerJpaController customerJpa;
#PostConstruct
public void init() {
customer = new Customer();
}
public String addCustomer() throws Exception {
customerJpa.create(customer);
return "customer";
}
// getter and setter
}
The CustomerJpaController looks like below:
public class CustomerJpaController implements Serializable {
#PersistenceContext(unitName = "JFSCustomerPU")
private EntityManagerFactory emf = null;
private UserTransaction utx = null;
public CustomerJpaController(UserTransaction utx, EntityManagerFactory emf) {
this.utx = utx;
this.emf = emf;
}
// ...
}
When addCustomer() is invoked from the view, it throws java.lang.NullPointerException at line customerJpa.create(customer);. How is this caused and how can I solve it?
In your code sample, your CustomerJpaController is never instantiated. So, you get a null pointer exception.
I advise you to switch to CDI and rely on its injection method to have your entity manager (factory?) properly instantiated and injected in your controller when this last is instantiated. And, so, to use #Named instead of #ManagedBean.
So, you would have :
#Named
#RequestScoped
public class CustomerJpaController implements Serializable {
...
}
(or whichever scope better fits your need)
It seems to me that you should use an EntityManager (EM) rather than an EntityManagerFactory (EMF) in your controller.
If your EMF is container managed and you have only one persistence unit, you can use the standard JPA #PersistenceContext annotation :
#PersistenceContext
private EntityManager entityManager;
If your EMF is not managed, you can leverage the power of deltaspike JPA module (remember : deltaspike is good for you :-) ) and inject an EntityManager in your controller :
#Named
#RequestScoped
public class CustomerJpaController implements Serializable {
#Inject
private EntityManager em;
}
This requires the implementation of an EntityManagerProducer class, which can have any name but must have one method annotated #Produces #RequestScoped returning an EntityManager and another one taking an EntityManager parameter annotated with #Disposes. Ex :
public class MyEntityManagerProducer {
#Inject
#PersistenceUnitName("myPU")
private EntityManagerFactory emf;
#Produces
#RequestScoped
public EntityManager createEntityManager() {
return emf.createEntityManager();
}
public void disposeEntityManager(#Disposes em) {
if (em.isOpen()) {
em.close();
}
}
Note the usage of #PersistenceUnitName("myPU"), the deltaspike annotation that will handle the instanciation of the EMF.
If you have multiple persistence units, as it is often the case in the real world, you can set them apart with qualifiers. To declare a qualifier, declare an #interface with the following annotations :
#Target({ FIELD, METHOD, PARAMETER, TYPE })
#Retention(RUNTIME)
#Documented
#Qualifier
public #interface MyQualifier {
}
Then, add this qualifier to all #Produces, #Disposes and #Inject, to allow CDI to decide which persistence unit / entity manager you are willing to use :
public class MyEntityManagerProducer {
#Inject
#PersistenceUnitName("myPU")
private EntityManagerFactory emf;
#Produces
#MyQualifier
#RequestScoped
public EntityManager createEntityManager() {
return emf.createEntityManager();
}
public void disposeEntityManager(#Disposes #MyQualifier em) {
if (em.isOpen()) {
em.close();
}
}
and in your controller :
#Named
#RequestScoped
public class CustomerJpaController implements Serializable {
#Inject
#MyQualifier
private EntityManager em;
}
All this requires CDI. Configuring CDI is way beyond a short answer to your question. I use OpenWebBeans in all my projects. Weld is also very popular.
This is my understanding of things (it might not be 100% correct but it will give you a general idea) :
Where in your bean is your Service instantiated ? Nowhere. In other words customerJpa is null.
Starting a connection to a db weights a lot on resources. So instead of you instantiating different services by yourself and opening-closing connections, the container has a pool of services and give the free ones to whoever needs it (in your case your bean needs one). How do you ask the container to give you a service :
Annotate #EJB above your service:
#EJB
private CustomerJpaController customerJpa;
and I think you are missing #Stateless as well
#Stateless
public class CustomerJpaController...
It's advised to switch to #Named and #RequestScoped (the other package) instead of #ManagedBean. Then you can use #Inject to inject your service instead of #EJB.here you can read further on the subject.
I am using picketlink to authenticate a user on project. I also created a #produces annotated method, so I would be able to inject the authenticated user in other places. Now, I am using envers and besides the default information, I would like to store the user that performed the action, but I cannot inject it in the envers listener. It is always null. How can I make this injection, or retrieve this information?
The producer class:
#SessionScoped
public class Resources implements Serializable {
private static final long serialVersionUID = 1L;
#EJB
private AuthenticationManagerBean authenticator;
#Inject
private Identity credentials;
#CurrentUser
private AuthenticatedUser currentUser;
#Produces
#CurrentUser
#SessionScoped
private AuthenticatedUser createAuthenticatedUser() {
AuthenticatedUser user = new AuthenticatedUser();
org.picketlink.idm.model.basic.User loggedInUser = (org.picketlink.idm.model.basic.User) credentials.getAccount();
User pu = authenticator.getUserRoles(loggedInUser.getLoginName());
if (pu != null) {
user.setUser(pu.getName());
for (Role role : pu.getRoles()) {
user.getRoles().add(role.getName());
}
}
return user;
}
#Produces
public Logger produceLog(InjectionPoint injectionPoint) {
return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
and the envers listener:
public class AuditListener implements RevisionListener, Serializable {
private static final long serialVersionUID = 1L;
#Inject
#CurrentUser
private AuthenticatedUser identity; //this is always null
public void newRevision(Object revisionEntity) {
System.out.println(identity.getUser());
}
}
I had a similiar problem. The injection does not work because RevisionListener is not managed by CDI. That way, you have to lookup for the bean yourself. This is the way you could do it:
public AuthenticatedUser getAuthenticatedUser() {
BeanManager beanManager = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
Bean<AuthenticatedUser> bean = (Bean<AuthenticatedUser>) beanManager.getBeans(AuthenticatedUser.class, new AnnotationLiteral<CurrentUser>() {
}).iterator().next();
CreationalContext<AuthenticatedUser> ctx = beanManager.createCreationalContext(bean);
return (AuthenticatedUser) beanManager.getReference(bean, AuthenticatedUser.class, ctx);
}