Maven2 Archetypes – Yes or No ?

A good friend of my is working on a cool project. A plugin for the Hibernate Persistence Framework. I am helping out with testing. And a couple days ago we had this discussion about how to get started with a project. I recommended to offer a Maven2 Archetype.

I asked Max if I can publish his E-Mail on my blog and take the conversation public. And here is his E-Mail:

———–

Hi Robert,
further thoughts on the Maven archetype idea. Having played with it, it doesn’t really seem practical because we don’t know what framework our users will be using. We could conceivably come up with an archetype for Grails, one for Spring, one for ZK, etc…
What we have done is Mavenize the basic demo so you can just download it and run it with mvn tomcat:run. That makes the zip file just 97k, which is nice. This is also true for the Grails demo.
I think it makes sense to make the tutorial a Maven project, but I don’t really see the value of making it an archetype. People will not want to create new projects based on this particular project — which uses plain old JSP. They’ll just get the basic project and fiddle with it while following the tutorial.
Your thoughts would be appreciated.
Thanks,
— Max

Archetype: RichFaces 4.1.0.Final + Spring 3.1.0.RELEASE + Hibernate 3.3.0

This maven2 archetype contains a little sample web application with this Frameworks:

  • Spring 3.1.0.RELEASE Framework
  • Servlet-API 2.5
  • JSF 2.0 (mojarra 2.1.2)
  • RichFaces 4.1.0.Final
  • ploinFaces 1.6
  • ploinMailFactory 1.3.1
  • Hibernate 3.3.0
  • TestNG 5.8
  • Log4J 1.2.15
  • HSQLDB 1.8.0.7

The configuration is annotation-driven. It is deployed on the PLOIN Repository-Server

http://www.ploin-m2.de/nexus/content/groups/public/

you can create a project from the archetype with the following command:

mvn archetype:generate -DarchetypeGroupId=org.ploin.archetype -DarchetypeArtifactId=demoSpringRichHibernate-archetype -DarchetypeVersion=1.2 -DarchetypeRepository=http://www.ploin-m2.de/nexus/content/groups/public/ -DgroupId=com.versioneye -DartifactId=myNewWebApp

The created project is a very simple web-application with a login mask and 2 xhtml-sites. I have tested the app on a tomcat 6.0.35 and Java 1.6 on Mac OS X Lion.

On the second page there is a small demonstration of the JSF 2.0 AJAX feature. Every time you type something in into the first input field, there is a whole server roundtrip. The ManagedBean gets updated immediately.

On the same page there is a small demo for the RichFaces calendar.

After the creation the app is running with the HypersoniceSQL DBMS. But it is very easy to switch to MySQL or Oracle. I put the drivers for MySQL and Oracle as a comment in the pom.xml. So you just need to comment in the right lines in the pom.xml.

Archetype: RichFaces 4.0.0.M1 + Spring 3.0.5.RELEASE + Hibernate 3.3.0

This maven2 archetype contains a little sample web application with this Frameworks:

  • Spring 3.0.5.RELEASE Framework
  • Servlet-API 2.5
  • JSF 2.0 (mojarra 2.1.2)
  • RichFaces 4.0.0.M1
  • ploinFaces 1.6
  • ploinMailFactory 1.3.1
  • Hibernate 3.3.0
  • TestNG 5.8
  • Log4J 1.2.15
  • HSQLDB 1.8.0.7

The configuration is annotation-driven. It is deployed on the PLOIN Repository-Serve

http://www.ploin-m2.de/nexus/content/groups/public/

you can create a project from the archetype with the following command:

mvn archetype:generate -DarchetypeGroupId=org.ploin.archetype -DarchetypeArtifactId=tempSpringRichHibernate -DarchetypeVersion=1.7.2 -DarchetypeRepository=http://www.ploin-m2.de/nexus/content/groups/public/ -DgroupId=org.ploin -DartifactId=demoSpringRichHibernate

The created project is a very simple web-application with a login mask and 2 xhtml-sites. I have tested the app on a tomcat 6.0.20 and Java 1.6 on Mac OS X Snow Leopard.

rich-faces-login
rich-faces-login

You can login with the username “admin” and the password “admin”.

After the creation the app is running with the HypersoniceSQL DBMS. But it is very easy to switch to MySQL or Oracle. I put the drivers for MySQL and Oracle as a comment in the pom.xml. So you just need to comment in the right lines in the pom.xml.

SqlServer 2008 with Hibernate 3.6.4

The current stable version if Hibernate is 3.6.4.FINAL. In this version the Dialect for the SqlServer 2008 from Microsoft looks like this:

public class SQLServer2008Dialect extends SQLServerDialect {
  public SQLServer2008Dialect(){
    registerColumnType( Types.DATE, "date" );
    registerColumnType( Types.TIME, "time" );
    registerColumnType( Types.TIMESTAMP, "datetime2" );

    registerFunction( "current_timestamp", new NoArgSQLFunction("current_timestamp", Hibernate.TIMESTAMP,false) );
  }
}

A litle bit short. If you have some problems with this Dialect you should write your own Dialect. This class here is a customized SqlServerDialect from the Hibernate 4 Project. For me it works fine together with SqlServer 2008 R2.

import org.hibernate.Hibernate;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.SQLServer2005Dialect;
import org.hibernate.dialect.function.*;
import org.hibernate.type.StandardBasicTypes;

import java.sql.Types;

public class SqlServer2008Dialect extends SQLServer2005Dialect {

 public SqlServer2008Dialect(){
 super();

 registerColumnType( Types.DATE, "date" );
 registerColumnType( Types.TIME, "time" );
 registerColumnType( Types.TIMESTAMP, "datetime2" );

 registerFunction( "current_timestamp", new NoArgSQLFunction("current_timestamp", Hibernate.TIMESTAMP,false) );

 registerColumnType( Types.BIT, "tinyint" ); //Sybase BIT type does not support null values
 registerColumnType( Types.BIGINT, "bigint" );     //changed
 registerColumnType( Types.SMALLINT, "smallint" );
 registerColumnType( Types.TINYINT, "tinyint" );
 registerColumnType( Types.INTEGER, "int" );
 registerColumnType( Types.CHAR, "char(1)" );
 registerColumnType( Types.VARCHAR, "varchar($l)" );
 registerColumnType( Types.FLOAT, "float" );
 registerColumnType( Types.DOUBLE, "double precision" );

 registerColumnType( Types.VARBINARY, "varbinary($l)" );
 registerColumnType( Types.NUMERIC, "numeric($p,$s)" );
 registerColumnType( Types.BLOB, "image" );
 registerColumnType( Types.CLOB, "text" );
 registerColumnType( Types.ROWID, "bigint");

 registerFunction( "ascii", new StandardSQLFunction("ascii", StandardBasicTypes.INTEGER) );
 registerFunction( "char", new StandardSQLFunction("char", StandardBasicTypes.CHARACTER) );
 registerFunction( "len", new StandardSQLFunction("len", StandardBasicTypes.LONG) );
 registerFunction( "lower", new StandardSQLFunction("lower") );
 registerFunction( "upper", new StandardSQLFunction("upper") );
 registerFunction( "str", new StandardSQLFunction("str", StandardBasicTypes.STRING) );
 registerFunction( "ltrim", new StandardSQLFunction("ltrim") );
 registerFunction( "rtrim", new StandardSQLFunction("rtrim") );
 registerFunction( "reverse", new StandardSQLFunction("reverse") );
 registerFunction( "space", new StandardSQLFunction("space", StandardBasicTypes.STRING) );

 registerFunction( "user", new NoArgSQLFunction("user", StandardBasicTypes.STRING) );

 registerFunction( "current_timestamp", new NoArgSQLFunction("getdate", StandardBasicTypes.TIMESTAMP) );
 registerFunction( "current_time", new NoArgSQLFunction("getdate", StandardBasicTypes.TIME) );
 registerFunction( "current_date", new NoArgSQLFunction("getdate", StandardBasicTypes.DATE) );

 registerFunction( "getdate", new NoArgSQLFunction("getdate", StandardBasicTypes.TIMESTAMP) );
 registerFunction( "getutcdate", new NoArgSQLFunction("getutcdate", StandardBasicTypes.TIMESTAMP) );
 registerFunction( "day", new StandardSQLFunction("day", StandardBasicTypes.INTEGER) );
 registerFunction( "month", new StandardSQLFunction("month", StandardBasicTypes.INTEGER) );
 registerFunction( "year", new StandardSQLFunction("year", StandardBasicTypes.INTEGER) );
 registerFunction( "datename", new StandardSQLFunction("datename", StandardBasicTypes.STRING) );

 registerFunction( "abs", new StandardSQLFunction("abs") );
 registerFunction( "sign", new StandardSQLFunction("sign", StandardBasicTypes.INTEGER) );

 registerFunction( "acos", new StandardSQLFunction("acos", StandardBasicTypes.DOUBLE) );
 registerFunction( "asin", new StandardSQLFunction("asin", StandardBasicTypes.DOUBLE) );
 registerFunction( "atan", new StandardSQLFunction("atan", StandardBasicTypes.DOUBLE) );
 registerFunction( "cos", new StandardSQLFunction("cos", StandardBasicTypes.DOUBLE) );
 registerFunction( "cot", new StandardSQLFunction("cot", StandardBasicTypes.DOUBLE) );
 registerFunction( "exp", new StandardSQLFunction("exp", StandardBasicTypes.DOUBLE) );
 registerFunction( "log", new StandardSQLFunction( "log", StandardBasicTypes.DOUBLE) );
 registerFunction( "log10", new StandardSQLFunction("log10", StandardBasicTypes.DOUBLE) );
 registerFunction( "sin", new StandardSQLFunction("sin", StandardBasicTypes.DOUBLE) );
 registerFunction( "sqrt", new StandardSQLFunction("sqrt", StandardBasicTypes.DOUBLE) );
 registerFunction( "tan", new StandardSQLFunction("tan", StandardBasicTypes.DOUBLE) );
 registerFunction( "pi", new NoArgSQLFunction("pi", StandardBasicTypes.DOUBLE) );
 registerFunction( "square", new StandardSQLFunction("square") );
 registerFunction( "rand", new StandardSQLFunction("rand", StandardBasicTypes.FLOAT) );

 registerFunction("radians", new StandardSQLFunction("radians", StandardBasicTypes.DOUBLE) );
 registerFunction("degrees", new StandardSQLFunction("degrees", StandardBasicTypes.DOUBLE) );

 registerFunction( "round", new StandardSQLFunction("round") );
 registerFunction( "ceiling", new StandardSQLFunction("ceiling") );
 registerFunction( "floor", new StandardSQLFunction("floor") );

 registerFunction( "isnull", new StandardSQLFunction("isnull") );

 registerFunction( "concat", new VarArgsSQLFunction( StandardBasicTypes.STRING, "(","+",")" ) );

 registerFunction( "length", new StandardSQLFunction( "len", StandardBasicTypes.INTEGER ) );
 registerFunction( "trim", new SQLFunctionTemplate( StandardBasicTypes.STRING, "ltrim(rtrim(?1))") );
 registerFunction( "locate", new CharIndexFunction() );

 getDefaultProperties().setProperty(Environment.STATEMENT_BATCH_SIZE, NO_BATCH);
 }

}
 

You can just copy & pate it to your own project. If you want to use it, just add the dialect to your hibernate.properties.

hibernate.dialect=org.<your_package_name>.SqlServer2008Dialect

Customized MySql5Dialect for Hibernate

By default the MySqlDialect who is coming with Hibernate does MySQL not force to UTF. And by default all binary columns are mapped to “tinyblob”. That’s why I wrote my own Dialect. It is very easy to do. Just a fiew lines of code. Here is my own MySql5Dialect.

import org.hibernate.dialect.MySQL5InnoDBDialect;

import java.sql.Types;

public class MySql5Dialect extends MySQL5InnoDBDialect {

  public String getTableTypeString() {
    return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
  }

  public MySql5Dialect() {
    super();
    registerColumnType( Types.BINARY, "MEDIUMBLOB" );
  }

}

You can use by adding this to your hibernate.properties files:

hibernate.dialect=org.<your_package_name>.MySql5Dialect

Could not initialize class JavaReflection

By migrating to Hibernate 3.6.4.FINAL and Spring 3.0.5.RELEASE I got this Exception:

Could not initialize class org.hibernate.annotations.common.reflection.java.JavaReflection

I could solve the problem by adding this to my pom.

       <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.6.1</version>
            <scope>compile</scope>
        </dependency>