How to exclude beans/packages from Spring AOP processing scope - java

How to exclude beans, or packages from Spring AOP processing scope?
I encountered this, while fixing Spring Integration JMX support issue on JBoss.
As a development environment, we are using Spring 3.2.0.RELEASE, Spring Integration 2.2.0.RELEASE and Jboss AS 7.1.1.
When enabling Spring Integration JMX, you are actually creating IntegrationMBeanExporter, which extracts all Spring Integration related beans from the underlying ApplicationContext and creates appropriate managed MBeans. For assigning created MBeans to server MBeanServer required, which must be defined in ApplicationContext, which is generally done using standard MBeanServerFactoryBean, which returns platform related MBeanServer.
The problem appeared, because we were using Spring AOP for some enhanced operations, and AOP post processing mechanism was trying to process platform mbeanServer like regular bean, validating initial platform ClassLoader against internal pointcuts, which it eventually failed to do.
This seems to be similar to https://jira.springsource.org/browse/SPR-9335, but with generic specifics.
So as a solution, I prevented spring from processing mbeanServer as a part ApplicationContext :
<bean id="jmxIntegration" scope="singleton" class="org.springframework.integration.monitor.IntegrationMBeanExporter">
<property name="server" value="#{ T(org.springframework.jmx.support.JmxUtils).locateMBeanServer() }"/>
</bean>
This worked, but this seems to be of a more generic problem, with AOP.
Also interesting note is that MBeanExporter in spring also refers to JmxUtils instead of context's MBeanServer.

Related

Use of Bean configuration XML File

I am a new user of Spring framework. I am facing some confusion in understanding the difference between core spring framework and spring boot. As far as I understand, Spring boot is a framework which performs the initial setup automatically (like Setting up Maven dependencies and downloading the jar files) and comes with an embedded Tomcat server which makes it ready to deploy in just one click., Whereas, Spring MVC requires manual setup. All the tutorials that I watched for core spring show bean configuration using bean factory which configures the beans using a .XML file. In Spring boot, this bean configuration file is absent. My question is, what is the use of this bean configuration file? I did not find any legitimate use of this file in making a REST service with spring. I didn't see any use of the Application Context, Bean Factory in creating web application. Can someone point out how can bean factory be used in Spring web apps? Is there any fundamental difference between core spring and spring boot other than the additional components?
The Spring application context is essentially the "pool" of beans (service objects, which include controllers, converters, data-access objects, and so on) and related information that define an application; I recommend the reference introduction. In theory, you can get complicated with the context setup and have hierarchical organization and such, but in most real-world cases you just have a single plain context.
Inside this context you need to install all of the beans that provide the logic for your application. There are several possible ways to do this, but the two main ways are by providing XML files with have directives like bean (define an individual bean) or component-scan (automatically search for classes with certain annotations, including #Controller) and by using Java classes annotated with #Configuration, which can use annotations and #Bean methods.
The XML style is generally older, and newer applications mostly use Java configuration, but both provide entries that are collected into the context, and you can use both simultaneously. However, in any application, you have to provide some way of getting the registration started, and you will typically have one "root" XML file or configuration class that then imports other XML files and/or configuration classes. In a legacy web.xml-based application, you specify this in your servlet configuration file.
Spring Boot is, as you said, essentially a collection of ready-to-go configuration classes along with a mechanism for automatically detecting configurations and activating them. Even this requires a configuration root, though! This is the #EnableAutoConfiguration instruction, frequently used through its composite #SpringBootApplication. The application context and configuration mechanisms work normally once Boot finds them and pulls them in. Spring knows where to get started because you give it an explicit instruction to build a context starting with that entry point, usually with SpringApplication.run(MyApplication.class, args).
The embedded-server configuration just happens to be a particular set of configuration that is really useful and comes with one of the Boot starter packages. There's nothing there that you couldn't do in a non-Boot application.

spring integration and component scan

I'm a newbie with Spring MVC but now i've been moved to a new project which uses Spring Integration to turn in channel some service. Example in the context.xml
<int:channel id="example-channel" />
<int:service-activator input-channel="example-channel" ref="exampleServiceFacade" />
For every servicefacade i have to bind the service to a channel.
I was wandering, what if I could map the classes to be turned into channels as i could map the beans with component-scan?
<context:component-scan base-package="com.package" />
so i ended up with this tutorial which speaks about some annotation:
#IntegrationComponentScan
But i cannot understand how it's related to the xml tag service activator and channel.. So i'm quite confused. Does anyone with more experience have an idea if what i'm trying to do can be done?
I just want to scan con the classes which defines channels in integration without having to declare every class.
Thanks.
Your question is a bit unclear. Any Spring Integration custom XML tag is parsed by infrastructure and registered as beans in the application context. Like you'd do that via raw <bean>.
#ComponentScan, #Configuration, #Bean and so on are marker annotations to say application context which classes treat as beans.
So, using both techniques for application context configuration you don't lose anything and can continue to mark you class with #Service and use its bean name from <service-activator ref="">.
From other side now you can fully build Spring Integration without any XML! Please, read the mentioned doc in its entirety.

Spring MVC 3.1.0 bug? After upgrade controllers are no more autodetected

I'm writing web application that uses Spring MVC to bind Spring beans with REST-like channels.
I've created the configuration basic both on my previous apps (pure XML configuration) and example, which used <mvc:annotation-driven/> feature. I'm pointing a package with controllers with <context:component-scan base-package="my.package"/> in spring xml file.
It is working - in Spring 3.0.6.RELEASE. However, after upgrading to 3.1.0.RELEASE my controllers stopped to be detected and no channel was registered. Spring context contains no implementation of HelloChannel interface.
Is this a bug in this Spring version, or I'm using deprecated configuration, which stopped to be supported in newer version? I got no error or warning, simply no bean is auto-detected.
The controller interface definition looks like that:
#RequestMapping("/config") public interface ConfigChannel
And the implementation:
#Controller
public class ConfigChannelImpl implements ConfigChannel
The Spring documentation indicates that interface-based #Controllers are for proxying transactional methods. As such, you are probably using the <tx:annotation-driven /> tag. The problem you now seem to have is that Spring 3.1 introduced support for CGLIB, a runtime-based bytecode manipulator. You need to add proxy-target-class="true" to your transaction configuration and add CGLIB to your classpath.
<tx:annotation-driven proxy-target-class="true" />
From http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping

Is there any way to enable or disable the Spring bean definition in applicationContext.xml file?

Is there any way to enable or disable a java bean definition in application context?
<bean id="enBean" classs="com.en.bean.BeanName">
<property name="prop1"/>
</bean>
Or, is there any way to load the bean conditionally defined in application context?
There is a new feature #Profile in spring 3.1 that would do the job
From here
Spring 3.1 introduces the concept of environment profiles. A common
use case is the setting up of beans that are different between
development, QA and production environments. A typical example is
going against a standalone DataSource in development versus looking up
the DataSource from JNDI in production. Another example is a beans
profile for profiling that can easily be turned on or off. You can add
a profile attribute on a beans element in XML or add #Profile
annotation in code. Note that a Spring bean can be assigned to
multiple profiles.
<beans profile="dev">
...
</beans>
#Profile("dev")
public class Bean {
...
}
These profiles can be activated through the spring.profiles.active
property which may be specified through an environment variable, a JVM
system property, a Servlet in web.xml or JNDI. These
profiles can also be activated through code using
Environment.setActiveProfiles(String ...). To make bean profiles work,
nested beans elements are now allowed in the Spring XML, although
constrained only at the end of the file. Note that it's recommended to
keep your bean topology as close as possible between environments, so
your application gets properly tested across environments. You also
use the Environment.containsProperty() method to search for properties
across the different property sources. This property resolution also
works for ${placeholder} variables in XML bean definitions.

Forcing Spring's MBeanExporter to use a particular MBeanServer

I have a web application running on JBoss 4.2.2. In order to monitor performance I have enabled the internal platform JMX server that ships with Java 5. In other words, I added:
-Dcom.sun.management.jmxremote
to JBoss' launch script. This works as expected. However, as a result of this, all MBeans are now registered on the platform MBeanServer. I don't want that, I want them to be registered on JBoss' MBeanServer.
The difficulty lies in the fact that I use Spring to register my managed beans. For this, MBeanExporter is used. Thus, I need to tell my MBeanExporter to use JBoss' MBeanServer when registering beans. However, the only exposed method in MBeanExporter to affect what server is used is setServer(MBeanServer mBeanServer). The problem is that I only know how to get a reference to the correct MBeanServer programmatically, and not in Spring's XML, where the MBeanExporter is declared.
My options appears to be:
Write a subclass to MBeanExporter, overriding certain methods, so the correct MBeanServer is loaded
Write a PostBeanProcessor that finds JBoss' MBeanServer and then calls setServer
JNDI? Only works if the MBeanServer is exposed in JNDI, and I haven't been able to find it.
What is the most idiomatic way? Am I doing something really silly?
You can use the static factory method from the JBoss API to inject the MBeanServer into the MBeanExporter:
<bean class="org.springframework.jmx.export.MBeanExporter">
<property name="server">
<bean class="org.jboss.mx.util.MBeanServerLocator" factory-method="locateJBoss"/>
</property>
<!-- Add the rest of your MBeanExporter properties here -->
</bean>
The problem is that I only know how to
get a reference to the correct
MBeanServer programmatically
If you can get the reference programmatically, why can't you wire it in through the MBeanExporter#server property?

Categories