spring integration and component scan - java

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.

Related

Getting bean descriptions from a spring application context xml without initializing the beans?

Is there a decent way to read a spring application context from xml without initializing the beans right away, so they can be mocked or not, before they are actually created?
Yes, I know about lazy-init, but the actual applicationContext.xml is taboo for me.
The situation is that I have to create some JUnit tests on an application which has been created in a way that puts some difficulties in the way:
the configuration file must not be altered, nor the code that is to be tested
there are a lot of beans, some of them rather complex and hard to mock
part of the test is to use as many of the beans un-mocked as possible
some of the beans implement InitializingBean, verifying the environment on initialization and throw errors when Jenkins tries to build.
new FileSystemXmlApplicationContext("config.xml") immediately initializes the beans and throws errors if not in an appropriate environment.
What I have tried:
I have tried Powermock whenNew to mock the offending beans but to do that I would have to know the class which actually creates the beans. As this class belongs to the spring framework, it may change with future versions. When using #PrepareEverythingForTest it results in an StackOverflow exception. The application is real life, not a small piece of code from some tutorial.
I also searched for something like ForceLazyFileSystemXmlApplicationContext but didn't find anything.
Pleas don't start nagging about bad design, I know about that.
You can write your own applicationContext for your testing purpose. There you need to write your own BeanFactory. In that factory you can replace some of beans with mocks.
I just remembered about an option. Evaluate if you can use spring profiles. It will allow to choose a different implementation based on profiles.
Example:
<!-- This is the default myBean -->
<beans>
<bean id="myBean" class="mypackage.MyBean" />
</beans>
<!-- This is the mocked myBean for testing purposes, it will take place when testingProfile is active -->
<beans profile="testingProfile">
<bean id="myBean" class="mypackage.MyBeanMock" />
</beans>
You can indicate which profile to use via properties or environment variables. Example, if you are using maven in your project you could run the tests as:
mvn test -Dspring.profiles.active="testingProfile"
Take a look at:
http://www.baeldung.com/spring-profiles
https://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/

How is Spring Container created?

I am studying for the Spring Core certification and I have following doubt about this question:
What is meant by “container” and how do you create one?
I know that the Spring container is at the core of the Spring Framework. The container will create the objects, wire them together, configure them, and manage their complete lifecycle from creation till destruction. The Spring container uses dependency injection (DI) to manage the components that make up an application. These objects are called Spring Beans which we will discuss in next chapter.
And I know that there exist 2 containers:
Spring BeanFactory Container: This is the simplest container providing basic support for DI and defined by the org.springframework.beans.factory.BeanFactory interface. The BeanFactory and related interfaces, such as BeanFactoryAware, InitializingBean, DisposableBean, are still present in Spring for the purposes of backward compatibility with the large number of third-party frameworks that integrate with Spring.
Spring ApplicationContext Container: This container adds more enterprise-specific functionality such as the ability to resolve textual messages from a properties file and the ability to publish application events to interested event listeners. This container is defined by the org.springframework.context.ApplicationContext interface.
Ok...this is pretty clear for me but what is the correct answer about How to create a container?
I think that it is automatically created by the Spring when it reads the configuration class or the XML configuration file.
Or not? What am I missing?
In short, "The Container" is a Spring instance in charge of managing the lifecycle of your beans.
To create one, basically, you should do something like
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/application-context.xml");
Remember replacing /application-context.xml by the file where you define your own Spring beans.
Take a look at http://www.springbyexample.org/examples/intro-to-ioc-creating-a-spring-application.html
You could also substitute the xml by a configuration class. On that case you should have something like this:
#Configuration
public class Myconfig{
#Bean
public MyBean myBean(){
return new MyBean();
}
}
For this, take a look at http://www.tutorialspoint.com/spring/spring_java_based_configuration.htm

Spring support for #Controller given by <context:component-scan /> vs <mvc:annotation-driven>

I've been researching what additional capabilities we have when using the mvc:annotation-driven tag and I'm having a difficult time digesting the results, especially in regards to the #Controller annotation. I know this is very similar to this question but please hear me out.
According to the Spring docs
The basic purpose of the #Controller annotation is to act as a stereotype for the annotated class, indicating its role. The dispatcher will scan such annotated classes for mapped methods, detecting #RequestMapping annotations (see the next section).
The documentation then goes on to show that the context:component-scan tag provides this support. So that's all well and good, but then I was looking at what mvc:annotation-driven gives us, and the aforementioned stackoverflow question provides the following answer
mvc:annotation-driven declares explicit support for annotation-driven MVC controllers (i.e. #RequestMapping, #Controller, although support for those is the default behaviour), as well as adding support for declrative validation via #Valid and message body marshalling with #RequestBody/ResponseBody.
This seems kind of redundant to me. Maybe I don't get what this explicit support is. Again, referring back to the official Spring documentation we get the following
[mvc:annotation-driven] registers the DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter beans that are required for Spring MVC to dispatch requests to #Controllers.
That sounds pretty similar to the last example I provided from the docs. If anyone can provide some examples as to what we can do with the #Controller annotation using only the context:component-scan tag, what some of the limitations are, then the additional functionality of what we get when adding the mvc:annotation-driven tag, I think that would be very helpful. Thanks in advance for any support on this.
Both elements serve an entirely different purpose.
<context:component-scan /> is, as the name implies, for component scanning. It by default scans for all beans with the #Component annotation (or "sub"annotations like #Controller, #Service etc.). It will only register instances of those classes in the application context as beans. That is all.
<mvc:annotation-driven /> is for bootstrapping Spring MVC and it registers, amongst others, a RequestMappingHandlerMapping and RequestMappingHandlerAdapter. The first links requests to a certain method (the #RequestMapping annotation on methods in a #Controller annotated class). The last knows how to execute methods annotated with #RequestMaping.
Now <mvc:annotation-driven /> does nothing for scanning or detecting #Controllers if there are none in the application context then no request mappings are made. Now you have several ways of registering those beans in the application context and one of them is the aforementioned <context:component-scan />.
Basically a #Controller without <mvc:annotation-driven /> is, well, pretty useless as it does nothing but take up memory. It will not be bound to incoming requests, it just hangs around in the application context. It is just another bean like all other beans and nothing special is being done to it. (Recent, but deprecated, versions of Spring register the DefaultAnnotationHandlerMapping which processes the #Controller, this is however deprecated).
The context:component-scan element lists a package that Spring should scan for #Controller annotations (in the base-package attribute).
the mvc:annotation-driven has no such attribute. This is a convenience element that installs a lot of default MVC elements into the application context. These elements are listed in section 16.14.1 of the Spring framework reference. This element does not appear to scan for #Controller annotations.
Contrary to popular belief, there is no dependancy between these elements. An #Controller without mvc:annotation-driven will function without an issue and handle HTTP requests just fine, as long as you have included context:component-scan with an appropriate base-package attribute.
Case 1(annotation-driven)
This is Enabling Spring annotations tag.
All the annotations such as #Controller, #Service, #Autowired etc.. can be used.
This doesn't creates a bean, but find the the annotations, and spring creates corresponding bean for that class if found annotation(such as #Controller, #Service, #Autowired etc..) .
Case 2(component-scan)
Spring will scan the package (and subpackages) of the classes specified in declaration and creates bean for it.

How to exclude beans/packages from Spring AOP processing scope

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.

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

Categories