Thursday, December 14, 2017

OmniFaces 3.0-RC1 ready for testing!

You can grab it here.

This is the first release candidate of OmniFaces 3.0, which is the first version developed specifically for JSF 2.3 and Java 1.8. As of now, it won't run when you still have JSF 2.2 or Java 1.7 installed, but it will run when you still have CDI 1.1 installed, in spite of a CDI 2.0 dependency marked provided. It may change later when CDI 1.2 or 2.0 specific features are utilized.

I will later go in more detail about the changes when 3.0 final is released, for now below is a quick overview of all changes so far as compared to 2.6.7 (which was also released today):

Breaking changes:

  • <o:form useRequestURI="true"> is now the default behavior of <o:form> as it was basically the main reason to use <o:form>. I.e. it will always submit to exactly the same URL as in browser's address bar whereas the <h:form> only submits to the forwarded URL without query string, causing among others view parameters and path parameters to get lost every time. You can if necessary disable this by <o:form useRequestURI="false"> or switching back to <h:form>.
  • <o:form> will now by default perform a partial submit on any JSF ajax request. In other words, only the parameters actually covered by execute attribute of <f:ajax> will be sent, hereby reducing the request payload to not contain unnecessary parameters. This is similar to PrimeFaces partialSubmit feature. You can if necessary disable this by <o:form partialSubmit="false">.
  • <o:validateBean showMessageFor="@violating"> will not anymore show the "remaining" messages (coming from other bean properties which are not covered by the JSF form) as a global message but just suppress them.
  • ValidateMultipleFields (all multi-field validators basically) have previously skipped all disabled/readonly/nonrendered inputs. Now they won't anymore be skipped, and the values argument (3rd argument of validate method) will contain their current model value (and thus not the submitted value).
  • Package org.omnifaces.component.output.cache has been migrated to org.omnifaces.util.cache and several previously private/hidden artifacts have been made public, so that it's now more useful for non-component related caches.
  • All Faces/FacesLocal/Components/Servlets methods which previously threw IOException will now throw Java8's java.io.UncheckedIOException instead, hereby reducing down unnecessary throws IOException boilerplate in methods because those should always be bubbled up into the container.
  • org.omnifaces.facesviews.FacesServletDispatchMethod and ViewHandlerMode which was deprecated since 2.6 have now been removed without replacement (as they have become superfluous since Servlet 3.0).
  • org.omnifaces.renderkit.Html5RenderKit which was deprecated since 2.2 has now been removed without replacement (as this has become superfluous since JSF 2.2 with new passthrough attribtue feature).
  • org.omnifaces.config.BeanManager which was deprecated since 2.5 has now been removed with org.omnifaces.util.Beans as replacement.
  • RichFaces targeted hacks have been removed. OmniFaces 3.0 is therefore not anymore compatible with RichFaces. Note that RichFaces itself was declared "End of Life" June 2016 and is already not compatible with JSF 2.3.

New things:

  • <o:selectItemGroups> has been added which should remove the need to manually bake SelectItemGroup/SelectItem[] instances in beans as there's (still) no corresponding tag in standard JSF for this.
  • <o:url> has been extended with a value attribute which can take an arbitrary/external URL.
  • omnifaces.ImplicitNumberConverter which extends <f:convertNumber>, but doesn't annoyingly require enduser to explicitly input the percent or currency symbol when using type="percent" or type="currency".
  • org.omnifaces.eventlistener.FacesRequestLogger phase listener is introduced which will print detailed logs of JSF requests, including request method/URI/params, session/viewstate ID, remote user, action method expressions, faces messages and phase timings.
  • Faces#getRequestAttribute()/getFlashAttribute()/getViewAttribute()/getSessionAttribute()/getApplicationAttrubute() got an overload which takes a new argument representing the supplier which will be computed in case the attribute is absent.
  • Servlets#isSecure() has been added which also checks the de-facto X-Forwarded-Proto header which returns the protocol as obtained by the proxy. Useful in case the server runs HTTP but proxy runs HTTPS.
  • #{of:isInstance('com.example.ClassName', object)} has been added to act as instanceof in EL.
  • #{of:parenthesize(object)} has been added which will print parenthesis around the given object only and only if it isn't null nor empty nor equals zero.
  • NoAutoGeneratedIdViewHandler will now also recognize prependId="false" and log a warning because this is bad practice.
  • Under the covers, many things are replaced by new JSF 2.3 API things (among others, a bunch of new constants, improved faces wrappers and ResourceHandler#markResourceRendered() / isResourceRendered()) and also Java8 lambdas and streams have been introduced where possible.

Deprecated things:

  • <o:commandScript> has been deprecated as it's now moved into JSF 2.3 as <h:commandScript> with exactly the same functionality.
  • <o:importConstants> has been deprecated as it's now moved into JSF 2.3 as <f:importConstants> with the only difference that <f:importConstants> requires being placed in <f:metadata>.
  • GenericEnumConverter has been deprecated as it's now built into JSF 2.3's <h:selectManyXxx> components with the additional "side effect" that those components now also work on non-enum collections without need for any custom converter.
  • fixviewstate.js has been deprecated as it's now finally solved in JSF 2.3 (by yours truly).
  • <o:form includeViewParams="true"> as well as <o:form includeRequestParams="true"> have been deprecated as those have never proven to be more useful than useRequestURI="true".

Noted should be that the <o:socket> is also moved into JSF 2.3 as <f:websocket> with here and there a few small API generifications. But this won't be deprecated anywhere in OmniFaces 3.x as it still has room for new ideas and improvements.

Installation

Non-Maven users: download OmniFaces 3.0-RC1 JAR and drop it in /WEB-INF/lib the usual way, replacing the older version if any.

Maven users: use <version>3.0-RC1</version>.

<dependency>
    <groupId>org.omnifaces</groupId>
    <artifactId>omnifaces</artifactId>
    <version>3.0-RC1</version>
</dependency>

If you have found any issues or comments related to above listed changes, please by all means report an issue.

Thursday, February 2, 2017

OmniFaces 2.6 enables saving entire @ViewScoped bean in client side state

OmniFaces 2.6 has been released!

The main new things are a bunch of general purpose converters for strings and collections, a new implicit EL object #{faces} which delegates to Faces utility class and last but not least a new attribute for @ViewScoped which triggers saving the entire physical bean in JSF view state when client side state saving is enabled, hereby making it effectively to be not expirable and thus live forever as long as the associated page lives, even when cached/copied.

You can find the complete list of additions, changes and fixes at What's new in OmniFaces 2.6? list in showcase.

Update 14 December 2017: OmniFaces 2.6.7 has been released with the main bugfixes being: 1) Removed accidentally introduced Java 1.8 specific methods causing OmniFaces 2.6 it to not run on Java 1.7 anymore. 2) Fixed several MyFaces incompatibilities with @ViewScoped unload. 3) Fixed the problem of standard JSF converters not being useable anymore when a @FacesConverter is created which extends from a standard JSF converter while having beans.xml with bean-discovery-mode set to all.

Installation

Non-Maven users: download OmniFaces 2.6.7 JAR and drop it in /WEB-INF/lib the usual way, replacing the older version if any.

Maven users: use <version>2.6.7</version>.

<dependency>
    <groupId>org.omnifaces</groupId>
    <artifactId>omnifaces</artifactId>
    <version>2.6.7</version>
</dependency>

For CDI-less users, the latest 1.1x version is still 1.14.1.

If you need some arguments to move to CDI:

  • Upcoming JSF 2.3 will require a CDI dependency
  • JSF own @ManagedBean and @XxxScope annotations are marked deprecated in JSF 2.3 (already as of 2.3-m06)
  • Spring 3.x already supports javax.inject API from CDI, so Spring services (which are often used to substitute the lack of EJB support in Tomcat) can seamlessly be injected in CDI managed beans.

@ViewScope(saveInViewState=true)

The @ViewScoped annotation got a new attribute: saveInViewState. When you're using client side state saving by having the javax.faces.STATE_SAVING_METHOD context parameter set to client along with a valid jsf/ClientSideSecretKey in web.xml as below...

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>
<env-entry>
    <env-entry-name>jsf/ClientSideSecretKey</env-entry-name>
    <env-entry-type>java.lang.String</env-entry-type>
    <env-entry-value><!-- See http://stackoverflow.com/q/35102645/157882 --></env-entry-value>
</env-entry>

...and you explicitly want to store the whole view scoped bean instance in the JSF view state instead of in the HTTP session, then set the annotation's saveInViewState attribute to true.

import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;

@Named
@ViewScoped(saveInViewState=true)
public class OmniCDIViewScopedBean implements Serializable {}

It's very important that you understand that this setting has potentially a major impact on the size of the JSF view state, certainly when the view scoped bean instance holds "too much" data, such as a collection of entities for a data table, and that such beans will in fact never expire as they are stored entirely in the javax.faces.ViewState hidden input field in the HTML page. Moreover, the @PreDestroy annotated method on such bean will explicitly never be invoked, even not on an unload as it's quite possible to save or cache the page source and re-execute it at a (much) later moment.

It's therefore strongly recommended to use this setting only on a view scoped bean instance which is exclusively used to keep track of the dynamically controlled form state, such as disabled, readonly and rendered attributes which are controlled by ajax events.

New converters

A bunch of new converters have been added. It's after all a bit embarrassing why they were not added to OmniFaces much sooner as they are all quite "general purpose" and have been repeated in all our projects for years. Anyway, better late than never ;)

  • omnifaces.TrimConverter: the getAsObject() trims any whitespace from submitted string values. The getAsString() does effectively nothing.
  • omnifaces.ToLowerCaseConverter: the getAsObject() lowercases any character in submitted string values based on current locale. The getAsString() does effectively nothing.
  • omnifaces.ToUpperCaseConverter: the getAsObject() uppercases any character in submitted string values based on current locale. The getAsString() does effectively nothing.
  • omnifaces.ToCollectionConverter: the getAsObject() converts any commaseparated string to a collection, along with trimming away any whitespace around the delimiters. The delimiter is configurable via an attribute. The getAsString() does effectively the reverse, but when using for output only, you could also use the existing #{of:joinXxx()} functions instead.

#{faces}

The well-known Faces utility class got a counterpart in EL with help of FacesELResolver. All methods which start with get or is, and take no parameters, and return either String or boolean, and are not related to response nor to session or flash (for which already implicit EL objects #{session} and #{flash} exist), will be available as properties of the implicit object #{faces}. Examples are:

  • #{faces.development}
  • #{faces.serverInfo}
  • #{faces.ajaxRequest}
  • #{faces.requestBaseURL}
  • #{faces.requestURLWithQueryString}

To find out all of them, check the javadoc whether the method explicitly states This is also available in EL as #{faces.xxx}.

OmniFaces 3.x

The 2.6.x will be the latest OmniFaces release for JSF 2.2. The focus will now be moved to OmniFaces 3.0 for JSF 2.3. JSF 2.3 itself is scheduled to be finalized this quarter. Major change will be the upgrade from Java 7 to —finally— Java 8 with all of its awesomeness. With this new major release, a bunch of OmniFaces artifacts which are already taken over in JSF 2.3 will be deprecated (except of <o:socket> as it still allows room for new ideas and improvements), and the ones already deprecated in OmniFaces 2.x will be removed.

To learn what's new in JSF 2.3, head to this complete overview of new JSF 2.3 features in Arjan Tijms' blog.

Maven download stats

Here are the Maven download stats after previous release:

  • October 2016: 11663
  • November 2016: 12911
  • December 2016: 13439
  • January 2017: 10889
  • February 2017: 12060
  • March 2017: 14669