Friday, May 29, 2015

PrimeFaces Cookbook Second Edition has been published

PrimeFaces Cookbook Second Edition was published today. This is an updated second edition of the first PrimeFaces book ever published. PrimeFaces Cookbook Second Edition covers over 100 effective recipes for PrimeFaces 5.x which this leading component suite offers you to boost JSF applications - from AJAX basics, theming, i18n support and input components to advanced usage of datatable, menus, drag-&-drop, charts, client-side validation, dialog framework, exception handling, responsive layout, and more.


I have updated the book's homepage with a new table of contents. There are 11 chapters and more than 380 pages. You can download the book's code, clone the project on GitHub, compile and run it. Please follow the instructions on the GitHub.

I would like to thank my family, especially my wife, Veronika; our advisers from Packt Publishing, Llewellyn Rozario and Ajinkya Paranjape, our reviewers, the PrimeFaces project lead Çağatay Çivici and JSF specification lead Ed Burns. These people accompanied us during the entire writing process and made the publication of the book possible with their support, suggestions, and reviews. Thanks a lot!

Wednesday, April 22, 2015

PrimeFaces Extensions 3.1.0 released

Today, we released the PrimeFaces Extensions 3.1.0. It is built on top of PrimeFaces 5.2 and is fully compatible with PrimeFaces 5.2.

Closed issues are available on the GitHub. Please consider some enhancements in the existing components like Timeline, DynaForm, InputNumber and CKEditor.

The new deployed showcase will be available soon as usually here. The next release will be a maintenance release again.

Have fun!

Sunday, April 5, 2015

A way to read properties with variable interpolation

Recently, I tried to define and read a global properties in an application server. The benefit of such property configured in the application server - it can be shared across all web applications that are deployed on this server. Every deployed application can read the same property which is configured just once at one place. What I tried to do was a system property with another system property in the value part. In the application server JBoss / WildFly, you can e.g. define a system property in the configuration file standalone.xml. I set the property exporting.service.config.file.
<system-properties>
    <property name="exporting.service.config.file" value="${jboss.server.config.dir}\exporting\exporting-service.properties"/>
</system-properties>
jboss.server.config.dir points to the base configuration directory in JBoss. This property is set automatically by JBoss. In this example, we have a so-called Variable Interpolation. The definition from the Wikipedia: "Variable interpolation (also variable substitution or variable expansion) is the process of evaluating a string literal containing one or more placeholders, yielding a result in which the placeholders are replaced with their corresponding values". Another example for placeholders ${...} in property value would be the following configuration:
application.name=My App
application.version=2.0
application.title=${application.name} ${application.version}
When we now try to get the system property from the first example with Java's System.getProperty(...)
 
String globalConfigFile = System.getProperty("exporting.service.config.file");
 
we will get the value ${jboss.server.config.dir}\exporting\exporting-service.properties. The placeholder ${jboss.server.config.dir} is not resolved. There are the same troubles in the second example as well.

What would be the simplest way to read properties with variable interpolation? Well, there is the Spring Framework with PlaceholderConfigurerSupport and so on. But it is an overhead to have such big framework as dependency. Is there a lightweight library? Yes, sure - Apache Commons Configuration. Apache Commons Configuration provides special prefix names for properties to evaluate them in a certain context. There are for instance:
  • sys: This prefix marks a variable to be a system property. Commons Configuration will search for a system property with the given name and replace the variable by its value.
  • const: The prefix indicates that a variable is to be interpreted as a constant member field of a class. The name of the variable must be fully qualified class name.
  • env: The prefix references OS-specific environment properties.
 Some examples from the documentation:
user.file = ${sys:user.home}/settings.xml
action.key = ${const:java.awt.event.KeyEvent.VK_CANCEL}
java.home = ${env:JAVA_HOME}
Now, I could add the needed dependency to my Maven project
<dependency>
    <groupId>commons-configuration</groupId>
    <artifactId>commons-configuration</artifactId>
    <version>1.10</version>
</dependency>
set the prefix sys: before jboss.server.config.dir
<system-properties>
    <property name="exporting.service.config.file" value="${sys:jboss.server.config.dir}\exporting\exporting-service.properties"/>
</system-properties>
and write the following code
import org.apache.commons.configuration.SystemConfiguration;

...

SystemConfiguration systemConfiguration = new SystemConfiguration();
String globalConfigFile = systemConfiguration.getString("exporting.service.config.file");
...
The String globalConfigFile on my notebook has the value C:\Development\Servers\jboss-as-7.1.1.Final\standalone\configuration\exporting\exporting-service.properties. The prefix sys: marks a variable to be a system property. Commons Configuration will search for a system property with the given name and replace the variable by its value. The complete code:
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.SystemConfiguration;

...

PropertiesConfiguration propertiesConfiguration = new PropertiesConfiguration();
SystemConfiguration systemConfiguration = new SystemConfiguration();
String globalConfigFile = systemConfiguration.getString("exporting.service.config.file");
if (globalConfigFile != null) {
    try {                
        propertiesConfiguration.setDelimiterParsingDisabled(true);                
        propertiesConfiguration.load(globalConfigFile);
    } catch (ConfigurationException e) {
        LOG.log(Level.INFO, "Cannot read global properties");
    }            
}
Any single property can be read e.g. as
propertiesConfiguration.getString("someKey")
propertiesConfiguration.getString("someKey", someDefaultValue)
propertiesConfiguration.getBoolean("someKey")
propertiesConfiguration.getBoolean("someKey", someDefaultValue)
propertiesConfiguration.getInteger("someKey")
propertiesConfiguration.getInteger("someKey", someDefaultValue)
usw. That's all. Let me know if you know another simple ways to read properties with variable interpolation.

Friday, April 3, 2015

Caching of web content with Spring's cache manager


I this post, I would like to show basics how to cache and manage the caching of web content with Spring's CacheManager, @Cacheable and JMX annotations. Imagine a web shop which fetches some content, such as header, footer, teasers, main navigation, from a remote WCMS (Web Content Management System). The fetching may e.g. happen via a REST service. Some content is rarely updated, so that it makes sense to cache it in the web application due to performance reasons.

Getting Started

First, we need a cache provider. A good cache provider would be EhCache. You need to add the EhCache as dependency to your project. You also need to configure ehcache.xml which describes, among other things, the cache name(s), where and how long the cached content is stored. Please refer to the documentation to learn how the ehcache.xml looks like. The central class of the EhCache is the net.sf.ehcache.CacheManager. With help of this class you can add or remove any objects to / from the cache and much more programmatically. Objects can be cached in memory, on the disk or somewhere else.

The Spring framework provides a CacheManager backed by the EhCache - org.springframework.cache.CacheManager. It also provides the @Cacheable annotation. From the documentation: "As the name implies, @Cacheable is used to demarcate methods that are cacheable - that is, methods for whom the result is stored into the cache so on subsequent invocations (with the same arguments), the value in the cache is returned without having to actually execute the method. In its simplest form, the annotation declaration requires the name of the cache associated with the annotated method". We will use the JMX annotations as well. These are Spring's annotations @ManagedResource and @ManagedOperation. Why do we need those? We need them to be able to clear cache(s) via an JMX console. Why? Well, e.g. the underlying data have been changed, but the cache is not expired yet. The outdated data will be still read from the cache and not from the native source. The beans annotated with @ManagedResource will be exposed as JMX beans and methods annotated by @ManagedOperation can be executed via an JMX console. I recommend to use JMiniX as a simple JMX entry point. Embedding JMiniX in a webapp is done simply by declaring a servlet. Parametrized methods are supported as well, so that you can even input some real values for method's parameters and trigger the execution with these values.

How to do it...

Now we are ready to develop the first code. We need a service which communicates with a remote backend in order to fetch various contents from the WCMS. Let's show exemplary a basic code with one method fetchMainNavigation(). This method fetches the structure of the main navigation menu and converts the structure to a DTO object NavigationContainerDTO (model class for the menu). The whole business and technical logic is resided in the bean MainNavigationHandler. This logic is not important for this blog post. The method fetchMainNavigation() expects two parameters: locale (e.g. English or German) and variant (e.g. B2C or B2B shop).
@Component
public class WCMSServiceImpl extends BaseService implements WCMSService {
 
    // injection of Spring's CacheManager is needed for @Cacheable
    @Autowired
    private CacheManager cacheManager;
 
    @Autowired
    private MainNavigationHandler mainNavigationHandler;
 
    ...
 
    @Override
    @Cacheable(value = "wcms-mainnavigation",
                        key = "T(somepackage.wcms.WCMSBaseHandler).cacheKey(#root.methodName, #root.args[0], #root.args[1])")
    public NavigationContainerDTO fetchMainNavigation(Locale lang, String variant) {
        Object[] params = new Object[0];
        if (lang != null) {
            params = ArrayUtils.add(params, lang);
        }
        if (variant != null) {
            params = ArrayUtils.add(params, variant);
        }
 
        return mainNavigationHandler.get("fetchMainNavigation", params);
    }
}
The method is annotated with the Spring's annotation @Cacheable. That means, the returned object NavigationContainerDTO will be cached if it was not yet available in the cache. The next fetching will return the object from the cache until the cache gets expired. The caching occurs according to the settings in the ehcache.xml. Spring's CacheManager finds the EhCache provider automatically in the classpath. The value attribute in @Cacheable points to the cache name. The key attribute points to the key in the cache the object can be accessed by. Since caches are essentially key-value stores, each invocation of a cached method needs to be translated into a suitable key for the cache access. In a simple case, the key can be any static string. In the example, we need a dynamic key because the method has two parameters: locale and variant. Fortunately, Spring supports dynamic keys with SpEL expression (Spring EL expression). See the table "Cache SpEL available metadata" for more details. You can invoke any static method generating the key. Our expression T(somepackage.wcms.WCMSBaseHandler).cacheKey(#root.methodName, #root.args[0], #root.args[1]) means we call the static method cacheKey in the class WCMSBaseHandler with three parameters: the method name, first and second arguments (locale and variant respectively). This is our key generator.
public static String cacheKey(String method, Object... params) {
    StringBuilder sb = new StringBuilder();
    sb.append(method);

    if (params != null && params.length > 0) {
        for (Object param : params) {
            if (param != null) {
                sb.append("-");
                sb.append(param.toString());
            }
        }
    }

    return sb.toString();
}
Let's show how the handler class MainNavigationHandler looks like. This is just a simplified example from a real project.
@Component
@ManagedResource(objectName = "bean:name=WCMS-MainNavigation",
                                description = "Manages WCMS-Cache for the Main-Navigation")
public class MainNavigationHandler extends WCMSBaseHandler<NavigationContainerDTO, Navigation> {

    @Override
    NavigationContainerDTO retrieve(Objects... params) {
        // the logic for content retrieving and DTOs mapping is placed here
        ...
    }
 
    @ManagedOperation(description = "Delete WCMS-Cache")
    public void clearCache() {
        Cache cache = cacheManager.getCache("wcms-mainnavigation");
        if (cache != null) {
            cache.clear();
        }
    } 
}
The CacheManager is also available here thanks to the following injection in the WCMSBaseHandler.
@Autowired
private CacheManager cacheManager;
@ManagedResource is the Spring's JMX annotation, so that the beans are exported as JMX MBean and become visible in the JMX console. The method to be exported should be annotated with @ManagedOperation. This is the methode clearCache() which removes all content for the main navigation from the cache. "All content" means an object of type NavigationContainerDTO. The developed WCMS service can be now injected into a bean on the front-end side. I already blogged about how to build a multi-level menu with plain HTML and shown the code. This is exactly the main navigation from this service.

There is more...

The scanning of JMX annotations should be configured in a Spring's XML configuration file.
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="server" ref="mbeanServer"/>
    <property name="assembler" ref="assembler"/>
    <property name="namingStrategy" ref="namingStrategy"/>
    <property name="autodetect" value="true"/>
</bean>
The JMX console of the JMiniX is reachable under the http(s)://:/mct/webshop/admin/jmx/ A click on the execute button of the clearCache() method triggers the cache clearing.

Saturday, March 7, 2015

HTTP web server for Chrome to test local web applications

If you are writing HTML and JavaScript on your PC and testing the output in your browser without setting up a server, you will probably get some error messages about Cross Origin Requests. Your browser will render HTML, run JavaScript, jQuery or AngularJS web app, and ... block requests. This is a common behavior of many web browsers due to possible cross site attacks. That is understandable because it is not clever to allow someone to read your hard drive from your web browser. Right?

More concrete example. Assume, you develop an AngularJS web app with custom directives. Maybe you're quickly testing some AngularJS features without any web server. AngularJS loads HTML files of custom directives on page initial load. All files are loaded by AJAX from your PC, so that you will see an error message such as "XMLHttpRequest cannot load file:///C:/somefolder/somefile.html". I had e.g. these messages in the browser console:


This is because your browser doesn't allow AJAX requests for file:/// Obviously, you need to serve all files over HTTP. The simplest solution would be to install a web server for Chrome. It serves web pages from a local folder over the network, using HTTP and comes exactly to rescue. After installing this small server app from the Google Web Store, you will see a Web Server icon. I have e.g. something like


Open the web server for Chrome and choose a directory to serve static content. In our case, this is the main folder of your project.


It is now able to stream large files and handle range requests. It also sets mime types correctly. Navigate to http://127.0.0.1:8887 You will see all content of you project. Assume, the main file is called myapp.html. After choosing this file, you will see the URL http://127.0.0.1:8887/myapp.html The web app is fine now because all separate files for AngularJS's includes or directives are streamed down by AJAX over HTTP. Changes in files are visible on-the-fly without any restarts or redeployments.

Have fun!