@Validateable – thank you ….

Today I learn about cool feature of Grails, that I missed or maybe it appear recently in documentation. As you probably know, I am talking about @Validateable annotation. Just mark your class with @Validateable and all it instances will provide validation mechanisms, like domain classes and command objects.

Where it can be use? Good example is service level, where the only object that provide such functionality is domain class and initialized command object will be simple POGO, without validation functionality.

Grails 1.1.1 and plugin release problems

Creating plug-in in Grails is easy, but it releasing is not. When I was trying to release my Burning Image plug-in I was hit with two problems. First was "svn: Authentication required" :

Importing project to https://svn.codehaus.org/grails-plugins/grails-burning-image. Please wait...
org.tmatesoft.svn.core.SVNAuthenticationException: svn: Authentication required for ' grails-plugins primary Subversion repository

To work around this problem just add file setting.groovy into your ~/.grails/ directory and add this lines:

grails.plugin.repos.discovery.grailsplugins="https://svn.codehaus.org:443/grails-plugins"
grails.plugin.repos.distribution.grailsplugins="https://svn.codehaus.org:443/grails-plugins"

Now you should be asked about yours credentials after executing:

grails release-plugin "-repository=grailsplugins"

Second problem was error:

Error executing script ReleasePlugin: groovy.lang.MissingMethodException: No signature of method: _PluginDependencies_groovy$_run_closure2.doCall() is applicabl
e for argument types: (java.lang.Boolean, java.lang.String) values: [true, distribution]
gant.TargetExecutionException: groovy.lang.MissingMethodException: No signature of method: _PluginDependencies_groovy$_run_closure2.doCall() is applicable for a
rgument types: (java.lang.Boolean, java.lang.String) values: [true, distribution]
        at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:331)
        at gant.Gant$_dispatch_closure6.doCall(Gant.groovy:334)
        at gant.Gant$_dispatch_closure6.doCall(Gant.groovy)
        at gant.Gant.withBuildListeners(Gant.groovy:344)
        at gant.Gant.this$2$withBuildListeners(Gant.groovy)
        at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
        at gant.Gant.dispatch(Gant.groovy:334)
        at gant.Gant.this$2$dispatch(Gant.groovy)
        at gant.Gant.invokeMethod(Gant.groovy)
        at gant.Gant.processTargets(Gant.groovy:495)
        at gant.Gant.processTargets(Gant.groovy:480)
Caused by: groovy.lang.MissingMethodException: No signature of method: _PluginDependencies_groovy$_run_closure2.doCall() is applicable for argument types: (java
.lang.Boolean, java.lang.String) values: [true, distribution]
        at ReleasePlugin$_run_closure3.doCall(ReleasePlugin.groovy:75)
        at ReleasePlugin$_run_closure1.doCall(ReleasePlugin.groovy:42)
        at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:324)
        ... 10 more

It occurs when I try to execute release plug-in command like this:

grails release-plugin -repository=grailsplugins

Just add " like previously and all should go smoothly.

Burning Image Grails plugin

Today I ended my work over my first Grails plug-in: Burning Image. This simple plug-in for images manipulation provides two types of image scaling, and allows to watermark image. In future i want to add crop option and maybe rounding image corner. If you looking for some more informations or you want to try it you could fine it Google code repository.

Groovy closure – will it work?

Lets say we have Groovy class like this:

 
class Foo {
 
    def bar(myClosure) {
        myClosure(this)
    }
 
   private def bas(myName) {
       println "hello from ${myName}"
  }
}
 

and I am wonder what should happen if I execute this line of code:

 
new Foo().bar {
    it.bas("Steve Zissou")
}
 

Should it throw exception that I want execute private method? But this method is execute inside Foo object instance. So, should it print

hello from Steve Zissou

Unfortunately question is still open because Groovy private method / field bug. Or maybe is time to start using Scala and Lift?

    Grails multiple select binding

    When first time I try to use html select tag with multiple selection, I spent about 1h to figure "how to" because user guide is, hmmm, as is. So, there is my little example:

    Lets create domain objects:

     
    Author {
        String firstName
        String lastName
        static hasMany = [books:Book]
    }
     
     
    Book {
        String title
        static belongsTo = [author:Author]
    }
     

    Author form will contain select with books like this:

     
    <g:select optionKey="id" optionValue="title"  multiple="multiple" name="author.books" id ="author_books" from="${allBooks}" value="${authorInstance?.books*.id}"/>
     

    Multiple select binding to Author.books is now available.

    Prepare Grails hosting: Apache + Tomcat

    My last weekend I spent fighting with my VPS, try to configure it to host Grails applications on Tomcat server. Because there are some applications writed in PHP already on it, there is no way to bring tomcat on the front (port 80). Only way is to use Apache2 server as a proxy for Tomcat.

    Our work we start from installing Apache HTTP Server (v. 2.2):

     
    sudo apt-get install apache2
     

    Next step is to install Apache Tomcat. To avoid problems after apt-get tomcat installation, try this tutorial.

    Now we ready to download mod_jk that will act as bridge between two servers

     
    sudo apt-get install libapache2-mod-jk
     

    now configure it:

    /etc/apache2/mods-available/jk.conf

    JkWorkersFile      /etc/apache2/workers.properties
    JkLogFile          "|/usr/sbin/rotatelogs /var/log/apache2/mod_jk.log 86400"
    JkLogLevel         info
    JkLogStampFormat   "[%a %b %d %H:%M:%S %Y] "
    JkRequestLogFormat "%w %V %T"
    JkOptions          +ForwardKeySize +ForwardURICompat -ForwardDirectories
    

    /etc/apache2/workers.properties

    worker.list=tomcat6
    
    worker.tomcat6.type=ajp13
    worker.tomcat6.host=localhost
    worker.tomcat6.port=8009
    

    and create link to jk.conf:

     
    ln -s /etc/apache2/mods-available/jk.conf  /etc/apache2/mods-enabled/jk.conf
     

    Now we may configure virtual host in Apache:

     
    <virtualHost *:80>
        ServerName grailsappliaction.com
        LogLevel warn
        ServerSignature On
        JkMount /* tomcat6
    </virtualHost>
     

    and set tomcat host (conf/server.xml):

     
    ...
     
    <host name="grailsappliaction.com" appBase="/path/to/grails/app">
     
    ...
     

    Deploy your grails application in appBase as default (ROOT) application and restart Apache and Tomcat. Your application should be online now.

    You may removed this line from tomcat server.xml file, to avoid direct request on 8080 port:

     
    ...
     
    <connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000"  redirectPort="8443" />
     
    ...
     

    If there is better way to configure Apache and Tomcat, please let mi know.

    Grails custom NIP validation

    In my last project I worked on application where client was identified by NIP number. Validation of such number is depend on client country, so in my domain object representing client I used custom validator.

    First step was to create util objects that will calculate NIP control sum to check if number is correct. I created interface:

     
    interface CustomValidator{
        Boolean validate(value);
    }
     

    Next created validator for Polish Nip number:

     
    class NipValidatorPolish implements CustomValidator {
     
        def static final CHECK_SUM_DIVISION = 11
     
        def static final NIP_CORRECT_LENGTH = 10
     
        def weights = [6, 5, 7, 2, 3, 4, 5, 6, 7]
     
        Boolean validate(rawNip){
            if (!canBySumed(rawNip)){
                return false;
            }
     
            def checkSum = 0
            weights.eachWithIndex(){value, index -> checkSum += value * rawNip.getAt(index).toInteger()}
            return checkSum % CHECK_SUM_DIVISION == rawNip.toList().last().toInteger()
        }
     
        private Boolean canBySumed(String rawNip){
            clearNip.size() == NIP_CORRECT_LENGTH && rawNip.isNumber()
        }
    }
     

    and default NIP validator for all countries where we don't want to validate controll sum:

     
    class DefaultNipValidator implements CustomValidator {
        Boolean validate(rawNip){
            true
        }
    }
     

    Next, I created factory that produce specified validator depends on country code:

     
    class NipValidatorFactory {
        static CustomValidator produce(String countryCode){
            if (countryCode == CountriesCodes.Poland){
                return new NipValidatorPolish()
            }
            return new DefaultNipValidator()
        }
    }
     

    where CountriesCodes is container with countries iso codes. Finally we could use this in ours domain object :

     
    class Country {
        String name
        String countryCode
    }
     
    ...
     
    class Client {
        ....
        Country country
        String nip
        ...
        static constraints = {
            nip (nullable: true,
                validator: {value, object ->
                    return value ? NipValidatorFactory.produce(object.properties['country']?.countryCode).validate(value) : true
                }
           )
        }
    }
     

    Pimp my Grails Bootstrap

    If you want to depend data loaded in bootstrap from environment that application is currently running in, try this solution:

     
    import grails.util.GrailsUtil
    import org.codehaus.groovy.grails.commons.GrailsApplication
     
    class BootStrap {
     
        def init = { servletContext ->
            if(!envMapping[GrailsUtil.environment]){
                return
            }
     
            envMapping[GrailsUtil.environment]()
        }
     
        def destroy = {
        }
     
        def initTest = {
        ...
        }
     
        def initDev = {
        ...
        }
     
        def initProd = {
        ...
        }
     
        def envMapping = [(GrailsApplication.ENV_TEST):initTest,
                          (GrailsApplication.ENV_DEVELOPMENT):initDev,
                          (GrailsApplication.ENV_PRODUCTION):initProd]
    }
     

    Variable envMapping is on the end BootStrap class becouse in other case values in map were set as null (???).

    Grails upgrade from 1.0.4 to 1.1 problems – part 2

    If after upgrade to version 1.1 you will be hit by error like this:

     
    ...
    log4j:ERROR Could not read configuration file from URL [file:/C:/GrailsApp/web-app/W
    java.io.FileNotFoundException: C:\GrailsApp\web-app\WEB-INF\classes\log4j.properties
    ...
     

    go to web.xml template file in \src\templates\war\ directory of your project and delete lines:

     
    ...
    <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/classes/log4j.properties</param-value>
    </context-param>
    ...
     

    Grails file upload service

    In ours application we want to create service that will move uploaded file to specified directory. We want only to give name for the file, relative path to the directory where file should be stored, and of corse a file. This is simple example of sutch service:

     
    import org.springframework.context.*
     
    class FileUploadService implements ApplicationContextAware {
     
        ApplicationContext applicationContext
     
        boolean transactional = false
     
        def moveFile(file, folderRelativePath, fileName) {
            try {
                file.transferTo(new File(getAbsolutePath(folderRelativePath, fileName)))
                return true
             }catch(Exception exception){
                 log.error "File move error, ${exception}"
             }
            return false
        }
     
        private String getAbsolutePath(folderPath, fileName){
            "${applicationContext.getResource(folderPath)).getFile()}${File.separatorChar}${fileName}"
        }
    }
     

    We specify aboslute path for uploading file, to prevent problems with upload after application deploy on i.e. Tomcat server. To retrive absolute path we need application context, so we just implementing ApplicationContextAware interface.

    Now we are ready to use service in ours controller:

     
    ...
     
    def logo= request.getFile('logo')
     
    if(!logo.empty) {
        if (fileUploadService.moveFile(logo, 'relative/path/to/dir', 'myLogo.jpg')){
             render('file uploaded')
        }else{
             render('error while file upload')
        }
    }
     
    ...
     

Powered by WordPress with GimpStyle Theme design by Horacio Bella.
Entries and comments feeds. Valid XHTML and CSS.