Spring Integration: Autowiring Queues Failing when using JMX - java

I can autowire two QueueChannel instances using #Autowired and #Qualifier in a test class just fine, until I add JMX export namespace handlers.
I've not got the exact config handy (it was a problem at work that's now bugging me out of hours!), but I'm using these elements:
<int-jmx:mbean-export default-domain="com.business" server="mbeanServer" />
<context:mbean-export />
<context:mbean-server />
When I've got these three things defined, the autowiring process fails throwing a NoSuchBeanException. However, I can see that there are beans with the IDs of my queues, as I've got a post processor that's iterating over all beans in the context.
Is this something to do with proxying obfuscating the declared type of the QueueChannels, preventing autowiring-by-type working?

You need to autowire using the interface instead of the concrete class because the JMX export wraps the channel in a proxy. Use PollableChannel for QueueChannel, or SubscribableChannel for DirectChannel.
It's always good practice to code using interfaces rather than concrete classes, for exactly this reason.

Related

Spring without getBean(..)

I'm trying to get a better understanding of the #Autowired annotations component scanning, but all the examples I found so far use context.getBean(..) at some point to get at least one Bean to start with.
I also read that doing that is considered bad practice , but I can't seem to find any information on how to do it without context.getBean(..)
Could somebody please enlighten me with an example and information on how to do this ?
Define your bean in xml and use
<context:component-scan base-package="com" />
<mvc:annotation-driven />
Bean def
<bean id="processEngine" class="com.processEngine">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
now you can get bean as following
#Autowired
private ProcessEngine processEngine;
how it works
spring scans the bean's recipes either from xml or java configuration. then spring creates a beanDefinitions which are 'loaded' into BeanFactory. BeanFactory triggers a set of BeanPostProcessors (BPP) which are scanning classes for particular annotations like Autowired/Resource/PostProcessor and etc. and do appropriate actions. in case when your class contains #Autowired annotation, AutowiredAnnotationBeanPostProcessor would auto wire required field (dependencies), and when creation of an object is done and all BPP worked out, object is ready to be used by the app, from this point your code can get 'ready' objects from container.
there are some cases when you would need to access this beans from the code which is out of spring's control and not managed by container. in order to do so, you would need to get the ApplicationContext (container) and call #getBean specifying either name or type. using applicationContext directly is not a good practice because there are some problems that you can come to, f.ex. id of a bean might be changed and if you refer to bean by id then NPE would be thrown.
configuration
there are several approaches to configure spring to scan the classes for finding bean recipes. one would be defining component-scan, in this case classes which are located in the path that you've set and having any of valid spring annotations like #Component, #Service, #Repository, #Controller (for web container) would be considered. another way would be specifying each bean separately using <bean> or #Bean.
examples.
if you want to create a web app then you should see DispatcherServlet with ContextLoaderListener classes. this classes would boot your app and load everything according to configuration. f.ex. here,
but if you want to create a desktop app, then you would end up with something like this
From time to time (usually when not using Spring Boot), I use something along the lines of the following code:
public static <T> T autowire(ApplicationContext ctx, T bean) {
ctx.getAutowireCapableBeanFactory().autowireBean(bean);
return bean;
}
In my main, I create an instance of the main application class that contains a few #Autowired annotations for the main services / entry points to my Spring application.

Registering DirectChannelMetrics as a JMX Bean programmatically

I have a Spring integration application with several FileTailingMessageProducers and DirectMessageChannels created programmatically -- i.e. not through XML configuration, but within a ApplicationListener<ContextRefreshedEvent>. Now I would like to monitor the message channels using JMX. I guess I will have to add them using my integrationMBeanExporter.
This is what I tried:
DirectChannelMetrics directChannelMetrics = new DirectChannelMetrics(tailedLines, "tailedLines");
integrationMBeanExporter.getServer().registerMBean(directChannelMetrics, new ObjectName("d:foo=foo"));
Yet I am getting the following Exception:
javax.management.NotCompliantMBeanException: MBean class org.springframework.integration.monitor.DirectChannelMetrics does not implement DynamicMBean, and neither follows the Standard MBean conventions
It is surprising to me, that the DirectChannelMetrics does not fulfill JMX requirements, since when I look into my application with jvisualvm I can see other beans of this type registered without problems.
Any ideas?
From one side MBeanExporter does this on the matter:
return new StandardMBean(bean, ((Class<Object>) ifc));
Before registering bean as an MBean.
From other side I think your logic smells a bit. It looks abnormal to create MessageChannels at runtime. Especially those which are for the JMX export.
I can agree about dynamic FileTailingMessageProducers, but seems for me we can avoid dynamic channels with refactored logic for the predefined channels.
You could leverage Spring's MBeanExport.registerManagedResource(directChannelMetrics, new ObjectName("d:foo=foo")). Spring will generate a management interface for the instance of DirectChannelMetric class. But DirectChannelMetric class needs either to implement the Mbean/MXBean interface or to match current MBeanInfoAssembler expectations(be marked with the #ManagedResource annotation in the case of MetadataMBeanInfoAssembler or implements one of specified interfaces in the case of InterfaceBasedMBeanInfoAssembler etc).

Instantiating arbitrary classes thru Spring

I'm writing a service registry class. This service registry will scan packages for annotated classes and then populate some internal map. What I need then, is to be able to query for services (by String name) using some method (let's say Object get(String name)). This method will then search internal map for a service with such name and returns instance.
What I'm doing right now, is having this ServiceRegistryBean implement ApplicationContextAware and BeanDefinitionRegistryPostProcessor and a list of Strings (package names) given on construct.
Then, as soon as the bean is constructed, registry post processor kicks in (see note) and the registry class adds the service classes as new beans (singleton, lazy loaded) to the spring bean registry. Then, getting the service instance is as simple as requesting a bean from context, returning singleton instance.
My question is: is there a better way in Spring to do this? I've looked into bean factories, but it does not seem to me the same. Support for auto-wiring and DI in service instances is essential, that's why I want Spring to instantiate it. Also, I like the idea of Spring taking care of singletons.
Note: I've found out, that when I inline the bean creation in <constructor-arg> (that is, bean is not named and is just an instance passed as constructor argument of other bean - in my case, I'm passing registry as a parameter to other constructor), BeanDefinitionRegistryPostProcessor interface methods (namely public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)) is not called at all! I'm quite sure, it is some behavior of Spring I don't know about, but I was not able to find proper documentation for the post-processor.
Thank you for any hints or insights!
Scanning for custom annotations it's already supported, you only need to add a include-filter to <context:component-scan> tag, ie
<context:component-scan base-package="org.example">
<context:include-filter type="annotation" expression="some.Annotation"/>
</context:component-scan>
see http://static.springsource.org/spring/docs/current/spring-framework-reference/html/beans.html#beans-scanning-filters
If you turn on default-lazy-init I suppose that the DI Container is ready to use as Service Locator Registry.
About the note, only root bean definitions are taken into account when looking for BeanFactoryPostProcessors, inner beans are ignored.
Usually, scanning and registering beans is done by BeanDefinitionParsers instead because you known when the beans are registered and beans are visible for tools, like STS Spring Bean Explorer, but using a BeanDefinitionRegistryPostProcessor is correct. The interface ensures that beans are defined before other BeanFactoryPostProcessors run.

Spring 3 bean is not being wired correctly

I have a web controller which I configure in the controller-config.xml using
<mvc:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.ecommerce.web.controller" />
The controller has the #Controller annotation like below.
#Controller
public class HomeController
I have included the #Autowired annotation on the dependencies, but when I first start up the application I am unable to set any properties on the wired objects.
For example, I have a storeProfile object which when in debug mode I see has multiple properties set as it should.
But, when I try to set one of the storeProfile properties on an #Autowried bean it is still null or empty string!?
If you look at the attached images it shows that after I step past the line this.storeProfileContext.setStoreProfile(storeProf ile) the debugger still shows the storeProfile property as null
Actually, there are a couple dependencies which look like they are created (they are not null and the application functions), but I am unable to set anything on these objects.
I asked the same question on the Spring forums too - hoping to get this figured out.
Thanks so much!
That is because you are looking at the fields of the proxy, which gets created when you have <aop:scoped-proxy/>, if you invoke your getter for the set values, you should see the correct values retrieved from the proxied object.
The instances you are examining are CGLIB proxies.
CGLIB subclasses your beans, delegating all method invocations to the target beans.
So the fields of the super classes are still present but not used.

How to automatically create and inject a proxy of a missing dependency?

Given the following classes:
package com.acme;
public class Foo {
private Bar bar;
public void setBar(Bar newBar) {
this.bar = newBar;
}
}
#AcmeService
public interface Bar {}
and a Spring configuration file of:
<beans>
<bean id="foo" class="com.acme.Foo">
<property name="bar" ref="bar" />
</bean>
</beans>
when Spring's configuration phase runs, is it possible to do the following?
Catch the missing dependency exception (or detect that there is going to be one)
Discover that the missing dependency "bar" of bean "foo" is of type com.acme.Bar
Notice that Bar is an #AcmeService, and so we're going to handle it. Otherwise, the error can be considered fatal
Generate a proxy of type com.acme.Bar
Inject the Bar proxy into Foo, ensuring that method calls on Bar can be advised with Spring AOP just as if I had explicitly created the Bar proxy in the Spring config file and injected the proxy into the Foo bean.
I was initially drawn to BeanPostProcessor and BeanFactoryPostProcessor as a means to implement this, although upon reading the documentation I did not see an obvious way of doing precisely what I want.
In case you're wondering, the underlying use case is that I want to:
Replace all Spring context files with my service-layer bean definitions with a single context file that generates proxies of #AcmeService bean interfaces.
Advise invocations against those proxies to instead be invoked on interface mocks of the service layer bean proxies. (The kicker is that the mocks are defined at runtime by a remote system and are uploaded to this app for integration testing purposes. For my regular unit tests, I do the more sane thing of simply creating and injecting mocks as needed).
I have all of that working except for the whole "dynamically generate proxies" bit. Currently I have empty implementations of my service interfaces defined in my context file just so they can be injected and advised - but I'd rather not have so many empty interface classes generated and checked in. And lastly, I assume I need to generate these proxies as I do not know how to advise attempted invocations on null dependencies.
OK, there's a number of things in here to talk about.
Firstly, I don't think you'll be able to do exactly what you're asking. In particular, if you have <property name="bar" ref="bar"/> and there is no bean definition for bar, the bean initialization will fail, and I don't think you can intercept that easily. You could, of course, write your own subclass of the BeanFactory itself, but that's not something to be taken lightly.
The closest existing mechanism to what you're asking for is auto-wiring. Take a look at AutowiredAnnotationBeanPostProcessor. You could use this as a guide for writing your own BeanPostProcessor which looks at every bean as it's instantiated by the container, looking for properties which are of types which in turn have the #AcmeService annotation. When it finds one, it can generate a proxy for that type and inject it.
That brings us on to the proxy generation itself. The place to look for that is ProxyFactory. This allows you to generate objects at runtime that implement any interface or extend any class, whilst attaching advisors/interceptors. These interceptors can do all the work - the proxy doesn't have to have anything "behind" it if you don't want to.
With this approach, you wouldn't need the "hanging" <property name="bar" ref="bar"/> entry in your config - the presence of the property in Foo would be enough to trigger the process.

Categories

Resources