Loading...

Monday, January 31, 2011

Install Hudson JNLP Slave Agent on Ubuntu

In this blog post we learn how to install a Hudson JNLP slave agent that is started headlessly as a service on Ubuntu. There are many tutorials and how-to's available but for me this was the easiest way to install the Hudson slave agent. We use the default Hudson installation for Ubuntu and use the provided scripts as templates for the Hudson slave scripts.

Friday, January 28, 2011

Configure JDBCRealm in Tomcat for Container Managed Security

Every time I install a new version of Tomcat I change the file conf/tomcat-users.xml to add a administrator user with the correct roles for accessing the manager application. In this post we see how we can create an administrator with the correct roles in a MySQL database and re-use this administrator user in several Tomcat version installations. So now when we install a new version of Tomcat we don't have to change conf/tomcat-users.xml, but change the conf/server.xml to point to our database.

First we must create a new database in MySQL to store the username, password and user roles. In our example we create a database with the name tomcat and create two tables: users and user_roles. The users table has two columns to store the username and password. The user_roles table has two columns to store the username and role name for a user. Finally we create a new MySQL user account, tomcat, to access the tables.

CREATE DATABASE IF NOT EXISTS tomcat;

USE tomcat;

CREATE TABLE users(
    username VARCHAR(15) NOT NULL PRIMARY KEY,
    password VARCHAR(32) NOT NULL
);

CREATE TABLE user_roles(
    username VARCHAR(15) NOT NULL,
    rolename VARCHAR(20) NOT NULL,
    PRIMARY KEY(username, rolename)
);


CREATE USER 'tomcat'@'localhost' IDENTIFIED BY 'tomcat';
GRANT SELECT ON tomcat.* TO 'tomcat'@'localhost';
FLUSH PRIVILEGES;

Our database is setup so we can create a new administrator user with the roles manager-gui and manager-script to access the Tomcat manager web application:

USE tomcat;

INSERT INTO users VALUES('system', MD5('s3cr3t'));
INSERT INTO user_roles VALUES('system', 'manager-gui');
INSERT INTO user_roles VALUES('system', 'manager-script');

Notice we have created the MySQL user account tomcat with only SELECT privileges. So to add users to the tomcat.users table we must do so with the MySQL root account.

Now we only have to configure Tomcat so our database is used as extra realm to check the users. We open conf/server.xml and look for the lines <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"> and add the following code after it:

<Realm className="org.apache.catalina.realm.JDBCRealm"
    driverName="org.gjt.mm.mysql.Driver"
    connectionURL="jdbc:mysql://localhost/tomcat"
    connectionName="tomcat" connectionPassword="tomcat"
    userTable="users" userNameCol="username" userCredCol="password"
    userRoleTable="user_roles" roleNameCol="rolename"
    digest="md5"/>

Notice we define the digest attribute with the value md5. In our SQL script we saved the password using MD5 encryption, so we must define the digest attribute with the same encryption name value.

Because we are accessing MySQL from the Tomcat Java code we must add the MySQL JDBC driver to Tomcat's classpath. We copy the mysql-connector-java-5.1.14-bin.jar (or other suitable MySQL JDBC driver) to $CATALINA_HOME/lib. This is the lib directory of the directory Tomcat is installed in.

We can start Tomcat and access the manager application with the username system and password s3cr3t. For each new or other Tomcat version we only have to add the <Realm ... /> element to conf/server.xml and the MySQL JDBC driver to the lib directory and we can re-use the same user credentials.

Add APR Based Native Library for Tomcat on Mac OSX

We can enhance Tomcat's features by using the APR based native library with Tomcat. If we put this library in the Java library path we get better performance, secure session ID support and OS level statistics. The Tomcat documentation explains how to achieve this by compiling sources and the like. But with Mac OSX and MacPorts we don't have to do this ourselves.

With the following steps I was able to add the native library to Tomcat:

  1. Install the Java developer package from Apple's Developer Connection
  2. Add a link with the name include in the /System/Library/Frameworks/JavaVM.framework/Home/ directory. We need this step because later on when we install tomcat-native with MacPorts this path is used as an include for compiling the source files.
    $ ln -s /System/Library/Frameworks/JavaVM.framework/Headers include
  3. $ sudo port install apr
  4. $ sudo port install tomcat-native

After these steps the APR based native libraries are installed in /opt/local/lib. So all we have to do is add this path to the Java library path when we start Tomcat:

$ export CATALINA_OPTS=-Djava.library.path=/opt/local/lib
$ bin/catalina.sh run

Alternatively we can create a symbolic link to add the native library to the default Java installation, so we don't have to specify the /opt/local/lib directory as a Java library path.

$ sudo ln -s /opt/local/lib/libtcnative-1.* /usr/lib/java

The following links helped me a lot to add the APR native library to my system:

Tuesday, January 25, 2011

Grails Goodness: RSS Feeds for Newest and Recently Updated Plugins

At the Grails plugins website we can see the newest and last updated plugins. But there are no RSS feeds for these page (Update: Looking at the source code I found a RSS feed URL for the last updated plugins. We can use the RSS feed with last updated plugins in our RSS reader). And it would be so handy to have RSS feeds to subscribe to, so we can use a RSS reader to be kept up-to-date with the newest and last updated plugins.

I've created a simple Yahoo Pipe to generate RSS feeds for these pages. The pipe simply scrapes the page and turns the information to a RSS feed. We can subscribe to the following URLs:


The original Yahoo Pipes are also available:

Spocklight: Add Spock Support to Java Project in STS/Eclipse

Suppose we get assigned to an existing Java project and we want to use Spock for writing our tests (of course!). In this post we learn the steps we need to take to achieve this. We assume the Java project is built with Maven and imported into SpringSource Tool Suite (or Eclipse). For an easier way to add Spock to STS/Eclipse using Gradle we can read this blog post written by Ken Kousen.

First we start with our Java project. The project for this sample is very simple. We only have one interface and an implementation class for finding a username in a list of users. The sources for this post can be found at Github. The following pom.xml is used:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.mrhaki.app.services</groupId>
    <artifactId>user-service</artifactId>
    <packaging>jar</packaging>
    
    <name>User Service</name>
    <description>Service to work with users</description>
    
    <version>1.2</version>

</project>

This project is imported as Maven project into SpringSource Tool Suite. Now it is time to add Spock support to our project. First we change the pom.xml and add the required plugins and dependencies:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mrhaki.app.services</groupId>
    <artifactId>user-service</artifactId>
    <packaging>jar</packaging>

    <name>User Service</name>
    <description>Service to work with users</description>

    <version>1.2</version>

    <properties>
        <spock.version>0.5-groovy-1.7</spock.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.gmaven</groupId>
                <artifactId>gmaven-plugin</artifactId>
                <version>1.3</version>
                <executions>
                    <execution>
                        <configuration>
                            <providerSelection>1.7</providerSelection>
                        </configuration>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.codehaus.gmaven.runtime</groupId>
                        <artifactId>gmaven-runtime-1.7</artifactId>
                        <version>1.3</version>
                        <exclusions>
                            <exclusion>
                                <groupId>org.codehaus.groovy</groupId>
                                <artifactId>groovy-all</artifactId>
                            </exclusion>
                        </exclusions>
                    </dependency>
                    <dependency>
                        <groupId>org.codehaus.groovy</groupId>
                        <artifactId>groovy-all</artifactId>
                        <version>1.7.5</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.spockframework</groupId>
                <artifactId>spock-maven</artifactId>
                <version>${spock.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>find-specs</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.spockframework</groupId>
            <artifactId>spock-core</artifactId>
            <version>${spock.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

Notice we must add the gmaven-plugin and spock-maven plugin to the plugins section. We must also add the spock-core dependency to our project. This is all we need to do to be able to run Spock specifications with Maven. But we need to do some extra steps to be able to run our Spock specifications from SpringSource Tool Suite.

First we add the directory src/test/groovy (which is used to save the Spock specifications in) to our project. Then we assign this new directory as source directory to the project. We open the properties of our project and select Java Build Path:

Next we click on the Add Folder... button and select the Create New Folder... button. We create the folder src/test/groovy:

We click on the Finish button and now we can select the newly created folder as a new source folder:

Now comes an important step, because we must change the Output folder of our newly created source folder. We select it and press the Edit... button. In the dialog window we select the radio button Specific output folder and fill in target/test-classes. If we don't change the output folder then STS cannot determine changes in the sources if we use the Run As | JUnit Test action.

Now we have added a new source folder to our project and assigned a correct output folder for the compiled class files:

Next we must make our Java project a Groovy project in STS. We right-click on our project and select Configure | Convert to Groovy Project:

Okay, STS is now ready for our Spock specifications! We write the following specification and save it as src/test/groovy/com/mrhaki/app/services/UserServiceImplSpec.groovy:

package com.mrhaki.app.services

import spock.lang.Specification

class UserServiceImplSpec extends Specification {
    
    UserServiceImpl userService = new UserServiceImpl();
    
    def "Search for existing name must return correct username"() {
        expect:
            userService.findUsername("Hubert A. Klein Ikkink") == 'mrhaki'
    }
    
    def "Search for non-existing name must return an empty String"() {
        expect:
            userService.findUsername('non-existing name') == ''
    }
    
    def "Search with null value for name must return an empty String"() {
        expect:
            userService.findUsername(null) == ''
    }
    
}

We can run our Spock specification with the Run or Run As | JUnit Test commands. STS recognizes the Spock specification as JUnit test and uses the testrunner to run our specification:

If the Run As command doesn't recognize the Spock specification as JUnit test then closing and reopening the source file may help.

Friday, January 21, 2011

Spocklight: Check for Exceptions with Spock

With Spock we can easily write feature methods in our specification to test if an exception is thrown by the methods invoked in a when block. Spock support exception conditions with the thrown() and notThrown() methods. We can even get a reference to the expected exception and check for example the message.

The following piece of code contains the specification to check for exceptions that can be thrown by a cook() method of the RecipeService class. And we check that exception are not thrown. The syntax is clear and concise, what we expect from Spock.

package com.mrhaki.blog

@Grab('org.spockframework:spock-core:0.5-groovy-1.7')
import spock.lang.Specification

class RecipeServiceSpec extends Specification {
    def "If cooking for more minutes than maximum allowed by recipe throw BurnedException"() {
        setup:
            def recipeService = new RecipeService()
            def recipe = new Recipe(time: 5, device: 'oven')

        when:
            recipeService.cook(recipe, 10, 'oven')

        then:
            thrown BurnedException
    }

    def "If cooking on wrong device throw InvalidDeviceException"() {
        setup:
            def recipeService = new RecipeService()
            def recipe = new Recipe(device: 'oven', time: 10)

        when:
            recipeService.cook(recipe, 2, 'microwave')

        then:
            InvalidDeviceException ex = thrown()
            // Alternative syntax: def ex = thrown(InvalidDeviceException)
            ex.message == 'Please use oven for this recipe.'
    }

    def """If the recipe is cooked on the right device and
           for the correct amount of minutes, 
           then no exception is thrown"""() {
        setup:
            def recipeService = new RecipeService()
            def recipe = new Recipe(device: 'oven', time: 30)

        when:
            recipeService.cook(recipe, 30, 'oven')

        then:
            notThrown BurnedException
            notThrown InvalidDeviceException
    }
}

class RecipeService {
    def cook(Recipe recipe, int minutes, String device) {
        if (minutes > recipe.time) {
            throw new BurnedException()
        }
        if (device != recipe.device) {
            throw new InvalidDeviceException("Please use $recipe.device for this recipe.")
        }
    }
}

class Recipe {
    int time
    String device
}

class BurnedException extends RuntimeException {
    BurnedException(String message) {
        super(message)
    }
}

class InvalidDeviceException extends RuntimeException {
    InvalidDeviceException(String message) {
        super(message)
    }
}

Tuesday, January 18, 2011

Redesign Site with Less Framework

Last month I have spent some time to redesign my Blogger template which is used for the Messages from mrhaki blog. The old template was almost two years old and was not good to read on mobile devices. I wanted to make the site more clean and with more focus on the content and the content must be easy to read on mobile devices. I think the use of mobile devices to read the website will increase in the coming months and years.

To support different viewport sizes for widescreen computers, laptops and mobile devices I choose Less Framework 3. The Less Framework 3 is a CSS grid system using inline media queries. We create a default layout which can be used by any web browser. Then we can define three additional layouts using inline media queries. If the web browser support these then the layout is used, otherwise the default layout is used.

The default layout supports 8 columns, bigger screens support 13 columns, landscape iPhones, narrow browsers support 5 columns. And finally a 3 column layout is available for mobile devices like iPhone. We can use CSS rules for the non-default layouts to rearrange elements or even hide or display elements with display:block or display:none.

This way of working is easy and the grid layout makes the content align correctly without any worries. I will use Less Framework 3 for more sites and make the browsing experience for mobile devices more pleasurable.

Monday, January 17, 2011

Gradle Goodness: Don't Let CodeNarc Violations Fail the Build

With the code-quality plugin for Groovy project we use CodeNarc to check our code. By default we are not allowed to have any violations in our code, because if there is a violation the Gradle build will stop with a failure. If we don't want to our build to fail, because of code violations, we can set the property ignoreFailures to true for the CodeNarc task.

The code-quality plugin adds two CodeNarc tasks to our project: codenarcMain and codenarcTest. We can simply set the property ignoreFailures for these tasks:

apply plugin: 'code-quality'

[codenarcMain, codenarcTest]*.ignoreFailures = true

We can also search for all tasks of type CodeNarc and set the ignoreFailures property. This is useful if we added new tasks of type CodeNarc to our project and want to change the property of all these tasks:

apply plugin: 'code-quality'

tasks.withType(CodeNarc).allTasks { codeNarcTask ->
    codeNarcTask.ignoreFailures = true
}

Saturday, January 15, 2011

Groovy Goodness: Create GMetrics Report with XSLT

With GMetrics we can analyze complexity and size of our Groovy classes and methods. The default HTML reports shows basic information, but if we want to create our own HTML report we best use the XML output and use XSLT to create a HTML report. In a previous blog we learned how to use XSLT to transform the XML output from CodeNarc to a HTML report. In this blog post we see how we can create XML output and how to format it to a HTML report.

Monday, January 10, 2011

Groovy Goodness: Create CodeNarc Reports with XSLT

CodeNarc is a tool to analyze Groovy code for style issues, bad practices and defects. The default output after running CodeNarc is a HTML report. In this report we can see which packages and files have violated the rules. We can change the default HTML report output and set it to XML output. With the XML output we can create flexible reports using XSLT. Now we can replace the more basic HTML default output with our own defined HTML reports. For example we can include our own logo or only display rule information for the rules that are violated. In this post we see how we can create a custom HTML CodeNarc report.

Gradle Goodness: Use Groovy Ruleset File with Code Quality Plugin

The code-quality plugin supports CodeNarc for Groovy projects. The default configuration file is XML based with the name codenarc.xml and must be placed in the directory config/codenarc. But CodeNarc also supports a Groovy DSL for writing configuration files. Suppose we have a configuration file with the name rules.groovy and we put it in the directory config/codenarc. In our build.gradle file we reference this file with the property codeNarcConfigFileName. The code-quality plugin will pass this value on to CodeNarc and the rules defined in our Groovy ruleset file are used.

// File: config/codenarc/rules.groovy

ruleset {
    description 'Rules Sample Groovy Gradle Project'

    ruleset('rulesets/basic.xml')
    ruleset('rulesets/braces.xml')
    ruleset('rulesets/exceptions.xml')
    ruleset('rulesets/imports.xml')
    ruleset('rulesets/logging.xml') {
        'Println' priority: 1
        'PrintStackTrace' priority: 1
    }
    ruleset('rulesets/naming.xml')
    ruleset('rulesets/unnecessary.xml')
    ruleset('rulesets/unused.xml')
}

// File: build.gradle
['groovy', 'code-quality'].each { 
    apply plugin: it 
}

repositories {
    mavenCentral()
}

dependencies {
    groovy group: 'org.codehaus.groovy', name: 'groovy', version: '1.7.6'
}

codeNarcConfigFileName = 'config/codenarc/rules.groovy'

Saturday, January 1, 2011

Happy New Year!

I wish everybody a happy, healthy and Groovy 2011!