jsf 2 managedproperty annotation and parameters - jsf-2

I'm using JSF 2 and Sprig 3, and I want to migrate from using faces-config.xml to annotations.
old one : faces-config.xml :
<managed-bean>
<managed-bean-name>banqueBean</managed-bean-name>
<managed-bean-class>commun.BanqueBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>banqueService</property-name>
<value>#{banqueService}</value>
</managed-property>
<managed-property>
<property-name>banqueId</property-name>
<value>#{param.banqueId}</value>
</managed-property>
</managed-bean>
new one :
public class BanqueBean{
private Banque banque;
#ManagedProperty(name = "banqueService", value = "#{banqueService}")
private BanqueService banqueService;
#ManagedProperty(value = "#{param.banqueId}")
private String banqueId;
// setters for banqueService and banqueId
the value of banqueId is set using :
<f:param value="#{banque.id}" name="banqueId" />
the problem is that when using faces-config.xml the "System" calls the setter of banqueService before the setter of parameter banqueId so that I can use banqueService inside setBanqueId method.
when using annotations it calls the setter of banqueId before banqueService so that I get null as a value of it.
why it inverses the call of this tow methods?

You should not rely on managed property setter method invocation order at all. This is nowhere definied in the specification.
Just hook at that point when JSF is finished with setting of all managed properties. That's the #PostConstruct annotated method.
#PostConstruct
public void init() {
banque = banqueService.find(banqueId);
}
Stop doing business logic in setters, this is only necessary if you're still using legacy JSF 1.1 which didn't support #PostConstruct.
Unrelated to the concrete problem, are you aware of the new JSF2 <f:viewParam>? It might as well help you to get rid of this boilerplate in the bean and end up having only a Banque property and a reusable Converter.
See also:
ViewParam vs #ManagedProperty(value = "#{param.id}")

Related

CDI/WELD can a custom qualifier work in combination with the #Named annotation?

While having a custom qualifier for CDI support as followed:
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD, PARAMETER, TYPE})
public #interface QualifiedFooBean {
}
#QualifiedFooBean
public class FooBean implements ImplFooBean {
}
public interface ImplFooBean {
}
I would like to bind FooBean #{fooBean} directly without requiring a wrapper or processor (seen from this example). The annotation "Named" (in class FooBean) seems not to work for my class layout.
My solution (without wrapper) which I'm wondering why it's not working and invoking: Target Unreachable, identifier 'fooBean' resolved to null
#Named
#QualifiedFooBean
public class FooBean implements ImplFooBean {
}
Has anyone any idea?
A wrapper is not needed. My solution is perfectly valid. It's also allowed to add Named in combination of a custom qualifier (in my case QualifiedFooBean). I had to just create an empty beans.xml file in WEB-INF folder in order to get CDI to work. Anyhow The question itself explains how custom qualifiers can work. You can also prefill beans.xml with following content:
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
It will serve as a skeleton for future use, if you need to configure more fancy stuff with CDI.
Adding #Named to your bean should work : it works for me.
In Fact #Named is a qualifier, when JSF resolve the Bean for displaying it does a lokup based on #Named qualifier. In CDI a bean is found if the lookup side (i.e. Injection point) ask for a subset of its Qualifier.
For instance a bean qualified like that :
#QualifiedFooBean
#SecondQualifier
public class FooBean {}
Will be found (if there is no ambiguous resolution) by
#Inject
#SecondQualifier
FooBean bean;
or even :
#Inject
FooBean bean;
But not by
#Inject
#SecondQualifier
#ThirdQualifier
FooBean bean;
So you can add the #Named qualifier and let CDI resolution engine do its job.

Context Initialization Parameters for Managed Bean

Background
A managed bean must have parameters configured through its web.xml file. The web.xml file defines context initialization parameters that are configured in JDeveloper (11.1.2.3) as follows:
The source for the definition of reporting.server.protocol follows:
<context-param>
<description>Defines the data transport mechanism to ret...</description>
<param-name>reporting.server.protocol</param-name>
<param-value>http</param-value>
</context-param>
The bean exposes public accessor methods for reportServerProtocol.
The source for the bean resembles:
#ManagedBean
#RequestScoped
public class OracleReportBean extends ReportBean {
#ManagedProperty("#{initParam['reporting.server.protocol']}")
private String reportServerProtocol = URLReportImpl.DEFAULT_PROTOCOL;
// ...
}
Problem
I would like to initialize the bean using context initialization parameters, rather than through FacesContext. In adfc-config.xml (note: not faces-confg.xml), some examples show references to initParam:
<managed-bean>
<managed-bean-name>reportBean</managed-bean-name>
<managed-bean-class>ca.corp.report.view.OracleReportBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>reportServerProtocol</property-name>
<property-class>java.lang.String</property-class>
<value>#{initParam['reporting.server.protocol']}</value>
</managed-property>
...
</managed-bean>
The key line being the value element #{initParam['reporting.server.protocol']}. However, JDeveloper shows the line as being incorrect. That is, the initParam context is not available within adfc-confing.xml.
The error is: "EL token initParam is unknown."
Question
Using an EL, how can the context initialization parameters be used to configure a managed bean, declaratively within ADFc?
Related Links
How to inject entire managed bean via #ManagedProperty annotation?
http://balusc.blogspot.ca/2011/09/communication-in-jsf-20.html
https://stackoverflow.com/tags/el/info
http://www.oracle.com/technetwork/developer-tools/adf/learnmore/43-remote-task-flow-169185.pdf
http://docs.oracle.com/cd/E25178_01/web.1111/b31974/taskflows_activities.htm
A bug in JDeveloper causes errors to be displayed:
However, even though the IDE displays an error, the code executes as expected.
In the ui layer you could try something like this :
<c:set target="${BeanName}" property="PropertyName" value="${true}"/>

To get current Instance of the session scoped bean in Jsf 2.0

i referred to this question and i've a similar problem
JSF - Get the SessionScoped Bean instance
I want to get the current instance of a managed bean in another managed bean. I've a SuperBean which is extended in a base Class - baseBean.
I set the value of a list - itemList in baseBean. The getter setter of the list are in SuperBean and I should use this SuperBean in my BackingBean to get the value of the itemList.
I tried using -
Application app = FacesContext.getCurrentInstance().getApplication();
ValueBinding vb = app.createValueBinding("#{superbean}");
SuperClass superclass = (SuperClass) vb.getValue(FacesContext.getCurrentInstance());
When I try to print superclass.getItems(); - It gives only this - []
And also this -
SuperClass superclass = (SuperClass)FacesContext.getCurrentInstance().
getExternalContext().getSessionMap().get("superbean");
When I try to print with this - It throws exception as my superbean entry is not present in the sessionMap even though the entry is placed in facesConfig and also as #ManagedBean and #sessionscoped
Kindly help me resolve this.
You can inject a managed bean into another if the injected bean has the same or broader scope. Here is an example:
#ManagedBean(name = "oneBean")
#ViewScoped
public class OneBean{
// injections
#ManagedProperty(value = "#{anotherBean}")
private AnotherBean anotherBean;
// don't forget to add getter and setter for anotherBean
...
}

CDI Injection into a FacesConverter

From just a few searches, this seems like a problem that has been around for a while. I have written a FacesConverter that looks like the following. The object Category is a JPA entity and CategoryControl is the DAO that fetches it.
#FacesConverter(value = "categoryConverter")
public class CategoryConverter implements Converter {
#Inject private CategoryControl cc;
public CategoryConverter() { }
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (cc != null) return cc.getByName(value);
System.out.println("CategoryConverter().getAsObject(): no injection!");
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (!(value instanceof Category)) return null;
return ((Category) value).getName();
}
}
As you probably guessed by now, I never get the injection. I got this workaround from this page, which looks like this.:
Workaround for this problem: create this method in your localeController:
public Converter getConverter()
{
return FacesContext.getCurrentInstance().getApplication().createConverter("localeConverter");
}
and use converter="#{localeController.converter}" in your h:selectOneMenu.
However I can't make this work either. My backing bean creates and returns a converter all right, but it doesn't get the object injected into it.
I am using MyFaces CODI 1.0.1. With the current GlassFish/Weld container. Can anyone suggest a solution before I re-code to not use a Converter?
Replace
#FacesConverter(value = "categoryConverter")
by
#Named
and use
<h:inputSomething converter="#{categoryConverter}" />
or
<f:converter binding="#{categoryConverter}" />
instead of
<h:inputSomething converter="categoryConverter" />
or
<f:converter converterId="categoryConverter" />
By the way, similar problem exist for #EJB inside a #FacesConverter. It however offers a way to be grabbed by JNDI manually. See also Communication in JSF 2.0 - Getting an EJB in #FacesConverter and #FacesValidator. This way you can use a #FacesConverter(forClass=Category.class) without manually defining it everytime. Unfortunately I can't tell from top of head how to realize that for CDI beans.
Update: if you happen to use JSF utility library OmniFaces, since version 1.6 is adds transparent support for using #Inject and #EJB in a #FacesConverter class without any additional configuration or annotations. See also the CDI #FacesConverter showcase example.
The #Inject Annotation only works in CDI managed instances. If you want to use CDI features inside a non-CDI managed instance (Like a JSF Validator or a JSF Converter) you can just programm against the CDI API.
This works only in at least Java EE 7 + CDI 1.1 server.
#FacesValidator("userNameValidator")
public class UserNameValidator implements Validator {
private UserService userService;
public UserNameValidator(){
this.userService = CDI.current().select(UserService.class).get();
}
#Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
....
}
}
https://docs.oracle.com/javaee/7/api/javax/enterprise/inject/spi/CDI.html
With all the AnnotationHell in Java EE people forget how to code.
Just use #Advanced of CODI for your #FacesConverter see the Wiki.
As soon as a converter or a validator is annotated with #Advanced it's possible to use #Inject.
Per BalusC's answer here, I decided to add JSF (requestscoped) managed beans that only contained #FacesConverter and Converter to resolve this issue in my app, since I'm migrating from JSF managed beans to CDI managed beans.
I tried CODI #Advanced against #FacesConverter, but it does not inject the bean at all.

#ManagedProperty injected AFTER #PostConstruct

THIS PROBLEM IS ALREADY SOLVED IN THE MYFACES 2.1 IMPLEMENTATION
I have a link which passes an Integer parameter properly like this:
<h:link outcome="/process/createProcess">
<f:param name="id" value="#{process.idprocess}" />
Edit
</h:link>
It goes to "createProcess.xhtml?id=21" properly, and I have this code in the request scope backing Bean createProcess:
#ManagedProperty(value="#{param.id}")
private Integer idProcess;
private Process newProcess;
#PostConstruct
public void init()
{
log();
if (idProcess!=null)
newProcess = Dao.getProcessDAO().get(idProcess);
else
newProcess = new Process();
}
I've notice that idProcess is always null. After debugging I realized that setIdProcess method is called AFTER #PostConstruct.
I understand that injection is done just after the construction of the bean and all the managedProperties are available in #PostConstruct.
What am I missing?
Just for reference, I think the issue in this post is MYFACES-3116, with was already fixed at , so 2.0.6, 2.1.0 and upper versions does not have it.

Resources