Unit test of Spring Webflow which uses bean configuration inheritance by extending AbstractXmlFlowExecutionTests - spring

We have upgraded Spring WebFlow from 1 to 2.4.1. Now we need to rewrite all of our Unit tests. One issue is stopping us dead in our tracks. Most of our flows still import action beans and forms, as we are still using XML configurations. In addition, all of the action beans inherit configuration via an abstract bean reference in the webflow configuration file. So we have the following bean reference in our webflowContext.xml:
<bean id="serviceInjected" abstract="true">
<property name="serviceLocator" ref="serviceLocator"/>
<property name="misAssembler" ref="misAssembler"/>
<property name="formObjectScope" value="FLOW"/>
</bean>
All of the Action beans thus inherit the serviceLocator, misAssembler and formObjectScope. When I try to unit test the flows, the tests fails because there is no "serviceInjected" bean reference. So my question is:: How can we insert bean configuration inheritance into the test before we attempt to start the flow. Using configureFlowBuilderContext will not work as this change the ApplicationContext and not the ExternalContext. I have only seen one other reference to this on the internet and that question was not answered, so here is hoping I have better luck.

Related

Spring Config Client XML equivalent of #RefreshScope

We have an existing Spring MVC application (non Spring-boot application) with all (or most) of the beans configured in the XML. We wanted to use this as a Spring Cloud Config Client (we have a Spring Boot application acting as config server).
In this regard, what is the XML equivalent of configuring the beans in XML with refresh scope (same as #RefreshScope annotation). Tried configuring the RefreshScope as bean and using scope="refresh" but could see that the beans are not reflected with new values after peforming /refresh endpoint (from actuator)
Any help on this is highly appreciated
As pointed out in other answers 'refresh' scope is just another scope. However there's an issue where the bean properties are not updated with new values after /refresh call - if you define and inject properties in XML. More on the issue here. However the bean (i.e. actually the proxy) is instantiated after each /refresh call - but you need "aop:scoped-proxy" config since bean to which you inject the 'refresh' scoped bean, could be on a different scope. i.e.
<bean name="xmlValueBean" class="me.fahimfarook.xml.XMLValueBean" scope="refresh">
<aop:scoped-proxy proxy-target-class="true" />
</bean>
Well if you want to use #RefreshScope in core Spring(also Spring MVC) as people already pointed out, you have to implement the scope yourself also.
I also had the same dilemma and I did, I also wrote a blog about it, you can find there all the implementation details.
You can also use Spring Boot Configuration Server with your Spring MVC application, if you like to.
#RefreshScope for Spring MVC
#RefreshScope is just another scope. Look at how the RefreshScope class is implemented. It is creating a new scope named "refresh".
That means you should be able to use the new scope in your XML configuration, like this.
<bean id = "..." class = "..." scope = "refresh">
</bean>

Why is Spring 4.0.9 applicationContext initialization getting stuck but not 3.2.1?

My applicationContext initialization was working fine with Spring 3.2.1.
But when I upgraded to 4.0.9 without changing any code or bean definitions), the initialization got stuck. The following statement kept on happening. There's no obvious circular reference though.
Requested bean is currently in creation: Is there an unresolvable circular reference?
I continued to investigate. I deliberately removed a bean definition.
Spring 3.2.1 had the expected outcome: threw a fatal error almost immediately.
Spring 4.0.9 was still getting into this infinite loop, trying to find a different seed bean definition to make things work.
Here's the log statement that kept on happening.
[factory.support.DefaultListableBeanFactory.getTypeForFactoryBean()] - Ignoring bean creation exception on FactoryBean type check:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'someSeedBean-which-is-different-in-every-instance-of-this-log' defined in the class path resource ........ ;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'someDataSource' is defined
What's changed? Any ideas would be helpful.
Bean definitions that work in both Spring 3.x and 4.x
<bean id="abstractDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" abstract="true" scope="singleton">
<property ....>
</bean>
<bean id="someDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" scope="singleton" parent="abstractDataSource">
<property name="driverClass" .... />
</bean>
<bean id="someSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource"> <ref bean="someDataSource" /> </property>
<property name="packagesToScan"> <list>......</list> </property>
....
Bean definitions that work in Spring 3.x but not in 4.0.9.
#Configuration
public class SomeSpringConfiguration{
// Moving this beanDef to Java for features not available in XML
#Bean(destroyMethod = "close")
public DataSource someDataSource() { // also tried setting this to ComboPooledDataSource
// verified that this beanDefinition is recognized by Spring
// but this bean is never created / this method is never executed
...
return datasource;
}
}
<bean class="SomeSpringConfiguration" />
<bean id="someSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource"> <ref bean="someDataSource" /> </property>
<property name="packagesToScan"> <list>......</list> </property>
....
</bean>
Error I get with Spring 4.0.9 is
Cannot resolve reference to bean 'someSessionFactory' while setting constructor argument;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'someSessionFactory':
Requested bean is currently in creation: Is there an unresolvable circular reference?
Please note that the application has thousands of beans defined in/via xml, #Component, and #Configuration. I had to move above bean from xml to a #Configuration class to execute a complicated bean build procedure.
-----------------------UPDATE
I found the issue: 'tons of MethodInvokingFactoryBean[MIB] usages'. For some reason, Spring 4 was getting confused in presence of tons of MIBs. The exact same code base worked fine with Spring 3. I migrated all the logic performed by various MIBs to an ApplicationListener. Please note that ApplicationListener is not an intended replacement for MIBs but in my case I could reproduce the logic in a listener because the MIBs were just performing static injection of Spring beans into classes not managed by Spring. It not only fixed this issue but decreased Spring startup time to ~200 seconds from ~300 seconds.
Unfortunately, I neither could figure out the root cause in Spring nor could reproduce the issue in a smaller code-base (to share here).
Remove
<bean class="SomeSpringConfiguration" />
from XML, it's already annotated with #Configuration. If it's being scanned it's likely the beans in it are getting created twice. You should move everything into Javaconfig.
Circular references are common during development, when you have a lot of beans and are not careful when you autowire them together. The stacktrace should contain the complete list of beans, telling you where the circular reference starts and ends.
I have never seen random circular references (and I encountered circular references many times over the last 7 years)! As far as I know, the code that builds the dependency tree and instantiates/wire the beans is deterministic. So you should always get the same circular reference every time you run. If you don't, I can only thing of two reasons
There is a bug in the Spring version you are using (I'm 99% sure there is a unit test for this)
You have one of more beans that starts a thread as part of bean instantiation, and the thread uses the applicationContext to load another bean lazily (while the context is still loading).
When I teach Spring classes, I recommend that constructors should only contain field assignments, if you need to start threads (or anything else with a lifecycle) you should use the lifecycle methods. Personally I prefer to implement SmartLifeCycle (over InitializingBean/DisposableBean, #PostConstruct/#PreDestroy), since this ensures that nothing will started until after all beans have been instantiated and wired together.
The core of it is as Strelok says, you are mixing annotations and xml config.
The point of the #Configuration annotation is to avoid xml. When you added the component scan for the package after removing SomeSpringConfiguration from xml.
You would start to create multiples of someDataSource, because it is defined in multiple places (#Bean annotation, and in xml).
Please avoid mixing annotations and xml, only use one of them and stick to that, and this problem will, if not resolved but at least much easier to spot.
If you can create an example project and upload it somewhere I can take a closer look if you are still having this issue.

Spring AOP not working on all annotation methods

I have created a custom annotation in my spring mvc project.
The annotation is used to do an AOP
#Around("execution(#Cached * * (..)) && #annotation(cache)")
Here the annotation that I have created is "Cached", any method with the annotation is cached in couch base with the response as its value and the method argument as its key.
The problem is the annotation works (AOP works) on the controllers well. However from controllers, I am making call to different callable classes and utils. When I add the annotation" #Cached" on the callable classes or the util funcations the AOP doesn't work.
In the XML file, the following is what I have declared.
<aop:aspectj-autoproxy/>
<context:spring-configured/>
<context:component-scan base-package="com.abc.xyz">
<!--<context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/>-->
</context:component-scan>
<bean id="universalController" class="com.abc.xyz.misc.UniversalController"/>
<bean class="com.abc.xyz.api.metric.SystemTiming"/>
<bean class="com.abc.xyz.api.annotations.URLCacheImpl"/>
With Spring AOP, your classes which match the pointcut (where you have placed your #Cached annotation in this specific case) should be Spring beans. So the best guess that I can make is that your utility classes are very likely not Spring beans and that is reason why they are not getting woven in. You have two options that I can think of:
Make your utility classes also clean Spring beans
Use full Aspectj support - this way even though your utility classes are not Spring beans they would be woven with the advice.

How to wire a SessionFactory into a Hibernate Interceptor with Spring? [duplicate]

I want to declare two beans and instantiate them using Spring dependency injection?
<bean id="sessionFactory" class="SessionFactoryImpl">
<property name="entityInterceptor" ref="entityInterceptor"/>
</bean>
<bean id="entityInterceptor" class="EntityInterceptorImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
But Spring throws an exception saying "FactoryBean which is currently in creation returned null from getObject"
Why is inter-dependent bean wiring not working here? Should i specify defferred property binding anywhere?
Unfortunately the way container initialization works in Spring, a bean can only be injected in another bean once it is fully initialized. In your case you have a circular dependency that prevents either bean to be initialized because they depend on each other. To get around this you can implement BeanFactoryAware in one of the beans and obtain the reference to the other bean using beanFactory.getBean("beanName").
neesh is right, Spring doesn't do this out of the box.
Interdependent beans hint at a design problem. The "clean" way to do this is to redesign your services in such a way that there are no such odd dependencies, of course provided that you have control over the implementations.
You can implement a BeanPostProcessor that sets the dependency.
Or...
See Costin's reply here:
http://forum.springframework.org/showthread.php?t=19569&highlight=circular+dependencies
See Andreas' reply here:
http://forum.springframework.org/showthread.php?t=29572&highlight=circular+dependencies
you can extend the ApplicactionContext that are using and override the method createBeanFactory()
protected DefaultListableBeanFactory createBeanFactory(){
DefaultListableBeanFactory beanFactory = super.createBeanFactory();
// By default this is false;
beanFactory.setAllowRawInjectionDespiteWrapping( true );
return beanFactory;
}
This works, but be careful because this allows circular references.

Replace spring bean in one context with mock version from another context

I'm writing an integration test where an application context xml is initialized during startup. There are several test methods in the test class which make use of a specific bean 'X'(already defined in the xml). My actual requirement is to mock bean X only for one of the test methods.
Inside a test method: I tried creating a separate application context using ClassPathXMLApplicationContext with only the mock bean 'M'.
Now I have two Application Contexts (AC):
1. One created during test case startup (which contains the actual bean X) and
2. One created using ClassPathXMLApplicationContext within the test method (which has the mock bean M).
I want to replaced the actual bean definition 'X' within AC:1, using the mock bean definition 'M' from AC:2.
Can somebody throw some light on this please?
You can :
use the Profile annotation if you have spring 3.1.
use the Primary annotation
use qualifiers
wire the bean yourself in the spring context
and i'm sure there are even more options.
There is not a clear way to replace a a bean in a refreshed ApplicationContext unless you close it and refresh it again.
To emulate it, the common approach is to use a Proxy of the bean that you want to replace and change the target at runtime.
You can do it easily using the framework aop support classes:
<bean id="realBean" class="RealClass" />
<bean id="mockBean" class="MockClass" />
<bean id="targetSource" class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg ref="realBean" />
</bean>
<bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref="targetSource" />
</bean>
#Test
public void testWithMockBean() {
Object real = targetSource.swap(mock);
....
// do your test work
...
targetSource.swap(real);
}
Create a testApplicationContext with
<beans>
<import resource="classpath*:appContext.xml" />
<bean id="mockbeanOfX" class=....../>
</beans>
and then load this test application context in your testcase. Now you can get the mock bean from the application context and pass it whereever needed.

Resources