Grails
  1. Grails
  2. GRAILS-7402

No thread-bound request / Hibernate exception when updating domain-object in quartz-job

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.3.7
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None
    • Environment:
      Grails-1.3.4 or Grails-1.3.5 (both), MySQL or default in-memory DB (doesn't matter), Linux (Kubuntu), Sun Java 6

      Description

      I've encountered the same problem as described in GRAILSPLUGINS-1807 when upgrading one of our apps from Grails 1.2.0 to 1.3.5. However, none of the fixes mentioned in the other ticket resolve the problem. The current 1.0-SNAPSHOT still produces that exception.

      331385 [quartzScheduler_Worker-4] ERROR org.codehaus.groovy.grails.plugins.quartz.listeners.ExceptionPrinterJobListener - Exception occured in job: GRAILS_JOBS.at.paraclub.webserver.booking.EmailJob
      org.quartz.JobExecutionException: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. [See nested exception: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.]
              at org.codehaus.groovy.grails.plugins.quartz.GrailsJobFactory$GrailsJob.execute(GrailsJobFactory.java:90)
              at org.quartz.core.JobRunShell.run(JobRunShell.java:216)
              at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
      Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
              at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:123)
              at org.springframework.web.context.request.RequestContextHolder$currentRequestAttributes.call(Unknown Source)
              at org.codehaus.groovy.grails.web.plugins.support.WebMetaUtils$_enhanceCommandObject_closure4.doCall(WebMetaUtils.groovy:172)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              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 org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod.invoke(ClosureMetaMethod.java:80)
              at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
              at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1602)
              at groovy.lang.ExpandoMetaClass.getProperty(ExpandoMetaClass.java:1099)
              at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3311)
              at groovy.lang.ExpandoMetaClass.getProperty(ExpandoMetaClass.java:1111)
              at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod.setupErrorsProperty(AbstractDynamicPersistentMethod.java:96)
              at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod.doInvokeInternal(AbstractSavePersistentMethod.java:117)
              at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod.invoke(AbstractDynamicPersistentMethod.java:59)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:597)
              at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:188)
              at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52)
              at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
              at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
              at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:132)
              at org.codehaus.groovy.grails.plugins.orm.hibernate.HibernatePluginSupport$_addBasicPersistenceMethods_closure71.doCall(HibernatePluginSupport.groovy:812)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              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 org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod.invoke(ClosureMetaMethod.java:80)
              at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoMetaMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:307)
              at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:63)
              at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
              at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
              at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
              at at.paraclub.webserver.booking.EmailJob$_execute_closure2.doCall(EmailJob.groovy:38)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              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 groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:886)
              at groovy.lang.Closure.call(Closure.java:276)
              at groovy.lang.Closure.call(Closure.java:289)
              at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1198)
              at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1174)
              at org.codehaus.groovy.runtime.dgm$109.invoke(Unknown Source)
              at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:270)
              at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52)
              at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
              at at.paraclub.webserver.booking.EmailJob.execute(EmailJob.groovy:29)
              at sun.reflect.GeneratedMethodAccessor360.invoke(Unknown Source)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:597)
              at org.codehaus.groovy.grails.plugins.quartz.GrailsJobFactory$GrailsJob.execute(GrailsJobFactory.java:83)
              ... 2 more
      331396 [quartzScheduler_Worker-4] ERROR org.codehaus.groovy.grails.plugins.quartz.listeners.SessionBinderJobListener - Cannot flush Hibernate Sesssion, error will be ignored
      java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
              at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:123)
              at org.springframework.web.context.request.RequestContextHolder$currentRequestAttributes.call(Unknown Source)
              at org.codehaus.groovy.grails.web.plugins.support.WebMetaUtils$_enhanceCommandObject_closure4.doCall(WebMetaUtils.groovy:172)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              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 org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod.invoke(ClosureMetaMethod.java:80)
              at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
              at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1602)
              at groovy.lang.ExpandoMetaClass.getProperty(ExpandoMetaClass.java:1099)
              at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3311)
              at groovy.lang.ExpandoMetaClass.getProperty(ExpandoMetaClass.java:1111)
              at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod.setupErrorsProperty(AbstractDynamicPersistentMethod.java:96)
              at org.codehaus.groovy.grails.orm.hibernate.metaclass.ValidatePersistentMethod.doInvokeInternal(ValidatePersistentMethod.java:68)
              at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod.invoke(AbstractDynamicPersistentMethod.java:59)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:597)
              at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:188)
              at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52)
              at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
              at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:54)
              at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:132)
              at org.codehaus.groovy.grails.plugins.orm.hibernate.HibernatePluginSupport$_addValidationMethods_closure19.doCall(HibernatePluginSupport.groovy:490)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              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 org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod.invoke(ClosureMetaMethod.java:80)
              at org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventListener.onPreUpdate(ClosureEventListener.java:264)
              at org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor.onPreUpdate(ClosureEventTriggeringInterceptor.java:167)
              at org.hibernate.action.EntityUpdateAction.preUpdate(EntityUpdateAction.java:237)
              at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:88)
              at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
              at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
              at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
              at org.codehaus.groovy.grails.orm.hibernate.events.PatchedDefaultFlushEventListener.performExecutions(PatchedDefaultFlushEventListener.java:46)
              at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
              at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
              at org.codehaus.groovy.grails.plugins.quartz.listeners.SessionBinderJobListener.jobWasExecuted(SessionBinderJobListener.java:59)
              at org.quartz.core.QuartzScheduler.notifyJobListenersWasExecuted(QuartzScheduler.java:1972)
              at org.quartz.core.JobRunShell.notifyJobListenersComplete(JobRunShell.java:374)
              at org.quartz.core.JobRunShell.run(JobRunShell.java:240)
              at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
      

      I have a stripped down demo version of our application that - over here - can reproduce the bug anytime. Here's how to do it:

      • Start the application
      • Point your browser to http://localhost:8080/webserver/booking/index
      • Click through the two following pages (the buttons).
      • Now wait for the EmailJob to execute again (5sec interval) and you should see the exception.

        Activity

        Hide
        Paul Alexandrow added a comment -

        Added a stripped down version of the appliation that produces the bug.

        Show
        Paul Alexandrow added a comment - Added a stripped down version of the appliation that produces the bug.
        Hide
        Paul Alexandrow added a comment -

        I digged deeper and found the source of the behaviour: It seems that this only occurs, when (at some point during runtime) the domainobject in question has been used as a commandobject. I updated the controller of the attached app to demonstrate this.

        Actually I don't know, if it's "OK" to use domainobjects within the commandobject-pattern - but until 1.2.0 it worked. And I'm somehow left with the suspicion, that this might not really be a quartz-plugin-problem, but that something strange is going on with commandobjects within Grails itself. However, as I have not enough insight into neither the quartz-plugin nor Grails, I'll leave the ticket as it is - hoping that some more knowing person might pick it up and decide, where it actually belongs to.

        Show
        Paul Alexandrow added a comment - I digged deeper and found the source of the behaviour: It seems that this only occurs, when (at some point during runtime) the domainobject in question has been used as a commandobject. I updated the controller of the attached app to demonstrate this. Actually I don't know, if it's "OK" to use domainobjects within the commandobject-pattern - but until 1.2.0 it worked. And I'm somehow left with the suspicion, that this might not really be a quartz-plugin-problem, but that something strange is going on with commandobjects within Grails itself. However, as I have not enough insight into neither the quartz-plugin nor Grails, I'll leave the ticket as it is - hoping that some more knowing person might pick it up and decide, where it actually belongs to.
        Hide
        Peter Ledbrook added a comment -

        This is a problem with using domain classes as command objects: the command object binding overrides the standard domain class properties and methods with regard to validation.

        The question is, should Grails even allow the use of domain classes as command objects? It's a security risk, so I think there should at least be a warning.

        Show
        Peter Ledbrook added a comment - This is a problem with using domain classes as command objects: the command object binding overrides the standard domain class properties and methods with regard to validation. The question is, should Grails even allow the use of domain classes as command objects? It's a security risk, so I think there should at least be a warning.
        Hide
        Greg Schueler added a comment -

        I'm getting this same problem, after upgrading a project from 1.2.0 to 1.3.7. It occurs calling a service method, and so I wouldn't think it is interpreting the domain object as a command object, but it does appear to be the underlying cause.

        Is there any way to work around this problem? I need a way to update domain object(s) at the end of a Quartz job execution

        Show
        Greg Schueler added a comment - I'm getting this same problem, after upgrading a project from 1.2.0 to 1.3.7. It occurs calling a service method, and so I wouldn't think it is interpreting the domain object as a command object, but it does appear to be the underlying cause. Is there any way to work around this problem? I need a way to update domain object(s) at the end of a Quartz job execution
        Hide
        Greg Schueler added a comment -

        I was able to work around the bug. In my case I was inadvertently using the domain class as an argument in some closures (actions) in a Controller, which should have been methods. I suppose this causes grails to then treat all instances of that class as Command objects. I modified my controller to use methods instead of closures, and the problem went away.

        Show
        Greg Schueler added a comment - I was able to work around the bug. In my case I was inadvertently using the domain class as an argument in some closures (actions) in a Controller, which should have been methods. I suppose this causes grails to then treat all instances of that class as Command objects. I modified my controller to use methods instead of closures, and the problem went away.

          People

          • Assignee:
            Unassigned
            Reporter:
            Paul Alexandrow
          • Votes:
            5 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

            • Created:
              Updated:
              Last Reviewed:

              Development