0
votes

I am developing an grails application(server) to track the mobile device which are in the Wi-Fi network. The users will send a request to the webservice which is running on grails applicion(server) along with Mobileid and Wi-Fi IP address.

In my grails application i am staring multiple external java threads, each thread will be pinging the Wi-Fi IP address of each mobile device(one thread per one device to track). If any device IP is not reachable then i will update mobile status as "Disconnected" in the database from the external thread. Here only i am facing the issue, if more than one device is in not reachable then multiple threads are going to update the status of each device in the same table using domain.withTransaction method while i am getting the following exception

org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is java.lang.NullPointerException at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:596) at org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager.super$3$doBegin(GrailsHibernateTransactionManager.groovy) at sun.reflect.GeneratedMethodAccessor492.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:88) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1058) at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1070) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuperN(ScriptBytecodeAdapter.java:127)

My Code:

Pinging device in thread

try {
    final InetAddress inet = InetAddress.getByName(ipAddress);
    boolean status = inet.isReachable(5000);
    if (status) {
        pool.run(MobileDeviceTracker.deviceMap.get(mobileId));
    } else {
         // Calling service to update the status of device as disconnected
        getUserMobileService().deviceDisconnected(mobileId, ipAddress);
    }
} catch (Exception e) { }

Updating Status in Database

class DisconnectionService implements UserMobileServiceInt{
     static transactional = true


    def void deviceDisconnected(String mobileId, String wifiIp){
        try{
            def mobile = Mobile.findByMobileId(mobileId)
            def userMobile = UserMobile.findByMobileAndWifiIp(mobile, wifiIp)
            userMobile.withTransaction {tx ->               
                userMobile.action = Constants.MOBILE_STATUS_DISCONNECTED
                userMobile.alarmStatus = Constants.ALARM_STATUS_TURNED_ON
                userMobile.modifiedDate = new Date()
                userMobile.save(flush: true)
        }
        }catch(Exception e){
            e.printStackTrace()
        }

I am trying last 4 days but i am not able solve this.

3

3 Answers

3
votes

Move the reads into the transaction, otherwise they'll be in a disconnected session and not the one that the transaction creates. Also, it's best to call static methods on the class, not an instance (in both Groovy and Java):

void deviceDisconnected(String mobileId, String wifiIp){
   try {
      UserMobile.withTransaction { tx ->
         def mobile = Mobile.findByMobileId(mobileId)
         def userMobile = UserMobile.findByMobileAndWifiIp(mobile, wifiIp)
         userMobile.action = Constants.MOBILE_STATUS_DISCONNECTED
         userMobile.alarmStatus = Constants.ALARM_STATUS_TURNED_ON
         userMobile.modifiedDate = new Date()
         userMobile.save(flush: true)
      }
   }
   catch(e) {
      e.printStackTrace()
   }
}
1
votes

Rather than using the verbose binding code suggested by Tiggerizzy. It is better to use the built in withNewSession method on domain classes:

Mobile.withNewSession {
   // your code here
}
0
votes

No need for me to spread mis-information and bad ways of doing things. Both the answers from Burt and Graeme will work. I just wrote a quick test app to prove this.