Latest Publications

Bash script to post/edit phpbb forum posts

If anyone has the desire to automate forum posts for whatever reasons, here is a bash script that will do:

(more…)

Using system dialogs in textmate commands / shell scripts (on a mac)

Sometimes you need to provide user input to your textmate scripts. The usual cocoa inputs as described in the textmate manual don’t work in a bash environment, therefor a wrapper is needed. One way to do this, is to use the library CocoaDialog. After the initial setup, as described here in the documentation we are able to call a dialog from the command shell which can now be exploited in our scripts.

An example command to replace a placeholder in your textmate file with iterating numbers (more dialog examples can be found on the cocoadialog examples page):

#!/usr/bin/perl -w
use strict;

our $CD = "$ENV{HOME}/Applications/CocoaDialog.app/Contents/MacOS/CocoaDialog";

my $rv = `$CD standard-inputbox --title "Enter increment start number" --no-newline \\
    --informative-text "Where to begin with incrementation?"`;

my ($button_rv, $retval) = split /\n/, $rv, 2;
my $inc = 1;

if ($button_rv == 1) {
     while(<>) { 
        if(m/^\\i\((\d+)\s*,\s*(\d+)\)$/) { 
                $retval=$1; 
                $inc=$2; 
                next; 
        } 
        while(s/\\i/$retval/) {$retval+=$inc;} 
        print; 
	} 
}

Now you can insert the placeholder \i whereever you like and apply your textmate command to replace every instance of the placeholder with an increasing number, starting by your provided number.

Creating Annotation-based Concurrency with AspectJ & Maven

For a project at the University we had the task to create Annotations that would remove the concurrency boilerplate Code from Java. The main Idea of the Annotation is to mark some kind of Collection-processing method with @Parallel, so that the method-body will be executed by several Threads, which after completion will be joined and passed back as return value. I thought that this would be the right time to finally take a look into AspectJ.

So at first we create a standard maven project and a basic Annotation:

package de.fabianmaass.abc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Parallel {
  int numThreads();
}

Then we create the Aspect (i read that the default maven directory for aspects is /src/main/aspect but somehow i feel that the location doesn’t really matter).

package de.fabianmaass.abc.aspect;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import junit.framework.Assert;
import de.fabianmaass.abc.annotation.Parallel;

public aspect ParallelAnnotationAspect {

  // The Pointcut to select all Methods that are annotated with @Parallel,
  // need a Collection as Parameter and return a Collection
  public pointcut parallelExecution(Object arg, Parallel parallel) : 
    execution(@Parallel Collection *(Collection)) 
                         && args(arg) 
                         && @annotation(parallel);

  // The advice to replace the original behaviour and run the Method with
  // parts of the Collection in several Threads instead
  Object around(Object arg, final Parallel parallel) : 
                                     parallelExecution(arg, parallel) {
    if (arg == null || parallel.numThreads() <= 1)
      return proceed(arg, parallel);
    
    final List<?> originalCollection = (List) arg;
    
    // if there are more Threads than Elements in the Collection specified
    // use the Collection-Size
    final int realNumOfThreads = parallel.numThreads() > originalCollection.size() ?
                                 originalCollection.size() :
                                 parallel.numThreads();
       
    final List<?> processedCollection = new ArrayList();
    
    ExecutorService executor = Executors.newFixedThreadPool(realNumOfThreads);
    
    final int stepSize = (int) Math.ceil(Double.valueOf(originalCollection.size()) / 
                                         Double.valueOf(realNumOfThreads));
    
    for (int i = 0; i<originalCollection.size(); i += stepSize) {
      final int counter = i;
      executor.execute(new Thread() {
        @Override
        public void run() {
          processedCollection.addAll(
              (List) proceed(originalCollection
                         .subList(counter, 
                           (
                              (counter+stepSize) < originalCollection.size()) ?
                               counter + stepSize :
                               originalCollection.size()
                           )
                         , parallel)
          );
        }
      });
    }
       
    executor.shutdown();
    
    while(!executor.isTerminated()) {
        try {
            executor.awaitTermination(60, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    Assert.assertEquals(originalCollection.size(), processedCollection.size());
    
    return processedCollection;
  }
}

Now, if you want to stop right here, you would need to add the AspectJ dependency and the compile-time weaving of the Aspects into your normal Java-Files to your maven pom file.

<build>
  <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>compile</goal>
              <goal>test-compile</goal>
            </goals>

            <configuration>
              <source>1.5</source>
              <target>1.5</target>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>${aspectj.version}</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

But the (imho) more elegant solution is to keep the aspects in a separate maven project and include it in your normal project. So the last thing left to do is to put the just created aspectj-library to your projects dependencies and tell the aspectj-maven plugin to use it as such:

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>aspectj-maven-plugin</artifactId>
      <executions>
        <execution>
          <goals>
            <goal>compile</goal>
            <goal>test-compile</goal>
          </goals>
          <configuration>
            <source>1.5</source>
            <target>1.5</target>
          </configuration>
        </execution>
      </executions>
      <configuration>
        <aspectLibraries>
          <aspectLibrary>
            <groupId>de.fabianmaass</groupId>
            <artifactId>abc</artifactId>
          </aspectLibrary>
        </aspectLibraries>
      </configuration>
    </plugin>
  </plugins>
</build>

<dependencies>
  <dependency>
    <groupId>de.unikonstanz</groupId>
    <artifactId>abc</artifactId>
    <version>1.0-SNAPSHOT</version>
  </dependency>
</dependencies>

Now you’ve got an AspectJ maven library and can annotate your collection-processing methods with @Parallel (woot!) πŸ˜‰

Personally I think AspectJ is worth the trouble to take a look into – I guess you can do some really powerful stuff with it. Next steps for me are creating a convenience project with common tools, like annotation-driven profiling and logging, just to eliminate the ramp-up obstacle for the next real usage…

Source Code:
Annotation & AspectJ Project
Sample usage


Running several Java Versions under Windows

Just found out that, if you run several Java Versions under Windows, Windows has this oddity to put the Java executables under \windows\system32, whenever you install a newer version of java. So if you have to build java code on the console with an older version, sometimes its not enough to set the %JAVA_HOME% environment variable or to set the version in systemcontrol, but to delete those executables.windows_screen

Creating hybrid Web-Applications with ICEFaces and Maven

Since ICEFaces is almost like ZK a container-agnostic Framework, I wanted to create an additional Archetype for creating Web-Apps with ICEFaces. This could have been any other JSF component framework, but ICEFaces happens to have their own Portlet-Bridge, which comes in handy when deploying to a portal. I tried RichFaces before, but RichFaces seems to be a major pain when trying to run in a non-ejb container like Tomcat. Maybe things will get better with the soon to be released JBoss Portlet-Bridge 2.0, but I doubt it, because its not really in their scope.
And because the settings are almost identical (besides the ICEFaces specific ones) like the ZK Archetype, i just post the svn url here:

checkout the archetype with:

svn co http://hybrid-web-applications.googlecode.com/svn/trunk/archetypes/hybrid-icefaces-archetype/

run:

mvn clean install

to deploy the archetype to your local maven repository. After that you are able to create your own hybrid ICEFaces Web-Applications with:

mvn archetype:generate -DarchetypeGroupId=de.fabianmaass.archetypes.hybrid.icefaces -DarchetypeArtifactId=hybrid-icefaces-webapp -DarchetypeVersion=1.0-SNAPSHOT

Again, you have to adjust the path of your local Tomcat/Liferay Installations in the pom.xml, or else the build will fail.
pom.xml

<properties>
    <tomcat.folder>${env.TOMCAT_HOME}/webapps</tomcat.folder>
    <liferay.folder>${env.LIFERAY_HOME}/tomcat-6.0.18</liferay.folder>
</properties>

When you changed it, simply run:

mvn clean install

in your newly created project and voila: you can run the application in both servlet- and portlet container πŸ™‚

Creating hybrid Web-Applications with ZK and Maven

I want to describe the basic steps to create a hybrid Web-Application, thats runnable in a normale Application Server, like Tomcat, and is also deployble to a Portlet Server like Liferay. There are lots of other well documented sources that describe the basic steps on each of those Web-Apps independently, so i dont want to get into too much detail here. I mainly want to describe the essential steps, so your Web-App is deployable in both containers. Im using Liferay 5.2.3, it should also be working in other Portlet-Containers, for example JBoss Portal, but i can’t guarantee it. Finally i want to provide a Maven Archetype for the hybrid Web-Application.

folder layout

First we need some deployment descriptors for our Portlet Application. Basically this has to be only the portlet.xml, Liferay is smart enough to figure out the rest, but since we want the portlet to be good-looking we add some Liferay specific descriptors as well:

portlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<portlet-app version="1.0"
  xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
                     http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd">
  <portlet>
    <description xml:lang="EN">ZKHybridPortlet</description>
    <portlet-name>ZKHybridPortlet</portlet-name>
    <display-name xml:lang="EN">ZKPortlet</display-name>
    <portlet-class>org.zkoss.zk.ui.http.DHtmlLayoutPortlet</portlet-class>

    <init-param>
      <name>zk_page</name>
      <value>/index.zul</value>
    </init-param>

    <!-- Notice that expiration-cache must be set to zero to prevent portals from caching the result. -->
    <expiration-cache>0</expiration-cache>

    <supports>
      <mime-type>text/html</mime-type>
      <portlet-mode>view</portlet-mode>
    </supports>
  </portlet>
</portlet-app>

The important part here is the ZK DHtmlLayoutPortlet portlet-class. This extends the GenericPortlet from Javas Portlet-API, and therefore implements the basic Portlet Lifecycle methods. Since we don’t have a common Portlet, we need to tell the Portal were to go, after initializing the Portlet. This is done with the zk_page init-param. As you can see, this portlet currently only supports the view portlet-mode, but you can easily add the help and edit mode with the according parameters in the portlet.xml

When deploying to a Liferay Portal, the most important file is the Liferay specific liferay-plugin-package.properties. Liferay adds several filters to the web.xml when you hot-deploy a war file, which renders the AJAX-ability of your zk portlet useless. To circumvent this behavior, you have to set this property and place the file under \WEB-INF.

liferay-plugin-package.properties

speed-filters-enabled=false

The other files under \WEB-INF\ are just to make Liferay happy, but you could easily skip those. The web.xml declaration is straight forward as well. There is actually only the Servlet declaration important. Look up the other settings at the ZKoss Page or in the archetype πŸ˜‰

web.xml

<servlet>
  <description>ZK loader for evaluating ZUML pages</description>
  <servlet-name>zkLoader</servlet-name>
  <servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>

  <init-param>
    <param-name>update-uri</param-name>
    <param-value>/zkau</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

The beauty of the ZK hybrid Application is, that those settings don’t interfere with each other. You can define your Web-Application Settings in the web.xml which dont mess up the portlet and vice versa.

An offset nevertheless is, that you cant redirect to other zul-pages with execution.sendRedirect() – this simply would’nt work in a Portlet-Environment. This means, that you have to manipulate the DOM-Tree of the Web-Application with Executions.createComponents() whenever the User wants to navigate to a new Page or updates it partially – which means that you loose your Page-URLs. This is not so important in a Portal, because you never really had page-URLS in the first place, but it might be important to consider in a Web Application.

The maven pom.xml is pretty straight forward aswell, so i don’t want to post it here. Its merely everything you need to get a ZK App up & running and deploy it in a Container. Additionally I added some deploy ant tasks: if you trigger a mvn clean, it will delete the exploded folders in both Tomcat and Liferay plus the tmp and work folders of your Liferay Installation. If you trigger a mvn install, it will copy the built war-file into the Tomcat webapps and Liferay deploy folder. You can replace those ant tasks with mavens cargo plugin, but i liked it that way, plus i wanted to make sure that my Web-App would run in a clean installation.

I provided a very simple zul file (copied from the ZK examples page), so you can see how to build your web-app. The one thing to notice here is, that you need a surrounding window element to avoid namespace clashes, like that:

index.zul

<window border="none" mode="embedded">

Thats all you have to do πŸ™‚ To get started, you can checkout my Archetype from the google code page and play around a little:

svn co http://hybrid-web-applications.googlecode.com/svn/trunk/archetypes/hybrid-zk-archetype
mvn clean install

After that you can create your own hybrid Web-Application with ZK:

mvn archetype:generate -DarchetypeGroupId=de.fabianmaass.archetypes.hybrid.zk -DarchetypeArtifactId=hybrid-zk-webapp -DarchetypeVersion=1.0-SNAPSHOT

A sidenote: The pom wants to deploy the war files to the liferay and tomcat deploy folder. You have to change the path in the pom file or set a system variable, or else the build will fail.

pom.xml

 <properties>
    <tomcat.folder>${env.TOMCAT_HOME}/webapps</tomcat.folder>
    <liferay.folder>${env.LIFERAY_HOME}/tomcat-6.0.18</liferay.folder>
  </properties>

sources:
http://devenphillips.blogspot.com/2009/04/developing-liferay-portlets-with-zk.html
http://docs.zkoss.org/wiki/Portal_integration

Liferay/Tomcat Bundle – Changing Timezone

If you are getting warning messages from your freshly unzipped liferay/tomcat bundle like this:

Warning: META-INF\MANIFEST.MF modified in the future.
Warning: WEB-INF\liferay-display.xml modified in the future.
Warning: WEB-INF\liferay-plugin-package.properties modified in the future.
Warning: WEB-INF\liferay-plugin-package.xml modified in the future.
Warning: index.zul modified in the future.

you have to add timezone settings in the setenv.sh/setenv.bat like that:

-Duser.timezone=Europe/BERLIN

A list of Java Timezones can be found here.

sources:
http://tinyurl.com/lrpbdu
http://tinyurl.com/nd8w5e