NMC DSP Getting Started

From BioAssist
Jump to: navigation, search

NMC DSP - Mainpage


Getting started with NMC-DSP

Installation

Before you continue: If this is the first time you are working with either Groovy or Grails we suggest you read the Getting started with Groovy and Grails first.

Step 1. Download the latest available version from the svn repository. Step 2. Open is as a Project in Netbeans. Netbeans should be configured with the Groovy and Grails Plug-in. Also the correct version of Grails should be configured correctly. For more information you can read the Getting started with Groovy and Grails guide on this page. Step 3. Right-click on the project and select "Run".

When all goes well a new browser(tab) should open with the "development" version of the NMC-DSP.

Getting started with Groovy and Grails

Installation (Netbeans/GG Plug-in)

  1. Download and extract Grails: http://www.grails.org/Download. (version used for this Getting Started guide is 1.1.2, has also been tested on version 1.2.0 of grails and works fine. More about this version can be found on: http://www.grails.org/1.2+Release+Notes.)
  2. Download and install Netbeans: http://netbeans.org/downloads/ (select the JavaSE edition).
  3. Start Netbeans > Go to Tools > Plugins.
  4. Check the "Groovy and Grails" plug-in and click on the "Install" button at the bottom.
  5. After installing and restarting the Netbeans IDE go to Tools > Options > Miscellaneous > Groovy. Here you point the "Grails Home" to the correct location (from first step). Please note, OSX users have to go to Netbeans > Preferences > Miscellaneous > Groovy.
  6. Now go to File > New Project > Groovy and select Grails application.
  7. Give your project a name and click on Finish. For this example I will use DemoApp.
  8. First we will test to see if the application runs. You do this by right clicking with the mouse on the name of the project and selecting Run. Depending on the version of Grails you will end up in your browser looking at the Grails logo with a Welcome to Grails message. If not please have a look at the FAQ section at the bottom of this page.
  9. Stop the application (in the footer of Netbeans you can click on the X to stop the Servlet Engine)

Creating the model

There are many tutorials on the internet like the PetClinic and the BookStore. For this tutorial I will use something more related to our business :). After this tutorial you will have a simple digital Lablog to use in your own laboratory.

To build the model we have to create domain classes. Right-click with the mouse on Domain Classes within the DemoApp. Select New > Grails Domain Class. Give it a name and define the package. Now create the following:

  • project (nl.nbic.bioassist)
  • entry (nl.nbic.bioassist)
  • user (nl.nbic.bioassist)

Project

package nl.nbic.bioassist

class Project {

    String  name            //name of the project
    String  description     //description of the project
    Date    dateCreated     //automatically set when doing a create

    static constraints = {
        name()
        description(nullable: true, maxSize:2000) //may be zero, max of 2000 characters
    }

    /* add transient property entries
     * transient properties are accessible like normal properties but are not saved in the database
     */
    static transients = [ "entries" ]

    /**
    * @return an ArrayList of entries
    * We sort by dateCreated descending
    */
    List getEntries() {
	return Entry.findAllByProject(this, [sort:"dateCreated", order:"desc"]);
    }

    String toString(){
        name //returns the name when Project object is displayed
    }
}

Entry

package nl.nbic.bioassist

class Entry {

    Project project         //reference to related project
    User    user            //reference to related user
    String  data            //data contains the actual log entry
    Date    dateCreated     //automatically set when doing a create
    Date    lastUpdated     //automatically set when doing an update

    static constraints = {
        project()
        user()
        data(maxSize:10000) //max of 10000 characters
    }

    String toString(){
        data //returns the data when Entry object is displayed
    }
}

User

package nl.nbic.bioassist

class User {

    String  name            //name of the user

    static constraints = {
        name(maxSize:100)   //max of 100 characters
    }

    String toString(){
        name //returns the name when User object is displayed
    }
}

Creating a basic Scaffolding interface

Now that we have the Model we can setup a simple Scaffolding interface. To enable Scaffolding we have to create controllers which expose this functionality through a browser.

Right-click on Controllers folder in the DemoApp project and select New > Grails Controller. Give it a name and define the package. Now create the following:

  • project (nl.nbic.bioassist)
  • entry (nl.nbic.bioassist)
  • user (nl.nbic.bioassist)

Project

package nl.nbic.bioassist

class ProjectController {

    def Scaffold = true
}

Entry

package nl.nbic.bioassist

class EntryController {

    def Scaffold = true
}

User

package nl.nbic.bioassist

class UserController {

    def Scaffold = true
}

This is a good moment to see the results. Right-click on the DemoApp project and select Run again. When the servlet engine is ready Netbeans will open your default browser again and show you the homepage. On the homepage you now see the Grails logo with a Welcome to Grails message again + the three controllers we just created. Select one of the controllers to have a look at the Scaffolding.

Bootstrap the Development environment

At this moment you are using a non-persistent in-memory database called HSqlDB. For now this is fine for your local development version of the application. However the downside is that you loose all data every time you restart the application. Within the NMC-DSP project we use the bootstrap to inject test data at start-up. In the Configuration folder of the DemoApp you will find a file called BootStrap.groovy. Open this file in the IDE and add the following code and restart the application

//import domain classes for creating the test date
import nl.nbic.bioassist.*

//required import to read from the Grails config
import grails.util.GrailsUtil

class BootStrap {
     def init = { servletContext ->

        if (GrailsUtil.getEnvironment() == "development") {
            // only for development

            //Create 3 Test projects
            def project1 = new Project(name:"Projct ABC").save()
            def project2 = new Project(name:"Projct DEF").save()
            def project3 = new Project(name:"Projct GHI").save()

            //Create 3 Test users
            def user1 = new User(name:"John Freeman").save()
            def user2 = new User(name:"Gill Johnson").save()
            def user3 = new User(name:"Randy Jackson").save()

            //Create 3 Test Entries (for project 1)
            new Entry(project: project1, user:user1, data:"Test Entry 1 Lorem ipsum dolor sit amet...").save()
            new Entry(project: project1, user:user2, data:"Test Entry 2 Lorem ipsum dolor sit amet...").save()
            new Entry(project: project1, user:user3, data:"Test Entry 3 Lorem ipsum dolor sit amet...").save()

        }

     }

     def destroy = {

     }
}

Creating the (real) interface

Page (main/homepage)

The interface starts with a controller and a view. First we create a controller called PageController

Page controller (/grails-app/controllers/nl/nbic/bioassist/PageController.groovy)

package nl.nbic.bioassist

class PageController {

    def index = {

	def entries = [] //create an empty list

	// check if a user is set. Without a user we cannot log anything
	if (!session.user){
	    // no user was set, forward to set user page
	    forward(controller:"user",action:"select")
	}

	// check if a project is set. Without a project we cannot log anything
	if (!session.project){
	    // no project was set, forward to set project page
	    forward(controller:"project",action:"select")
	}

	// this means we have a user and a project, load all entries (if there)
	if (session.project?.entries){
	    entries = session.project.entries
	}

	[ entries: entries ]
    }
}

This is a very basic controller that checks if a user and a project are set in the session. When no user is selected you will be forwarded to the user/select page. Next is the project, like the user we need a project to be selected. Same as with the user you are forwarded to the project/select page when there is no project.

Next is the view that lists the entries of the selected user/project.

Page view (/grails-app/views/page/index.gsp)

<html>
    <head>
        <title>Welcome to Lablog</title>
		<meta name="layout" content="main" />
    </head>
    <body>

      <div style="margin-left:20px; margin-right:20px; float: left;">
	<!-- a simple form to post a new entry -->
	<g:form controller="entry" method="post" action="postnew">
	    <b>New entry</b><br />
	    <textarea name="entry"></textarea><br />
	    <input type="submit" value="Save"/>
	</g:form>
	<br clear="all">
      </div>

      <h1 style="margin-left:20px;">Welcome ${session.user.name} to Lablog</h1>
      <p style="margin-left:20px;">
	This is a demo application written in Groovy using the Grails framework.
	Use it for testing, learning or playing but not for production!<br /><br />
	Enjoy!
      </p>

      <br clear="all">

      <h2 style="margin-left:20px;">Entries for project : ${session.project}</h2>
    
      <!-- when entries is set we list them -->
      <g:if test="${entries}">
	<g:each in="${entries}" var="entry">
	  <p style="margin:20px; font: 14px verdana, arial, helvetica, sans-serif;"><b>${entry.user.name} wrote:</b> ${entry.data}</p>
	  <p style="margin:20px; font: 11px verdana, arial, helvetica, sans-serif; font-style:italic; text-align:right;">
	    on <g:formatDate format="dd-MM-yyyy" date="${entry.dateCreated}"/>
	  </p>
	</g:each>
      </g:if>
      <g:else>
	<p style="margin-left:20px;">No entries found</p>
      </g:else>

    </body>
</html>

Set new homepage

By default you will be redirected to /grails-app/views/index.gsp. For our application the homepage is the page/index view. To change this go to the URLMappings file (/grails-app/conf/UrlMappings.groovy) and change it to:

class UrlMappings {
    static mappings = {
      "/$controller/$action?/$id?"{
	      constraints {
			 // apply constraints here
		  }
	  }
      "/"(controller:"page", view:"/index")
	  "500"(view:'/error')
	}
}

User select

For the user/select and the project/select to work we have to add them to the controller and create the views with a form to select them. The new user and project controller should look like this:

User controller (/grails-app/controllers/nl/nbic/bioassist/UserController.groovy)

package nl.nbic.bioassist

class UserController {

    def Scaffold = true

    def select = {

	// if a User ID is found in the POST/GET Params load the User into the SESSION
	if (params.userId){
	    session.user = User.get( params.userId.toLong() )

	    // a new user was set, forward to the main page
	    forward(controller:"page",action:"index")
	    
	}

	// fetch all users sorted by name
	def users = User.list(sort:"name", order:"asc")

	// return required data to the view
	[ users: users ]
    }

}

And the view... User view (/grails-app/views/user/select.gsp)

<html>
    <head>
        <title>Welcome to Lablog</title>
		<meta name="layout" content="main" />
    </head>
    <body>
        <h1 style="margin-left:20px;">Select a user</h1>

	<p style="margin-left:20px;">
	  <!-- see if a user has been selected -->
	  <g:if test="${session?.user?.id}">
	    Selected user: ${session?.user?.name}<br /><br />
	  </g:if>

	  <!-- the ArrayList with users was passed to the view by the controller -->
	  <g:each in="${users}" var="user">
	    <!-- the g:each tag can be used to iterate over the array values -->

	    <!-- we can use g:link to create a link to be able to select a user -->
	    <g:link controller="user" action="select" params="[userId:user.id]">${user.name}</g:link><br />

	  </g:each>
	</p>

    </body>
</html>

Project select

Project controller (/grails-app/controllers/nl/nbic/bioassist/ProjectController.groovy)

package nl.nbic.bioassist

class ProjectController {

    def Scaffold = true

    def select = {

	// if a Project ID is found in the POST/GET Params load the Project into the SESSION
	if (params.projectId){
	    session.project = Project.get( params.projectId.toLong() )

	    // a new project was set, forward to the main page
	    forward(controller:"page",action:"index")
	}

	// fetch all projects sorted by name
	def projects = Project.list(sort:"name", order:"asc")

	// return required data to the view
	[ projects: projects ]
    }
}

And the view... Project view (/grails-app/views/project/select.gsp)

<html>
    <head>
        <title>Welcome to Lablog</title>
		<meta name="layout" content="main" />
    </head>
    <body>
        <h1 style="margin-left:20px;">Select a project</h1>

	<p style="margin-left:20px;">
	  <!-- see if a project has been selected -->
	  <g:if test="${session?.project?.id}">
	    Selected user: ${session?.project?.name}<br /><br />
	  </g:if>

	  <!-- the ArrayList with projects was passed to the view by the controller -->
	  <g:each in="${projects}" var="project">
	    <!-- the g:each tag can be used to iterate over the array values -->

	    <!-- we can use g:link to create a link to be able to select a project -->
	    <g:link controller="project" action="select" params="[projectId:project.id]">${project.name}</g:link><br />

	  </g:each>
	</p>

    </body>
</html>

Entry create

To be able to create a new entry we setup a postnew function in the EntryController class. This allows other pages to post a new Entry. We don't have to create a view for this because we are either redirected to where we came from or we "render" an error message on the screen. Normally you would not do this with a render but for now it's fine.

Entry controller (/grails-app/controllers/nl/nbic/bioassist/EntryController.groovy)

package nl.nbic.bioassist

class EntryController {

    def Scaffold = true

    def postnew = {

	//check if a new entry was created via the form
	if (params.entry){
	    new Entry(	user: session.user,
			project: session.project,
			data: params.entry
		     ).save(flush: true)
		     //we forse a flush to the database

	    //redirect where you came from
	    redirect(url: request.getHeader('referer'))

	} else {
	    //render is easy, we don't need a view now.
	    render("Was unable to create an entry, no entry data was set")
	}
    }
}

Main layout

By default the layout is very basic. For this guide I made some changes to the default template (/grails-app/views/layouts/main.gsp) and I added an image (/web-app/images/nbiclogo.png)

Template (s)

The Grails application comes with a main.gsp template by default. You can edit this or create your own. Also you can setup your own templates for a header, menu, footer, etc... You can place them anywhere in the /grails-app/views/ folder. Make sure the name of your own templates start with a "_" underscore. This is the convention Grails uses to be able to identify a template. You can easily add a template to a gsp-file by using the following syntax

<g:render template="/header" />

This will include the /grails-app/views/_header.gsp template.

For our Lablog application we start by replacing the main.gsp (/grails-app/views/layouts/main.gsp) by the following:

<html>
    <head>
        <title><g:layoutTitle default="Grails" /></title>
        <link rel="stylesheet" href="${resource(dir:'css',file:'main.css')}" />
        <g:layoutHead />
        <g:javascript library="application" />				
    </head>
    <body style="background: #DCDCDC;">
      <div style="border: 1px solid #000; background: #FFF; margin: 1px auto 1px auto; width: 687px;">
        <div id="spinner" class="spinner" style="display:none;">
            <img src="${resource(dir:'images',file:'spinner.gif')}" alt="Spinner" />
        </div>

	<!-- header -->
	<g:render template="/header" />

	<!-- main menu -->
	<g:render template="/menu" />

        <div style="padding: 10px; margin: 15px; border: 0px solid #000;">
	  <g:layoutBody />
	</div>

	<!-- footer -->
	<g:render template="/footer" />
      </div>
    </body>	
</html>

A basic header template which is included in the main.gsp template above.

_header.gsp (/grails-app/views/_header.gsp)

<!-- header -->
<g:link controller="page" action="index">
  <img style="border: 0px solid #000; float: right; margin: 10px;" src="${resource(dir:'images',file:'nbiclogo.png')}" alt="NBIC LOGO" />
  <h1 style="font-size: 6em; margin-left:10px;">Lablog</h1>
</g:link>

To be able to navigate we create a template that holds the menu. This is included in the main.gsp template above.

_menu.gsp (/grails-app/views/_menu.gsp)

<!-- menu -->
<h2 style="margin-left:15px;">
  Menu :
  <!-- we can use g:link to create a links -->
  <g:link controller="user" action="select">User</g:link> - <g:link controller="project" action="select">Project</g:link>
</h2>

A basic footer template which is included in the main.gsp template above.

_footer.gsp (/grails-app/views/_footer.gsp)

<!-- footer -->
<div style="margin: 20px; text-align: center;">
  <h2 style="margin-left:15px;">Footer</h2>
  My default footer information goes here!<br />
  Date : <g:formatDate format="dd-MM-yyyy" date="${new Date()}"/>
</div>

Image You can download this from: https://gforge.nbic.nl/themes/nbic/images/nbiclogo.png and put it in the /web-app/images folder of the Grails application.

Deploying the application as a WAR-file

Now that we have a basic Grails application setup we can deploy it to our Tomcat/Jetty or other server. The best way to do that is to run "grails war" in the root of your application or right click on the project in Netbeans and select "Build". More about deploying you application on a server can be found on: http://www.grails.org/Deployment

Useful Plug-ins

dbUtil

Basic interface to the database tables. Useful when developing to see if database updates were done correctly.

URL: http://www.grails.org/plugin/db-util


classDiagram

Creates a nice overview of your domain classes and the relationships between them. Please note: the version we use is not able to display Floats and BigDecimals correctly. Also Graphviz (http://www.graphviz.org/) is required to see the diagram.

URL: http://www.grails.org/plugin/class-diagram


Quartz

Job scheduler like Cron.

URL: http://www.grails.org/plugin/quartz


Apache Shiro

Very easy to implement authentication system. By default most of the requirements we had were covered.

URL: http://www.grails.org/plugin/shiro

Useful Sites

Grails

Groovy

Download Source

Source here

FAQ


Author

For any question regarding this Getting Started Guide or the NMC-DSP project, please contact Michael van Vliet.