Loading...

Tuesday, March 31, 2009

Connect lifelines in UML Sequence diagrams in NetBeans

NetBeans has support for UML diagrams. We can create Activity, Class, Sequence, State and Use Case diagrams. In this post we will see how NetBeans helps with creating a sequence diagram.

To start we must create a new project. We go to File | New Project. From the dialog window we select the UML category. We can create three types of projects: Platform-Independent, Java-Platform, Reverse Engineered Java-Platform. For our example we select Platform-Independent Model and click on the Next button.

We can now choose a name for our project and the location. After we filled in the values we select the Finish button.

NetBeans creates a new project for us. The project node in the Projects view shows a Diagrams node. We can right-click on Diagrams node and select New | Diagram from the pop-up menu:

A dialog window is opened and we can select the type of diagram. Here we select Sequence Diagram and press the Finish button:

Netbeans shows us a empty sequence diagram. We can add lifelines to the diagram by opening the Palette and select Lifeline and we can drop it on the diagram:

Once we have lifelines on the diagram we can connect them. We select a lifeline on the diagram and NetBeans shows a small pop-up window with options to create synchronous, asynchronous and create messages:

When we click on the Synchronous Message option a new lifeline is added to the diagram with a message interaction between the new and old lifeline:

To connect the synchronous message to an existing lifeline we must simply hold the mouse button and drag the arrow to the existing lifeline. When we release the mouse button the message interaction is created:

Monday, March 30, 2009

Add Scala syntax coloring support to JEdit

Adding syntax coloring support for Scala source files to JEdit is easy. First we must download the Scala tool support files. We can do this with the following command:

sbaz install scala-tool-support

We find sbaz in the bin directory of SCALA_HOME (the directory where we installed Scala). This will download support for a lot of editors into the SCALA_HOME/misc/scala-tool-support directory, like bluefish, emacs, vim, gedit, notepad+, textmate, textpad, ultraedit and JEdit.

To enable syntax coloring for Scala file we must copy the file SCALA_HOME/misc/scala-tool-support/jedit/mode/scala.xml to the JEDIT_HOME/modes directory. Or we can copy it to the ~/.jedit/modes directory. Next we must change the file catalog in either the JEDIT_HOME/modes or ~/.jedit/modes directory. We add the following line:

<MODE NAME="scala" FILE="scala.xml" FILE_NAME_GLOB="*.scala"/>

Now we can restart JEdit, open a Scala source file and we get syntax coloring for the right keywords.

Friday, March 27, 2009

Interesting times

These are interesting times we live in. Java is definitely mainstream and it feels like there is not much more to add to the language. But then comes Groovy and Scala. Both dynamic languages which run on the JVM. So the JVM is becoming the new platform. Big advantage is we can use all known Java libraries from within Groovy and Scala. Anyway I've got a lot to read about and can't wait to develop applications with Groovy (Grails) and Scala.

Wednesday, March 25, 2009

Go to NetBeans website directly from NetBeans

To visit the NetBeans website we only have to go to View | Web Browser. NetBeans starts our web browser with the URL http://www.netbeans.org.

Use RESTClient to post and read XML RESTful webservice

When we want to access a RESTful webservice with Groovy we can use HTTPBuilder. The HTTPBuilder library also contains the RESTClient class. This class has a simple API to access RESTful webservices. For example if we want to POST an XML message to a RESTful webservice we can use the post() method. Because we set the request content type to XML we have a StreamingMarkupBuilder object we can use to build our XML.

The response object is automatically read by the XmlSlurper class, so we have access to the resulting GPathResult object. The following code snippet shows a simple POST to the RESTful webservice of Solr:

import groovyx.net.http.RESTClient
import groovy.util.slurpersupport.GPathResult
import static groovyx.net.http.ContentType.XML

@Grab(group='org.codehaus.groovy', module='http-builder', version='0.5.0-SNAPSHOT')
def samplePOST() {
    solr = new RESTClient('http://localhost:8080/solr/update')
            
    def response = solr.post(
        contentType: XML,
        requestContentType: XML,
        body: {
            add {
                doc {
                    field(name:"id", "SOLR1000")
                    field(name:"name", "Solr, the Enterprise Search Server")
                    field(name:"manu", "Apache Software Foundation")
                    field(name:"cat", "software")
                    field(name:"cat", "search")
                    field(name:"features", "Advanced Full-Text Search Capabilities using Lucene")
                    field(name:"features", "Optimized for High Volume Web Traffic")
                    field(name:"features", "Standards Based Open Interfaces - XML and HTTP")
                    field(name:"features", "Comprehensive HTML Administration Interfaces")
                    field(name:"features", "Scalability - Efficient Replication to other Solr Search Servers")
                    field(name:"features", "Flexible and Adaptable with XML configuration and Schema")
                    field(name:"features", "Good unicode support: héllo (hello with an accent over the e)")
                    field(name:"price", "0")
                    field(name:"popularity", "10")
                    field(name:"inStock", "true")
                    field(name:"incubationdate_dt", "2006-01-17T00:00:00.000Z")
                }
            }
        }
    )
    println "Solr response status: ${response.status}"
    assert response.success
    assert response.status == 200
    assert response.data instanceof GPathResult
    assert response.data.lst.int[0].@name == 'status' 
}
                    
samplePOST()

Tuesday, March 24, 2009

Monitoring TCP traffic with tcpmon

Monitoring HTTP requests can be very useful when developing for example RESTful webservices. The Java utility tcpmon provides such a monitoring utility. We must define a local port and a remote server and port. We then send our request to the local port of tcpmon, which will redirect it to the server. We can see the contents of the requests in tcpmon.

Sunday, March 22, 2009

Track Grails form remote submit in Google Analytics

Tracking AJAX requests in Google Analytics is easy as described in the Google help center. When we use the Grails formRemote taglib we can track a form submit in Google Analytics. We must execute the Javascript code pageTracker._trackPageview('/formsubmitted') and the "page" formsubmitted will show up in the Google Analytics reports.

The following snippet shows how we can use the onSuccess attribute to execute this code:

<g:formRemote name="formname" method="GET"
    url="[action:'handleSubmit']"
    onSuccess="if (pageTracker) pageTracker._trackPageView('/reservation');">
...
form fields here
...
</g:formRemote>

Friday, March 20, 2009

Create user/roles for Spring Security for Grails in Bootstrap

To secure a Grails application we can write our own code or use one of the available plugins, like the Spring Security plugin. If we use the plugin we can add user and roles to the database, which are used to authenticate the users. The plugin generates web pages we can use to add users and roles, but we can also use the Bootstrap class in the grails-app/conf directory to create users and roles. These users will be present when the application is started.

The code to achieve this is simple, but we need something special. The User object needs an MD5 encoded password. Luckily we can use the AuthenticateService from Spring Security to do this. We simply inject the service in our Bootstrap class and we can encode our password.

class BootStrap {
    def authenticateService
    
    def init = { servletContext ->
         def role = new Role(authority: 'ROLE_ADMIN', description: 'Admin role').save()
         def admin = new User(username: 'admin', userRealName: 'admin', 
                              passwd: authenticateService.encodePassword('admin'), 
                              enabled: true, email: 'admin@servername')
         admin.addToAuthorities(role)
         admin.save()
    }
    def destroy = {
    }
} 

Wednesday, March 18, 2009

Display Google Visualization charts in a Grails application

I use Google Analytics to monitor several websites to see how many visitors come to the site, which goals are attained and more. But each time I have to log in to Google Analytics to see something. In a previous post we learned how to get data out of Google Analytics. In this post we will see how can use this data and display our own graphs on a web page. We are going to use Grails and Google Visualization API to achieve this. The Grails web application will have a web page to show an areachart with the number of visitors we get from the XML report from Google Analytics.

First things first. We start by creating a new Grails application and create an AnalyticsService and AnalyticsController. The service will be reading the XML report and return a map with number of visitors. The controller is responsible for displaying the web page and transforming the data from the service to valid input for the area chart.

$ grails create-app dashboard-web
$ cd dashboard-web
$ grails create-service analytics
$ grails create-controller analytics

Our service class is responsible for reading the XML report from Google Analytics. These reports are stored on disk in a directory. We only want the latests report file, so our service first needs to find the newest file in the directory. After that we use the XmlSlurper to read in the XML report. We can then easily extract the information we want from the report. Our service class looks like this:

import grails.util.Environment
import java.text.SimpleDateFormat

class AnalyticsService {
    // Automatically injected by Grails.
    def grailsApplication
    
    // Default parser to read date formats from Google Analytics XML.
    def dateParser = new SimpleDateFormat("EEEE, MMMM ddd, yyyy", Locale.US)
    
    def visitors() {
        // Directory with XML reports defined in Config.groovy.
        def dir = new File(grailsApplication.config.input.dir)
        
        // List all files, reverse sort them on date, 
        // and the top one is the newest file.        
        def xmlFile = dir.listFiles().sort{ file -> file.lastModified() }.reverse()[0]
        
        // Read XML data.
        def report = new XmlSlurper().parse(xmlFile)

        // Fill list with number of visitor per day.
        // Data is found in XML:
        // AnalyticsReport / Report / Graph / Serie / Point / Value|Label
        def visitors = []
        report.Report.Graph[0].Serie[0].Point.each { 
            visitors << [visits: new Integer(it.Value.text()), 
                               date: dateParser.parse(it.Label.text())] 
        }
        return visitors
    }    
}

In our Config.groovy we must assign the property input.dir, which is used in line 12, the value for the directory name with all XML reports:

environments {
    development {
        input.dir = '/reports/analytics'
    }
    production {
        input.dir = '/applications/dashboard/reports/repository'
    }
}

Next we define the AnalyticsController class. The controller must display a web page and on the web page we want to include the area chart from Google Visualization API. And the controller must return the input for the area chart in the correct format for the Google Visualization API. We start by defining a new view for the controller. This view will be shown by the index method of the controller, so we create the file in grails-app/views/analytics/index.gsp. The contents of the file is:

<html>
    <head>
        <title>Google Analytics</title>
        <script type="text/javascript" src="http://www.google.com/jsapi"></script>
        <script type="text/javascript">
        
          // Load the Visualization API and the areachart package.
          google.load('visualization', '1', {'packages':['areachart']});
          
          // Set a callback to run when the API is loaded.
          google.setOnLoadCallback(initialize);
          
          function initialize() {
            var query = new google.visualization.Query("${createLink(action: 'visitors')}");
            query.send(drawChart);
          }
          
          // Callback that creates and populates a data table, 
          // instantiates the pie chart, passes in the data and
          // draws it.
          function drawChart(response) {
            var data = response.getDataTable();    
            var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
            chart.draw(data, {width: 860, height: 240, legend: 'none', title: 'Visits'});
          }
        </script>        
    </head>
    <body>
         <div id="chart_div"></div>        
    </body>
</html>

Notice how we use createLink to define the action which will return the necessary data from our AnalyticsController. We return the data in JSON format. The rest of the code is mostly JavaScript to setup Google Visualizations. Now it is time to see the controller class:

import grails.converters.JSON;

class AnalyticsController {
    
    // Automatically injected by Grails.
    def analyticsService
    
    def index = { // Return default view index.gsp
    }
    
    def visitors = {
        def map = [:]
        map.version = 0.5
        map.reqId = '0'
        map.status = 'ok'
        
        def columns = []
        columns << [label: 'Date', type: 'date']
        columns << [label: 'Visitors', type: 'number']

        def data = analyticsService.visitors()
        
        def rows = []
        def cells
        data.each {
            cells = []
            cells << [v: it.date] << [v: it.visits]
            rows << ['c': cells]
        }
        
        def table = [cols: columns, rows: rows]
        map.table = table
        
        render "google.visualization.Query.setResponse(" + (map as JSON) + ")"
    }
}

To support the correct date format we must change the default date format used by the JSON converter. We do this by changing the Config.groovy class and adding the following line:

grails.converters.json.date = "javascript"

Well that is all the code we need. We can start our Grails application, grails run-app, browse to http://localhost:8080/dashboard-web/analytics and get a nice chart in our web browser:

Monday, March 16, 2009

Handle Google Analytics scheduled e-mail reports with Apache James

Google Analytics doesn't have an API, but after reading this post I got an idea for a similar solution. We can configure Google Analytics to schedule e-mails with XML report attachments, we then handle the e-mail at the mail server to save the attachment to disk. The saved file can be used as input in other applications, for example a dashboard application. On my server I have an Apache JAMES server instance running. JAMES supports so called mailets. A mailet is a piece of Java code that can process e-mails and follows the Mailet API. This is ideal for our solution.

Let's see how we can use JAMES to get Google Analytics reports and save them automatically to disk. First we create a new user for the JAMES server. This user will get the e-mails from Google Analytics. To add a user the JAMES server must be running. We can then log in to the remote manager with a telnet client. With the command adduser google_analytics <password> we create the user google_analytics with e-mail address google_analytics@servername.

Okay we now have setup a e-mail address. Now we can create a scheduled e-mail report in Google Analytics. We must open Google Analytics and for this example we select Dashboard. At the top we must click on the Email button. Now we can select the Scheduled tab page. Here we use our newly created e-mail google_analytics@servername. We can also fill the other fields, we must make sure we use the XML format.

Now we get an e-mail with an XML attachment every day. It is time to setup JAMES with mailets so we can automatically extract the XML attachment and save it to disk. First we must checkout and build the Mailet base and standard packages:

$ mkdir mailet
$ cd mailet
$ svn checkout http://svn.apache.org/repos/asf/james/mailet/base/trunk apache-mailet-base
$ cd apache-mailet-base
$ mvn install
$ cd ..
$ svn checkout http://svn.apache.org/repos/asf/james/mailet/standard/trunk apache-standard-mailets
$ cd apache-standard-mailets
$ mvn install

Now we have two JAR files in apache-mailet-base/target/apache-mailet-base-1.0-SNAPSHOT.jar and apache-standard-mailets/target/apache-standard-mailets-1.0-SNAPSHOT.jar. We need to copy these to the JAMES directory: JAMES_HOME/apps/james/SAR-INF/lib. When we copy the files in this directory they will be included in the classpath of JAMES.

Next we must change the JAMES_HOME/apps/james/SAR-INF/config.xml file. Here we define the mailet in the <process name="root"> element. We place the following snippet at the end of the element:

<mailet match="RecipientIs=google_analytics@servername" class="StripAttachment">
    <pattern>.*\.xml</pattern>
    <directory>/home/google_analytics/xml</directory>
    <remove>no</remove>
</mailet>

The match attribute RecipientIs makes sure we can process all e-mail messages for google_analytics@servername. Processing is done with the StripAttachment class. With this class the attachment is simply stripped from the message and saved to disk. With the pattern, directory and remove we configure the StripAttachment. The pattern is set to .*\.xml so we find all XML attachments. In our case the e-mail from Google Analytics only contains one XML attachment. With directory we specify in which directory the XML file is saved. And finally remove let's us define if we want to remove the attachment from the original e-mail or just leave it in (as we did).

We restart JAMES and next time Google Analytics sends an e-mail with an XML report, the e-mail is intercepted by the JAMES mailet and the attachment is saved to the directory /home/googe_analytics/xml.

Friday, March 13, 2009

Take Command Console LE is a great free alternative for cmd.exe

I (have to) use Windows Vista for my development efforts. When working with Java, Groovy or Grails I spent a lot of my time at the command prompt. I couple of years back I purchased 4NT from JPSoft. This was a good move, because my command prompt productivity increased by 1000%. 4NT contained a lot of useful extra commands and environment variables.

But now JPSoft has released a free version of their command processor: Take Command Console LE. Really a must have if you are using Windows and spent your time at the command prompt. Together with Console2 I have a winning combination.

Make symbolic links with Windows Vista's mklink

Today I learned about a very useful command in Windows Vista: mklink. We create hard and soft links with mklink just like with Unix like operating system's ln command. Especially the soft links are useful, because we can create a link which points to another file or directory. The link can be accessed as if we access the original file or directory.

Personally I like to create a bin directory at the root of my drive and put it in the PATH variable. In this bin I create soft links to the executables I want accessible from the PATH variable. This way I don't have to add a lot of directories to the PATH environment variable.

mkdir \bin
cd bin
mklink java.exe %JAVA_HOME%\bin\java.exe

If we run the dir command we can see which files are links, because they are denoted by <SYMLINK>.

We can also use the mklink command to shorten deep directory names. For example if I work on a project in the directory C:\Users\hkleinikkink\data\work\projects\client\applications\dev I want to use the short name currentproject:

mklink /D C:\currentproject C:\Users\hkleinikkink\data\work\projects\client\applications\dev
cd \currentproject

To remove a directory link we must use the rmdir and not the del command. del will delete all files in the directory.

Wednesday, March 11, 2009

Default Log4j configuration expressed as closure for Grails 1.1

In Grails 1.1 the Log4j configuration has changed, because now a Log4j DSL is used. If we don't define a log4j closure in our Config.groovy we get a default configuration. The default configuration looks likes this if we had to define it as a closure:

log4j = {
    appenders {
        console name: 'stdout', layout: pattern(conversionPattern:'%d [%t] %-5p %c{2} %x - %m%n')
        file name: 'stackTraceLog', layout: pattern(conversionPattern:'%d [%t] %-5p %c{2} %x - %m%n'), file: 'stacktrace.log'
    }
    error 'org.springframework', 'org.hibernate'
    error stackTraceLog: 'StackTrace'
    root {
        error 'stdout'
    }
}

So we automatically get a console appender for root log level ERROR. And a file appender for the StackTrace logger with log level ERROR. Remember we don't have to define this closure, we can leave out the log4j closure to get these defaults.

Change Log4j log level for different environments in Grails 1.1

This blog post is an update for Grails 1.1 for a previous post. In Grails 1.1 the Log4j configuration is done with a Log4j DSL. We must define a closure in Config.groovy to define the Log4j configuration. We cannot override certain properties anymore for different environments, but we must define a new log4j closure for each environment we want a different Log4j configuration for.

So if we want to set a different loglevel for the root logger for each environment we can do so with this code:

environments {
    development {
        log4j = {
            root { debug() }
        }
    }
    test {
        log4j = {
            root { warn() }
        }
    }
    production {
        log4j = {
            root { error() }
        }
    }
}

Tuesday, March 10, 2009

Set bootstrap code for each environment in Grails 1.1

This blog post is an update of the previous blog post for Grails 1.1. We can now use the grails.util.Environment to determine which environment the application is running in. We now get the following code:

import grails.util.Environment

class BootStrap {

    def init = { servletContext ->
        switch (Environment.current) {
            case Environment.DEVELOPMENT:
                new Message(text: 'Hello world.').save()
                new Message(text: 'Another text message.').save()
                break
        } 
     }

     def destroy = {
     }
}

Set bootstrap code for each environment in Grails

The Bootstrap.groovy file let's us define actions that need to be taken when the web application starts up. But what if we want to do certain actions in the development environment, but none in the production? We can use the GrailsUtil.environment property to determine the current environment and then assign actions per environment.

The following code will only add Message objects in the database for the development environment:

import grails.util.GrailsUtil

class BootStrap {

    def init = { servletContext ->
        switch (GrailsUtil.environment) {
            case "development":
                new Message(text: 'Hello world.').save()
                new Message(text: 'Another text message.').save()
                break
        } 
     }

     def destroy = {
     }
}

Update for Grails 1.1 in this post.

Monday, March 9, 2009

Change Log4j log level for different environments in Grails

Grails uses Log4j for logging and we can find the Log4j configuration in the Config.groovy file. We can change the Log4j configuration for each environment. To achieve this we must override the default Log4j configuration for an environment. After the Log4j configuration block in the Config.groovy file we add for example the following code to change the rootLogger for the development, test and production environment:

environments {
    development {
        log4j {
           rootLogger="debug,stdout"
        }
    }
    test {
       log4j {
           rootLogger="warn,stdout"
       }
    }
    production {
       log4j {
           rootLogger="error,stdout"
       }
    }
}

This way we can override any setting of the Log4j configuration file for any environment.

Access Spring application context in JUnit 4 tests

Just read the Spring Annotations RefCardz and noticed the neat way to access the Spring application context in a JUnit 4 via autowiring. I read the Spring documentation and learned to extend the AbstractJUnit4SpringContextTests, but this is even easier.

The following two classes will do the same thing, but in the second example we don't have to extend a JUnit class.

package com.mrhaki.spring.test;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

// ApplicationContext will be loaded from "classpath:/com/mrhaki/spring/test/ContextTest-context.xml"
@ContextConfiguration
public class ContextJUnitTest extends AbstractJUnit4SpringContextTests {
    @Test
    public void testContext() {
        Assert.assertNotNull(applicationContext.getBean("test"));
    }
}
package com.mrhaki.spring.test;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext will be loaded from "classpath:/com/mrhaki/spring/test/ContextTest-context.xml"
@ContextConfiguration
public class ContextTest {
    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void testContext() {
        Assert.assertNotNull(applicationContext.getBean("test"));
    }
}

Weekly Sightings

DZone RefCardz
Great resource with a lot of PDF reference cards on subjects like Spring, Groovy, XML.

Use Spring Configurator to support different dev, test and production environments with Spring configuration files (Part 8)

The previous parts(part 1, part 2, part 3, part 4, part 5, part 6, part 7) where all about the settings provided with Spring Configurator. In this part we look at another component that is part of the Spring Configurator: the BeanMap.

The BeanMap can store beans found in the Spring context in a map, hence the name. We can define the type of beans we want to store in the map and the BeanMap component will find those beans. The name or id of the found bean is used as the key for storing it in the map.

We extend our little example from the previous parts and introduce a simple interface (yes, a really simple, do-nothing, marker interface) named SampleService:

package com.mrhaki.netbeans.mavenapp;

public interface SampleService {
    // Simple marker interface.
}

Next we change the Sample and let it implement the SampleService interface:

package com.mrhaki.netbeans.mavenapp;

import org.apache.cocoon.configuration.Settings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Sample implements SampleService{

    private Settings settings;

    private String text;

    private int timeout = 1000;

    @Autowired
    public void setSettings(Settings settings) {
        this.settings = settings;
    }

    public void setText(String name) {
        this.text = name;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public String getMachine() {
        return settings.getProperty("machine");
    }
    
    @Override
    public String toString() {
        return "Running in [" + settings.getRunningMode() + "] mode. "
                + "Text = [" + text + "] and timeout = [" + timeout + "].";
    }
}

We can now define a BeanMap in our applicationContext.xml that needs to store all beans found in the Spring context which implement the SampleService interface. The BeanMap can be defined standalone and have it's own name or id or it can be assigned to a property of another bean. For this example we use it standalone. We need to set the attribute type to the type of class we want to find, which in our case is com.mrhaki.netbeans.mavenapp.SampleService:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:configurator="http://cocoon.apache.org/schema/configurator"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://cocoon.apache.org/schema/configurator http://cocoon.apache.org/schema/configurator/cocoon-configurator-1.0.1.xsd">

    <context:component-scan base-package="com.mrhaki.netbeans.mavenapp"/>
    <configurator:settings>
        <configurator:include-properties dir="classpath*:META-INF/app-config/properties"/> 
        <configurator:include-beans dir="classpath*:META-INF/app-config/spring"/> 
    </configurator:settings>

    <configurator:bean-map type="com.mrhaki.netbeans.mavenapp.SampleService" name="beanMap" />

    <bean name="sample" class="com.mrhaki.netbeans.mavenapp.Sample">
        <property name="text" value="${sample.text1:Default value}"/>
    </bean>

</beans>

In our test code we add statements to print out the key/value pairs of the BeanMap:

package com.mrhaki.netbeans.mavenapp;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppTest extends TestCase {

    public AppTest(String testName) {
        super(testName);
    }

    public static Test suite() {
        return new TestSuite(AppTest.class);
    }

    public void testApp() {
        final ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        final Map<String, Object> map = (Map) appContext.getBean("beanMap");
        for (String key : map.keySet()) {
          System.out.println("key[" + key + "] = value[" + map.get(key) + "].");
        }
    }
}

Now if we run our little test (mvn test) we can see in the following output both Sample beans are found:

key[anotherSample] = value[Running in [prod] mode. Text = [I am the other sample from anotherContext.xml.] and timeout = [1000].].
key[sample] = value[Running in [prod] mode. Text = [We are alive!] and timeout = [1000].].

Of course this is just a simple example, but if we assign the BeanMap as a property we can write application code which have access to all beans of a certain type defined in the Spring context. So we can access beans we don't know about, because they can be defined in a third-party jar, but still use them in our code.

Sunday, March 8, 2009

Use Spring Configurator to support different dev, test and production environments with Spring configuration files (Part 7)

The Spring Configurator makes it very easy to configure beans in the Spring configuration files. We can read in the previous parts (part 1, part 2, part 3, part 4, part 5, part 6) the configurator by defaults assumes we put property files in directories named cocoon. That is because the Spring Configurator was first developed as part of Cocoon 2.2. But we can also use our own directory names so we don't see any cocoon in our definitions.

For example we rename the src/main/resources/META-INF/cocoon directory of our example to src/main/resources/META-INF/app-config. Next we must add extra elements to the configurator:settings in our applicationContext.xml, see lines 13 and 14. The configurator:include-properties element contains a Spring resource path. In our case all properties from META-INF/app-config/properties and META-INF/app-config/properties/[runningMode] in the classpath are loaded, where [runningMode] is replaced with the current running mode. So if we run the application in prod running mode the path will be META-INF/app-config/properties/prod. The configurator:include-beans elements loads Spring configuration files from the META-INF/app-config/spring and META-INF/app-config/spring/[runningMode] directories in the classpath. The runningMode is replaced by the current running mode, just as with the properties.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:configurator="http://cocoon.apache.org/schema/configurator"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://cocoon.apache.org/schema/configurator http://cocoon.apache.org/schema/configurator/cocoon-configurator-1.0.1.xsd">

    <context:component-scan base-package="com.mrhaki.netbeans.mavenapp"/>
    <configurator:settings>
        <configurator:include-properties dir="classpath*:META-INF/app-config/properties"/> 
        <configurator:include-beans dir="classpath*:META-INF/app-config/spring"/> 
    </configurator:settings>

    <bean name="sample" class="com.mrhaki.netbeans.mavenapp.Sample">
        <property name="text" value="${sample.text}"/>
    </bean>

</beans>

Now we can run our application (mvn test) and all properties and Spring configuration files are read from META-INF/app-config/properties, META-INF/app-config/properties/prod, META-INF/app-config/spring and META-INF/app-config/spring/prod.

We can put as many configurator:include-properties and configurator:include-beans elements in the configuration file as we want.

Use Spring Configurator to support different dev, test and production environments with Spring configuration files (Part 6)

In the previous parts (part 1, part 2, part 3, part 4, part 5) we learned a lot about the Spring Configurator. But the documentation of the Spring Configurator is a bit sparse (if we can find it on the website, which is a task in itself).

So browsing the mailing lists and source code I found a hidden feature. We can define default values for a property in the property references. If the value for the property cannot be found the default value is used. The following Spring configuration contains this default value for the property sample.text1. This property is not defined anywhere so the default value after the colon is used (see line 15):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:configurator="http://cocoon.apache.org/schema/configurator"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://cocoon.apache.org/schema/configurator http://cocoon.apache.org/schema/configurator/cocoon-configurator-1.0.1.xsd">

    <context:component-scan base-package="com.mrhaki.netbeans.mavenapp"/>
    <configurator:settings/>

    <bean name="sample" class="com.mrhaki.netbeans.mavenapp.Sample">
        <property name="text" value="${sample.text1:Default value}"/>
    </bean>

</beans>

If we run our test (mvn test) with the test class from part 1, we get as output:

Running in [prod] mode. Text = [Default value] and timeout = [1000].

We see how the property text now contains the default value we specified in the property reference in the Spring configuration file.

Saturday, March 7, 2009

Enable Log4j debug on initializing in Grails

In a Grails application we can set the Log4j configuration in Config.groovy. To see what is happening during the initialization process of Log4j we can set the debug property to true. The following code snippet shows this property at line 2:

// log4j configuration
log4j {
    debug = true
    appender.stdout = "org.apache.log4j.ConsoleAppender"
    appender.'stdout.layout'="org.apache.log4j.PatternLayout"
    appender.'stdout.layout.ConversionPattern'='[%r] %c{2} %m%n'
    appender.stacktraceLog = "org.apache.log4j.FileAppender"
    appender.'stacktraceLog.layout'="org.apache.log4j.PatternLayout"
    appender.'stacktraceLog.layout.ConversionPattern'='[%r] %c{2} %m%n'
    appender.'stacktraceLog.File'="stacktrace.log"
    rootLogger="error,stdout"
    logger {
        grails="error"
        StackTrace="error,stacktraceLog"
        org {
            codehaus.groovy.grails.web.servlet="error"  //  controllers
            codehaus.groovy.grails.web.pages="error" //  GSP
            codehaus.groovy.grails.web.sitemesh="error" //  layouts
            codehaus.groovy.grails."web.mapping.filter"="error" // URL mapping
            codehaus.groovy.grails."web.mapping"="error" // URL mapping
            codehaus.groovy.grails.commons="info" // core / classloading
            codehaus.groovy.grails.plugins="error" // plugins
            codehaus.groovy.grails.orm.hibernate="error" // hibernate integration
            springframework="off"
            hibernate="off"
        }
    }
    additivity.StackTrace=false
}

Friday, March 6, 2009

Use negative index in Groovy lists to get last entries

Groovy lists have a lot of features. One of them is the possibility to use negative indices. A negative index counts from the end of the list backward. So if we use -1 as index we get the last entry, if we use -2 as index we get the next-to-last entry.

def list = []
list << 'Item 1'
list << 'Item 2'
list << 'Item 3'

assert 'Item 3' == list[-1]
assert 'Item 2' == list[-2]
assert 'Item 1' == list[0 - list.size()]

Thursday, March 5, 2009

Use Spring Configurator to support different dev, test and production environments with Spring configuration files (Part 5)

We look into the Spring Configurator a bit more, because we have not seen all of the possibilities. If we read the previous parts (part 1, part 2, part 3, part 4) we already experienced the power of the Spring Configurator. In this part we learn how to add our own properties to the configurator.

It is a good idea to extract settings from the Java code and externalize into a configuration file. This configuration file can be a Java properties file. In the application we can load the properties files and use the property values in our code. This mechanism is very easy to implement with the Spring Configurator. The only thing we need to do is place the Java properties file at a certain location and inject the Spring Configurator settings object in our application. Every property in the properties file is then available via the Spring Configurator.

Let's see how this works with our example. First we create a new property file at src/main/resources/META-INF/cocoon/properties/settings.properties and define the property machine:

machine=My muscle machine

We change our Sample class so we can display the value of this property (see lines 28-30):

package com.mrhaki.netbeans.mavenapp;

import org.apache.cocoon.configuration.Settings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Sample {

    private Settings settings;

    private String text;

    private int timeout = 1000;

    @Autowired
    public void setSettings(Settings settings) {
        this.settings = settings;
    }

    public void setText(String name) {
        this.text = name;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public String getMachine() {
        return settings.getProperty("machine");
    }
    
    @Override
    public String toString() {
        return "Running in [" + settings.getRunningMode() + "] mode. "
                + "Text = [" + text + "] and timeout = [" + timeout + "].";
    }
}

The Settings class has two methods to get properties:

  • getProperty(String propertyName) to get the value for the property with propertyName
  • getProperty(String propertyName, String defaultValue) to get the value for the property and if it is not found use a default value
This way we can get the value for all available properties.

To test if we really get the value for our property we change our test class to output the property value:

package com.mrhaki.netbeans.mavenapp;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppTest extends TestCase {

    public AppTest(String testName) {
        super(testName);
    }

    public static Test suite() {
        return new TestSuite(AppTest.class);
    }

    public void testApp() {
        final ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println(((Sample)appContext.getBean("sample")).getMachine());
    }
}

If we run the test (mvn test) we get the following output:

Muscle machine

But wait that is not all. If we use the Settings object we also have access to the standard Java system properties and environment variables. The Java system properties can be accessed with their property name. The environment variables are prefixed with env.:

System.out.println(settings.getProperty("os.name"); // Output: Windows Vista
System.out.println(settings.getProperty("env.PROMPT"); // Output: $p$g

In this part we have learned how to access our own defined properties, Java system properties and environment variables.

Use Spring Configurator to support different dev, test and production environments with Spring configuration files (Part 4)

The Spring configurator has even more to offer than the things we have learned in the previous parts (part 1, part 2, part 3). If we place Spring configuration files at certain locations in our application classpath then they will be added to the existing Spring application context. This means we don't have to explicitly add the configuration files another configuration with an import, it is available automatically. And as we can guess we can use this even per running mode.

In the documentation we can see where we must place the Spring configuration files. For our example we create a new Spring configuration file in the src/main/resources/META-INF/cocoon/spring directory and name it anotherContext.xml. Here is the contents of the file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean name="anotherSample" class="com.mrhaki.netbeans.mavenapp.Sample">
        <property name="text" value="I am the other sample from anotherContext.xml."/>
    </bean>
</beans>

We define another bean for the same sample class and give the property text a new value (see line 8).

In our test class we add a statement to print out the value for this property (see line 21). So we get the following test:

package com.mrhaki.spring.mavenapp;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppTest extends TestCase {

    public AppTest(String testName) {
        super(testName);
    }

    public static Test suite() {
        return new TestSuite(AppTest.class);
    }

    public void testApp() {
        final ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println(appContext.getBean("sample"));
  System.out.println(appContext.getBean("anotherSample"));
    }
}

When we run the test (mvn test) we get the following output:

Running in [prod] mode. Text = [We are alive!] and timeout = [1000].
Running in [prod] mode. Text = [I am the other sample from anotherContext.xml.] and timeout = [1000].

So we see we didn't define anywhere to load anotherContext.xml, but we can use all beans defined in it! The Spring configuration file is loaded by the Spring configurator, because of the placement of the file in the classpath.

Create a Maven project site in NetBeans

Within a Maven project it is easy to create a project site. We need to create the src/site directory and place a site.xml file in it. Here is a very simple and basic site.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project name="app"/>

And of course we can add content files for the project site. To generate the site we only have to run mvn site. And if we use NetBeans we can generate the site with a mouse click.

In our Maven project we have a Project site node. If we right-click on the node we get the following pop-up menu:

We notice the options Generate Site and Deploy Site. If we select Generate Site we get a dialog window with the Maven command that is about to run:

We could change some fields here, but most of the time we just press the OK button. And the project site is generated. The generated site is placed in the target/site directory. If we look at the output window and see the Maven output we notice a link View Generated Project Site:

We can click on this link and NetBeans will open the site's index.html file in a web browser.

We can also deploy the project site to a web server with the Deploy Site option from the pop-up menu. This command is executed immediately by NetBeans and the if the configuration in our pom.xml is correct, the site is deploy to a web server.

Sunday, March 1, 2009

Use Spring Configurator to support different dev, test and production environments with Spring configuration files (Part 3)

Okay we have learned about the running modes in part 1 and we saw how to use the property configurer in part 2. In this part we see how we can use the property overrider.

Suppose we have a Java class configured in the Spring context with a default value and want to override this value for a specific running mode. That is where the property overrider comes into play.

We add a new timeout property to our Sample class:

package com.mrhaki.spring.mavenapp;

import org.apache.cocoon.configuration.Settings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Sample {

    private Settings settings;

    private String text;
 
    private int timeout = 1000;

    @Autowired
    public void setSettings(Settings settings) {
        this.settings = settings;
    }

    public void setText(String name) {
        this.text = name;
    }
 
    public void setTimeout(int timout) {
        this.timeout = timeout;
    }

    @Override
    public String toString() {
        return "Running in [" + settings.getRunningMode() + "] mode. "
                + "Text = [" + text + "] and timeout = [" + timeout + "].";
    }
}

If we read the documentation we see we must define a property file and can place it in different locations. For our example we create a property file at src/main/resources/META-INF/cocoon/spring/dev/timeout.properties. And we use the following content:

sample/timeout=42

This property file will be used in the dev running mode by the Spring Configurator. The property file will override bean configurations set in the Spring context. The Spring Configurator uses the / to separate the bean name and property. In our example we override the timeout property of the sample bean.

When we run the test in dev running mode, mvn test -Porg.apache.cocoon.mode=dev, we get the following output:

Running in [dev] mode. Text = [We are developing!] and timeout = [42].

And if we run the example in prod mode, mvn test, we get the following output:

Running in [prod] mode. Text = [We are alive!] and timeout = [1000].

This way we can easily override properties already set by code in Spring configurations! In the next part we see how the Spring Configurator can load Spring configuration files automatically.