I am using jsf2.2 with wildfly 8.1 and javaee7.
My CDI bean injection in the phaselistener works as expected, but the #PostConstuct method is never invocked
I have tried to annotate the phaselistener with #javax.enterprise.context.ApplicationScope, SessionScope and Dependent to no avail.
Apart from naming, this is the exact thing i do in my post construct.
//#ApplicationScope
//#SessionScope
//#Dependent
public class MyPhaseListener implements PhaseListener {
#Inject
#Any
private Instance<MyOrderedUrlHandler> myOrderedUrlhandlers;
private Map<String, List<MyOrderedUrlHandler> orderedUrlHandlersMap;
#PostConstruct
void mapOrderedUrlHandlers() {
LOG.info("Executing postconstruct");
orderedUrlHandlersMap = Maps.newHashMap();
for(final MyOrderedUrlHandler urlhandler : myOrderedUrlhandlers) {
final String handles = urlhandler.url();
final List<MyOrderedUrlHandler> registeredHandlers = orderedUrlHandlersMap.get(handles);
if(registeredHandlers == null) {
registeredHandlers = Lists.newArraList();
}
registeredHandlers.add(urlHandler);
orderedUrlHandlersMap.put(handles, registeredHandlers);
}
}
}
Method level injection also works fine.
Is it the case that #PostConstruct callback is not part of jsf phaselistener specs?
According to section 5.4.1 of the JSF 2.2 spec, PhaseListener is not a managed bean but is injectable.
According to section 5.4.2, managed beans must support lifecycle annotations #PostConstruct and #PreDestroy.
Since a PhaseListener is not a managed bean in the sense of JSF, it does not follow from the spec that a phase listener implementation must support #PostConstruct.
Related
The various #EnableXXXRepository annotations of Spring Data allow you to specify a custom base class for your repositories, which will be used as an implementation of methods in your repository.
If such a base class needs access to other beans in the ApplicationContext how does one get those injected? It doesn't work out of the box, because Spring Data instantiates those base classes itself, supporting only special store dependent constructor parameters.
Note: I created this answer in the chat to this now deleted question and thought it might be valuable for others, although the original question is gone.
In the #Enable...Repository annotation specify a repositoryBaseClass and repositoryFactoryBeanClass. Like this:
#EnableMongoRepositories(
repositoryBaseClass = MyBaseClass.class,
repositoryFactoryBeanClass = MyRepositoryFactoryBean.class)
In that RepositoryFactoryBean class, you can use normal dependency injection, because it is a Spring Bean, so, for example, you can get an instance of SomeBean injected via the constructor, as shown below:
public class MyRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends MongoRepositoryFactoryBean<T,S,ID>{
private final SomeBean bean;
public MyRepositoryFactoryBean(Class repositoryInterface, SomeBean bean) {
super(repositoryInterface);
this.bean = bean;
}
}
Your RepositoryFactoryBean now create an instance of a custom RepositoryFactory by overwriting 'getFactoryInstance'.
#Override
protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
return new MyMongoRepositoryFactory(operations, bean);
}
While doing so, it can pass on the bean to be injected. bean in the example above.
And this factory finally instantiates your repository base class. Probably the best way to do it is to delegate everything to the existing factory class and just add injecting of the dependency to the mix:
public class MyMongoRepositoryFactory extends MongoRepositoryFactory {
private final SomeBean bean;
MyMongoRepositoryFactory(MongoOperations mongoOperations, SomeBean bean) {
super(mongoOperations);
this.bean = bean;
}
#Override
protected Object getTargetRepository(RepositoryInformation information) {
Object targetRepository = super.getTargetRepository(information);
if (targetRepository instanceof MyBaseClass) {
((MyBaseClass) targetRepository).setSomeBean(bean);
}
return targetRepository;
}
}
There is a complete working example on Github.
Based on the third option/example provided in this answer https://stackoverflow.com/a/7531284/944396 I tried to have a converter be a property in my ViewScoped bean; however, when I do so it breaks the view scope for that bean (it gets constructed multiple times when it should not be).
I am not sure if I am doing something wrong, or if that example is assuming you are running a newer version of Mojarra that has fixed the ViewScope/binding issue. I myself am running Mojarra 2.1.6. Here is the bean code:
#ManagedBean
#ViewScoped
public class Bean {
private Double myVal;
private Converter converter;
public void Bean() {
converter = new MyCustomConverterClass();
}
public Converter getConverter() {
return converter;
}
public Double getMyVal() {
return myVal;
}
public void setMyVal(Double myVal) {
this.myVal = myVal;
}
}
And the usage:
<h:outputText value="#{bean.myVal}" converter="#{bean.converter}" />
You're right, it breaks the view scope. The converter attribute is evaluated during view build time. Apart from using other options listed in the answer you found How to set converter properties for each row of a datatable?, you'd need to upgrade to at least Mojarra 2.1.18.
I have a Managed Bean:
public class CategoriaManagedBean {
#EJB
private CategoriaBeanLocal categoriaBean;
private Categoria categoria;
private List<Categoria> menu;
}
In my constructor I try:
public CategoriaManagedBean() {
menu = categoriaBean.findByIdCategoriaPadre(0);
}
But I get a error "Cannot create the instance of the class", why can't I initialize the attribute in the constructor?
I fix the problem with:
#PostConstruct
public void init() {
menu = categoriaBean.findByIdCategoriaPadre(0);
}
But I want to know the reason and if I am doing well with #PostConstruct
Greetings.
Using #PostConstruct is the correct approach.
EJBs are injected after the constructor is invoked on a ManagedBean.
That's why there is a #PostConstruct annotation.
Here's the first line from the documentation:
The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization.
I have two beans:
#Named
#SessionScoped
public class Session implements Serializable {
private String temp;
+getter, setter
}
#Named
#RequestScoped
public class Test {
#Inject
private Session s;
#PostConstruct
public void init() {
this.sth = s.getTemp(); //here is exception
}
}
When I try to fetch in init same value from session I get NullPointerException. What am I doing wrong? Server is JBoss eap 6.0, JSF v2.1. Thanks in advance
Edit: I investigated that problem appears only when I have more than 11 items in primefaces submenu component. If I have less than 11 items every thinks work OK. I am using PrimeFaces v 3.5.
Edit 2: On session bean only constructor is invoked. I have method annotated with PostConstruct but it is not called. I always get NullPointerException after invoking any method on session from Test bean.
Is there a nice way to dependency inject using a jsp taglib?
either using ejb 3.0, spring, or guice...
I have a lot of services/pojos that I would like to use in my taglibs
I think you want Seam, it enables you to refer to a component by name. However, the released version is JSF based, but that's changing.
just stumbled upon your question because I plan to do the same. You can actually use Spring and its #Configurable annotation (with AspectJ load-time or compile-time weaving) to inject services into your tag implementations. For a detailed explanation of all options have a look at Ramnivas' blog post here.
Hope to help in case you still need a solution...
Keep a reference to your injector on the servletContext and then use in each tag as you need it. See
In your Guice setup:
public class GuiceServletConfig extends GuiceServletContextListener {
#Override
protected Injector getInjector() {
return Guice.createInjector(blah, blah);
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.removeAttribute(Injector.class.getName());
super.contextDestroyed(servletContextEvent);
}
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
Injector injector = getInjector();
ServletContext servletContext = servletContextEvent.getServletContext();
servletContext.setAttribute(Injector.class.getName(), injector);
super.contextInitialized(servletContextEvent);
}
}
And then in your taglib:
#Singleton
#SuppressWarnings("serial")
public class MySampleTag extends TagSupport {
#Inject private MyInjectedService myService;
#Override
public int doStartTag() throws JspException {
Injector injector = (Injector) pageContext.getServletContext().getAttribute(Injector.class.getName());
injector.injectMembers(this);
String value = myService.doSomething();
etc.
etc.