Based on CDI bean in JSF
I am having problems getting CDI working in a JSF project. I cannot get CDI to inject an interface based bean into the JSF file.
@Named
public class ClassBasedNamedBean {
public String getMessage() {
return "Class-based Hello World!";
}
}
@Named
public interface InterfaceBasedNamedBean {
public String getMessage();
}
public class InterfaceBasedNamedBeanImpl implements InterfaceBasedNamedBean {
@Override
public String getMessage() {
return "Interface-based Hello World!";
}
}
I can use both beans in the WebServlet environment:
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
@Inject
private ClassBasedNamedBean classBasedNamedBean;
@Inject
private InterfaceBasedNamedBean interfaceBasedNamedBean;
protected void doGet(...) ... {
PrintWriter pw = response.getWriter();
pw.println("classBasedNamedBean: " + classBasedNamedBean.getMessage());
pw.println("interfaceBasedNamedBean: " + interfaceBasedNamedBean.getMessage());
// Output:
// classBasedNamedBean: Class-based Hello World!
// interfaceBasedNamedBean: Interface-based Hello World!
}
}
But interfaceBasedNamedBean
not available on JSF page:
<p>ClassBasedNamedBean: #{classBasedNamedBean.message}</p>
<p>InterfaceBasedNamedBean: #{interfaceBasedNamedBean.message}</p>
Output:
<p>ClassBasedNamedBean: Class-based Hello World!</p>
<p>InterfaceBasedNamedBean: </p>
How can I fix this problem? Does JSF require explicit configuration for interfaceBasedNamedBean
?
source to share
What do I think best:
I don't think this is mentioned in the spec, but I'm pretty sure it is @Named
not intended to be used on interfaces.
At the end of the day, it's just a correspondence between type and EL name - and it seems that EL resolver can't find anything (specific) called interface name.
So, try annotating the implementation, not the interface - it should work. If you need to be flexible with different implementations of the same bean type - inject it into the controller bean and make the bean available.
source to share
Have you set javax.enterprise.inject.spi.BeanManager
as your BeanManager?
What happens if you add @Named("InterfaceBasedNamedBean")
to the class definition and remove the annotation from the interface? For what reason are you using annotations? CDI does not require them, unlike spring.
Have you tried using the manufacturer's method?
source to share
Try adding a scope to your bean using @RequestScoped for example. From Weld docs:
@Named annotations are not what class a bean does. Most of the classes in the bean archive are already recognized as beans. @Named annotations simply allow you to reference the bean to EL, most often from a JSF view.
source to share
CDI defines @Named as a String-based classifier. The purpose of the classifier is to distinguish which implementation to use at the injection point. The @Named javadoc provides an example:
public class Car {
@Inject @Named("driver") Seat driverSeat;
@Inject @Named("passenger") Seat passengerSeat;
...
}
Thus, @Named must annotate the concrete implementation.
@Named as a way of using CDI beans in JSF views can be thought of as a secondary function. @Named is not "@Inject for JSF" as it might seem.
source to share