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.