Can't find beans annotated with #ManagedBean - jsf

While upgrading the JSF version of an old web application from MyFaces 1.1 to MyFaces 2.2.12, I am trying to replace the <managed-bean> entries in my faces-config.xml file with #ManagedBean annotations directly in the bean classes. I am using Migrating from JSF 1.2 to JSF 2.0 as a general guide for the migration.
For example, I am replacing something like
<managed-bean>
<managed-bean-name>MyBean</managed-bean-name>
<managed-bean-class>some.package.MyBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
with
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class MyBean {
According to Are there going to be two instances for a bean if I write #managed bean annotation and define same in faces-config.xml, annotations are overwritten by corresponding entries in the faces-config.xml, so I deleted the <managed-bean> element in my faces-config.xml.
Since the project consists of several maven modules which are packed as jars individually before being deployed as a combined war file, I also tried to follow the advice from How does JSF find beans annotated with #ManagedBean? and added another META-INF folder containing a faces-config.xml to the submodule containing the bean, at the following location (respecting the accepted answer in How to reference JSF managed beans which are provided in a JAR file?):
MainProject
| SubModule
| |src
| | main
| | resources
| | META-INF
| | faces-config.xml
with the following content:
<faces-config
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
</faces-config>
Sadly, I still get the following error when trying to open the page that uses this specific bean:
javax.el.PropertyNotFoundException: Target Unreachable, identifier 'MyBean' resolved to null
Since I am using JSF for bean management, I followed the JSF part of the instructions in Identifying and solving javax.el.PropertyNotFoundException: Target Unreachable but even after verifying the individual points mentioned there, I still get the same error.
I am using Tomcat 7 as servlet container, which - according to http://tomcat.apache.org/whichversion.html - supports servlet specification up to version 3.0, which, in turn, should suffice for JSF 2.2, which - if I understand correctly - requires at least servlet spec 2.5, according to http://myfaces.apache.org/core22/.
I have already searched quite a lot for the cause of the problem (as mentioned, I tried several of the SO articles mentioned above), but still can't solve the problem. I would be very grateful for any help!

The answer can be found in the #ManagedBean Javadoc:
The value of the ManagedBean.name attribute is taken to be the managed-bean-name. If the value of the name attribute is unspecified or is the empty String, the managed-bean-name is derived from taking the unqualified class name portion of the fully qualified class name and converting the first character to lower case. For example, if the ManagedBean annotation is on a class with the fully qualified class name com.foo.Bean, and there is no name attribute on the annotation, the managed-bean-name is taken to be bean. The fully qualified class name of the class to which this annotation is attached is taken to be the managed-bean-class.
So your bean is named myBean and not MyBean. If you want it to be MyBean, provide the name with the annotation: #ManagedBean(name = "MyBean").

Related

What is the correct annotation for a java class to be injectable?

I have a POJO which I want to inject into a CDI Bean. Now I get that I could change the discovery mode in beans.xml from 'annotated' to 'all'. But I also could just give my POJO a bean defining annotation. I guess any annotation would work, but I was wondering, what is the correct annotation just for the single purpose to make my POJO injectable?
#Dependent will create a new instance for that bean on every injection point. Usually the least intrusive.
http://docs.oracle.com/javaee/7/api/javax/enterprise/context/Dependent.html
Assuming you want to stay with bean discovery mode annotated, you need to have a bean-defining annotation on your POJO which will make it so called implicit bean. Here is a relevant quotation from CDI spec:
The set of bean defining annotations contains:
#ApplicationScoped, #SessionScoped, #ConversationScoped and #RequestScoped annotations,
all other normal scope types,
#Interceptor and #Decorator annotations,
all stereotype annotations (i.e. annotations annotated with #Stereotype),
and the #Dependent scope annotation.
As for which annotation is correct - that depends on your use case. Typically you need to take into consideration the lifecycle of beans (requests, conversations, application scoped which lives as long as the app does). But if you really don't care, I would say just go for #Dependent.
In fact, if you have bean discovery mode all and had no annotation on that POJO class, it would be picked up by CDI as #Dependent anyway.
Hope that answers the question.
You may have no annotation at all, no annotation is required to make your bean injectable (i.e. to make it managed or cdi bean).
In order to inject class it should be:
Concrete class (i.e not abstract or interface) or it should annotated as #Decorator
Should have no-arg constructor or constructor annotated with #Inject
Should not have annotated with an EJB component-defining annotation or declared as an EJB bean class in ejb-jar.xml.
So you can inject, pretty much, all 'normal' classes. Also, the class should be located inside bean archive. Starting from CDI 1.1 there are two types of bean archives: implicit and explicit. From Oracle documentation:
An explicit bean archive is an archive that contains a beans.xml
deployment descriptor, which can be an empty file, contain no version
number, or contain the version number 1.1 with the bean-discovery-mode
attribute set to all. For example:
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
... CDI can manage and inject any bean in an explicit archive, except those annotated with #Vetoed.
An implicit bean archive is an archive that contains some beans
annotated with a scope type, contains no beans.xml deployment
descriptor, or contains a beans.xml deployment descriptor with the
bean-discovery-mode attribute set to annotated.
In an implicit archive, CDI can only manage and inject beans annotated
with a scope type.
For a web application, the beans.xml deployment descriptor, if
present, must be in the WEB-INF directory. For EJB modules or JAR
files, the beans.xml deployment descriptor, if present, must be in the
META-INF directory.

EL expressions in Omnifaces CDN resource handler not resolved in Wildfly 9

I am playing around with new Wildfly 9.0.0.Final. After the deployment of my JSF2.2 web application, the Omnifaces2.1 CDNResourceHandler stopped resolving EL expression.
My definition in web.xml:
<context-param>
<param-name>org.omnifaces.CDN_RESOURCE_HANDLER_URLS</param-name>
<param-value>
styles:*=#{CDNResourcesBean.styles}/*
</param-value>
</context-param>
In .xhtml, style.css file exists in resources of the project structure
<h:outputStylesheet library="styles" name="style.css"/>
Generated HTML:
<link type="text/css" rel="stylesheet" href="/style.css" />
My CDNResourceBean
#Named
#RequestScoped
public class CDNResourcesBean {
public String getStyles() {
return "https://abcdef.cloudfront.net/";
}
From what I see the CDNResourceHandler is called, it replaces links but from unknown reason the El expression #{CDNResourcesBean.styles} is ignored.
How should I make it working? Is that a question of CDI configuration, Bean initialization order, CDNResourceHandler not compatible with new WF?
Technology:
Application server: Wildfly 9.0.0.Final
Omnifaces: 2.1
It's consequence of a bugfix in Weld implementation of WildFly 9. As per issues CDI-525, WELD-1941 and WFLY-4877, the CDI spec appears to be not consistent with JavaBeans specification as to default managed bean name in case the unqualified classname starts with more than two capitals. CDI spec merely stated as below in the spec, while Weld was initially following the JavaBeans specification:
The default name for a managed bean is the unqualified class name of the bean class, after converting the first character to lower case.
Weld was been put back to take it literally. The CDNResourcesBean is now registered as as #{cDNResourcesBean} instead of #{CDNResourcesBean}.
For now, if you intend to follow the JavaBeans specification, then your best bet is to explicitly specify the managed bean name.
#Named("CDNResourcesBean")
#RequestScoped
public class CDNResourcesBean {}
This problem is not related to OmniFaces.
Unrelated to the concrete problem, get rid of the double trailing slash in URL.

Setting view scope on JSF 2.2

On JSF 2.2 we don't have the option to set the View Scope on faces-config.xml .
So how should it be done? Is the view scope missing on JSF 2.2 ?
Thank you!
Use #ViewScoped annotation on managed bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class AViewScopedBean {
//managed bean contents...
}
If you don't like the annotations configuration (really odd), you can just set the view scope on faces-config.xml
<managed-bean>
<managed-bean-name>aViewScopedBean<managed-bean-name>
<managed-bean-class>some.package.AViewScopedBean</managed-bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
Note that this only works on JSF 2. Check that your faces-config file is configured to handle JSF 2.x version:
<!-- relevant part of faces-config.xml file for this Q/A -->
<faces-config ... version="2.1">
Note: Warning make sure its Serializable
The error message is pretty straightforward:
java.io.NotSerializableException: com.bean.StatusBean2
This means that your com.bean.StatusBean2 must also implement the Serializable interface. From java.io.Serializable documentation:
When traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object. (this is the error you're getting)
You can learn more about Java Serialization here: Java Serialization
From your question: is it necessary to implement serializable?, BalusC already posted a good answer/explanation: JSF backing bean should be serializable?
Thanks for #Luiggi Mendoza

How to mix annotations with faces-config.xml

Using JBoss 6.0.0.Final, Richfaces 3.3.3.Final, MyFaces 2.0.6, facelets 1.1.15.B1 (a limitation of RF 3).
I'm on a legacy project which contains hundreds of beans defined in faces-config.xml. I'd like to keep those defined in faces-config.xml but use annotations for new beans. However, when I've tried this I've not had success. The beans defined by annotation i.e.
#ManagedBean
#ViewScoped
public class Foobar implements Serializable {
// ...
}
The bean is not accessible from my JSF page. I believe I've specified the 2.0 version in my faces-config.xml by using the proper header.
<faces-config
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/web-facesconfig_2_0.xsd"
version="2.0">
Is there anything else I need to do in the faces-config.xml to allow annotations to also be used?
Annotated beans will fail in the following cases:
/WEB-INF/faces-config.xml is not declared to conform to JSF 2.0.
#ManagedBean is of javax.annotation package instead of javax.faces.bean.
Bean class is not been compiled/built into WAR's /WEB-INF/classes.
Bean is packaged in a JAR file which is missing /META-INF/faces-config.xml.
A wrong managed bean name is being used in EL, it should be the bean class name with 1st character lower cased according Javabeans spec. So in your particular example, #{fooBar} should work, but #{FooBar} won't.
Webapp is actually using JSF 1.x libs (you can read JSF version in server startup log).

JSF 1.2 Application.getMessageBundle() returns null

I'm using Spring 2.5 with JSF 1.2, on Tomcat 6.0.13.
In one part of code, I'm trying to load ResourceBundle by using following approach:
ResourceBundle.getBundle(context.getApplication().getMessageBundle(), Locale.EN);
The problem is that getMessageBundle() method returns null. This used to work with JSF 1.1.
Does anybody have idea what could be the problem?
For now I'm going to hardcode bundle name, but I would prefer if all my configuration data will be placed inside faces-config.
Resource bundle is set as following:
<application>
<locale-config>
<default-locale>en</default-locale>
</locale-config>
<resource-bundle>
<base-name>org.mysite.MessageBundle</base-name>
<var>msgs</var>
</resource-bundle>
</application>
IgorB,
You may be able to use resource injection to have JSF provide your managed bean with the correct ResourceBundle. This would remove the need to hard-code anything in your Java source and keep the association nicely centralized.
Start by defining a managed property on your backing bean. In the JSF configuration, set the managed property's value to an EL expression that references your resource bundle.
I've done something like the following using Tomcat 6. The only caveat is that you can't access this value from your backing bean's constructor, since JSF will not yet have initialized it. Use #PostConstruct on an initialization method if the value is needed early in the bean's lifecycle.
<managed-bean>
...
<managed-property>
<property-name>messages</property-name>
<property-class>java.util.ResourceBundle</property-class>
<value>#{msg}</value>
</managed-property>
...
</managed-bean>
<application>
...
<resource-bundle>
<base-name>application_messages</base-name>
<var>msg</var>
</resource-bundle>
...
</application>
The getMessageBundle() returns the value of <message-bundle> entry in faces-config.xml, not the <resource-bundle> entry.
Its value is actually not avaliable by the JSF 1.2 API. You have to specify it yourself.
ResourceBundle bundle = context.getApplication().getResourceBundle(context, "org.mysite.MessageBundle");
The <message-bundle> is for validation/conversion messages. Probably you've actually used this in JSF 1.1.

Resources