How to see message.properties in a Jar using JSF? - 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.

Related

JSF do not execute the bean

im trying to learn JSF, but something i lost, cuz this button is not showing the message in eclipse console
the JAVA BEAN:
package beans;
public class protocoloBean {
public void incluirProtocolo() {
System.out.println("MSG");
}
}
the xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:button value="Protocolar"
action="#{protocoloBean.incluirProtocolo()}"></h:button>
</h:body>
</html>
and the faces-config:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.2" 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">
<managed-bean>
<managed-bean-name>protocoloBean</managed-bean-name>
<managed-bean-class>beans.protocoloBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<application/>
</faces-config>
what im doing wrong ? or i lost :(
Your JSF code is wrong. You're trying to fire an action using <h:button> when you need/want to use <h:commandButton>. <h:button> is intended for navigation purposes only. See here for a difference between them: Difference between h:button and h:commandButton
You should update your code to:
<h:body>
<ui:remove>
<h:button value="Protocolar"
action="#{protocoloBean.incluirProtocolo()}"></h:button>
</ui:remove>
<!--
Note that h:commandButton MUST ALWAYS be inside a h:form
Otherwise, the action won't fire
-->
<h:form>
<h:commandButton value="Protocolar"
action="#{protocoloBean.incluirProtocolo}" />
</h:form>
</h:body>
After updating your code, the log message will be printed as expected.
Since you're learning JSF 2.2, I would suggest start using JSF 2 features like barely using the faces-config.xml file for managed bean definitions. You could improve your code to this:
#ManagedBean
#SessionScoped
public class ProtocoloBean {
public void incluirProtocolo() {
System.out.println("MSG");
}
}
And your faces-config.xml file*:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.2" 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">
</faces-config>
* Yes, it is empty :).
Since you're new to JSF, I would recommend start declaring your beans as #RequestScoped or #ViewScoped instead of #SessionScoped. You cn read more info about this here: How to choose the right bean scope?
two mistakes in your code:
the first character of your class name should be Captialized. You should use "ProtocoloBean" insteads of "protocoloBean"
Action attribute is used for redirect page, the method type must be String instead of void. If you just want to execute some code, then you should use "actionListener" rather than "action", in this case your method return type can be void, but make sure (ActionEvent action) is defined as your method input argument

Manual for updating JSF 2.0 Project to 2.2

unfortunately there are no working tutorials to update a Eclipse (KEPLER) JSF 2.0 Project to JSF 2.2.
Should this update be done or should a new project be created (and import all files)?
What are the Steps to update the used JSF version properly and clean?
I'm just getting errors (from FactoryNotFound to StartupServletContextListener problems), when I change the faces.xml header to:
<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">
I additionally updated the library to Majorra 2.2.0 (JSF 2.2) and dynamic web project to 3.0 and java to 1.7 (in the preferences), but the server just prints errors and does not work...
From the JSF 2.2. Reference implementation manual
Faces 2.2 is backwards compatible with Faces 2.1 and 2.0. This means that a web-application that was developed to run
with Faces 2.1 or 2.0 won’t require any modification when run with Faces 2.2
Due to an error in previous versions of the specification, exceptions were silently being swallowed that now will
bubble up to the exception handler. Code that was relying on this incorrect behavior may need to be modified to
account for fixing this problem.
And also:
Any additional attributes on <composite:attribute/> are exposed as attributes accessible from the
getValue() and attributeNames() methods on PropertyDescriptor. The return type from getValue()
must be a ValueExpression with the exception of the getValue(“type”). The return type from
getValue(“type”) must be Class. If the value specified for the type attribute of <cc:attribute/>
cannot be converted to an actual Class, a TagAttributeException must be thrown, including the Tag and
TagAttribute instances in the constructor.
Conclusion: there is minimal breakage between JSF2.1. and 2.2.
EDIT: Some new things in JSF2.2:
New namespaces:
xmlns:f="http://xmlns.jcp.org/jsf/core" can replace xmlns:f="http://java.sun.com/jsf/core" and also
xmlns:h="http://xmlns.jcp.org/jsf/html" can replace xmlns:h="http://java.sun.com/jsf/html"
Based on your comment:
The preRenderView event type from the following construct in JSF2.0:
<f:metadata>
<f:event type="preRenderView" listener="#{viewActionManagedBean.validateUser()}"/>
</f:metadata>
Can be replaced with the following brand new <f:viewAction/> tag in JSF2.2:
<f:metadata>
<f:viewAction action="#{viewActionManagedBean.validateUser()}"/>
</f:metadata>
This tag also provides support for executing the managed bean method during specific phases of the request lifecycle with the phase attribute. Valid options are
RESTORE_VIEW (Restore View)
APPLY_REQUEST_VALUES(Apply Request Values)
PROCESS_VALIDATIONS(Process Validations)
UPDATE_MODEL_VALUES(Update Model Values)
INVOKE_APPLICATION(Invoke Application)
RENDER_RESPONSE(Render Response)
The tag also supports the if attribute that defines a boolean condition on which the action will be run. Take the following for example:
<f:metadata>
<f:viewAction action="#{viewActionManagedBean.validateUser()}" if="#{viewActionManagedBean.verifyCondition}" phase="APPLY_REQUEST_VALUES"/>
</f:metadata>
Note that this tag is available only in the new namespace xmlns:f="http://xmlns.jcp.org/jsf/core"
You can get your copy of the specification below. Look under the /Preface/Changes between 2.1. and 2.2. /Backwards Compatibility with Previous Versions
http://jcp.org/aboutJava/communityprocess/final/jsr344/index.html
Just replace the prototype of faces-config by :
`<?xml version="1.0" encoding="UTF-8"?>
<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">`
Then: select your web project, right click > property > Project facets > deselect jsf version > press ok.
Finaly : right click on your project than maven > update project ...
Restart your server ...
I hope that it help, it work for me

JSF 1.2 : Can I create reusable component inside JSF view

Is possible to something like this in jsf?
<ui:composition>
<x:reusableCode id="editScreen">InnerHtml ... </x:reusableCode>
code...
<x:use component="editScreen"/>
</ui:composition
I know I can create my own component and register it in jsf tagLib, but I need reusable HTML only in on jsf view file.
In Facelets 1.x you can create a tag file for this purpose.
Here's a basic kickoff example. Create /WEB-INF/tags/some.xhtml:
<ui:composition
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
<h:outputText value="#{foo}" />
</ui:composition>
Define it in /WEB-INF/my.taglib.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://example.com/jsf/facelets</namespace>
<tag>
<tag-name>some</tag-name>
<source>/WEB-INF/tags/some.xhtml</source>
</tag>
</facelet-taglib>
Register it in /WEB-INF/web.xml:
<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>
(note, when you have multiple, use semicolon ; to separate them)
Finally just declare it in your main page templates.
<ui:composition
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:my="http://example.com/jsf/facelets"
>
<my:some foo="value1" />
<my:some foo="value2" />
<my:some foo="value3" />
</ui:composition>
A more advanced example can be found here: How to make a grid of JSF composite component? Note: JSF 2.0 targeted, but with minor changes based on above example it works as good on Facelets 1.x.

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>

Why doesn't JSF 2.0 RI (Mojarra) scan my class' annotations?

I have a War and Jar project in my Eclipse-based JSF project. I have decided to use annotations to declare my FacesConverter, (among a myriad other things), rather than declare it using my faces-config.xml.
#FacesConverter(value="passwordFieldStringConverter")
public class PasswordFieldStringConverter implements Converter {
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) throws ConverterException {
try {
return arg2.getBytes("UTF-16BE");
}
catch(UnsupportedEncodingException uee) {
Assert.impossibleException(uee);
}
return(null);
}
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) throws ConverterException {
try {
return new String((byte[]) arg2, "UTF-16BE");
}
catch(UnsupportedEncodingException uee) {
Assert.impossibleException(uee);
}
return(null);
}
}
And then I use passwordFieldStringConverter directly in my .xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:sec="http://www.springframework.org/security/facelets/tags">
<ui:composition>
<f:view>
<f:loadBundle basename="landingPage.bundle" var="bundle" />
<ui:decorate template="/WEB-INF/jsf_helpers/htmlShell.xhtml">
<ui:param name="PageTitleParam" value="#{bundle.pageTitle}" />
<h:form>
<h:dataTable var="rowVar" value="#{userListContainer.users}">
<f:facet name="header"><h:outputText value="Users you are currently managing:" /></f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="Screen Name" />
</f:facet>
<h:outputText value="#{rowVar.screenName}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Password" />
</f:facet>
<h:outputText value="#{rowVar.password}">
<f:converter converterId="passwordFieldStringConverter" />
</h:outputText>
</h:column>
</h:dataTable>
</h:form>
</ui:decorate>
</f:view>
</ui:composition>
</html>
JSF is supposed to scan the jars in my War at deployment-time and detect which classes have annotations on them (and auto-configure the application accordingly). My problem is that JSF is apparently not detecting the classes I have which sport annotations.
The War project has all of my .xhtml files as well as the project's faces-config.xml, my Jar project has all of my faces related Java code (action beans, managed beans, custom converters, etc.)
Yes, I'm immediately answering my own question because I already spent a week banging my head on the table and I only figured out my problem after debugging through the JSF 2.0 RI (Mojarra) to see what it was doing.
Basically, the annotation scanner only consults the WAR's /WEB-INF/classes .class files for annotations (assuming you have a faces-config.xml in /WEB-INF). If you keep your code in separate Jar files and want your .class files you have in /WEB-INF/lib .jar files to be scanned for annotations, you must have a faces-config.xml in that Jar's META-INF folder. The faces-config.xml you plop into your jar can be empty, it just needs to be there or else the annotation scanner will passover your jar like it was leftover meatloaf.
Empty faces-config.xml:
<?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 /WEB-INF/schema/web-facesconfig_2_0.xsd"
version="2.0" metadata-complete="false">
<!-- This file must be present with our jar, even if it is empty. Otherwise, our Java annotations won't get scanned! -->
</faces-config>
I know a threw out a lot of -INF's there. So, just to recap. Your faces-config.xml in your War goes in WEB-INF. Your potentially empty, annotation scanner enabling, faces-config.xml in each of your Jar files goes in that Jar's META-INF.
If you're wondering why the behavior has to be so nutty, it's because the JSF configs can be decentralized and scattered across 1st and 3rd party libraries this way. And if you're wondering about the whole presence of the faces-config.xml in a jar being a factor, well, my opinion is that that is what marks a Jar as interesting to the engine - and the absence of a faces-config.xml means the annotation scanner can avoid that jar and save on processing at deployment time. It just would have been nice if those scanner semantics were a little more clearly explained somewhere, <expletives deleted>!
The following blog post was very useful in my understanding of what the code was doing:
http://one-size-doesnt-fit-all.blogspot.com/2007/01/using-multiple-faces-configxml-files-in.html
I really hope this saves someone from a week of pain like I had.
A JAR contains both EJB & FacesBeans:
In the case that the JAR that contains Faces Beans is already bundled in an ear (because it contains EJBs), then you also have to put the same JAR in the WEB-INF/lib of the war (on top of adding the faces-config.xml in the META-INF directory), so that the container recognizes the JSF 2.0 Annotations.
In this case, it is probably better to create two JARS, one for the EJBs and one for the FacesBeans.

Resources