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