JSF 1.2 Application.getMessageBundle() returns null - jsf

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.

Related

Use many beans from the same class, different scopes

I want to use a ManagedBean class, Users.java, to create 2 bean instances with different scopes. I tried to do this in 2 ways:
1.
Use ManagedBean and SessionScope annotations for Users (this creates a "users" with a session scope), and declare in faces-config.xml another MenagedBean from User, with request scope.
#ManagedBean
#Component
#SessionScoped
public class Users implements Serializable {...}
Note: "Component" is from Spring framework, this can be ignored for the moment.
In faces-config.xml:
<managed-bean>
<managed-bean-name>newUser</managed-bean-name>
<managed-bean-class>ro.telacad.model.Users</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
In login page I use "#{users.}" inside . For this case, the login works fine (is made with Spring Security). I created also a "Sign up" page, and there, I need the "Users" bean with request scope to create a new user in database, "#{newUser.}". I put a breakpoint inside a method, and when the application stopes there, all the attributes of this object are null, and the application throws a NullPointerException.
2.
Remove annotations "ManagedBean" and "SessionsScoped" from Users.java, and declare the 2 managed beans in faces-config.xml:
<managed-bean>
<managed-bean-name>currentUser</managed-bean-name>
<managed-bean-class>ro.telacad.model.Users</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>newUser</managed-bean-name>
<managed-bean-class>ro.telacad.model.Users</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Of course, this time I use in login page and in welcome page "#{currentUser.}". This time, the NullPointerException is thrown in both cases (login and sign up).
The file faces-config.xml is loaded. I tested this by creating a class TempBean.java with 1 attribute and 1 method, declaring a managed bean of this class in faces-config.xml and use this in a h:form. It worked.
I extended "Users" class, exactly like Selaron said in the comment. It works fine. But I think it is not a good idea to do this in a real application, but for the moment I don't have any better idea.

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

initial JSF1.1 bean after request parameters are set

I need to perform some initialization of a JSF1.1 bean after all URL request parameters are set. Is there a good way to do so? For example, if the manage-bean is setup in faces-config like below, I need to perform some initialization after all there param (Param1, 2, 3) are set.
<managed-bean>
<managed-bean-name>someBean</managed-bean-name>
<managed-bean-class>com.arch.SomeBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>param1</property-name>
<value>#{param.param1}</value>
</managed-property>
<managed-property>
<property-name>param2</property-name>
<value>#{param.param2}</value>
</managed-property>
<managed-property>
<property-name>param3</property-name>
<value>#{param.param3}</value>
</managed-property>
</managed-bean>
Normally, you would use a #PostConstruct annotated method for this, but the support for #PostConstruct is only available since JSF 1.2.
Your best bet is to lazily execute it in the setter method of the managed property. E.g.
public void setParam3(String param3) {
boolean wasNull = this.param3 == null;
this.param3 = param3;
if (wasNull) {
init();
}
}
See also:
Communication in JSF - Passing GET parameters to backing bean
Alternatively, just upgrade to JSF 1.2. JSF 1.1 is fully forward compatible with JSF 1.2 without any changes in the code (expect of code where in you're incorrectly assuming a JSF 1.1 specific bug to be correct behavior).

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 config-annotations not processed

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>

Resources