Posts Tagged ‘grails’

Shorter Grails textField

Thursday, July 24th, 2008

Making textFields in Grails is a bit verbose, at least if you want error highlighting and returned values on errors. This post shows a quick solution.

Problem

A full textField would be:

<g:textField class="${hasErrors(bean:user, field:'name', 'errors')}" value="${fieldValue(bean:user,field:'name')}" name="name"/>

Which clearly is very verbose; you have to specify “user” twice, and “name” even three times. This verbosity also makes the view less readable.

Googling for this problem resulted in: Smarter Grails Tags (a proposal). Funny that the writer exactly sees the same problem in it, also uses the “user” domain model, and also knows Stripes where you could just use something like

<stripes:text name="name"/>

and specify the bean name in the form. (Stripes has a very good Quick Start Guide, which also shows error highlighting.)

One of the less verbose proposed formats of textField is:

<g:textField bean="user" field="username" />

Implemented Solution

I found that implementing a quick version of this is surprisingly easy in Grails, it only takes for a few statements. Here is the code:

import org.codehaus.groovy.grails.plugins.web.taglib.FormTagLib

// file: project/grails-app/taglib/MyTagLib.groovy
class MyTagLib {
    // tagname "myTextField" within the "g" namespace
    def myTextField = {attrs ->
        // If a controller returned the bean, and the field has an error,
        // then "errors" will be returned as HTML class, otherwise the class will be empty.
        attrs.class = hasErrors(bean:attrs.bean, field:attrs.field, 'errors')
        // Retrieves the field value of the given bean to be rendered in the view.
        // Note: specify the bean and not the bean name. So "${user}" instead of "user"
        attrs.value = fieldValue(bean:attrs.bean, field:attrs.field)
        // Required for textField taglib. attrs.name is a keyname of the params map
        attrs.name = attrs.field
        // renders the HTML tag
        out << new FormTagLib().textField(attrs)
    }
}

Usage

<g:myTextField bean="$user" field="name" />

And ofcourse some CSS to highlight the error in a color. This can be put in the HTML head (or better, a seperate CSS file) :

<style type="text/css">
   .errors {
      background-color: red;
   }
</style>

Grails and existing Java Hibernate DAO’s

Sunday, July 20th, 2008

If you have some existing Java Hibernate entity classes (outside Grails), you only have to add one line in Datasource config, and you can use them immediately. However, if you have some exising POJO (Plain Old Java Object) Hibernate DAO’s (classes that implement a Data Access Object pattern), you’ll have to do some additional steps to make it a bit suitable.

(The solution described in this post can also be handy when you need data access on places where GORM is NOT available. GORM not available? Yes, GORM is not fully available when you access collections via a taglib that is accessed via a Sitemesh layout. (A scenerio that isn’t rare.) (Should be considered as a bug?) In that case you will get a lazily initialize a collection error. If you use HibernateUtil, you can get around this by just opening new session yourself.)

Existing Hibernate entities and GORM

You can use existing Hibernate Java entities directly in Grails. The only thing that you’ll have to configure is:

  1. define mappings in hibernate.cfg.xml
  2. set GrailsAnnotationConfiguration as configClass in DataSource.groovy

For example:
webapp/grails-app/conf/hibernate/hibernate.cfg.xml :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <mapping class="myPackage.Product"/>
        <mapping class="myPackage.Customer"/>
        <mapping class="myPackage.Supplier"/>
    </session-factory>
</hibernate-configuration>

webapp/grails-app/conf/DataSource.groovy :

import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration

dataSource {
    configClass = GrailsAnnotationConfiguration.class
    pooled = true
    driverClassName = "com.mysql.jdbc.Driver"
    url = "jdbc:mysql://localhost/mydb"
    username = "myusername"
    password = "mypass"
    dbCreate = "create" // one of 'create', 'create-drop','update'
    dialect= org.hibernate.dialect.MySQLInnoDBDialect
}
hibernate {
    cache.use_second_level_cache=true
    cache.use_query_cache=true
    cache.provider_class='com.opensymphony.oscache.hibernate.OSCacheProvider'
}

Now you can put your existing Hibernate java entities in webapp/src/entities (or any other package), and they will work immediately and have GORM functionality.
For example, in the Grails controller classes, you can direcly use Product.get(100) (to get a Product instance that has id 100). Hibernate sessions and transactions are created/invoked automatically.

Exising Hibernate DAO’s

If you don’t need any GORM functionality and you don’t want Grails to touch sessions, then you can use your existing unaltered full hibernate.cfg.xml.

However, if you have some POJO DAO’s that use the HibernateUtil helperclass, you will have to do some additional steps to make it a bit suitable. (In this example, I use the configurations above.)

By default Grails injects a SessionFactory
First, your DAO’s will need a HibernateSession to perform work. By default Grails injects a SessionFactory into Grails controllers that have a “sessionFactory” variable defined. So the following controller will automatically have a SessionFactory available:

import org.hibernate.*;

class ProductController {
    // This one will be injected
    SessionFactory sessionFactory

    def index = {
        Session session = sessionFactory.getCurrentSession()
        println session.createQuery("from Product").list()
    }
}

(You can also use Gorm in this controller example and don’t use the SessionFactory yourself, but this just to show that a SessionFactory will be injected.)

HibernateUtil used by the DAO’s
In the example, the DAO’s use HibernateUtil to get a SessionFactory. By default HibernateUtil create a SessionFactory itself, but the SessionFactory provided by Grails is needed instead, so we alter HibernateUtil slightly:

package persistence;

import org.hibernate.*;

public class HibernateUtil {
    private static SessionFactory sessionFactory;

    public static SessionFactory getSessionFactory() { return sessionFactory; }
    public static void setSessionFactory(SessionFactory sf) { sessionFactory = sf; }

    public static void shutdown() { sessionFactory.close(); }
}

Set SessionFactory for HibernateUtil
We want HibernatUtil to be ready with a SessionFactory after booting, so we configure HibernateUtil during the bootstap. We alter webapp/grails-app/conf/BootStrap.groovy to:

import persistence.HibernateUtil
import org.springframework.web.context.support.WebApplicationContextUtils

class BootStrap {

     def init = { servletContext ->
        def ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)
        def sf  = ctx.getBean('sessionFactory')
        HibernateUtil.setSessionFactory(sf)
     }

     def destroy = {
         HibernateUtil.shutdown()
     }
}

Now the DAO’s can use HibernateUtil.getSessionFactory().getCurrentSession() to get a HibernateSession.

Grails & Jetty with multiple contexts

Saturday, July 12th, 2008

A webapp usually contains both dynamic resources (scripts, config files, html files) and static resources (jpg, zip files, data etc). These resources can be deployed all together as one package, but when you have a lot of static resources, you usually want them to be seperate from the dynamic resources. Reasons might be that you have that much static resources that it will slow down deployment or testing when packaged as a single unit, or you might want static resources to be served by a seperate service to improve performance, or you might want them to be in seperate filesytem hierarchy because the static resources might also be needed outside the webapp. In this post I describe two methods to solve the problem of seperating dynamic from static resources when using Grails and Jetty.

The methods are tested using:

  • Grails 1.0.3
  • Jetty 6.1.4 (default Jetty for Grails 1.0.3)
  • Static Resources 0.5 plugin

Method 1: Static Resources plugin & symbolic links

The Grails Static-Resources plugin is designed to separate dynamic from static resources.

Install:

  1. open a cmd/shell prompt and go into the directory of your Grails webapp project. I will call this directory <myapp-grails-project-base>.
  2. type: grails install-plugin static-resources
    The plugin will now be installed for the current webapp only.

I’ll show by example how the Static-Resources plugin works. Suppose you have a website called example.com and a webapp called myapp, then the webapp is available at http://example.com:8080/myapp/. When you have the plugin installed, everything under the /static/ (filesystem directory) will be available under http://example.com:8088/ when run in dev environment. Notice that port 8088 is used instead of port 8080. The plugin does this by starting a NanoHTTPD, which is a lightweight single class Java HTTP server. The plugin calls this the resource server.
When you go to http://example.com:8088/, you will get a directory listing of all the files located in the static directory, so you can start using them and linking to them, but there is a better way (read on).

If you put a pdf file at <myapp-grails-project-base>/static/archive/catalog2005.pdf (filesystem) then it will be available automatically and directly at http://example.com:8088/archive/catalog2005.pdf in a dev env.
You can hardcode links to http://example.com:8080/archive/catalog2005.pdf manually in the view, but you can also use the plugins dedicated resourceLinkTo tag for this. For the pdf link, this tag is used as: <g:resourceLinkTo dir=”archive” file=”catalog2005.pdf”/>

When running in prod env instead of dev, the resourceLinkTo tag will link to the URI /resources/archive/catalog2005.pdf instead of http://example.com:8080/archive/catalog2005.pdf. And this time it won’t start a NanoHTTPD server, it only changes the link. So in a prod env, you have to map /resources/ to <myapp-grails-project-base>/static/ yourself, in whatever production HTTP server you are using. You could do this in Tomcat 6 by putting something like <Context docBase=” <myapp-grails-project-base>/static/” path=”/resources”/> in the host element of server.xml, or better, in context.xml.

If you don’t want your resources to be located in the <myapp-grails-project-base>/static/ directory, you can use symbolic links in the static directory, and map them to elsewhere. Note that symbolic links are not only available on POSIX systems (Linux etc), but also on Windows systems using special tools. (I’m not talking about Windows Shortcuts, but Windows symbolic links, hard links or junctions.)

Another way is to change the static directory location by modifying <myapp-grails-project-base>\plugins\static-resources-0.5\grails-app\services\ExternalResourceServerService.groovy.

Method 2: a second Jetty webapp context

The static resources method (described above) doesn’t have a complete built-in solution for a production environment; you have to make/map the /resources/ URI yourself.

If want you to use Jetty in both dev and prod env, or if you want to have a separate static resources directory without using the Static-Resources plugin, then read on:

1) Open %GRAILS_HOME%\scripts\RunApp.groovy
2) change

    target( configureHttpServer : &quot;Returns a jetty server configured with an HTTP connector&quot;) {
    def server = new Server()
    grailsServer = server
    def connectors = [new SelectChannelConnector()]
    connectors[0].setPort(serverPort)
    server.setConnectors( (Connector [])connectors )
    setupWebContext()
    server.setHandler( webContext )
    event(&quot;ConfigureJetty&quot;, [server])
    return server
}

to

    target( configureHttpServer : &quot;Returns a jetty server configured with an HTTP connector&quot;) {
    def server = new Server()
    grailsServer = server
    def connectors = [new SelectChannelConnector()]
    connectors[0].setPort(serverPort)
    server.setConnectors( (Connector [])connectors )
    setupWebContext()

    server.addHandler( webContext )
    WebAppContext resourceContext = new WebAppContext(&quot;D:/myapp-grails-project-base/static&quot;, &quot;/resources&quot;)
    server.addHandler(resourceContext);

    event(&quot;ConfigureJetty&quot;, [server])
    return server
}

Now, everything under D:/myapp-grails-project-base/static will be mapped to http://…../resources, in both dev and prod evironment, and will be served seperate from the webapp.

A drawback of placing this in RunApp.groovy is that every Grails app will have a /resources context running next to it.

Note that Jetty 5 and earlier versions of Grails probably needs different code.

Edit:
Grails maintains a temperary directory for scripts in %userhome%\.grails\1.0.3\scriptCache. I you find that modifications aren’t visible, then try deleting that directory.

More info: