Results 1 to 10 of 14

Thread: AOP Publisher?

Hybrid View

  1. #1
    Join Date
    Jun 2008
    Posts
    18

    Default AOP Publisher?

    I'm trying to use the Publisher annotation to create a simple event based handler (that is, the method I'm interested in has Publisher on it, and my handler has Subscribe on it), but no matter what I do I can't seem to get the Publisher method to do anything. I tried running the code through a debugger and it doesn't look like the object with the Publisher annotation on its method is being proxied in any way which I'm fairly certain is the problem. I checked and I have the aopalliance.jar, spring.jar (which contains all the spring-aop.jar contents), and cglib-no-deps.jar in my classpath, but it still doesn't work. Prior to including Spring Integration the project was already annotation driven and all the other annotations seem to be working fine (both beans with the Publisher and Subscriber annotations are spring injected using Autowired) so I can't understand why if the Publisher annotation is working like it's supposed to that the bean with that annotation isn't being proxied. Did I miss a dependency somewhere?

    Excerpt from applicationContext.xml:

    Code:
    <integration:annotation-driven/>         
    <integration:message-bus auto-create-channels="true" channel-factory="queueChannelFactory" error-channel="errorChannel"/>
    
    ...
    
    <context:component-scan base-package="paths to scan"/>
    P.S. The forum software on here seems to think anything with an at symbol in it is a link.

  2. #2
    Join Date
    Oct 2007
    Location
    London, England
    Posts
    108

    Default

    What makes you think this is not being proxied?

    Did you add @Component to your publisher?

    Below is a sample I tested against head.

    Regards

    Jonas

    Code:
    @Component
    public class PublisherBean {
    	
    	public PublisherBean(){
    		System.out.println("publisher created");
    	}
    	
    	@Publisher(channel="messageChannel")
    	public String getMessage(){
    		return (new Date()).toString() + " hello";
    	}
    
    }
    Code:
    public class PublisherDemo {
    
    	public static void main(String[] args){
    		ApplicationContext appCtx = new ClassPathXmlApplicationContext("annotationDemo.xml", PublisherDemo.class);
    		PublisherBean publisher = (PublisherBean)appCtx.getBean("publisherBean");
    		
    		publisher.getMessage();
    		publisher.getMessage();
    	}
    
    }
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/integration"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:beans="http://www.springframework.org/schema/beans"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
    			http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    			http://www.springframework.org/schema/integration
    			http://www.springframework.org/schema/integration/spring-integration-1.0.xsd
    			http://www.springframework.org/schema/context
    			http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
    	<message-bus />
    	<annotation-driven />
    	<context:component-scan base-package="org.springframework.integration.samples.annotations"/>
    	<channel id="messageChannel"/>
    	<console-target id="console"/>
    	<target-endpoint target="console" input-channel="messageChannel"></target-endpoint>
    	
    </beans:beans>

  3. #3
    Join Date
    May 2007
    Location
    Netherlands
    Posts
    614

    Default

    Quote Originally Posted by kmurphy View Post
    Code:
    <context:component-scan base-package="paths to scan"/>
    There's your problem. You have to specify the proper path ("com.yourcompany.yourpackage") in the component scan, otherwise your component won't be picked up.

    You can try to wire the bean in the context using <bean:bean .../>. Then you'll be sure that the proxying works like it should.

    What really makes me scratch my head though is how you can debug something that isn't being invoked... or how you can have it invoked if it wasn't proxied. I must be missing something. Does Jonas' config work for you?

  4. #4
    Join Date
    Jun 2008
    Posts
    18

    Default

    Quote Originally Posted by iwein View Post
    There's your problem. You have to specify the proper path ("com.yourcompany.yourpackage") in the component scan, otherwise your component won't be picked up.
    That was purely for example, the actual application context has the full path (actually several comma delimited) specified and I know it's working because all the beans are being injected properly. Almost all the components of the project use one of the Component annotations and they're injected into each other using the Autowired annotation on various properties.

    Quote Originally Posted by iwein View Post
    What really makes me scratch my head though is how you can debug something that isn't being invoked... or how you can have it invoked if it wasn't proxied. I must be missing something. Does Jonas' config work for you?
    It is being invoked, because the bean (the one that should be proxied) is being injected into another one and the method with the Publisher annotation is being called. When I breakpoint on that method though, there's no trace of the proxy in the call stack (and my Subscriber annotated method never gets called). I know what a java or cglib proxy looks like when you're doing debugging as I've worked with AOP before, but for whatever reason it seems like the around advice isn't being applied. I haven't tried the code Jonas provided yet, but that will be my next test.

  5. #5
    Join Date
    Jun 2008
    Posts
    18

    Default ?

    Well, I just tried Jonas code, and it works using all the same libraries as included in my project. I even modified it to make it more like my code by removing the retrieval and invocation of PublisherBean from the main method and instead injecting the bean inside another one and calling its getMessage method in a PostConstruct annotated method. I can see when I debug this one that it is being proxied by cglib, which makes me wonder what I'm doing wrong in my project that's preventing the proxy from being created as the code is nearly identical.

    Ok, inside my main method I've got a block of code that looks more or less like this:
    Code:
    		log.debug("Instantiating ApplicationContext from " + applicationContext);
    		this.context = new ClassPathXmlApplicationContext(applicationContext);
    		log.debug("Registering shutdown hooks.");
    		context.registerShutdownHook();
    Then on the bean I'm trying to make into a publisher I have Component and 'Publisher(channel="selectionChannel")' annotations. On another bean in the project I have:
    Code:
    @Autowired
    	private PublisherBean publisherBean;
    Which in that beans PostConstruct annotated method injects that bean into another one. However, when I breakpoint inside that bean to see what's being injected into the other one, it's the raw PublisherBean without a cglib proxy around it. In contrast when I breakpoint the code Jonas posted at that same point (I reworked the code so it injects the PublisherBean into another bean) I can clearly see a cglib proxy around PublisherBean.

    This really has me scratching my head. I can't understand why, when using exactly the same libraries, and more or less exactly the same code in the various classes, I'm getting two completely different results. I even checked to see how the applicationContext.xml files differ and they're virtually identical.

  6. #6
    Join Date
    Jun 2008
    Posts
    18

    Default Updated Code

    If you're curious the extra bean I added to Jonas code follows (and works apparently):

    Code:
    import javax.annotation.PostConstruct;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class InjectionTest {
    	@Autowired
    	private PublisherBean publisherBean;
    	
    	@PostConstruct
    	public void init() {
    		publisherBean.getMessage();
    	}
    }

  7. #7
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,853

    Default

    Quote Originally Posted by kmurphy View Post
    Which in that beans PostConstruct annotated method injects that bean into another one. However, when I breakpoint inside that bean to see what's being injected into the other one, it's the raw PublisherBean without a cglib proxy around it.
    Can you post the code for your PostConstruct-annotated method? (the original, not the modified version of Jonas' code). Based on the quote above, it sounds like you may be passing a 'this' reference to another bean?

    Regards,
    Mark

  8. #8
    Join Date
    Jun 2008
    Posts
    18

    Default

    Quote Originally Posted by Mark Fisher View Post
    Can you post the code for your PostConstruct-annotated method? (the original, not the modified version of Jonas' code).
    It's pretty big, but I can post the relevant parts. Also, because the forum software on here treats anything with an at symbol in it as a link I can't post the annotations properly.

    Code:
    	Autowired
    	private PublisherBean publisherBean;
    
    ...
    
    	SuppressWarnings("unused")
    	PostConstruct
    	private void doInit() {
    		initComponents();
    		resetModel();
    		this.validate();
    		setWriteable();
    	}
    
    ...
    
    	private void initTableGroups() {
    
    		...
    
    		jTable.getSelectionModel().addListSelectionListener(
    				publisherBean);
    
    		...
    
    	}
    When I breakpoint on the line inside the initTableGroups() method and check this.publisherBean it's not wrapped in a cglib proxy like it should be (incidentally my PublisherBean is a ListSelectionListener). I could understand maybe if the class was final, although if I remember trying to proxy a final class throws an exception at runtime, but the class isn't final so that can't be the problem.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •