Comment Maven System Path – Including local JAR files in a Maven project - 05/4/10

Sometimes it’s a real pain to add JAR’s to Maven, especially when the project doesn’t use Maven as the build system or provide scripts for this purpose. This is even more painful when we have to deal with the dependencies that a particular framework needs.

One solution to avoid this (at least temporarily) is to use Maven’s system scope and systemPath feature:

 XML |  copy |? 
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/zookeeper-3.3.0.jar</systemPath>
</dependency>

This will reference a dependency from the local filesystem, which means you do not have to install the JAR into the repository in order to use it. This is particularly useful when you’re doing some prototyping or research into a new technology.

By the way Zookeeper does provide support for Maven, see https://issues.apache.org/jira/browse/ZOOKEEPER-224

For more information see: http://maven.apache.org/general.html#tools-jar-dependency

4 Comments MySQLdb – EnvironmentError: mysql_config not found - 07/21/09

Had a bit of a snag installing MySQLdb tonight, which is required when installing Django.  I ran into the following error when trying to install the MySQLdb egg under Debian Lenny.

EnvironmentError: mysql_config not found
When trying to install MySQL-python

It was fixed by installing the libmysqlclient15-dev package and the installing the egg again:

 Bash |  copy |? 
sudo apt-get install libmysqlclient15-dev
easy_install MySQL_python-1.2.3c1-py2.5-linux-i686.egg

Package details here:

http://packages.debian.org/search?searchon=contents&keywords=mysql_config&mode=path&suite=stable&arch=any

Comment Pastebin – CakePHP + SyntaxHighlighter + Eclipse Plugin - 03/10/09

I’ve revamped the pastebin website (http://pbin.oogly.co.uk) – which is based on CakePHP (a model view controller PHP framework) and SyntaxHighlighter (http://alexgorbatchev.com/wiki/SyntaxHighlighter).  I also created an Eclipse plugin to interface with the website.

pbin-sel5

A pastebin allows you to share a patch/code selection/text selection with other people without having to resort to email/instant messenger.  You can either interact with pastebin via the URL or above or install the Eclipse plugin.  If you’ve installed the Eclispe plugin you then right click on the code/text you want to share and select Pastebin->Create Pastebin from the menu.  More instructions and screenshots are available on the website.

The Eclipse architecture is a little strange to start with, the support it provides via the extensions framework is easy enough to understand, although I’m a little confused now that they’ve announced declarative services and their bizarre use of OSGi. The plugin uses the org.eclipse.ui.popupmenus extension.  Dependency wise, I used the Eclipse UI and runtime along with the JFace Textfield components to provide the URL for the created pastebin.  The main plugin itself is made up of an Activator class along with a NewPastebinAction class which implements IObjectActionDelegate which provides a run(IAction action) method.  This obtains the current selection and checks to see whether it is a TextSelection (editor content selection) or a StructuredSelection (a package explorer/navigator file selection).

The selection is then wrapped in a simple domain object and passed to a web client facade that uses the Apache HttpClient (http://hc.apache.org/httpclient-3.x/) framework to provide connectivity with the pastebin website.

Finally, it uses a custom OkInputDialog to present the pastebin URL back to the user.

It’s not perfect at present (I need to unpick the dependency on the JDT plugin for the StructuredSelection), but it serves as a first attempt at creating a Eclipse plugin and understanding the internals of the Eclipse API.  Also, it unfortunately does not autodetect the file type and convert it into the internal pastebin format.

Packaging the plugin was very straightforward.  It involved using the File->Export function provided by Eclipse to package it into an appropriate JAR file.  Alternatively, you can publish an update site, I did this by creating a new feature project (and adding the plugin to it) then exporting the the update site using Eclipse.

I’m going to take the pastebin as a starting point for more collaborative features.

1 Comment Eclipse Shortcut Keys - 01/6/09

I’ve found a few Eclipse shortcut tutorials around that explain how to access features through shortcuts in Eclipse. One of the most useful I’ve found, and use all the time is the old CTRL+SHIFT+R shortcut for opening a resource.  I’ve noticed that there are a number of these documented within the Eclipse help menu here:

Help Contents > Java Development User Guide > Reference > Menus and Actions

You can also view a list of common shortcut keys using the shortcut:

CTRL+SHIFT+L

From here you can also access the key bindings menu by hitting CTRL+SHIFT+L again (as indicated in the diagram).  This allows you to remap the key bindings or setup new key bindings.  Eclipse also supports Emacs type bindings.

There are also a number of cheat sheets on the internet that you can print out and stick on the wall (or cubicle or whatever) to help you out. I’ve not found an editable template for these so I created my own in Microsoft Word format which can be found below.  This includes a list of the shortcuts I commonly use on a day to day basis.

http://blog.oogly.co.uk/downloads/eclipsesk.doc

The one annoying thing about shortcuts is that you can’t create them for new actions (I found this annoying because I wanted a shortcut for Checkstyle->Check Code With Checkstyle).  However, this functionality is available in the form of Eclipse Monkey (formally Groovy Monkey) which allows you to automate repetitive tasks.

Finally there is another option for memorising shortcuts in the form of Mousefeed - this displays the shortcut for the action you have recently carried out allowing you to memorise it for next time.

Hope that helps with your magical shortcut trickery.

Comment Hibernate Enum Persistence - 11/28/08

I had some minor issues persisting an Enum using Hibernate a while back and thought I ought to post an explanation of how I managed to do this based on some code from the Hibernate website along with an example, which seemed to be missing from every example I found.

The code for the customer Hibernate type is as follows:

 Java |  copy |? 
package com.oogly.dao.support.impl;
 
import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
 
import org.hibernate.HibernateException;
import org.hibernate.type.NullableType;
import org.hibernate.type.TypeFactory;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
 
/**
 * GenericEnumUserType.
 * Modified from http://www.hibernate.org/272.html.
 * @author jholloway
 */
public class GenericEnumUserType implements UserType, ParameterizedType { // NOPMD
 
    private static final String DEFAULT_IDENTIFIER_METHOD_NAME = "name";
    private static final String DEFAULT_VALUE_OF_METHOD_NAME = "valueOf";
 
    private Class&lt; ? extends Enum&gt; enumClass;
    private Class&lt; ? &gt; identifierType;
    private Method identifierMethod;
    private Method valueOfMethod;
    private NullableType type;
    private int[] sqlTypes;
 
    /**
     * Set parameter values.
     * enumClassName is the className of the enum
     * identifierMethodName is the method name to use for retrieval
     * type is the identifier type
     * valueOfMethod is the method name to use for retrieval
     * @param parameters are the parameters from which we obtain our values for this type
     */
    public void setParameterValues(final Properties parameters) {
 
        String enumClassName = parameters.getProperty("enumClassName");
 
        try {
            enumClass = Class.forName(enumClassName).asSubclass(Enum.class);
        } catch (ClassNotFoundException cfne) {
            throw new HibernateException("Enum class not found", cfne);
        }
 
        String identifierMethodName = parameters.getProperty("identifierMethod", DEFAULT_IDENTIFIER_METHOD_NAME);
 
        try {
 
            identifierMethod = enumClass.getMethod(identifierMethodName,
            									   new Class[0]);
            identifierType = identifierMethod.getReturnType();
 
        } catch (Exception e) {
            throw new HibernateException("Failed to obtain identifier method", e);
        }
 
        type = (NullableType) TypeFactory.basic(identifierType.getName());
 
        if (type == null) {
            throw new HibernateException("Unsupported identifier type " + identifierType.getName());
        }
 
        sqlTypes = new int[] { type.sqlType() };
 
        String valueOfMethodName = parameters.getProperty("valueOfMethod", DEFAULT_VALUE_OF_METHOD_NAME);
 
        try {
            valueOfMethod = enumClass.getMethod(valueOfMethodName,
                new Class[] { identifierType });
        } catch (Exception e) {
            throw new HibernateException("Failed to obtain valueOf method", e);
        }
    }
 
    /**
     * Get the returned class.
     * @return the enum class
     */
    public Class returnedClass() {
        return enumClass;
    }
 
    /**
     * Null safe get.
     * @param resultSet is the result set
     * @param names are the names
     * @param owner is the owner
     * @return an identifier object
     * @throws HibernateException if we cannot invoke the correct method
     * @throws SQLException a SQL exception if there is a syntax error
     */
    public Object nullSafeGet(final ResultSet resultSet,
    		                  final String[] names,
    		                  final Object owner) throws HibernateException, SQLException {
 
        Object identifier = type.get(resultSet, names[0]);
 
        if (resultSet.wasNull()) {
            return null;
        }
 
        try {
            return valueOfMethod.invoke(enumClass, new Object[] { identifier });
        } catch (Exception e) {
            throw new HibernateException("Exception while invoking "
                + "valueOf method " + valueOfMethod.getName() + " of "
                + "enumeration class " + enumClass, e);
        }
    }
 
    /**
     * Null safe set method.
     * @param statement is the prepared statement
     * @param value is the value of the object
     * @param index is the index
     * @throws HibernateException a Hibernate type exception
     * @throws SQLException a SQL exception
     */
    public void nullSafeSet(final PreparedStatement statement, final Object value, final int index) throws HibernateException, SQLException {
 
        try {
            if (value == null) {
                statement.setNull(index, type.sqlType());
            } else {
                Object identifier = identifierMethod.invoke(value,
                    new Object[0]);
                type.set(statement, identifier, index);
            }
        } catch (Exception e) {
            throw new HibernateException("Exception invoking id method "
            		                     + identifierMethod.getName()
            		                     + " of enum class "
            		                     + enumClass, e);
        }
    }
 
    /**
     * Return the SQL types as an array.
     * @return an int array of SQL types
     */
    public int[] sqlTypes() { //NOPMD
        return sqlTypes;
    }
 
    /**
     * Assemble a cached object.
     * @param cached is the cached object
     * @param owner is the owner here
     * @return the assembled object
     * @throws HibernateException a hibernate type exception
     */
    public Object assemble(final Serializable cached,
    					   final Object owner) throws HibernateException {
        return cached;
    }
 
    /**
     * Return a deep copy of the object.
     * @param value is the object to copy
     * @return a copy as an object
     * @throws HibernateException a hibernate type exception
     */
    public Object deepCopy(final Object value) throws HibernateException {
        return value;
    }
 
    /**
     * Disassemble an object.
     * @param value is the object to disassemble
     * @return a Serializable object
     * @throws HibernateException a hibernate type exception
     */
    public Serializable disassemble(final Object value) throws HibernateException {
        return (Serializable) value;
    }
 
    /**
     * Equals method to compare two objects.
     * @param objectA is the first object to compare
     * @param objectY is the second object to compare
     * @return whether the objects are equal
     * @throws HibernateException a hibernate type exception
     */
    public boolean equals(final Object objectA, final Object objectY) throws HibernateException { // NOPMD
        return objectA == objectY;
    }
 
    /**
     * Return the hashcode of the object x.
     * @param objectX is the object to return a hashcode for
     * @return the hashcode integer
     * @throws HibernateException a hibernate type exception
     */
    public int hashCode(final Object objectX) throws HibernateException {
        return objectX.hashCode();
    }
 
    /**
     * Return an immutable object boolean flag.
     * @return an immutable flag
     */
    public boolean isMutable() {
        return false;
    }
 
    /**
     * Replace an owners object with a target object.
     * @param original is the original object
     * @param target is the target object
     * @param owner is the owner of the object
     * @return the object replaced
     * @throws HibernateException a hibernate type exception
     */
    public Object replace(final Object original, final Object target, final Object owner) throws HibernateException {
        return original;
    }
} 

Like I said what’s often missing is an example of using this… so here we go:

 XML |  copy |? 
<typedef class="com.oogly.dao.support.impl.GenericEnumUserType" 
             name="yourEnumType">
        <param name="enumClassName">com.oogly.domain.YourEnum</param>
        <param name="identifierMethod">getEnumTypeCode</param>
        <param name="valueOfMethod">getEnumTypeUsingCode</>
</typedef>

The last part here for the value of method needs some explanation…

 Java |  copy |? 
public static EnumType getEnumTypeUsingCode(final int code) {
 
		// Find the  matching eligibility level code
		for (EnumType yourEnumType : VALS) {
 
			if (yourEnumType.geCode() == code) {
				return yourEnumType;
			}
		}
 
		return null;
	}

This essentially looks up the enum based on the code that’s passed in. This can be fairly performance intensive based on the implementation you use for this… since you’re looping through the list of enum types you have. I figured the best way to do this was to use the built in values() method for the enum and define an array of types at the top of the EnumType class, e.g.

private static final EnumType[] VALS = values();


Taken from the 5.0 language guide…

“Note that each enum type has a static values method that returns an array containing all of the values of the enum type in the order they are declared. This method is commonly used in combination with the for-each loop to iterate over the values of an enumerated type”

See: See: http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html

Just a follow-up on this and a quick note about commons-enum.  This is a pre JDK 5.0 Apache commons implementation that is extensible and can be used in place of the standard Java 5.0 enum.  It’s part of commons-lang here:

http://commons.apache.org/lang/

Comment Eclipse Not Starting - 10/12/08

Had a weird issue with Eclipse not starting, it would bomb out with the following exception:

 Bash |  copy |? 
JVM terminated. Exit code=1
/usr/bin/java
-Dosgi.requiredJavaVersion=1.5
-XX:MaxPermSize=768m
-Xms256m
-Xmx1024m
-jar /home/jon/eclipsercp/plugins/org.eclipse.equinox.launcher_1.0.1.R33x_v20080118.jar
-os linux
-ws gtk
-arch x86_64
-showsplash
-launcher /home/jon/eclipsercp/eclipse
-name Eclipse
--launcher.library /home/jon/eclipsercp/plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.0.3.R33x_v20080118/eclipse_1023.so
-startup /home/jon/eclipsercp/plugins/org.eclipse.equinox.launcher_1.0.1.R33x_v20080118.jar
-exitdata 257000e
-clean
-vm /usr/bin/java
-vmargs
-Dosgi.requiredJavaVersion=1.5
-XX:MaxPermSize=768m
-Xms256m
-Xmx1024m
-jar /home/jon/eclipsercp/plugins/org.eclipse.equinox.launcher_1.0.1.R33x_v20080118.jar

Under the workspace folder there are a number of files and directories:

 Bash |  copy |? 
.plugins
.mylyn
version.ini
.lock
.log

Normally deleting the .lock file seems to cure this problem, but it didn’t in this case.

In order to cure it I had to go into

 Bash |  copy |? 
.plugins/org.eclipse.core.resources

and remove the .snap file. This sorted out the issue and allowed me to start Eclipse again. Unfortunately I lost all the projects within the workspace and had to reimport them (grrr).

You can alternatively try running the Eclipse Workspace Rebuilder (http://www.eclipse.org/eclipse/platform-core/downloads.php). Unzip the rebuilder zip file and run it using:

 Bash |  copy |? 
eclipse -application org.eclipse.core.tools.restorer.application

It doesn’t restore everything, only the basic state of your projects.

|