Monday, December 22, 2008

Bookmark and Share

A geo cache which a friend of mine tried to spot recently (see here, in German) required to do some MD5 hash calculation.

Using Java's java.security.MessageDigest this is actually a no-brainer, and if you need MD5 hashes for short strings rather than whole files, a utility class such as the following comes in handy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MD5Helper {

    public static String getMD5Hash(String input) {

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] messageDigest = md.digest(input.getBytes());

            return new BigInteger(1, messageDigest).toString(16);
        }
        catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

}

If you want to have an MD5 hash for a whole file, you probably don't want to read this file entirely into a string. In that case you can use MessageDigest's methods update(byte[] input) and digest() to calculate the hash chunk-wise, as you are reading the file into a buffer. A complete code example can be found here.

If you do not necessarily have to work with MD5 hashes, Apache Commons IO might be an alternative as well. Its class FileUtils offers – besides a lot of other very convenient functions, in especially for copying files and directories – the method checksumCRC32(File file), which calculates a file checksum using the CRC32 routine.

Sunday, December 14, 2008

Bookmark and Share

While trying to build a Maven based project using JAX-WS RI 2.1.5, I noticed, that Maven tried to download the artifact wstx-asl-3.2.3.pom upon each build. Unfortunately without much success, but resulting in an increased build time.

As it turned out, the dependency to the Woodstox XML processor in JAX-WS RI's pom.xml is apparently wrong. There is also an item at JAX-WS RI's issue tracker commenting on that problem.

Until this is fixed, you can help yourself by excluding the flawed dependency in your project's pom.xml and adding the correct one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
<dependencies>
    ...
    <dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-rt</artifactId>
        <version>2.1.5</version>
        <exclusion>
            <exclusion>
                <groupId>woodstox</groupId>
                <artifactId>wstx-asl</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.codehaus.woodstox</groupId>
        <artifactId>wstx-asl</artifactId>
        <version>3.2.3</version>
    </dependency>
    ...
</dependencies>
...

In the likely case, that you are also using the JAX-WS Maven plugin, you have to circumvent the bug in the plugin's dependencies as well:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
...
<build>
    ...
    <plugins>
        ...
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxws-maven-plugin</artifactId>
            <executions>
            ...
            </executions>
            <dependencies>
                <!-- Use current JAX-WS RI version -->
                <dependency>
                    <groupId>com.sun.xml.ws</groupId>
                    <artifactId>jaxws-tools</artifactId>
                    <version>2.1.5</version>
                </dependency>
                <dependency>
                    <groupId>com.sun.xml.ws</groupId>
                    <artifactId>jaxws-rt</artifactId>
                    <version>2.1.5</version>
                    <exclusions>
                        <exclusion>
                            <groupId>woodstox</groupId>
                            <artifactId>wstx-asl</artifactId>
                        </exclusion>
                    </exclusions>
                </dependency>
                <dependency>
                    <groupId>org.codehaus.woodstox</groupId>
                    <artifactId>wstx-asl</artifactId>
                    <version>3.2.3</version>
                </dependency>
            </dependencies>
        </plugin>
        ...
    </plugins>
    ...
</build>
...

Having pimped your pom.xml as described above, Maven should stop wasting your time by trying to resolve the flawed dependency over and over again.

Friday, December 12, 2008

Bookmark and Share
For a recent project, a colleague of mine and I created a Maven archetype, allowing for a very simple creation of web service projects (more to follow in a future post). Everything worked out fine on our boxes, but another colleague we asked for testing the archetype, reported, that he had some trouble using it.

After some investigations, we found out, that there is an issue with the Maven archetype plugin, which ignores your proxy settings, if you specify an archetype catalog (This JIRA-Issue seems to describe that problem). So, if you are sitting behind a web proxy, e.g. the command
$ mvn archetype:generate -DarchetypeCatalog=http://maven-instant-ws.googlecode.com/svn/repo/archetype-catalog.xml
might lead to the following error after some time:
[WARNING] Error reading archetype catalog http://maven-instant-ws.googlecode.com/svn/repo/archetype-catalog.xml
For me, it helped to remove the archetype plugin from my local Maven repository by deleting the folder /home/<username>/.m2/repository/org/apache/maven/plugins/maven-archetype-plugin before issuing the command above.

This forces Maven to download the archetype plugin again, for some reason causing it to find the archetype catalog properly. If I try to create another project from using the catalog – having the archetype plugin in my local repo now – the same error as before occurs.

Tuesday, December 2, 2008

Bookmark and Share
Redmine is a project management software written in Ruby. It offers a lot of interesting features such as an issue tracker, wiki functionality and news feeds. This post will show up the steps required to install Redmine and run in it on JRuby using Glassfish application server.

This tutorial is based on the following assumptions:
  • Ubuntu is being used as OS
  • Java is installed on your system
  • Glassfish is installed (%GLASSFISH_HOME% will be used in the following to refer to the installation directory)
  • All downloads go to /tmp

Install JRuby

In order to run Redmine, a Ruby runtime has to be installed first. We will use JRuby 1.1.4 (the current version at the time of this writing - 1.1.5 - didn't work, probably due to this bug). Download it and add JRuby to your path as follows:
$ wget dist.codehaus.org/jruby/jruby-bin-1.1.4.tar.gz
$ cd /opt
$ sudo tar -xzvf /tmp/jruby-bin-1.1.4.tar.gz
$ sudo ln -s jruby-1.1.4 jruby
$ export PATH=$PATH:/opt/jruby/bin
Verify that JRuby is set up properly by issuing:
$ jruby -v
This should yield in:
jruby 1.1.4 (ruby 1.8.6 patchlevel 114) (2008-08-28 rev 7570) [i386-java]

Download required gems

Having JRuby up and running, we need to install the ActiveRecord JDBC MySQL adapter for Rails. Furthermore it is recommended to install JRuby's Open SSL support as well. Finally, we need Warbler, which will allow us to package the Redmine application as a WAR archive. Using the RubyGems package manager, this is easy:
$ sudo gem install jruby-openssl activerecord-jdbcmysql-adapter warbler
All required dependent gems (such as activerecord-jdbc-adapter) will automatically be downloaded by RubyGems.

Install and set up MySQL database server

Next, the database to be used by Redmine needs to be set up. We will be using MySQL, as it is a very common companion for RoR apps, though other database servers should do the trick as well.

Install the server:
$ sudo apt-get install mysql-server
Login into MySQL:
$ mysql -u root -p %YOUR_PASSWORD%
Create a database:
mysql> CREATE DATABASE redmine_production character set utf8;
Create a database user:
mysql> GRANT ALL ON redmine_production.* TO 'redmine'@'localhost' IDENTIFIED BY 'redmine';
Repeat the latter two steps for schemas redmine_test and redmine_development and leave the MySQL shell.
mysql> exit

Create data source in Glassfish

In order to set up a MySQL based data source in Glassfish, the server has to be provided with the MySQL JDBC driver. Ensure that Glassfish is stopped for the following. So let's download the driver, un-tar it and copy it into the server's lib dir:
$ wget
dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.7.tar.gz/from/http://sunsite.informatik.rwth-aachen.de/mysql/
$ tar -xzvf mysql-connector-java-5.1.7.tar.gz
$ sudo cp /mysql-connector-java-5.1.7/mysql-connector-java-5.1.7-bin.jar %GLASSISH_HOME/lib/
Now start up Glassfish:
$ %GLASSISH_HOME/bin/asadmin start-domain domain1
Create a connection pool and a JDBC resource (if you prefer a more visual way of doing such things, help can be found here):
$ %GLASSISH_HOME/bin/asadmin create-jdbc-connection-pool
--datasourceclassname
com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource --restype
javax.sql.DataSource --property
"User=redmine:Password=redmine:URL=jdbc\:mysql\://localhost\:3306/redmine_production"
jdbc/RedminePool
$ %GLASSISH_HOME/bin/asadmin create-jdbc-resource --connectionpoolid jdbc/RedminePool jdbc/Redmine

Install and set up Redmine

Now it's time to install Redmine itself (refer to the official installation guide for further information). So download and extract the archive:
$ wget rubyforge.org/frs/download.php/39477/redmine-0.7.3.tar.gz
$ tar -xzvf redmine-0.7.3.tar.gz
Create a new database environment "production_setup" and the database config file:
$ cp config/environments/production.rb config/environments/production_setup.rb
$ cp config/database.yml.example config/database.yml
Edit config/database.yml:
production:
  adapter: jdbc
  jndi: jdbc/Redmine

production_setup:
  adapter: jdbcmysql
  database: redmine_production
  host: localhost
  username: redmine
  password: redmine
  encoding: utf8

development:
  adapter: jdbcmysql
  database: redmine_development
  host: localhost
  username: redmine
  password: redmine
  encoding: utf8

test:
  adapter: jdbcmysql
  database: redmine_test
  host: localhost
  username: redmine
  password: redmine
  encoding: utf8
The "production" environment is configured to use the data source, which we previously created within the Glassfish server. No credentials are stored here, as they are part of the connection pool's configuration. Note the special environment "production_setup" which we'll use now to initialize the database:
$ rake db:migrate RAILS_ENV="production_setup"
$ rake redmine:load_default_data RAILS_ENV="production_setup"
Now we can test the application using Webrick:
$ jruby script/server -e production_setup

Package and deploy Redmine

Running the application on Webrick is fine for testing purposes, but now let's deploy Redmine on Glassfish. For this target, the Warbler gem comes into play. It takes a Rails application and creates a WAR archive from it. Besides the application itself, JRuby and all required gems are packaged into the archive as well. Therefore, this WAR is fully self-contained and can be deployed on every web container or application server. First, we have to create the Warbler configuration:
$ warble config
This will create the file config/warble.rb. Edit this file, find the line beginning with "config.dirs ..." and replace it with the following:
config.dirs = %w(app config lib log vendor tmp extra files lang)
This will cause the named directories to be packaged into the resulting WAR. Find the line beginning with "#config.gems += " and uncomment it, allowing for the gems active-record-jdbcmysql-adapter and jruby-openssl to be packaged into the WAR as well.

Having configured warbler, the web archive can be created. Go to the application's root dir and enter:
$ warble
The resulting WAR file can now be deployed to the app server. Either do this within the admin console or just by copying it to Glassfish's auto deploy folder:
$ cp redmine-0.7.3.war %GLASSFISH_HOME%/domains/domain1/auto-deploy
Upon success, Redmine can be accessed at http://localhost:8080/redmine-0.7.3. Click "Sign in" in the upper right, log in using "admin"/"admin" as user/password and you should see your personal Redmine page as depicted below.

Typically, you would now create a project or other user accounts, which can be done under "Administration".

Monday, December 1, 2008

Bookmark and Share
Welcome to this blog. I am a Java EE developer, and will report here on my latest insights from time to time.