JSF config-annotations not processed - jsf

I am running a JSF 2 application on JBoss AS 6.
Somehow the Annotations, like #FacesComponent or #FacesValidator, etc are not processed by the container. If I annotate a Bean with #FacesValidator("fooValidator") and try to set the validatorId on some component to "fooValidator" I get:
Caused by: javax.faces.FacesException: Expression Error: Named Object: fooValidator not found.
at com.sun.faces.application.ApplicationImpl.createValidator(ApplicationImpl.java:1530) [:2.0.3-]
...
However, If I add
<validator>
<validator-id>fooValidator</validator-id>
<validator-class>foo.MyClass</validator-class>
</validator>
To my faces-config.xml everything works as expected. Same goes for components and converters.
Any idea why the annotations are not processed? I am out of ideas...
Thanks in advance...

Got it. It is very similar to this one: Why doesn't JSF 2.0 RI (Mojarra) scan my class' annotations?
My project uses a skinny war, so the lib folder in the war is empty/nonexistent. And to make it worse, the Controller Beans are not located in the war but in a seperate jar. As this jar is not in the war, the jsf annotation processor does not scan it.
I guess, I will restructure the project and likely throw out the skinny war. That should fix it.

So, you were using #Named instead of #ManagedBean on your managed beans? :)
This can happen if the faces-config.xml is not declared conform JSF 2.0 spec. Ensure that the root declaration look like this:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- config here -->
</faces-config>

Related

Can't find beans annotated with #ManagedBean

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").

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).

How to see message.properties in a Jar using JSF?

Using: JSF 1.2, Facelets 1.1.15, GateIn 3.1 GA, Richfaces 3.3.3
I have some common .xhtml and backing bean in a JAR that our portlets can see. I did this by overriding ResourceResolver as described in other posts:
http://ocpsoft.com/opensource/create-common-facelets-jar/
How to use Facelets composition with files from another context
The portlets can load the XHTML and use the backing bean.
Here is my problem: I cannot get the xhtml to substitute the messages defined in messages_en.properties. I have tried moving the properties file outside of the JAR and placing directly in /lib folder. I have also tried putting a / in front of the name to try to get the resolver to find it. I have also put it in the components folder.
The common jar info is: I hava a my-portlet-common-resources.jar which resides in server/my-portal/lib. The jar is structured like so:
com/portlet/common/CustomResourceResolver.class
com/portlet/common/FilterCreateBean.class - backing bean for the common popup
messages_en.properties
faces-config.xml
META-INF/components/commonPopups.xhtml
META-INF/faces-config.xml - declares the FilterBean
META-INF/Manifest.mf
faces-config.xml contents:
<?xml version="1.0" encoding="UTF-8"?>
<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_1_2.xsd"
version="1.2">
<application>
<locale-config>
<default-locale>en</default-locale>
</locale-config>
<message-bundle>/messages_en.properties</message-bundle>
</application>
<managed-bean>
<managed-bean-name>FilterCreateBean</managed-bean-name>
<managed-bean-class>com.portlet.common.FilterCreateBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>
Include the messages in commonPopups.xhtml (partial snip):
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<a4j:loadBundle basename="messages" var="msgs"/>
<rich:panel style="border-style:none;" id="addNewChainPanel">
<rich:modalPanel id="modalNewChainPanel" autosized="true">
<f:facet name="header"><h:outputText value="#{msgs['filterset.modal.new.title']}" /></f:facet>
</ui:composition>
This should work. Perhaps you already have a messages*.properties file in the classpath root of your main webapp. This one has then precedence in classloading. You need to put it in a more specific package. Put the JAR's one in for example the com/portlet/common folder so that it becomes member of the com.portlet.common package. This way it'll be available by:
<a4j:loadBundle basename="com.portlet.common.messages" var="msgs"/>
Unrelated to the concrete problem, the <message-bundle> entry in faces-config.xml has a completely different purpose. It's supposed to override JSF default validation/conversion messages which are returned by JSF default validators/converters. It is not intended to provide localized content. There you use the <resource-bundle> entry or <xxx:loadBundle> tag for. I'd remove that entry from the faces-config.xml.

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.

JSF 2 Annotations with Websphere 7 (JEE5, JAVA 1.6)

I'm currently writing a simple JSF 2 app for WAS 7. When I define the bean via the faces-config.xml, everything works great
<managed-bean>
<managed-bean-name>personBean</managed-bean-name>
<managed-bean-class>com.prototype.beans.PersonBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
When I try to use the annotations below instead, the app failes.
package com.prototype.beans;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean(name="personBean")
#RequestScoped
public class PersonBean {
....
}
I've set the WAS classloader to Parent Last, and verified in the logs that Mojarra 2.x is loading.
[5/17/10 10:46:59:399 CDT] 00000009 config I Initializing Mojarra 2.0.2 (FCS b10) for context '/JSFPrototype'
However, when I try to use the app (which had worked with XML based config) I see the following
[5/17/10 10:48:08:491 CDT] 00000016 lifecycle W /pages/inputname.jsp(16,7) '#{personBean.personName}' Target Unreachable, identifier 'personBean' resolved to null
org.apache.jasper.el.JspPropertyNotFoundException: /pages/inputname.jsp(16,7) '#{personBean.personName}' Target Unreachable, identifier 'personBean' resolved to null
Anyone know whats going wrong?
Looks like I may have resolved my own issue (again). The problem looks like it was caused by an improper schema location/config on the faces config. Here's what I am using now, and it seems to work.
<?xml version="1.0"?>
<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">
</faces-config>
the bean name in should be the name of your bean class
so change beanName in faces-config.xml as
<managed-bean-name>PersonBean</managed-bean-name>

Resources