Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@JmsListener annotated method need to be extracted to interface even if CGLIB used [SPR-16557] #21100

Closed
spring-issuemaster opened this issue Mar 6, 2018 · 4 comments

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Mar 6, 2018

Anton Filatov opened SPR-16557 and commented

Before bugfix #20744 it was impossible to use @JmsListener annotation with cglib-proxied classes at all.
Now it works fine, but stil we need to extract annotated method into interface because processJmsListener try to search invocableMethod as follows

Method invocableMethod = AopUtils.selectInvocableMethod(mostSpecificMethod, bean.getClass());

and this lead to

...
Caused by: java.lang.IllegalStateException: Need to invoke method 'process' declared on target class 'Example', but not found in any interface(s) of the exposed proxy type. Either pull the method up to an interface or switch to CGLIB proxies by enforcing proxy-target-class mode in your configuration.
	at org.springframework.core.MethodIntrospector.selectInvocableMethod(MethodIntrospector.java:135)
	at org.springframework.aop.support.AopUtils.selectInvocableMethod(AopUtils.java:130)
	at org.springframework.jms.annotation.JmsListenerAnnotationBeanPostProcessor.processJmsListener(JmsListenerAnnotationBeanPostProcessor.java:262)
	at org.springframework.jms.annotation.JmsListenerAnnotationBeanPostProcessor.postProcessAfterInitialization(JmsListenerAnnotationBeanPostProcessor.java:240)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:423)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1633)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
	... 56 common frames omitted

Message is discouraging :)

I suppose that

Method invocableMethod = AopUtils.selectInvocableMethod(mostSpecificMethod, AopUtils.getTargetClass(bean));

will fix this problem.


Affects: 4.3.14

Issue Links:

  • #20744 Combining @Retryable and @Scheduled/@JmsListener doesn't work
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 6, 2018

Juergen Hoeller commented

Could you provide a few details on your setup there? MethodIntrospector.selectInvocableMethod attempts to find a method of the same signature on the proxy class... which should always work with a CGLIB proxy. Are there additional interfaces involved, or possibly generics?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 7, 2018

Anton Filatov commented

The simpliest class reproducing problem in my environment:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

import javax.transaction.Transactional;

@Component
public class MessageProcessor {

    private Logger log = LoggerFactory.getLogger(MessageProcessor.class);

    @JmsListener(destination = "event_queue")
    @Transactional
    public void process(String event) {
        log.info("Event received: " + event);
    }
}

In context.xml cglib-proxies are activated:

<tx:annotation-driven proxy-target-class="true"/>

Indeed, this does not matter - activated cglib-proxies or not... Exception in both cases the same, but in case of java interface-based proxies exception is correct.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 7, 2018

Anton Filatov commented

You was right! More investigation showed that proxy-target-class somewhy is ignored and proxies actually are java interface-based.

My real configuration contains

...
    <aop:aspectj-autoproxy proxy-target-class="true"/>
...
    <tx:annotation-driven proxy-target-class="true"/>
...

And i was sure that cglib proxies used.
Moreover for classes with @Transactional annotation i have aop aspect for logging where code like ```java
((MethodSignature) pjp.getSignature()).getParameterNames()

One more experiment showed that classes without @Transactional methods are correct instrumented with cglib and when i add @JmsListener-annotated method in such class it works fine.

I don`t understand situation in this point, but problem not in spring-jms obviously.
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Mar 7, 2018

Juergen Hoeller commented

Alright, I'll mark this issue as invalid for the time being. If there is anything we need to do at the JmsListenerAnnotationBeanPostProcessor level, please reopen it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.