I have a JSF managed bean and a JAX-RS web service.
ManagedBean - myBean class
#ManagedBean
#ViewScoped
public class MyBean implements Serializable {
private String id;//getters && setters ommited
}
Web Service - myService class
#ApplicationPath("/myService")
#Path("/")
#Consumes("application/json")
public class MyService extends Application {
#Inject
MyBean myBean;
#Path("doSth")
#POST
public Response doSomething(){
//make an action here and set myBean.id value
myBean.id = 'a random value';
}
}
I debugged the code above, but then I realised that inside myBean class, the property "id" was equal to null even though I had set it in the doSomething() method before, is it possible to achieve the scenario described above with these technologies? Before #Inject, I also tried the injection of my managedBean using #ManagedProperty, but the managedBean was null and not injected.
Then I would like this myBean.id property to be changed for the bean when I call it using myBean.id, is that feasible?
Thanks in advance!
How can I inject a dependency like #EJB, #PersistenceContext, #Inject, #AutoWired, etc in a #FacesConverter? In my specific case I need to inject an EJB via #EJB:
#FacesConverter
public class MyConverter implements Converter {
#EJB
protected MyService myService;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
// myService.doSomething
}
}
However, it didn't get injected and it remains null, resulting in NPEs. It seems that #PersistenceContext and #Inject also doesn't work.
How do I inject a service dependency in my converter so that I can access the DB?
Can I use #EJB to inject my service into a #FacesConverter?
No, not until JSF 2.3 is released. The JSF/CDI guys are working on that for JSF 2.3. See also JSF spec issue 1349 and this related "What's new in JSF 2.3?" article of my fellow Arjan Tijms. Only then dependency injection like #EJB, #PersistenceContext, #Inject, etc will work in a #FacesConverter when you explicitly add managed=true attribute to the annotation.
#FacesConverter(value="yourConverter", managed=true)
public class YourConverter implements Converter {
#Inject
private YourService service;
// ...
}
If not, what's the "correct" way to do this?
Before JSF 2.3, you have several options:
Make it a managed bean instead. You can make it a JSF, CDI or Spring managed bean via #ManagedBean, #Named or #Component. The below example makes it a JSF managed bean.
#ManagedBean
#RequestScoped
public class YourConverter implements Converter {
#EJB
private YourService service;
// ...
}
And the below example makes it a CDI managed bean.
#Named
#RequestScoped
public class YourConverter implements Converter {
#Inject
private YourService service;
// ...
}
Reference it as <h:inputXxx converter="#{yourConverter}"> instead of <h:inputXxx converter="yourConverter">, or as <f:converter binding="#{yourConverter}"> instead of <f:converter converterId="yourConverter">. Don't forget to remove the #FacesConverter annotation!
The disadvantage is that you cannot specify forClass and thus need to manually define the converter everywhere in the view where necessary.
Inject it in a regular managed bean instead.
#ManagedBean
#RequestScoped
public class YourBean {
#EJB
private YourService service;
// ...
}
And in your converter, grab or call it via EL.
YourBean yourBean = context.getApplication().evaluateExpressionGet(context, "#{yourBean}", YourBean.class);
// Then e.g. either
YourEntity yourEntity = yourBean.getService().findByStringId(value);
// Or
YourEntity yourEntity = yourBean.findEntityByStringId(value);
This way you can keep using #FacesConverter.
Manually grab the EJB from JNDI.
YourService yourService = (YourService) new InitialContext().lookup("java:global/appName/YourService");
The disadvantage is that there is a certain risk that this is not entirely portable. See also Inject EJB bean from JSF managed bean programmatically.
Install OmniFaces. Since version 1.6, it transparently adds support for #EJB (and #Inject) in a #FacesConverter without any further modification. See also the showcase. If you happen to need the converter for <f:selectItem(s)>, then the alternative is to use its SelectItemsConverter which will automatically perform the conversion job based on select items without the need for any database interaction.
<h:selectOneMenu ... converter="omnifaces.SelectItemsConverter">
See also Conversion Error setting value for 'null Converter'.
See also:
How to inject in #FacesValidator with #EJB, #PersistenceContext, #Inject, #Autowired
CDI Injection into a FacesConverter
Getting an #EJB in a #FacesValidator and #FacesConverter
The answer is Yes if you can accommodate Seam Faces module in your web application. Please check this post Injection of EntityManager or CDI Bean in FacesConverter. You can use #EJB in similar fashion.
You could access it indirectly through FacesContext, which is a parameter in both Converter methods.
The converter could be also annotated CDI Named with Application scope. When accessing the facade, two instances of the same class are used. One is the converter instance itself, dumb, without knowing EJB annotation. Another instance retains in application scope and could be accessed via the FacesContext. That instance is a Named object, thus it knows the EJB annotation. As everything is done in a single class, access could be kept protected.
See the following example:
#FacesConverter(forClass=Product.class)
#Named
#ApplicationScoped
public class ProductConverter implements Converter{
#EJB protected ProductFacade facade;
protected ProductFacade getFacadeFromConverter(FacesContext ctx){
if(facade==null){
facade = ((ProductConverter) ctx.getApplication()
.evaluateExpressionGet(ctx,"#{productConverter}",ProductConverter.class))
.facade;
}
return facade;
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return getFacadeFromConverter(context).find(Long.parseLong(value));
}
...
#Inject will only works in CDI managed instances
This only works at least Java EE 7 and CDI 1.1 server:
#FacesConverter
public class MyConverter implements Converter {
protected MyService myService;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
myService = CDI.current().select(MyService .class).get();
myService.doSomething();
}
}
https://docs.oracle.com/javaee/7/api/javax/enterprise/inject/spi/CDI.html
https://stackoverflow.com/a/33017416/5626568
By Luis Chacon, Sv
Works fine, tested
definition EJB :
#Stateless
#LocalBean
public class RubroEJB {
#PersistenceContext(unitName = "xxxxx")
private EntityManager em;
public List<CfgRubroPres> getAllCfgRubroPres(){
List<CfgRubroPres> rubros = null;
Query q = em.createNamedQuery("xxxxxxx");
rubros = q.getResultList();
return rubros;
}
}
define bean with the Aplication bean scope, for get the EJB Object
#ManagedBean(name="cuentaPresService", eager = true)
#ApplicationScoped
public class CuentaPresService {
#EJB
private RubroEJB cfgCuentaEJB;
public RubroEJB getCfgCuentaEJB() {
return cfgCuentaEJB;
}
public void setCfgCuentaEJB(RubroEJB cfgCuentaEJB) {
this.cfgCuentaEJB = cfgCuentaEJB;
}
}
final Access to Ejb Object from Converter:
#FacesConverter("cuentaPresConverter")
public class CuentaPresConverter implements Converter {
#EJB
RubroEJB rubroEJB;
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
if(value != null && value.trim().length() > 0) {
try {
CuentaPresService service = (CuentaPresService) fc.getExternalContext().getApplicationMap().get("cuentaPresService");
List<CfgCuentaPres> listCuentas=service.getCfgCuentaEJB().getAllCfgCuentaPres();
................
Edit: The comment section solved my problem! The problem was that I was using incorrect imports for the Scopes.
I have a simple JSF application (login, pull data from database, allow user to edit data). It works well, I want to update the code to use CDI (Weld), but I am having trouble.
I am following / looking at: http://docs.jboss.org/weld/reference/latest/en-US/html/example.html
Original stuff without Weld:
login.xhtml
<h:form id="inputForm">
<h:panelGrid columns="2" cellpadding="5" cellspacing="1">
<h:outputText id="nameDesc" value="Name"></h:outputText>
<h:inputText id="nameInput" value="#{login.loginName}" binding="#{name}"></h:inputText>
<h:outputText id="passwordDesc" value="Password"></h:outputText>
<h:inputSecret id="passwordInput" value="#{login.password}" binding="#{password}"></h:inputSecret>
</h:panelGrid>
<h:commandButton value="Login" action="#{login.login(name.value, password.value)}"/>
</h:form>
LoginBean.java:
#ManagedBean(name="login")
#SessionScoped
public class LoginBean implements Serializable {
private static final long serialVersionUID = 1L;
#ManagedProperty(value="#{db}")
private DatabaseBean db;
private String password;
private String loginName;
// other stuff and functions
public String getLoginName () {
return loginName;
}
public void setLoginName (String name) {
this.loginName = name;
}
public String getPassword () {
return password;
}
public void setPassword (final String password) {
this.password = password;
}
public void setDb(DatabaseBean db) {
this.db = db;
}
DatabaseBean.java:
#ManagedBean(name="db", eager=true)
#ApplicationScoped
public class DatabaseBean implements Serializable {
#PostConstruct
public void init() {
//... connect to database etc
}
}
---------What I tried to get it running with Weld (only changes from above to make it a bit shorter): --------
LoginBean.java, changed to #Named from #ManagedBean, added #Inject for DatabaseBean
#Named("login")
#SessionScoped
public class LoginBean implements Serializable {
// stuff
private #Inject DatabaseBean db;
}
DatabaseBean.java, changed to #Named from #ManagedBean:
#Named("db")
#ApplicationScoped
public class DatabaseBean implements Serializable {
}
LoginBean has a function:
public String login(String name, String password) {
System.out.println("login called"+name);
// other stuff
}
With my second implementation (the one where I try to use Weld), the print is called once: "login called", and the username is empty (I checked this with name.IsEmpty()).
I have also tried injecting it by constructor:
loginBean.java
#Inject
public LoginBean(DatabaseBean db) {
System.out.println("constructor");
this.db = db;
}
When I do this the I get lots of "constructor" prints, so it is called several times, but I don't see why - I guess this is the problem though, only one instance of LoginBean gets the input (username and password) and then lots of new ones are created for some reason. Why is that?
I use Eclipse and Tomcat8 to run it.
Thank you for reading!
managed bean constructor called multiple times
CDI may call constructor more often than expected while generating/creating enhanced subclasses/proxies. See also Field.get(obj) returns all nulls on injected CDI managed beans, while manually invoking getters return correct values. Just do not log constructor invocation, it would only confuse yourself. #PostConstruct is the only interesting method to hook on.
the print is called once: "login called", and the username is empty (I checked this with name.IsEmpty()).
As to the concrete problem of form input values being null when the action method is invoked, and thus the #SessionScoped CDI managed bean seemingly being recreated on every access, this matches the behavior of a #Dependent scoped bean. This is the default scope when no valid CDI managed bean scope can be found. See also What is the default Managed Bean Scope in a JSF 2 application?
This in turn suggests you imported #SessionScoped from the wrong package. Make sure it's from the javax.enterprise.context package and not from e.g. javax.faces.bean. JSF managed bean scopes are not recognizable as valid CDI managed bean scopes.
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
#Named("login")
#SessionScoped
public class LoginBean implements Serializable {
// ...
}
I'm trying to use an application scoped bean in JSF2, but for some reason it is always null in my request scoped bean. Here's the code I'm using:
The application scoped bean:
#ManagedBean(eager=true, name="applicationTracking")
#ApplicationScoped
public class ApplicationTracking implements Serializable {
private static final long serialVersionUID = 4536466449079922778L;
public ApplicationTracking() {
System.out.println("ApplicationTracking constructed");
}
}
The request scoped bean:
#ManagedBean
#RequestScoped
public class SearchResults implements Serializable {
private static final long serialVersionUID = 4331629908101406406L;
#ManagedProperty("#{applicationTracking}")
private ApplicationTracking appTracking;
public ApplicationTracking getAppTracking() {
return appTracking;
}
public void setAppTracking(ApplicationTracking appTrack) {
this.appTracking = appTrack;
}
#PostConstruct
public void init() {
System.out.println("SearchResults.init CALLED, appTracking = " + appTracking);
}
}
According to everything I'm seeing in the forums this should work without any other configurations. When I start the server (Tomcat) I'm seeing the ApplicationTracking constructor and init methods getting called.
But in my SearchResults component the printout in the PostConstruct is always null:
SearchResults.init CALLED, appTracking = null
What am I missing?
Provided that you imported those annotations from the right package javax.faces.bean.*, then this problem will happen if you re-registered the very same managed bean class in faces-config.xml on a different managed bean name. Get rid of that faces-config.xml entry. That's the JSF 1.x style of registering managed beans. You don't need it in JSF 2.x. When you do so anyway, then it will override any annotation based registration on the managed bean class, causing them to be ineffective.
Make sure you don't read JSF 1.x targeted resources while learning and working with JSF 2.x. Many things are done differently in JSF 2.x.
I am trying to inject a named bean in another one.
When I try to access properties of the injected bean , it returns null which means that the injection fails.
Here is the first Bean:
#Named
#SessionScoped
public class FirstMBean {
String caracter;
..........
public String goToNext(){
String caracter=FacesContext.getCurrentInstance().getExternalContext().
getRequestParameterMap().get("caracter"); this.caracter=caracter;
System.out.println("the selected caracteris"+ caracter);
return "/pages/next?faces-redirect=true"; }
}
The second named bean:
#Named
#SessionScoped
public class SecondMBean {
#Inject
FirstMBean firstMBean ;
String injectedCaracter ;
#PostConstruct
public void init() {
this.injectedCaracter = this.firstMBean.getCaracter();
System.out.println("injectedCaracter ----" + this.injectedCaracter);
}
In my .xhtml page :
<p:commandButton value="see caracter" action="#{firstMBean.goToNext}">
<f:param name="caracter" value="#{caracter}" />
</p:commandButton>
Please note that I am using tomcat server to which I added WELD to support CDI AND when I put the scope to ApplicationScoped, everything works fine.