EL expressions in Omnifaces CDN resource handler not resolved in Wildfly 9 - jsf

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.

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

#NotNull Bean Validation ignored for viewParam

Problem
I'm trying to validate a mandatory GET request parameter.
In the view I've added a corresponding viewParam tag.
<f:metadata>
<f:viewParam name="customerId" value="#{customerDetailBean.customerId}"/>
</f:metadata>
And my CDI bean looks like this
#Model
public class CustomerDetailBean {
#NotNull
private Integer customerId;
public Integer getCustomerId() {
return customerId;
}
public void setCustomerId(Integer customerId) {
this.customerId = customerId;
}
}
When I use the following request, validation works fine and the expected validation message is displayed.
http://localhost:8080/getsupport/customerdetail.jsf?customerId=
However, when I change the request by removing the parameter customerId, validation is skipped and no message is shown.
http://localhost:8080/getsupport/customerdetail.jsf
Is there a way to make it work as expected?
Workaround
I've changed my viewParam declaration to
<f:metadata>
<f:viewParam name="customerId" value="#{customerDetailBean.customerId}" required="true" />
</f:metadata>
That updated version works fine with the second request. Anyway I would prefer to use bean validation.
My setup
Mojarra JSF 2.2.7
Weld 2.2.1.Final
Hibernate Validator 5.1.1.Final
Tomcat 7.0.54
web.xml
<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>
This is, unfortunately, "working as designed". All validation is skipped when nothing's been submitted. Only the <f:viewParam required> has special treatment. It's also considered when nothing's been submitted. See also UIViewParameter#processValidators() javadoc and source code.
In the Mojarra issue tracker I can only find issue 3058 as a related issue, whereby the <f:validateRequired> isn't being considered. This is technically actually exactly the same problem as you're facing with #NotNull. I've created issue 3339 on this.
In the meanwhile, your best bet is falling back to required="true". A custom component can also, but as far as I see this isn't going to be trivial.
Update: after all, the fix is relatively easy and has been implemented in OmniFaces <o:viewParam> in the current 2.0 snapshot release.
Prior to JSF 2.0, validation was simply not run at all on fields whose values were
empty or null. JSF 2.0 changes this default behavior slightly. If the JSF runtime is executing in
an environment that supports bean validation, empty fields are validated by default. Otherwise,
the behavior is the same as it was prior to JSF 2.0: empty fields are not validated.
Since Tomcat(& Jetty) is not a J2EE compliant server bean validation is not enabled by default. That is the reason why your validation is skipped.
To force JSF to validate empty fields, add this to your web.xml file:
<context-param>
<param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
<param-value>true</param-value>
</context-param>
The Bean validation(JSR 303) can be configured on non j2ee compliant server with minimal configuartion(I have never configured this :)). In some way you have enabled bean validation and you have not above context param then jsf runtime would consider it as true and validate empty and null fields for validation.
But I suggest to use required attribute which is suggested experts for performance because using annotations invove reflections. So we could avoid for atleast in one case.
And ensure context param javax.faces.validator.DISABLE_DEFAULT_BEAN_VALIDATOR is not set to true in web.xml.
To have a look at list of these parameters see
Overview of all JSF-related web.xml context parameter names and values
Hope this helps.

using JSF EL expression inside web.xml

Can I use EL expression inside web.xml ?
Like this
Web.xml
<context-param>
<param-name>primefaces.DIR</param-name>
<param-value>#{userUtilityBacking.direction}</param-value>
</context-param>
and my JSF bean like this
JSF bean
#ManagedBean(name="userUtilityBacking")
#SessionScoped
public class UserUtilityBacking implements Serializable {
private static final long serialVersionUID = 1L;
private String direction ;
// and public setters and getter
Will it work ?
Can I use EL expression inside web.xml ?
Not exactly that. By default, the servletcontainer doesn't EL-evaluate the context parameters when the web.xml is been parsed during application startup. However, build tools like Ant and Maven and some servletcontainers like JBoss (after setting a specific configuration setting) support using ${...} syntax similar to EL to inline environment variables and/or VM arguments by their name in several deployment descriptor XML files such as web.xml, ejb-jar.xml and persistence.xml. Note: that are thus not those variables which you've declared in JSF EL scope, such as managed bean.
Will it work ?
It will only work if PrimeFaces gets the static value "#{userUtilityBacking.direction}" as String and then programmatically EL-evaluates it in the current EL context using for example Application#evaluateExpressionGet(). But, based on the PrimeFaces 3.5 source code, it is not doing that anywhere. It look like they implemented it for 4.x only.
In your particular case, you'd better just specify the direction directly on <html> element to apply it document-wide and/or in dir attribute of an arbitrary HTML or JSF component.
<html dir="#{userUtilityBacking.direction}">

Invoking methods with parameters by EL in JSF 1.2

I am using a datatable and for each row I have two buttons, an "Edit" and a "Delete".
I need these buttons to be read-only, i.e. disabled, if a certain condition is met for the row in question. I have seen in JSF 2 that it is possible to pass parameters to method calls. Is there anything equivalent in JSF 1.2?
Ideally what I would like it something like (the looping variable is loop and there is another bean, helper, which contains the method I would like to invoke):
<h:commandButton value="Edit"
disabled="#{helper.isEditable(loop.id)}" />
In this case it does not make semantic sense to add an isEditable attribute to the bean and it is not practical to create a wrapper Object around the bean.
Thanks in advance.
I have seen in JSF 2 that it is possible to pass parameters to method calls. Is there anything equivalent in JSF 1.2?
Passing parameters to method calls is not specific to JSF 2. It is specific to EL 2.2, which is in turn part of JSP 2.2 / Servlet 3.0 / Java EE 6. JSF 2 just happens to be part of Java EE 6 as well. In other words, if you deploy your JSF 1.2 web application to a Servlet 3.0 compatible container like Tomcat 7, Glassfish 3, etc and your web.xml is declared conform Servlet 3.0 spec version, then it'll just work out the box for JSF 1.x as well.
If you're however still targeting a container of an older Servlet version, then you need to supply a different EL implementation which supports invoking methods with arguments. One of those implementations is JBoss-EL which you can install by just dropping the jboss-el.jar file in /WEB-INF/lib of your webapp and adding the following context parameter to the web.xml. Here's a Mojarra-specific example (Mojarra is the codename of JSF RI):
<context-param>
<param-name>com.sun.faces.expressionFactory</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>
If you're using MyFaces as JSF implementation, you need the following context parameter instead:
<context-param>
<param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
<param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>
See also:
Invoke direct methods or methods with arguments / variables / parameters in EL

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

Resources