Grails: handling StaleObjectStateException and making executeUpdate transactional

March 6th, 2010

Recently I encountered a StaleObjectStateException which said “Row was updated or deleted by another transaction.” We were just updating multiple objects of the same domain inside a loop. So we used executeUpdate statement instead of myClass.save() method to update the records, which worked.

ReserveAccount.executeUpdate("update ReserveAccount set currentBalance=(:balance) where id=(:id)", [balance: currBalance, id: reserveAccount.id])

Later we also needed to update multiple objects of the same domain with same values. But grails executeUpdate statement doesn’t support list as a parameter. So here on the mailing list I found the solution

AccountTransactionStatus.withSession {session ->
      session.createQuery("""update AccountTransactionStatus t set t.thru=(:today) where
                            t.statusFor in (:selectedList)""")
			     .setParameterList('selectedList', transactions)
			     .setParameter('today', new Date()).executeUpdate()
    }

Now the concern was to retain my service as transactional since with executeUpdate statement in there, it couldn’t be transactional anymore. So then we used withTransaction on the parent domain as a block to sorround the executeUpdate statement and along with other statements, which worked.

 Servicer.withTransaction {
	myMap.each {servicerId, amount ->
	      def servicer = Servicer.read(servicerId)
	      BigDecimal currBalance = servicer.reserveAccount.currentBalance
	      currBalance -= amount
	      ReserveAccount.executeUpdate("update ReserveAccount set currentBalance=(:balance) where id=(:id)", [balance: currBalance, id:
		 servicer.reserveAccount.id])
    }
 }

And other solution to handle StaleObjectStateException exception is given here in the mailing list

Hope it helped!

~~Amit Jain~~
amit@intelligrape.com

http://www.intelligrape.com

Programmatically logging in user in jsecurity plugin

March 4th, 2010

In our current project we are using jsecurity plugin and some of our bootstrap code required a user to be logged in. I found a nice blog http://www.intelligrape.com/blog/?p=335 on this topic but it was using groovy metaprogramming to override the normal behaviour of SecurityUtils.getSubject() which is suitable for test environment.

After a few minutes of digging into jsecurity plugin we found an easy solution :-

class MyController{
  def jsecSecurityManager
 
  def myAction={
        def authToken = new org.jsecurity.authc.UsernamePasswordToken("bootstrapuser", "password")
        jsecSecurityManager.login(authToken)
 
	/*
	Your code here that depends on logged in user.
	e.g. String userId=org.jsecurity.SecurityUtils.getSubject()?.getPrincipal()
	*/
 
   }
}

It worked for us.Hope it will save your time too.

~~~~Bhagwt Kumar~~~~
bhagwat@intelligrape.com
IntelliGrape Softwares

Monitoring ajax call response

March 4th, 2010

Recently I have faced a problem of monitoring all the ajax calls. Based on the response from server I have to perform some task depending on the contents of response. If the html response contains some text input field, the first text input field should be automatically focused otherwise leave the response as it is.

Here is the javascript code :

<span id="ajax_spinner" style="display:none"></span>
<script type="text/javascript">
            jQuery("#ajax_spinner").ajaxComplete(function(event, xhr, options)
            {
                var data = jQuery.httpData(xhr,options.dataType);
		/* 
                 Now data contains the responseText if the response type
		 is text/html or text/palin otherwise it is undefined.
                 */
                var inputFieldIndex=-1;
                try{
			/* try-catch because data may be undefined as mentioned above. */
			inputFieldIndex=data.indexOf("<input");
		}catch(err){}
                if(inputFieldIndex>-1){	
                   /* response contains input tag */
                    jQuery('input:text:visible[disabled=false]:first').focus();
                }
            });
 
          });</script>

The above trick worked for me and hope it works for you guys too.

Helpful links :-
http://api.jquery.com/ajaxComplete/

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

Migrating from grails 1.1.1 to grails 1.2.1

February 26th, 2010

Recently I migrated my project which is in development from grails version 1.1.1 to grails 1.2.1 using grails upgrade.. and it worked like charm, though there were some issues with a couple of plugins, just upgrading their versions took care of them. The problem came while submitting the forms.

we had created some forms and a few hyper links the problem was the createLink was not functioning properly,

<g:form name="myForm" action="${createLink(action:'action',controller:'controller')}"  method="post" >

this won’t work with <g:link> either but it works with <a> tag and <form> tag. but that of course is not a good thing to do when u have <g:link> and <g:form> available. The solution was simple

<g:formname="myForm" url="[controller:'controller',action:'action']" method="post">

so avoid using createLink if you have other options, migrating may just become a bit of a niggle if you are using createLink in g:forms and g:links.

I think the problem can be reproduced in g:remoteField and other similar tags.

Sachin
sachin@intelligrape.com

Tracking Image Clicks using Google Analytics

February 25th, 2010

In one of the projects, it was required to track the number of times an image (which linked to another page) was clicked using Google Analytics. We found a very informative article here. It talks about tracking external links and file downloads. This wasn’t exactly our purpose, but the javascript downloaded from there acted as a very good starting point.

What we did was to add a code block like this after line no. 13 of the javascript code from the link given above.

var imgs = document.getElementsByTagName("img");
for(var l=0; l <imgs.length; l++) {
       try {
               var path = imgs[l].getAttribute('src');
               var isDoc = path.match(/\.(?:jpg|png|gif|svg)($|\&|\?)/);
               startListening(imgs[l],"click", trackImageClicks);
       }
       catch(e){
           continue;
       }
    }

And a method before the Analytics script provided by Google for the site

function trackImageClicks(evnt) {
    var e = (evnt.srcElement) ? evnt.srcElement : this;
    var lnk = (e.getAttribute("src").charAt(0) == "/") ? e.getAttribute("src") : "/" + e.getAttribute("src");
    if (typeof(pageTracker) == "object") pageTracker._trackPageview(lnk);
    while (e.tagName != "A") {
        e = e.parentNode;
    }
     lnk = (e.pathname.charAt(0) == "/") ? e.pathname : "/" + e.pathname;
    if (e.search && e.pathname.indexOf(e.search) == -1) lnk += e.search;
    if (e.hostname != location.host) lnk = e.hostname + lnk;
    if (typeof(pageTracker) == "object") pageTracker._trackPageview(lnk);
}

Now, the clicks on each image were getting tracked.

Error Compiling .jrxml file with iReport 2.0.5

February 25th, 2010

Recently I encountered an error , while working  on iReports ,

iReport it was not able to compile .jrxml file to generate .jasper file , whilst  it used to show  compile time.

Error :

Compiling to file... ./<filename>.jasper -> /usr/share/iReport/bin/<filename>.java
Errors compiling ./<filename>.jasper.
net.sf.jasperreports.engine.JRException: Error saving expressions class file : /usr/share/iReport/bin/<filename>_1267071292035_83340.java
Compilation running time: 80

Basically I found two way out this situation

1) Changing permission of usr/share/iReport/bin/ directory .

This can be done with CHMOD command
sudo chmod 777 usr/share/iReport/bin

or

2)  change the directory where reports are compiled.

check "option -> setting -> compiler --> Use Report Directory to Compile"

________________________
Regards
Hitesh Bhatia

http://www.IntelliGrape.com

________________________

Implementing Delay Between Ajax Calls

February 25th, 2010

Implementing search functionality on the keyup event using ajax has one pitfall. It can bombard our server with unnecessary ajax calls. So it becomes imperative for us to introduce some delay between the ajax calls. One way to implement it will be to make an ajax call after some delay(say 500 ms) after the first character has been typed in the text box. But,a better solution will be to make the ajax call after 500ms, after the last character has been typed. The idea is to clear the timer on each key-up event till the user types in the last charecter.
This solution can be implemented as given below:

<input type="text" onkeyup="activateTimer(this.id)" id="firstName"/>
 var alertTimerId = 0;
function activateTimer(objId) {
    clearTimeout(alertTimerId);
    alertTimerId = setTimeout('sendData("' + objId + '")', 500);
  }
  function sendData(objId) {
    ajax call 
  }

Here, the instance or identifier of the time out call is captured in a variable and then this identifier is passed to clearTimeout function to clear the timer.
Another problem associated with ajax search on keyup event is that if we are using tab button to navigate between different search fields, unnecessary ajax calls are shooted. To prevent this we can modify our activateTimer function like this :

function activateTimer(objId, event) {
    if (event.which == 9) {
    }
    else {
      clearTimeout(alertTimerId);
      alertTimerId = setTimeout('sendData("' + objId + '")', 500);
    }
  }

Event argument can be passed as parameter like this :

  <input type="text" onkeyup="activateTimer(this.id,event)" id="firstName"/>

Hope you find this useful.
Imran Mir
imran@intelligrape.com

My experience of using jasper reports with grails application

February 25th, 2010

In my project we needed to generate certain pdf reports. Then while exploring the options available, I encountered a PDF plugin, which renders gsp page and returns the PDF report. It looked good for the simple reports but may not be a good idea if the report are complex. Then with the help of one of my collegue, we decided to rather generate jasper reports. And as expected, there exists a plugin called ‘jasper’ to integrate jasper reports with a grails application, which made my job really easy.

Things looked good, now we were only left with an IDE to rapidly generate jasper reports and then we finally found a tool called IReport. We could make version 2.0.5 working flawlessly with the jasper plugin.

As our reports became more complex and our understanding about jasper reports grew, even things which looked big like required page breaks on certain conditions etc. became really easy to handle with the IReport tool. We could generate a complex jasper report in 3 days time which includes the time taken to get accustomed to iReport and jasper report and its integration. I will soon write more about jasper reports and few changes we made to the jasper plugin to suit our requirements like directly sending emails with jasper report as an attachment…

Cheers!
~~Amit Jain~~
amit@intelligrape.com
IntelliGrape Softwares

http://intelligrape.com

Grails Integration Tests : Access your application path

January 21st, 2010

Hi Friends,

Recently I needed to access my grails application’s path while writing an integration test. I tried to do it with servlet context, Application Holder and few more options. But none worked. Then I encountered the simplest way as given below, which worked.

System.properties['base.dir']

Cheers!
~~Amit Jain~~
amit@intelligrape.com
IntelliGrape Softwares

http://www.intelligrape.com/

Login user for Integration test when using Jsecurity plugin

December 7th, 2009

Hello Friends,

I was using Jsecurity plugin in my project. There was an action in a controller which needed logged in user information and I was finding it difficult to write an integration test for the same. Then Brent Fisher shared the following code which worked nicely for both services and controllers:

import org.jsecurity.SecurityUtils
import com.aps.domain.security.JsecUser
import org.jsecurity.subject.Subject

class MyControllerTests extends GrailsUnitTestCase {	

  protected void setUp() {
	super.setUp()
	//following code sets admin as a logged in user
	def subject = [isAuthenticated: true,
		       principal: "admin"
		      ] as Subject

	SecurityUtils.metaClass.static.getSubject = {-> return subject }
	Subject.metaClass.getPrincipal = {-> return "admin" }
	...
  }
 ...
}	

Using metaclass, We changed the implementation of getPrincipal() and getSubject() to work in our way. So looking at this, I could see the power of a metaclass, which can be used to change or add new method implementations to an API which is not even accessible to us.

Cheers!

~~Amit Jain~~
amit@intelligrape.com
IntelliGrape Softwares

http://www.intellgrape.com

IntelliGrape Software is a young, small and dynamic software development company, based in New Delhi, India. IntelliGrape has an experienced team of technical programmers focusing on the latest web development technologies.

Our Clients