Monday, July 4, 2016

Integrating Tomcat 8.5.x and TomEE 7.x in Eclipse

Are you also seeing below error when trying to integrate Tomcat 8.5.x or TomEE 7.x using Tomcat v8.0 Server plugin in Eclipse?

For searchbots, the error says The Apache Tomcat installation at this directory is version 8.5.3. A Tomcat 8.0 installation is expected. This error even occurs in the current Eclipse Neon release. Perhaps they'll fix it in Neon SR1 by adding a new Tomcat v8.5 Server plugin. But for now and for older versions a workaround is needed.

The Eclipse built-in Tomcat server plugin basically detects the server version based on server.info property of org/apache/catalina/util/ServerInfo.properties file of Tomcat's /lib/catalina.jar file which looks like below in case of Tomcat 8.5.3:

server.info=Apache Tomcat/8.5.3
server.number=8.5.3.0
server.built=Jun 9 2016 11:16:29 UTC

All we need to do is to edit the version in server.info property to start with 8.0. Any ZIP or JAR aware tool should do it to edit it on the fly. I'm myself using WinRAR for the job.

server.info=Apache Tomcat/8.0.8.5.3
server.number=8.5.3.0
server.built=Jun 9 2016 11:16:29 UTC

Finally, it works.

INFO: Starting Servlet Engine: Apache Tomcat/8.0.8.5.3

The same procedure applies to TomEE 7.x which is based on Tomcat 8.5.x.

The difference between Tomcat 8.0 and 8.5 is the integration of Jaspic which is the first step towards standardizing Java EE authentication as part of JSR375. You probably already know that the ways to configure Java EE container managed authentication are totally scattered across different servers, making third party libraries such as Shiro and Spring Security more attractive. Each server needed its own way of configuring "realms" or "identity stores" to manage the database of users, passwords and roles. This will with JSR375 be unified using annotations and CDI provided via standard javax.security.* API. See also a.o. the question Java EE authentication: how to capture login event?

Friday, July 1, 2016

OmniFaces 2.4 revives c:url, improves @Param and simplifies logging

OmniFaces 2.4 has been released!

This version has relatively few new additions, only one brand new tag <o:url> which revives good 'ol JSTL <c:url> for Facelets, and a few utility methods/functions. There are several enhancements and bugfixes in existing stuff, such as the @Param finally supporting injecting multi-valued parameters such as foo=bar1&foo=bar2 into a String[] or List<String> and injecting into primitive type fields. Those few utility methods and enhancements must further simplify logging of JSF (ajax) actions, exceptions and JavaScript errors.

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

Installation

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

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

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

For users who don't want to use CDI, there's the CDI-less 1.14 with all 2.4 enhancements and fixes (but no brand new 2.x additions nor the o:url!).

Good ol' JSTL <c:url> revived

Sometimes there's need to access and/or print the current request URL "plain vanilla" in a JSF page. Common use cases are to prepopulate a ?from= request parameter for the login form so it can figure out where to redirect back after a successful login, and filling the HTML5 link relations referring the current or another page on the same site. Previously, this could to some extent (no control over domains) be done with JSTL ><c:url> which was removed in Facelets.

This has now been revived in OmniFaces 2.4 as <o:url> and even further enhanced. It supports setting the (relative) domain via domain attribute and it supports the same includeViewParams, includeRequestParams and useRequestURI attributes as <o:form>. The <o:url> also supports the var attribute allowing to set the value as an EL variable which can in turn be used in an EL expression elsewhere in the page.

Here's an example:

<o:url var="currentURL" />
...
<h:head>
    ...
    <link rel="canonical" href="#{currentURL}" />
    ...
</h:head>
<h:body>
    ...
    <h:link value="Login" outcome="login">
        <f:param name="from" value="#{currentURL}" />
    </h:link>
    ...
</h:body>

@Param now supports multiple values and primitives

The CDI @Param annotation has in OmniFaces 2.4 been further improved to also support injecting multi-valued request parameters such as foo=value1&foo=value2&foo=value3 into an array or List.

@Inject @Param(name="foo")
private List<String> foos;

@Inject @Param(name="bar")
private String[] bars;

Conversion and validation is also supported on multi-valued parameters like as already supported on single-valued parameters. On multi-valued parameters, JSF native conversion and validation will run on each submitted value. Bean Validation, if any, will however be performed on the entire List or array property and not on each individual item.

Furthermore, the @Param now also supports injecting into a primitive field. Previously this wasn't possible because CDI would attempt to inject an empty value as null into the field, which would only throw an exception (no autoboxing magic there in reflection). The @Param will now automatically take care about injecting the right default value of the primitive field in case the value is absent or empty.

Logging made easier

OmniFaces 2.4 comes with several utilities and enhancements which should further simplify logging of (ajax) actions, exceptions and JavaScript errors.

First, the Components got two new utility methods, one to find out the source component of the (ajax) form submit and another to extract all actions and listeners from it as a list of EL expression strings such as #{bean.action}, #{bean.actionListener}, #{bean.ajaxListener}.

UIComponent actionSource = Components.getCurrentActionSource();
List<String> actionExpressions = Components.getActionExpressionsAndListeners(actionSource);
// ...

This also works for e.g. <h:inputText><f:ajax listener="#{bean.listener}">. You can find a concrete example as PhaseListener in my answer to How can I log method expressions of JSF ajax requests.

Second, the FullAjaxExceptionHandler got a new logException overloaded method with a LogReason enum argument which should help in determining when exactly the exception has been caught and whether it was successfully handled or not. For example, if handling has failed because the response was already committed, or the error page itself contained an error, then you could take additional action by sending an email to site admin.

@Override
protected void logException(FacesContext context, Throwable exception, String location, LogReason reason) {
    switch(reason) {
        case RENDER_EXCEPTION_UNHANDLED:
        case ERROR_PAGE_ERROR:
            yourMethodToSendAnEmailToAdmin(exception, reason);
            break;
        default:
            super.logException(context, exception, location, reason);
    }
}

Third, the CombinedResourceHandler and <o:deferredScript> have been altered to always render crossorigin="anonymous" attribute to the generated <script> element. This will basically enable JavaScript error logging via window.onerror on scripts possibly served via a CDN. Such a logger can look like below, with little help of jQuery and a servlet:

$(window).on("error", function(message, source, line, column, error) {
    try {
        $.post("/script-error", $.param({
            url: window.location.href,
            client: navigator.userAgent,
            message: message,
            source: source,
            line: line,
            column: column,
            error: error ? error.stack : null
        }));
    }
    catch(e) {
        // Ignore.
    }
});
@WebServlet("/script-error")
public class ScriptErrorServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String url = request.getParameter("url");
        String client = request.getParameter("client");
        String message = request.getParameter("message");
        String source = request.getParameter("source");
        String line = request.getParameter("line");
        String column = request.getParameter("column");
        String error = request.getParameter("error");
        // ...
    }

}

Noted should be that the detail of the information being sent depends on the client used. Chrome for example is very kind to include the full stack trace

More OmniFaces in upcoming JSF 2.3

Besides the new JSF 2.3 <f:websocket>, which is largely based on <o:socket> introduced in previous OmniFaces version, more OmniFaces solutions have been integrated into upcoming JSF 2.3 the last months. The FixViewState is now in standard jsf.js as per spec issue 790, the <o:commandScript> is integrated as new JSF 2.3 <h:commandScript> as per spec issue 613, and the <o:importConstants> is integrated as new JSF 2.3 <f:importConstants> as per spec issue 1424 (which should be declared inside <f:metadata>). Those OmniFaces artifacts will be deprecated as per upcoming OmniFaces 3.0 for JSF 2.3.

Maven download stats

Here are the Maven download stats after previous release:

  • April 2016: 8050
  • May 2016: 8590
  • June 2016: 8560