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

roni

Posts by roni:

  • Grails: Get table name mapped to a domain

    19 Aug 2011 in Grails

    Hi guys,

    Recently while working on a project, I needed to get the table names associated with a particular domain as I needed to perform complex join operations on a particular table. The database that my team was working on was a legacy database. The domains that were created were mapped to particular tables to provide backward compatibility with the existing system’s database and, hence the table names were specified in the mapping closure. Now I needed a way to get the names of the tables that were associated with a particular domain.

    The SessionFactoryProxy can be directly used to get the table name associated with the domain. So the code is as follows:

    import org.hibernate.metadata.ClassMetadata
    import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder
    import org.codehaus.groovy.grails.commons.ApplicationHolder
    
    Class clazz = Class.forName("com.intelligrape.domain.Album", true, Thread.currentThread().getContextClassLoader())
    
    String mappedTable 
    
    def sessionFactory = ApplicationHolder.application.mainContext.getBean("sessionFactory")
    ClassMetadata hibernateMetaClass = sessionFactory.getClassMetadata(clazz)
    mappedTable = hibernateMetaClass.getTableName()
    
    println "Mapped table name: " + mappedTable
    

    Now the above modified code returns the table name associated with a domain.

    Cheers
    Ron
    roni[at]intellligrape[dot]com

    • Share/Bookmark
  • Batch update performance enhancements using SQL withBatch()

    05 Jul 2011 in Database& Grails& Groovy

    Hi guys,

    Recently as part of a project, I had to populate a SQLite database with large amounts of data pertaining to a number of classes requiring more than 5000 inserts and updates per class. I created a new SQLite database using Groovy’s Sql class. The initial strategy involved creating prepared statements and executing individual insert/update statements for each record that needed to be inserted/updated in the new SQLite database.

    However the process was taking longer than expected, and the cumulative time taken for the whole application to sync less than 30 classes was coming to be more than 2 minutes. This time taken was extremely high regarding the context of the application and was a real performance bottleneck. What I did notice was that the insert statements were identical for a particular class, disregarding the values that needed to be inserted. The same was the case with the update statements.

    After looking through the Sql GDK, I found a method named Sql.withBatch() that performs batch manipulation of records in a database. See the following code for illustration:

    Sql sql = Sql.newInstance("jdbc:sqlite:/home/ron/Desktop/test.db", "org.sqlite.JDBC")
    sql.execute("create table dummyTable(number)")
    Long startTime = System.currentTimeMillis()
    100.times {
         sql.execute("insert into dummyTable(number) values(${it})")
    }
    Long endTime = System.currentTimeMillis()
    
    println "Time taken: " + ((endTime - startTime)/1000)
    

    The output of the above code comes out to be 14.313 seconds. That is to execute 100 insert statements with only a single attribute, it would take around 15 seconds. The time taken to insert records is dependent on the number of records being inserted and increases exponentially. Clearly a performance bottleneck in any application involving batch inserts and updates.

    Let us consider the same code and the performance with the withBatch() closure.

    Sql sql = Sql.newInstance("jdbc:sqlite:/home/ron/Desktop/test.db", "org.sqlite.JDBC")
    sql.execute("create table dummyTable(number)")
    Long startTime = System.currentTimeMillis()
    sql.withBatch {stmt->
        100.times {
          stmt.addBatch("insert into dummyTable(number) values(${it})")
        }
        stmt.executeBatch()
    }
    Long endTime = System.currentTimeMillis()
    println "Time taken: " + ((endTime - startTime)/1000)
    

    The time taken with the above code comes out to be 0.103 seconds! A remarkable performance improvement over the conventional method of inserting records using the execute() method.

    The only drawback with using the withBatch() closure is that it does not allow prepared statements to be added to the batch. This limits the use of batch statements as we have to manually create insert or update statements.

    Cheers
    Ron
    roni[at]intelligrape[at]com

    • Share/Bookmark
  • Grails: Dynamically create instance of a POGO class

    15 Jun 2011 in Grails

    Hi guys,

    Recently on a project, I was creating a number of command objects to accept incoming parameters from a POST call from an iPhone with which I needed to sync data. I created a parent class for all command object classes to accept the common properties and created individual command object classes to accept any additional parameters.

    The use case was that the name of the command object class was being created dynamically from the URL. Now, when I was trying to create a new instance of a command object in a controller using the following code, I got a ClassNotFoundException to my utter surprise:

    DefaultGrailsApplication grailsApplication = ApplicationHolder.application.mainContext.getBean("grailsApplication")
    def clazz = grailsApplication.getClassForName("com.intelligrape.co.sync.SyncCO").newInstance()
    

    So I tried going through the Java style of fetching a class instance as follows:

    def clazz = Class.forName("com.intelligrape.co.sync.SyncCO").newInstance()
    

    Needless to say, I ran into the same problem again. After a lot of searching on the Internet and headbanging, I realized that classes in the src/groovy or src/java are not available to the grails class loader and they are loaded by the URLClassLoader which is a subclass of Java’s ClassLoader. Along with Uday’s help and a nabble post, I realized that I needed to use the three parameter Class.forName() method to create a new instance of a POGO or a POJO.

    I ended up using the following syntax which worked for me in this case:

    def clazz = Class.forName("com.intelligrape.co.sync.SyncCO", true, Thread.currentThread().getContextClassLoader()).newInstance()
    

    The above code gets a reference of the current executing thread’s root class loader to fetch an instance of all classes loaded in the current executing application. Documentation for the method is located here: Class.forName()

    I hope this helps any lost soul who has tried and failed at creating a new instance of a POGO.

    Cheers
    Ron
    roni[at]intelligrape[dot]com

    • Share/Bookmark
  • Star Rating Made Easy

    22 Feb 2011 in Grails

    Hey guys. Since this is my first blog, i don’t even know that the subject I’m going to write on is even bloggable. But here I go.

    As part of my responsibility in a recent project, I was asked to implement a taglib that could allow a user to rate his likeness for a movie using a rating scale that could use customised images for the rating scale. Most of us have seen such a a rating scale. A typical example would be such a scale.

    For this purpose, I created a tag library which had two tags named “resource” and “rating”. The tags are used as follows:

    <html>
        <head>
            <title>Welcome to Grails</title>
            <meta name="layout" content="main" />
    
            <script type="text/javascript" src="${resource(dir:'js', file:'jquery-1.4.4.js')}"></script>
        </head>
        <body>
    
        <igui:resources />
        <igui:rating units='20'
                     id="1"
                     backgroundImage="${resource(dir:'images',file:'combinedStar.png')}"
                     overImage="${resource(dir:'images',file:'star.png')}"
                     outImage="${resource(dir:'images',file:'star-outline.png')}"
                     controller='dummy'
                     action='dummy'
                     rating='5'/>
    
        </body>
    </html>
    

    The first tag <igui:resources> imports the necessary CSS stylesheets and javascript files needed. The second tag <igui:rating> is the real deal actually. This injects the actual HTML code into the page which is used to render the rating scale.  The following options are available in this tag:

    1. id: The ID of the object to be modified which is passed to the appropriate controller and action
    2. dynamic: Specifies whether the scale responds to user input, i.e. send the rating to the appropriate action. Defaults to false.
    3. units: Specifies total number of units out of which the rating is based
    4. rating: Specifies the current rating of the scale
    5. controller:Specifies the required controller
    6. action: Specifies the appropriate action
    7. overImage: Image to be displayed on mouse hover
    8. outImage: Image to be displayed when mouse moves out of the rating scale

    On clicking on the rating scale, an AJAX call is sent to the appropriate controller and action which updates the rating of the object. This rating is immediately visible on the page without refreshing any page. A quick look is given below.


    Work is still going on and I hope that when it is finished, we’ll have much more options and a more versatile taglib. Till then, take care.

    Ron

    roni[at]intelligrape[dot]com

    • Share/Bookmark