Saturday, December 27, 2008

Simplistic CRUD application with Grails on GlassFish V3 Prelude

My colleague Matt wrote a brilliant tutorial: EJB 3.1 and JSF 2.0 with GlassFish V3 Prelude.

A commenter on Matt's post claimed that using Grails to create the same application would be a tremendous simplification.
I wanted to find out if this was really true, and how much effort it would actually take to achieve the same functionality with Grails.

This post is not a Grails tutorial, and it is also not the goal to create an intelligent application. The goal is to reimplement Matt's application as efficiently as possible.

I assume, that you have GlassFish V3 Prelude installed.

Step 1: Install Grails
Start the updatetool or start glassfish an go to the updatetool inside the admin console. Select Grails for installation and perform the installation. Set the environment variable GRAILS_HOME to point to the Grails installation inside GlassFish, and include the Grails binary in your PATH.

On my OS X system this meant putting the following lines in my .profile:
export GRAILS_HOME=/Applications/NetBeans/glassfish-v3-prelude/glassfish/grails
export PATH=$PATH:$GRAILS_HOME/bin


Step 2: Create a new Grails application
Execute grails create-app CRUD-GRAILS in on the console.
This creates a directory named CRUD-GRAILS with a fully functional Grails project skeleton.

You can start your new Grails project with grails run-app. This starts up GlassFish and loads the application. The application is available at http://localhost:8080/CRUD-GRAILS.
As you can see there is not much there apart from a welcome screen.


Step 3: Create the Book entity
Execute grails create-domain-class book from inside your project directory.
This creates the file grails-app/domain/Book.goovy that contains a skeleton class for the book entity.
You could also create the file manually, the grails command just also creates a file for tests...

Edit Book.groovy to add properties:
class Book {
	String name
	String isbn
}


Step 4: Create a controller
Execute grails create-controller book from inside your project directory.
This creates the file grails-app/controllers/BookController.goovy that contains a skeleton class for the book controller.

As with the Book entity, you could also create the file manually, the grails command just also creates a file for tests...

Edit BookController.groovy to provide the CRUD operations on the book entity (this is called scaffolding):
class BookController {

    def scaffold = true;
}


That's basically it! The application can create, update, show and delete books.

It took typing three commands and writing three lines of code ... all completed in less than 10 minutes ... not bad I would say!

Let's see what Grails has to say: grails stats
	+----------------------+-------+-------+
	| Name                 | Files |  LOC  |
	+----------------------+-------+-------+
	| Controllers          |     1 |     3 | 
	| Domain Classes       |     1 |     4 | 
	| Integration Tests    |     2 |     8 | 
	+----------------------+-------+-------+
	| Totals               |     4 |    15 | 
	+----------------------+-------+-------+

Ok, using dynamic scaffolding is a bit like comparing apples with oranges ... lets change that: grails generate-all
This generates the concrete views and the controller for the book entity, that have been generated dynamically by scaffolding up to now...
... now you can look at the code and adjust it to your needs.

Another little thing is getting rid of the Grails logo. Edit grails-app/view/layouts/main.gsp: Delete the lines between the <body></body> tags except <g:layoutBody /> ... I think we stay with the nice CSS and icons :-)

Ok, I don't claim that Grails is a silver bullet, but it is quite impressive how fast you can achieve some core functionality! The question is now how well it scales for real-world-requirements ...

Matt are you ready to implement some entity-relations, validations, conversations, AJAX-UI ... ? I would be ready for the challenge :-)

Friday, December 26, 2008

Using JPA and Hibernate with Maven

I have been fighting a bit to set up a Maven project with JPA and Hibernate as persistence provider.

The final solution is very simple. But when you get on a wrong track at the beginning, you end up in a terrible maze...

So here the most important hint:
The JBoss repository (http://repository.jboss.org/maven2/) is quite a mess.
In the root of the repository you find directories (matching Maven GroupIds) for hibernate , hibernate-annotations and hibernate-entitymanager.
Do not use them!
They are outdated, do not provide current versions and most annoying do not declare their dependencies... so your pom will get a mess.

All dependencies should use the GroupId org.hibernate (browse into the org directory in the Maven repository).

So here is my working pom.xml:
<?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>domain</groupId>
  <artifactId>cascaded-locking</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>cascaded-locking</name>
  <url>http://maven.apache.org</url>
  <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
        </plugins>
  </build>
    
  <dependencies>
	
	<dependency>
		<groupId>org.hibernate</groupId>
		<artifactId>hibernate-entitymanager</artifactId>
		<version>3.4.0.GA</version>
	</dependency>
	
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.5.2</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

	<dependency>
		<groupId>org.apache.derby</groupId>
		<artifactId>derby</artifactId>
		<version>10.3.2.1</version>
		<scope>test</scope>
	</dependency>
	
  </dependencies>
  
  <repositories>
      <repository>
          <id>jboss</id>
          <url>http://repository.jboss.org/maven2</url>
      </repository>
  </repositories>

</project>


Thursday, December 25, 2008

Don't be too clever...

Brain-Power.jpg
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.

--Brian Kernighan

Wednesday, December 24, 2008

Take it slow ...

snail.jpg
A unit test that takes 1/10th of a second to run is a slow unit test.

- Michael C. Feathers
Working effectively with legacy code

Thursday, December 18, 2008

If programming languages were ...

braindead-closeup.jpg After Web Framework Trolling and Language Wars now come the comparisons:

  • If programming languages were religions...
  • If programming languages were cars...


  • My favorites:
    APL would be Scientology - There are many people who claim to follow it, but you've always suspected that it's a huge and elaborate prank that got out of control.

    Eiffel is a car that includes a built-in driving instructor with a French accent. He will help you quickly identify and learn from your mistakes, but don't you dare argue with him or he'll insult you and throw you out of the car.

    Wednesday, December 17, 2008

    Go go java! ... play catch-up with C#!

    z1xgZtgVQr5h.jpg I am reading Stephen Colebourne's JDK 7 language changes - Devoxx votes!.

    At the devoxx conference people voted on possible future features of the Java language.

    As a developer with a .NET background, I can't help to compare with C# ...
  • Properties: In C# since 1.0
  • Null handling: In C# 2.0 with nullable types and according operators
  • List/Map syntax: In C# since 1.0 with Indexers
  • Extension methods: In C# since 3.0. See here, but C# is going much further with LINQ
  • Method pointers: In C# since 1.0 with delegates. Later extended with anonymous delegates and Lambda Expressions
  • Multiline Strings: In C# since 1.0 with the @-syntax
  • Infer generics: In C# since 3.0 with general type inference

  • ... go go Java! C# is not resting ... 4.0 is in the pipes, offering another truckload of innovation (dynamic capabilities, co-contravariant features for generics, optional parameters (small thumbs up for Java) and named parameters ...)

    Update: The post is discussed at Hacker News.

    Tuesday, December 16, 2008

    UML redefined

    Mona ASCII.gif
    True, a picture says more than thousand words. Yet UML is not a picture but graphically arranged text.

    -- Daniel Tobler (Zühlke LAT)


    Monday, December 15, 2008

    The root of all evil ...

    http://www.sorgonet.com/supercomputing/films/hal9000.gif For years Donald Knuths famous quote was standing:
    Premature optimization is the root of all evil


    But in his recent blog-post Adam Bien is taking it up with Donald Knuth:
    Premature encapsulation is the root of all evil


    In his sweeping post Adam also kills a pattern (seems to be his latest hobby), encompasses leaky abstraction and promotes KISS/YAGNI.

    Interesting read...

    Related Posts Plugin for WordPress, Blogger...