Bhagwat Kumar « Intelligrape Groovy & Grails Blogs
Subscribe via E-Mail:

Bhagwat Kumar

http://www.IntelliGrape.com

Groovy, Grails, Java, J2EE, Open Source, Agile enthusiast , JQuery lover

Posts by Bhagwat Kumar:

  • uploading multiple files with same name

    18 Nov 2011 in File Upload& Grails

    A good binding feature in grails is that when you have multiple input fields with same name, they are available as a list in params. But this does not hold with html file input fileds. If you have multiple file input fields with same name, params.fieldName will not return a list but the first input field with name fieldName. This is due to using fileMap attribute of request object. Here is the relevant part of GrailsParameterMap class(I suspected this class because of params.getClass() returned GrailsParameterMap) :

        GrailsParameterMap(HttpServletRequest request) {
    	//.............................
            if (request instanceof MultipartHttpServletRequest) {
                def fileMap = request.fileMap
                for (fileName in fileMap.keySet()) {
                    requestMap.put(fileName, request.getFile(fileName))
                }
            }
    	//.............................
        }
    

    Due to above implementation, If you have three file input fields with name familyPics, only the first one will be available via params.familyPics of type CommonsMultipartFile.

    In one of the mail thread(links at the end of the blog), I got to know that grails uses Spring 3.0 starting from grails version 1.2 which supports multiFileMap attribute in request object. Using this attribute you can access multiple files from inputs with the same name (or that uses the HTML5 multiple attribute). So if the implementation is changed to something like :

       GrailsParameterMap(HttpServletRequest request) {
    	//.............................
            if (request instanceof MultipartHttpServletRequest) {
                        def multipleFileMap = request.multiFileMap
    /* instead of using fileMap. However this map value is always a list even if there is only one file input for a name */
                        multipleFileMap.each {fieldName, files ->
                            if (files.size() == 1) {
                                requestMap.put(fieldName, files.first())
    /* Make this available as a single element instead of list, if the user wants he can use params.list('fieldName') for list version */
                            } else {
                                requestMap.put(fieldName, files)
                            }
                        }
            }
    	//.............................
        }
    

    Then if there are three file input fields with name familyPics, then params.familyPics will return a list of CommonsMultipartFile objects. If there is only one file input field with name profilePic then params.profilePic will return an object of type CommonsMultipartFile and params.list('profilePic') will return a list of CommonsMultipartFile objects.

    This feature can be added using Groovy/Grails MetaProgramming(Until grails is updated for this feature). However I went with Grails Filter solution. Create/update a filter with this entry :

            multipartFileSupport(controller: '*', action: '*') {
                before = {
                    if (request instanceof MultipartHttpServletRequest) {
                        def multipleFileMap = request.multiFileMap
                        multipleFileMap.each {fieldName, files ->
                            if (files.size() == 1) {
                                params.put(fieldName, files.first())
                            } else {
                                params.put(fieldName, files)
                            }
                        }
                    }
                }
            }
    

    Now inside any controller/action you can access statements like(even grails auto binding will work fine) :

    /* Suppose there is a file input field with name profilePic */
    CommonsMultipartFile profilePic=params.profilePic
    List<CommonsMultipartFile> profilePicAsList=params.list('profilePic')
    
    /* Suppose there are three file input fields with same name familyPics */
    List<CommonsMultipartFile> familyPics=params.familyPics
    

    Hope this feature will be available soon in grails without having to write filters or doing meta programming.

    Helpful links :

    http://stackoverflow.com/questions/3710232/how-to-iterate-over-uploaded-files-in-grails

    https://jira.springsource.org/browse/SPR-3964

    http://forum.springsource.org/showthread.php?44632-CommonsMultipartResolver-Uploading-many-files-with-same-html-name

    ~~~~~~Cheers~~~~~~~
    Bhagwat Kumar
    bhagwat(at)intellligrape(dot)com

    • Share/Bookmark
  • Validating emails, urls and date using Java API

    14 Nov 2011 in Grails& Groovy

    Recently I was looking for a programmatic way for validating data against well known validation e.g. email and date. I have to use them inside custom validator and sometimes in controller/action. Creating Command objects for validating was not suitable in my case(overkilling solution). Writing/looking for regular expression was another solution. I found a special class GenericValidator in org.apache.commons.validator package (commons-validator jar file, bundled with grails jars) . The class has many useful static methods for validating data. e.g. for validating email, url, credit card, date etc. Here is the sample code for validation using GenericValidator class:

    import org.apache.commons.validator.GenericValidator
    
    assert GenericValidator.isEmail("bhagwat@intelligrape.com")  //valid email
    assert !GenericValidator.isEmail("bhagwatintelligrape.com")  // invalid email
    
    assert GenericValidator.isUrl("http://www.intelligrape.com")  //valid URL
    assert !GenericValidator.isUrl("www.intelligrape.com") //invalid URL
    
    assert GenericValidator.isCreditCard("4111111111111111") // valid visa card number
    assert !GenericValidator.isCreditCard("4111111111111112") // invalid visa card number
    
    assert GenericValidator.isDate("2011-12-30", "yyyy-MM-dd", true) // valid date(last argument for checking strict)
    assert GenericValidator.isDate("2011-02-28", "yyyy-MM-dd", true) // valid date - 28th Feb
    assert !GenericValidator.isDate("2011-02-29", "yyyy-MM-dd", false) // invalid date - 29th Feb 2011
    

    For other useful methods and their details follow the link :
    http://commons.apache.org/validator/apidocs/org/apache/commons/validator/GenericValidator.html.

    In addition to GennericValdator class there are separate classes for validating date, email, credit card, ISBN validator in the org.apache.commons.validator package viz. DateValidator, CreditCardValidator, EmailValidator, ISBNValidator, UrlValidator and so on. Here is the sample code for using DateValidator class.

    import org.apache.commons.validator.DateValidator
    
    DateValidator dateValidator=DateValidator.getInstance()
    assert dateValidator.isValid("11-02-28", "yy-MM-dd", true)
    assert !dateValidator.isValid("11-02-29", "yy-MM-dd", true)
    

    Hope it helps you.

    Bhagwat Kumar
    bhagwat(at)intelligrape(dot)com

    • Share/Bookmark
  • Playing with call() using Groovy Metaprogramming

    15 Sep 2011 in Groovy

    In groovy you can use "()" with any groovy object which in turn evaluates to invocation of call() method on that object.
    For example, the following are valid Groovy statements :

    List myList=["one", "two"]
    myList()
    10()
    500 6+5
    [name:"Bhagwat", profession:"Software engineer"] name
    

    Obviously they will throw Runtime exception (MissingMethod/MissingProperty) instead of compilation error. Using meta programming support you can make them happen even though they are Java objects.

    Think of this sample groovy code :

    List myList=["Apple", "Banana", "Orange"]
    myList()
    

    After executing the above code you will get an exception : “No signature of method: java.util.ArrayList.call() is applicable for argument types: () values: []“.

    Here myList() statement is equivalent to myList.call(). This gives us a clue that we can catch method calls like above. Lets inject the call method using groovy metaprogramming in List interface :

    List.metaClass.call={index->
     delegate.getAt(index) 	//delegate[index]
    }
    
    /* Now the following statements work : */
    List myList=["Apple", "Banana", "Orange"]
    
    myList[1]		// Using the overloaded operator [] bygroovy
    
    myList.call(1) 	// index will be 1 ; will return "Banana"
    myList(1)		//  recall the syntax used in Microsoft VB.net to access Array
    myList 1		// you can omit parenthesis if there is at least one argument
    

    We can move one step ahead by passing a Map to the closure to make the method having named parameters :

    List.metaClass.call={Map namedArgs->
        namedArgs.each{
    	delegate[it.key]=it.value
        }
    }
    
    List demo=[]
    demo(0:"Java", 1: "Groovy", 2: "Scala")
    
    demo(0) // "Java"
    demo(1) // "Groovy"
    

    When I was learning computer science, I used to write statements like :

    x=5
    println 5+2(5+x(4)/2)  // should be 35
    

    But that always threw an exception, can you make this work as expected? Give it a try if you really think this blog taught you something. Compare your solution here http://groovyconsole.appspot.com/script/557002.

    Hope this let you think in groovy way.

    Bhagwat Kumar
    bhagwat@intelligrape.com

    • Share/Bookmark
  • Grails domain class and DDL sql file using schema-export

    04 May 2011 in Database& Grails

    While debugging a domain and its database schema I found an interesting grails command line Gant script: schema-export.

    One of the great Grails command line Gant script to generate SQL scripts(DDL) which is executed against your database to model your grails domain. You can control the environment and the output file to generate the SQL script. Without going into much details lets see an example. Here is the only domain in my grails project :

    Class Person{
    	String name
    	Integer age
    
    static hasMany=[emails:String]
    }
    

    And here is the script I used

    grails schema-export
    

    Here is the content of generated DDL file which is created in project’s target folder with name ddl.sql by default(obviously data source settings of Development environment).

    alter table person_emails drop foreign key FKADA31081669C99A9;
    drop table if exists person;
    drop table if exists person_emails;
    create table person (id bigint not null auto_increment, version bigint not null, name varchar(255) not null, primary key (id)) ENGINE=InnoDB;
    create table person_emails (person_id bigint, emails_string varchar(255)) ENGINE=InnoDB;
    alter table person_emails add index FKADA31081669C99A9 (person_id), add constraint FKADA31081669C99A9 foreign key (person_id) references person (id);
    

    You can also specify the environment (e.g. prod) whose data source settings will be used to generate DDL and output to a different file(e.g. prodDDL.sql) like :

    grails prod schema-export prodDDL.sql
    

    Full documentation ca be found here schema-export.

    Hope it encourage you to read the Grails documentation in spare time to find and share hidden features of grails.

    ~~~~Cheers ~~~~

    Bhagwat Kumar
    bhagwat(at)intelligrape(dot)com

    • Share/Bookmark
  • Grails taglib and JavaScript file

    We use internationalization feature in grails using message tag in GSP pages. However arbitrary Groovy/Grails (e.g. tags) code can not be used in JavaScript as they are not executed on server side. To overcome this I used the following way :

    Declare a JSON object in js file or any where else so that this object is global one. Create a global JavaScript function that can populate this JSON object. Here is the sample code:

    
    var i18nmessages={};
    
    function updateConfigurationMap(newConfigurationMap) {
    	for(key in newConfigurationMap){
    		i18nmessages[key] = newConfigurationMap[key];
    	}
    /*
    	//or in jQuery way
    	jQuery.each(newConfiguration, function(key, val) {
    		i18nmessages[key] = val
    	});
    */
    }
    

    Now you can write code like below inside HTML head tag in GSP pages to populate the i18nmessages JSON map:

    
    <script type="text/javascript">
    
     updateConfigurationMap({
    
       noResultError : '${message(code:'project.noResultError'')}.encodeAsHTML()',
    
       rangeError : '${message(code:'project.rangeError', args:[50, 100]).encodeAsHTML()}',
    
       ajaxCallUrl : '${createLink(controller:'myController', action: 'myAction')}',
    
       deleteImagePath : '${resource(dir:'images', file:'myimage.png')}'
    
     });
    
    </script>
    

    After execution of the above GSP code considering that the JavaScript code written above has executed, you can use messages like this in javascript :

    
    function findResult(){
    	alert("Error occurred during processing : "+i18nmessages.noResultError)
    }
    
    function getRemoteData(dataToSend){
           /*  note that you can not use createLink grails tag here  */
    	jQuery.get(i18nmessages.ajaxCallUrl+"?"+dataToSend, function(response){
    		// Process response here.
    	})
    }
    
    function insertDeleteImage(){
           /* As you can not use resource tag of grails here */
    	jQuery('selector').append("<img src='"+ i18nmessages.deleteImagePath +"' />")
    }
    

    Obviously there is a drawback with this approach that the JavaScript for setting messages can not be cached in browser. But the advantage is that you are free to use arbitrary Server side code to generate messages. As you have noticed in above code snippet the URL for ajax call and image paths generated using Grails tags can not be used inside the js files.

    Another idea will be to create separate js files name ending with language suffix(e.g. *-en.js, *-sv.js etc) for each language your app support. Populate the i18nmessages there. Use appropriate js file depending on the request locale(e.g. session.'org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE'). This way you can enable caching of js files in browser but you are limited to messages with static content only.



    Please share your ideas how you solved this situation.


    Cheers!
    ~~Bhagwat Kumar~~
    bhagwat(at)intelligrape(dot)com

    • Share/Bookmark
  • Externalize and reload grails configuration dynamically

    15 Oct 2010 in Grails& Groovy

    Configuration file plays great role in grails. You can store application specific configuration at one place. One of the grails goodies is that you can externalize configuration file i.e. store them at a location so that it is not packed with the war file.

    Here is the part of Config.groovy that describes how to specify external configuration file :

    // configuration files can either be Java properties files or ConfigSlurper scripts.
    //Note that the file whose path is specified below is not included in war file.
    
    grails.config.locations = ["file:${userHome}/.myConfigurations/${appName}-config.groovy"]
    

    Externalizing the configuration helps us to change the configuration without re-creating the war file. But the problem I faced was changes to this external configuration file was not reloaded by grails automatically. I found the code to reload the configuration in Grails Quartz plug-in source code. Here is the code snippet.

            def config = ConfigurationHolder.config
            GroovyClassLoader classLoader = new GroovyClassLoader(getClass().classLoader)
    
            // merging default Quartz config into main application config
            config.merge(new ConfigSlurper(GrailsUtil.environment).parse(classLoader.loadClass('DefaultQuartzConfig')))
    

    However the code is reloading configuration from a groovy class(it should be in the class-path) that I could not use in my use case.

    Doing some googling and thanks to Himanshu for useful code snippets, I found the constructor that accepts String . I used the following code to merge the changed external configuration file with the configuration of running application :

    def config = ConfigurationHolder.config
    def locations = config.grails.config.locations
    
    locations.each {
    	String configFileName = it.split("file:")[1]
    	config.merge(new ConfigSlurper().parse(new File(configFileName).text))
    }
    //above code iterates over all the external config files and
    //merges them with the running application configuration
    

    I wrote the above code inside a controller-action. Now whenever I change the external configuration file I simply hit the URL of the controller-action and the changes take effect that point onward. You can also use Grails Console plug-in that lets you execute groovy code from the running application or use Grails Quartz Job to periodically reload the external configuration.


    Hope this helps you !


    Bhagwat Kumar
    bhagwat(at)intelligrape(dot)com

    • Share/Bookmark
  • Asynchronous behavior of AJAX

    14 Sep 2010 in Javascript/Ajax/JQuery

    Ajax (shorthand for Asynchronous JavaScript and XML) is used to retrieve data from the server asynchronously without interfering with the display and behavior of the existing page. Forgetting this asynchronous behavior will produce incorrect result if it depends on the response from Ajax call.

    Lets take an example(I am using JQuery to illustrate the example). Here is a JavaScript function to perform server side check of the form. Depending on the response of Ajax call the function either submits the form or does nothing.

    function submitForm(){
    	var isFormValid=false;
    	var dataToBeSent=$('form').serialize();
    	$.get(url, dataToBeSent, function(result){
    		isFormValid=result;
    	})
    	if(isFormValid){
    		$('form').submit();
    	}
    }

    The statement $('form').submit() will never be called irrespective of the result (AJAX call response). After executing $.get statement it will execute the next statement  if(isFormValid) without waiting for the statement isFormValid=result inside the callback function to be executed.

    There exist a dirty solution for the problem : using JavaScript sleep API. But how long you are going to halt the execution of JavaScript code. You are back to the same problem of getting the incorrect behavior.

    One good solution is to make the $.get call synchronous by making changes to the global AJAX configuration like :

    $.ajaxSettings.async=false;

    or using calls like :

    $.ajax({type: "GET", url: url, data: dataToBeSent, success: function(){
    		isFormValid=result;
    	}
    });

    Now the if(isFormValid) statement will be executed only after the $.ajax statement has completed its execution. However this approach has its own drawback. Obvious one is the execution of JavaScript halts until it receives the response.

    However the better solution  is to execute $('form').submit() inside the callback function like :

    $('submitButton').click(function(){
    	var isFormValid=false;
    	var dataToBeSent=$('form').serialize();
    	$.get(url, dataToBeSent, function(result){
    		isFormValid=result;
    	if(isFormValid){
    		$('form').submit();
    	}
    	})
    return false;  // Needless if the button is not a submit button
    })

    return false statement at the end of the function prevents the form from being submitted. Now the form submission code will be executed only after the response to $.get statement is true.

    There exist JQuery plugins (e.g. JQuery validation plugin) for doing form validation in a better way where you get support for server side validation also. But the case discussed above was to make you understand the asynchronous behavior of AJAX calls.

    Hope this helps you while using Ajax.  :)

    Cheers,
    ~~Bhagwat Kumar~~
    bhagwat(at)intelligrape(dot)com

    http://www.intelligrape.com

    • Share/Bookmark
  • Criteria Query and pagination params

    14 Jul 2010 in Grails

    I have been using the following code to get paginated result and the total number of results returned irrespective of the pagination params.

     def result=SampleDomain.createCriteria().list(){
    // multiple restrictions
       maxResults(params.max)
       firstResult(params.offset)
    } // Return type is ArrayList
     
    Integer  totalResult=SampleDomain.createCriteria().count(){
    // multiple restrictions
    // maxResults(params.max)
    // firstResult(params.offset)
    }

    Clearly duplicating the same closure except for the pagination restrictions was not a good solution.

    After a little googling and reading mailing lists I got the solution. Passing pagination params to createCriteria.list() returns result of type PagedResultList which provides many useful methods. The getTotalCount() method of PagedResultList class returns the actual number of results returned irrespective of the pagination restrictions(maxResults and firstResult). Also the result contains only those records fulfiling maxResults and firstResult restrictions.

    def result=SampleDomain.createCriteria().list(max:params.max, offset:params.offset){
    // multiple/complex restrictions
       maxResults(params.max)
       firstResult(params.offset)
    } // Return type is PagedResultList

    Thanks to all the active users of Grails mailing list.

    Here are few useful links:
    http://www.pubbs.net/grails/200912/2269
    http://www.grails.org/doc/1.0.x/api/grails/orm/PagedResultList.html
    http://jira.codehaus.org/browse/GRAILS-2672

    Bhagwat Kumar
    bhagwat(at)intelligrape(dot)com

    • Share/Bookmark
  • Running multiple instances of a quartz job dynamically

    14 Jun 2010 in Grails

    I have been facing a problem of running configurable number of instances of the same job to consume the traffic that was varying over time. In order to dynamically create an instance of a job and run it immediately, I googled and found some interesting facts like each trigger is fired with a new instance of the job. We can create any no. of trigger for a job.

    Here is a sample code to dynamically create a new trigger for a job and scheduling it to run immediately…

    //import org.codehaus.groovy.grails.plugins.quartz.GrailsTaskClassProperty as GTCP
    //import org.codehaus.groovy.grails.plugins.quartz.GrailsTaskClass
    //import org.quartz.Trigger
    //import org.quartz.SimpleTrigger
    // def quartzScheduler /*inject qartzScheduler bean*/
    
    GrailsTaskClass tc=grailsApplication.taskClasses.find{it.fullName=='myPackage.MySampleJob'}
    // fully packaged name of the Job. There may be better way to find the Grails Job.
    
    String triggerName='mytrigger'+System.currentTimeMillis() // unique trigger name
    
    Trigger trigger = new SimpleTrigger(triggerName,
                            GTCP.DEFAULT_TRIGGERS_GROUP,
                            tc.getFullName(),
                            tc.getGroup(),
                            new Date(),
                            null, 0, 1000)
    /*
    Created a simple trigger using constructor :
    
    SimpleTrigger(String name, String group, String jobName, String jobGroup, Date startTime, Date endTime, int repeatCount, long repeatInterval)
    */
    
    trigger.jobDataMap.putAll(['triggerName':triggerName, 'myData':1000]) 
    
    /*
    passing map to the trigger that can be accessed inside execute() method of the job using context.mergedJobDataMap
    */
    
    quartzScheduler.scheduleJob(trigger) //execute the job for this trigger.
    

    The above sample code can be used to create any number of triggers that are executed with a new instance of the specified Quartz Job.

    Helpful Links :

    1. http://www.quartz-scheduler.org/docs/api/1.8.0/org/quartz/SimpleTrigger.html
    2. Quartz Plugin source code(QuartzGrailsPlugin.groovy)

    Hope it helps you.

    ~~~~Bhagwat Kumar~~~~
    bhagwat@intelligrape.com
    IntelliGrape Software

    • Share/Bookmark
  • List of fields in error of a domain instance

    29 Apr 2010 in Grails& Groovy

    I have been working with domain and command object validation. I needed to get all the fields in error as a list so that I can display a single line error message like : please enter valid values in the following fields- filed1, field2. Another use case was to check the list of fields for error. Here is the code to get list of errorneous fields:

    List fieldsInError = domainInstance.errors.allErrors.collect {it.properties['field']}
     
    // Generate error message
     
    String errorMessage= "Enter valid values in fields - ${fieldsInError.join(', ')}"
     
    // check if both field1 and field2 are in error
     
    if(fieldsInError.containsAll(['field1', 'field2']){
    	// Both the fields are in error irrespective of other fields
    }

    Hope it helps you guys too.

    ~~~~Bhagwat Kumar~~~~
    bhagwat@intelligrape.com
    IntelliGrape Software

    • Share/Bookmark