Overriding PrimeFaces renderer not working when provided via module library - jsf

I have a very tricky problem when overriding JSF-renderers.
This is a part of my faces-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xi="http://www.w3.org/2001/XInclude" 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">
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.MenubarRenderer</renderer-type>
<renderer-class>de.mycompany.web.MenuRenderer</renderer-class>
</renderer>
</render-kit>
<factory>
<exception-handler-factory>de.mycompany.web.ValidationExceptionHandlerFactory</exception-handler-factory>
</factory>
</faces-config>
The structure of my web-project is following
webapp (building war), Dependencies to core and gui
core (building jar)
gui (building jar), Dependencies to core, containing xhtmls and #Named Beans, Dependency to com.sun.faces:jsf-impl Version 2.1.25
When I place the content of the faces-config.xml in
webapp/src/main/webapp/META-INF or
core/src/main/webapp/META-INF
both, the MenuRenderer and the ValidationExceptionHandlerFactory, are getting used. Yeah.
When I place the content of the faces-config in
gui/src/main/webapp/META-INF
the ValidationExceptionHandlerFactory is getting used, but not the MenuRenderer. WTF?
Also all other features (phase-listeners, system-event-listeners I use in my faces-config are working except ones in the render-kit-nodes.
What am I doing wrong?

You're trying to override a renderer supplied by another external library, not a standard renderer.
The loading order of faces-config.xml provided by external libraries is by default undefined. In your specific case, your library is apparently loaded before PrimeFaces library is loaded.
You can explicitly specify the loading order via <ordering> element in faces-config.xml. The name of the PrimeFaces library is primefaces. So, just add the below entry to your faces-config.xml. Make sure you supply your library a name too so that endusers can in turn reorder in their own faces-config.xml if necessary.
<name>yourlibrary</name>
<ordering>
<after>
<name>primefaces</name>
</after>
</ordering>
A real world example can be found in e.g. OptimusFaces which also extends PrimeFaces.

Related

JSF1064 when using tags defined in the taglib.xml

I've created my own custom myfw:repeat tag for our project as described in JSF ui:repeat in ui:repeat with dynamically assigned var-value and defined it in the myfw.taglib.xml:
<?xml version="1.0"?>
<facelet-taglib 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-facelettaglibrary_2_0.xsd"
version="2.0" id="myfw">
<namespace>http://company.at/myfw</namespace>
<composite-library-name>myfw</composite-library-name>
<!-- Other tags -->
<tag>
<tag-name>repeat</tag-name>
<component>
<component-type>at.company.myfw.jsf.component.repeat.UIRepeatForFloatingTable</component-type>
</component>
</tag>
</facelet-taglib>
The tag used in the page is working fine but every time the page is viewed the warning message:
13:03:30,577 WARNING [javax.enterprise.resource.webcontainer.jsf.application] (http-/127.0.0.1:8080-2) JSF1064: Unable to find or serve resource, repeat.xhtml, from library, myfw.
shows up in the logs. This is not just the case with the repeat tag, it also happens to every tag defined in the taglib like ui:compositions. So the log is currently spammed by these messages but the page/tags work properly. A current workaround is to change the log-level, but it is not the desired solution. Using EAP 6.2.0.GA with Mojarra 2.1.19.
This is a bug in Mojarra. It's during Development stage too eagerly logging JSF1064 for tagfiles which couldn't be found in <composite-library-name>, while it should still continue to work through <tag> entries registered directly in taglib itself.
This is not your fault. Those warnings aren't logged in Production stage. I reported this issue as JAVASERVERFACES-3696 (update: this was fixed only a few hours later and will be available as per Mojarra 2.3.0-M02).

Flow scope navigation to start page does not work

It is not so much a question, more of a note.
With Glassfish4, in a JEE7 application I tried to use the flow scope using programmatic flow definition (java class annotated with #Produces #FlowDefinition).
I navigated to the start page of the flow with a h:commandButton (just as it is done in the JEE7 tutorial example https://svn.java.net/svn/javaeetutorial~svn/trunk/examples/web/jsf/checkout-module.
When I pressed the button it stayed on the same page, where the button was, instead of going to the flow's start page.
After many hours of suffering, I realized that the problem is in the beans.xml, in my beans.xml I had this:
bean-discovery-mode="annotated"
which is the recommended setting according to the documentation (http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/beans_1_1.xsd).
When I changed this to
bean-discovery-mode="all"
it started to work.
Somehow CDI does not recognize the flow definition as an annotated class. I tried to make it a #Named class, or a #ApplicationScoped class, but non of these helped.
I don't know if it is the intended behavior, or a bug.
Hope it saves a few ours to someone.
This is related to how CDI detects bean archives. When bean-discovery-mode="annotated", only classes annotated with bean defining annotations are picked up by CDI; note that #Named and #FlowScoped aren't on that list.
Because of this, as you've documented here, using Flow annotations requires bean-discovery-mode="all" to be set.
There's a spec issue open to discuss if this is a desired behavior.
Thank you!
Of course you can always fallback to using an XML declaration for your view. Such as creating a file example/example-flow.xml with contents such as
<?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">
<flow-definition id="example">
<flow-return id="actionId" >
<from-outcome>#{somebean.returnValue}</from-outcome>
</flow-return>
</flow-definition>
</faces-config>

JSF 2.1 - Facelet cache factory configuration

I am using Mojarra 2.1.2 and want to configure the facelet cache factory. I tried the following in my WEB-INF/faces-config.xml but it does not seem to work.
<factory>
<facelet_cache_factory>org.valuesource.custdb.web.extension.SimpleFaceletCacheFactory</facelet_cache_factory>
</factory>
You shouldn't use underscores. Use hyphens.
<facelet-cache-factory>
No one XML element of faces-config.xml uses underscores. Note that the FaceletCacheFactory was introduced in JSF 2.1, so ensure that your faces-config.xml root declaration conforms JSF 2.1:
<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_1.xsd"
version="2.1">

Render JSF component based on user role

How do I render JSF components based on a logged in user's role? I know the external context exposes the principals, but how should I do the rendering properly in JSF? In JSP it would be something like
<% isUserInRole(Roles.ADMIN) { %>
<button>Edit!</button>
<% } %>
How do I write this in JSF the best possible way? My best guess is the rendered attribute tied to a backing bean's method that returns a boolean, but that would introduce an irrelevant backing bean if I have to render some navigation items only for admins...
Glassfish V3.1, JSF 2.x
If your web.xml is declared as Servlet 3.0 (which implicitly relates to JSP/EL 2.2)
<?xml version="1.0" encoding="UTF-8"?>
<web-app
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-app_3_0.xsd"
version="3.0">
then you can take benefit of being able to invoke methods with arguments in EL like as ExternalContext#isUserInRole():
rendered="#{facesContext.externalContext.isUserInRole('ADMIN')}"
Note that this requires a Servlet 3.0 capable container, but since you're using Glassfish 3 (which supports Servlet 3.0), it should work without any issues.
Also note that if you're using Facelets instead of JSP, then you've the HttpServletRequest available as #{request} in EL, allowing you the following shorter expression:
rendered="#{request.isUserInRole('ADMIN')}"
Conditionally displaying JSF components
Conditional rendering of non-JSF components (plain vanilla HTML and template text)
JSF: How control access and rights in JSF?
In response to #wasimbhalli, there are two reasons I have found that the expression would always return false:
The role name is case sensitive.
rendered="#{facesContext.externalContext.isUserInRole('ADMIN')}" may return false, but try
rendered="#{facesContext.externalContext.isUserInRole('admin')}", or rendered="#{facesContext.externalContext.isUserInRole('Admin')}".
You have to define your roles in both web.xml (or as annotations) and map it in glassfish-web.xml.
The following is how to specify a role in web.ml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<security-role>
<role-name>admin</role-name>
</security-role>
</web-app>
The following is how to map the authentication group to the role in glassfish-web.xml.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>
<security-role-mapping>
<role-name>admin</role-name> <!-- name defined in web.xml or annotations -->
<group-name>admin</group-name><!-- name from authentication mechanism -->
</security-role-mapping>
</glassfish-web-app>
In my testing it was necessary to do the mapping even when the names were the same, as I show in my example code. Also in my testing, I tried to only define the mapping and only to define the role in web.xml, and neither worked. I needed both, as specifying the role name in the correct case.
Store role in session attribute and just compare that using rendered attribute.
e.g. rendered="#{yoursessionbean.userRole == Roles.ADMIN}"

Custom Facelets components and attributes defined in taglib

Defining custom components in Facelets is easy and quick but there's one thing I can't figure out.
Is it possible with Facelets to define what attributes my custom component has? I.e: I've created a component which is used in such a way:
<blue:modalWindow id="editFeesWizard" width="500" height="440" title="Wizard">
and is defined in taglib.xml as follows:
<!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>...</namespace>
<tag>
<tag-name>modalWindow</tag-name>
<source>components/modalWindow.xhtml</source>
</tag>
</facelet-taglib>
Taglib doesn't contain any information on component's attributes (id, width, height, title) and IDE cannot therefore check my syntax nor can it suggest attributes while I'm typing.
I cannot find anything on this subject in Facelets documentation. Thought you could help. Thanks!
It seems there isn't a way. But even if there was, I don't think Eclipse (for example) would be able to handle it and offer autocomplete. That's why you can define a .tld, containing the attributes:
<?xml version="1.0" encoding="utf-8"?>
<taglib
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1">
......
</taglib>
Just for the sake of autocompletion. Ugly, I know.
I don't know about before, but it is possible now. Just add:
<tag>
<tag-name>mycustomtag</tag-name>
<source>tags/mycustomtag.xhtml</source>
<attribute>
<description>What does this do?!</description>
<name>attribute</name>
</attribute>
</tag>
I'm looking forward to being able to create composite components using JSF 2 and facelets; from what I've read, it seems very quick and easy, and you define what attributes your composite component accepts.

Resources