You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Ryan Gardner <ry...@gmail.com> on 2009/02/26 04:55:29 UTC

Camel's @Consume on a @Transactional method

I'm able to use a processor with @Transactional methods called from  
the DSL via beanRef("fooBean", "fooTransactionalMethod") and things  
work just fine - but trying to step a bit away from the DSL to using  
the annotations to drive some of my routes.

I tried doing this:

@Consume(uri = "activemq:newIncident")
@Transactional(readOnly = false)
public void handleNewFoo(@Body Foo foo, @Headers Map<String,Object>  
messageHeaders) {
	...
}

and I get this exception:

Caused by: org.hibernate.HibernateException: No Hibernate Session  
bound to thread, and configuration does not allow creation of non- 
transactional one here
	at  
org 
.springframework 
.orm 
.hibernate3 
.SpringSessionContext.currentSession(SpringSessionContext.java:63)
	at  
org 
.hibernate 
.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
	at  
com 
.digitalbridge 
.dbdocs.dao.impl.GenericDAOImpl.saveOrUpdate(GenericDAOImpl.java:69)
	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 
.springframework 
.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
	at  
org 
.springframework 
.aop 
.framework 
.ReflectiveMethodInvocation 
.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
	at  
org 
.springframework 
.aop 
.framework 
.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
	at  
org 
.springframework 
.dao 
.support 
.PersistenceExceptionTranslationInterceptor 
.invoke(PersistenceExceptionTranslationInterceptor.java:138)
	... 21 more

(I'm pretty sure I have the annotation-based @Transactional stuff  
setup correctly...)

Is there some other way to configure this to be both messagedriven and  
transactional?

Ryan

Re: Camel's @Consume on a @Transactional method

Posted by Claus Ibsen <cl...@gmail.com>.
Hi Ryan

Did you get a solution to this or any news?


On Thu, Feb 26, 2009 at 4:55 AM, Ryan Gardner <ry...@gmail.com> wrote:
>
> I'm able to use a processor with @Transactional methods called from the DSL
> via beanRef("fooBean", "fooTransactionalMethod") and things work just fine -
> but trying to step a bit away from the DSL to using the annotations to drive
> some of my routes.
>
> I tried doing this:
>
> @Consume(uri = "activemq:newIncident")
> @Transactional(readOnly = false)
> public void handleNewFoo(@Body Foo foo, @Headers Map<String,Object>
> messageHeaders) {
>        ...
> }
>
> and I get this exception:
>
> Caused by: org.hibernate.HibernateException: No Hibernate Session bound to
> thread, and configuration does not allow creation of non-transactional one
> here
>        at
> org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
>        at
> org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
>        at
> com.digitalbridge.dbdocs.dao.impl.GenericDAOImpl.saveOrUpdate(GenericDAOImpl.java:69)
>        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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
>        at
> org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
>        at
> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
>        at
> org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:138)
>        ... 21 more
>
> (I'm pretty sure I have the annotation-based @Transactional stuff setup
> correctly...)
>
> Is there some other way to configure this to be both messagedriven and
> transactional?
>
> Ryan
>



-- 
Claus Ibsen
Apache Camel Committer

Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/

Re: Camel's @Consume on a @Transactional method

Posted by Claus Ibsen <cl...@gmail.com>.
Hi Ryan

Just to let you know this mail is still highlighted in my gmail as
something to revisit.

I am sure its the proxy thing. The is some code in camel bean
component - BeanInfo or the like that has a TODO / code comment about
having a list of well known proxies. The issue is that we dont know if
its a proxy or the real object. So if you can find out what the
classname is for the proxied class that would be great. Spring have
some AopUtils.isProxy or the like. Maybe we can leverage that if
spring is on the classpath.

If you have a small sample with a maven pom.xml that would be great
for starters to use to dig into the matter.




On Wed, Mar 4, 2009 at 5:56 PM, Ryan Gardner <ry...@gmail.com> wrote:
> I didn't get a solution to using it the way I intended originally. I
> may revisit this later to try to get a simple test case to submit.
>
> I was using the annotations like:
>
> @Transactional(readOnly=false)
> @Consume("seda:someQueue")
>  public Blarg doFoo(@Body Foo foo, @Header(name="foo") {
> ...
> }
>
> When it would try to invoke the method, it was complaining about
> duplicate method signatures available - I wonder if it was because it
> was somehow seeing both the transactional proxy and the unproxied
> thing and being confused somehow, or if I was doing something wrong.
>
> What I've done in the meantime is just made my bean implement
> Processor and have the Process method call the previously-annotated
> method. Calling the transactional processor via a bean: reference
> works - it was the beanRef: methodName= part that I wasn't able to get
> to work.
>
> For now, this works for my intended case - which is to have my
> transaction manager in spring be able to open up hibernate sessions
> for my seda routes or other things that are not invoked with an
> existing hibernate session (If I wasn't wanting to have multiple
> threads processing the messages or spawned in my messages I could use
> the direct: routes exclusively for some of what I am trying to do and
> rely on the openSessionInView to keep a long-lived session open - but
> given the ease of marking things @Transactional there's no real reason
> for doing that)
>
> It would be really cool if the @Transactional annotation could be used
> to configure transactional endpoints across the JMS stuff and the
> hibernate stuff - i.e. have it rollback db stuff and put the message
> back in the queue if there is an unchecked exception.
>
> So the short answer is, I'm not sure what the nature of the original
> problem was - but my workaround is working currently. Hibernate,
> @Transactional, Seda routes, and using Bean: (for beans that implement
> processor) in a route definition all seem to work nicely. The beanRef:
> for things using annotations on the methods mixed with @Consume
> doesn't seem to work for me.
>
> Ryan
>
> On Wed, Mar 4, 2009 at 7:00 AM, James Strachan <ja...@gmail.com> wrote:
>> Are you dependency injecting the bean using Spring? All Camel does is
>> get spring to create the bean (along with whatever interceptors for
>> transactions/security etc).
>>
>> 2009/2/26 Ryan Gardner <ry...@gmail.com>:
>>>
>>> I'm able to use a processor with @Transactional methods called from the DSL
>>> via beanRef("fooBean", "fooTransactionalMethod") and things work just fine -
>>> but trying to step a bit away from the DSL to using the annotations to drive
>>> some of my routes.
>>>
>>> I tried doing this:
>>>
>>> @Consume(uri = "activemq:newIncident")
>>> @Transactional(readOnly = false)
>>> public void handleNewFoo(@Body Foo foo, @Headers Map<String,Object>
>>> messageHeaders) {
>>>        ...
>>> }
>>>
>>> and I get this exception:
>>>
>>> Caused by: org.hibernate.HibernateException: No Hibernate Session bound to
>>> thread, and configuration does not allow creation of non-transactional one
>>> here
>>>        at
>>> org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
>>>        at
>>> org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
>>>        at
>>> com.digitalbridge.dbdocs.dao.impl.GenericDAOImpl.saveOrUpdate(GenericDAOImpl.java:69)
>>>        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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
>>>        at
>>> org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
>>>        at
>>> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
>>>        at
>>> org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:138)
>>>        ... 21 more
>>>
>>> (I'm pretty sure I have the annotation-based @Transactional stuff setup
>>> correctly...)
>>>
>>> Is there some other way to configure this to be both messagedriven and
>>> transactional?
>>>
>>> Ryan
>>>
>>
>>
>>
>> --
>> James
>> -------
>> http://macstrac.blogspot.com/
>>
>> Open Source Integration
>> http://fusesource.com/
>>
>



-- 
Claus Ibsen
Apache Camel Committer

Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus
Apache Camel Reference Card:
http://refcardz.dzone.com/refcardz/enterprise-integration

Re: Camel's @Consume on a @Transactional method

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

I have looked into this with CAMEL-1663 and CAMEL-1601.
I have fixed issues in Camel 2.0 with Spring not being able to do post
processing on some beans.
It reports this as not eligible to ... See CAMEL-1663 for samples with
before and after.

However to construct a sample in 1.x that fails is harder than first sight.

Well the sympton should be the not eligible reported by Spring.
I really assume its fixed in trunk and we will backport the fix to
Camel 1.6.2 later.



On Wed, Mar 4, 2009 at 5:56 PM, Ryan Gardner<ry...@gmail.com> wrote:
> I didn't get a solution to using it the way I intended originally. I
> may revisit this later to try to get a simple test case to submit.
>
> I was using the annotations like:
>
> @Transactional(readOnly=false)
> @Consume("seda:someQueue")
>  public Blarg doFoo(@Body Foo foo, @Header(name="foo") {
> ...
> }
>
> When it would try to invoke the method, it was complaining about
> duplicate method signatures available - I wonder if it was because it
> was somehow seeing both the transactional proxy and the unproxied
> thing and being confused somehow, or if I was doing something wrong.
>
> What I've done in the meantime is just made my bean implement
> Processor and have the Process method call the previously-annotated
> method. Calling the transactional processor via a bean: reference
> works - it was the beanRef: methodName= part that I wasn't able to get
> to work.
>
> For now, this works for my intended case - which is to have my
> transaction manager in spring be able to open up hibernate sessions
> for my seda routes or other things that are not invoked with an
> existing hibernate session (If I wasn't wanting to have multiple
> threads processing the messages or spawned in my messages I could use
> the direct: routes exclusively for some of what I am trying to do and
> rely on the openSessionInView to keep a long-lived session open - but
> given the ease of marking things @Transactional there's no real reason
> for doing that)
>
> It would be really cool if the @Transactional annotation could be used
> to configure transactional endpoints across the JMS stuff and the
> hibernate stuff - i.e. have it rollback db stuff and put the message
> back in the queue if there is an unchecked exception.
>
> So the short answer is, I'm not sure what the nature of the original
> problem was - but my workaround is working currently. Hibernate,
> @Transactional, Seda routes, and using Bean: (for beans that implement
> processor) in a route definition all seem to work nicely. The beanRef:
> for things using annotations on the methods mixed with @Consume
> doesn't seem to work for me.
>
> Ryan
>
> On Wed, Mar 4, 2009 at 7:00 AM, James Strachan <ja...@gmail.com> wrote:
>> Are you dependency injecting the bean using Spring? All Camel does is
>> get spring to create the bean (along with whatever interceptors for
>> transactions/security etc).
>>
>> 2009/2/26 Ryan Gardner <ry...@gmail.com>:
>>>
>>> I'm able to use a processor with @Transactional methods called from the DSL
>>> via beanRef("fooBean", "fooTransactionalMethod") and things work just fine -
>>> but trying to step a bit away from the DSL to using the annotations to drive
>>> some of my routes.
>>>
>>> I tried doing this:
>>>
>>> @Consume(uri = "activemq:newIncident")
>>> @Transactional(readOnly = false)
>>> public void handleNewFoo(@Body Foo foo, @Headers Map<String,Object>
>>> messageHeaders) {
>>>        ...
>>> }
>>>
>>> and I get this exception:
>>>
>>> Caused by: org.hibernate.HibernateException: No Hibernate Session bound to
>>> thread, and configuration does not allow creation of non-transactional one
>>> here
>>>        at
>>> org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
>>>        at
>>> org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
>>>        at
>>> com.digitalbridge.dbdocs.dao.impl.GenericDAOImpl.saveOrUpdate(GenericDAOImpl.java:69)
>>>        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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
>>>        at
>>> org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
>>>        at
>>> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
>>>        at
>>> org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:138)
>>>        ... 21 more
>>>
>>> (I'm pretty sure I have the annotation-based @Transactional stuff setup
>>> correctly...)
>>>
>>> Is there some other way to configure this to be both messagedriven and
>>> transactional?
>>>
>>> Ryan
>>>
>>
>>
>>
>> --
>> James
>> -------
>> http://macstrac.blogspot.com/
>>
>> Open Source Integration
>> http://fusesource.com/
>>
>



-- 
Claus Ibsen
Apache Camel Committer

Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus

Re: Camel's @Consume on a @Transactional method

Posted by Ryan Gardner <ry...@gmail.com>.
I didn't get a solution to using it the way I intended originally. I
may revisit this later to try to get a simple test case to submit.

I was using the annotations like:

@Transactional(readOnly=false)
@Consume("seda:someQueue")
 public Blarg doFoo(@Body Foo foo, @Header(name="foo") {
...
}

When it would try to invoke the method, it was complaining about
duplicate method signatures available - I wonder if it was because it
was somehow seeing both the transactional proxy and the unproxied
thing and being confused somehow, or if I was doing something wrong.

What I've done in the meantime is just made my bean implement
Processor and have the Process method call the previously-annotated
method. Calling the transactional processor via a bean: reference
works - it was the beanRef: methodName= part that I wasn't able to get
to work.

For now, this works for my intended case - which is to have my
transaction manager in spring be able to open up hibernate sessions
for my seda routes or other things that are not invoked with an
existing hibernate session (If I wasn't wanting to have multiple
threads processing the messages or spawned in my messages I could use
the direct: routes exclusively for some of what I am trying to do and
rely on the openSessionInView to keep a long-lived session open - but
given the ease of marking things @Transactional there's no real reason
for doing that)

It would be really cool if the @Transactional annotation could be used
to configure transactional endpoints across the JMS stuff and the
hibernate stuff - i.e. have it rollback db stuff and put the message
back in the queue if there is an unchecked exception.

So the short answer is, I'm not sure what the nature of the original
problem was - but my workaround is working currently. Hibernate,
@Transactional, Seda routes, and using Bean: (for beans that implement
processor) in a route definition all seem to work nicely. The beanRef:
for things using annotations on the methods mixed with @Consume
doesn't seem to work for me.

Ryan

On Wed, Mar 4, 2009 at 7:00 AM, James Strachan <ja...@gmail.com> wrote:
> Are you dependency injecting the bean using Spring? All Camel does is
> get spring to create the bean (along with whatever interceptors for
> transactions/security etc).
>
> 2009/2/26 Ryan Gardner <ry...@gmail.com>:
>>
>> I'm able to use a processor with @Transactional methods called from the DSL
>> via beanRef("fooBean", "fooTransactionalMethod") and things work just fine -
>> but trying to step a bit away from the DSL to using the annotations to drive
>> some of my routes.
>>
>> I tried doing this:
>>
>> @Consume(uri = "activemq:newIncident")
>> @Transactional(readOnly = false)
>> public void handleNewFoo(@Body Foo foo, @Headers Map<String,Object>
>> messageHeaders) {
>>        ...
>> }
>>
>> and I get this exception:
>>
>> Caused by: org.hibernate.HibernateException: No Hibernate Session bound to
>> thread, and configuration does not allow creation of non-transactional one
>> here
>>        at
>> org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
>>        at
>> org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
>>        at
>> com.digitalbridge.dbdocs.dao.impl.GenericDAOImpl.saveOrUpdate(GenericDAOImpl.java:69)
>>        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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
>>        at
>> org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
>>        at
>> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
>>        at
>> org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:138)
>>        ... 21 more
>>
>> (I'm pretty sure I have the annotation-based @Transactional stuff setup
>> correctly...)
>>
>> Is there some other way to configure this to be both messagedriven and
>> transactional?
>>
>> Ryan
>>
>
>
>
> --
> James
> -------
> http://macstrac.blogspot.com/
>
> Open Source Integration
> http://fusesource.com/
>

Re: Camel's @Consume on a @Transactional method

Posted by James Strachan <ja...@gmail.com>.
Are you dependency injecting the bean using Spring? All Camel does is
get spring to create the bean (along with whatever interceptors for
transactions/security etc).

2009/2/26 Ryan Gardner <ry...@gmail.com>:
>
> I'm able to use a processor with @Transactional methods called from the DSL
> via beanRef("fooBean", "fooTransactionalMethod") and things work just fine -
> but trying to step a bit away from the DSL to using the annotations to drive
> some of my routes.
>
> I tried doing this:
>
> @Consume(uri = "activemq:newIncident")
> @Transactional(readOnly = false)
> public void handleNewFoo(@Body Foo foo, @Headers Map<String,Object>
> messageHeaders) {
>        ...
> }
>
> and I get this exception:
>
> Caused by: org.hibernate.HibernateException: No Hibernate Session bound to
> thread, and configuration does not allow creation of non-transactional one
> here
>        at
> org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
>        at
> org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
>        at
> com.digitalbridge.dbdocs.dao.impl.GenericDAOImpl.saveOrUpdate(GenericDAOImpl.java:69)
>        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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
>        at
> org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
>        at
> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
>        at
> org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:138)
>        ... 21 more
>
> (I'm pretty sure I have the annotation-based @Transactional stuff setup
> correctly...)
>
> Is there some other way to configure this to be both messagedriven and
> transactional?
>
> Ryan
>



-- 
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://fusesource.com/