I have two Spring proxies set up:
<bean id="simpleBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="simpleBeanTarget"/>
</property>
<property name="interceptorNames">
<list>
<value>cacheInterceptor</value>
</list>
</property>
</bean>
<bean id="springDao" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="springDaoTarget"/>
<property name="interceptorNames">
<list>
<value>daoInterceptor</value>
</list>
</property>
</bean>
simpleBean works just fine -- springDao does not.
The SpringDao class looks like:
public class SpringDao extends JdbcDaoSupport {
private SimpleJdbcTemplate simpleJdbcTemplate;
public SimpleJdbcTemplate getSimpleJdbcTemplate() {
if (simpleJdbcTemplate==null) {
simpleJdbcTemplate= new SimpleJdbcTemplate(getDataSource());
}
return simpleJdbcTemplate;
}
...
And I have my unit test autowired like this:
#Autowired
#Qualifier("springDao")
protected SpringDao springDao;
And the first indication something is wrong is I get this error:
Could not autowire field: . . . nested
exception is
java.lang.IllegalArgumentException
If I comment out the #Qualifier annotation and run my unit test again, I get this:
No unique bean of type ... expected
single matching bean but found 2:
[springDaoTarget, springDao]
That is what I expected.
So I changed my autowiring to
#Autowired
#Qualifier("springDaoTarget")
protected SpringCustomerCapacityDao springDao;
And added the following to my unit test:
Object proxy = applicationContext.getBean("springDao");
Assert.assertNotNull(proxy);
Assert.assertTrue(proxy instanceof SpringDao);
And the instanceof test failed, which (to me) means that my proxy is not really my proxy.
So I'm confused. What's going on? How can I fix this?
Edit Here is the requested springDaoTarget definition, which will disappoint many people:
<bean id="springDaoTarget" class="com.company.SpringDao">
If the target of your proxy implements at least one interface then Spring's default behavior is to create a JDK Proxy that implements all the interfaces of the target. This means it will not be a subclass of the target class. You can override this by forcing the creation of CGLIB proxies instead which are dynamic subclasses of the target.
As a general rule, if you are going to use AOP but only use interfaces in a limited fashion you'll want to force CGLIB. Otherwise you will have lots of JDK Proxies in your container which are not of the same type as the bean implementations you loaded.
See Cliff Meyers blog: Spring AOP: CGLIB or JDK Dynamic Proxies?
It was easy to fix, once I figured it out. SpringDao no longer inherits from JdbcDaoSupport and now it works.
Related
A class named DefaultGetFreeSchedulePolicyImpl have a field whose type is an interface named IRemoveSchedulePolicy, while IRemoveSchedulePolicy have 2 implements: DefaultRemoveFreeSchedulePolicyImpl and DefaultRemoveSchedulePolicyImpl.
public class DefaultGetFreeSchedulePolicyImpl {
...
IRemoveSchedulePolicy removeSchedulePolicy;
}
In spring xml, there do exist two version of class DefaultGetFreeSchedulePolicyImpl bean configs, but both of them use the same removeSchedulePolicy :
<bean id="extendsGetFreeSchedulePolicy"
class="com.xx.xx.xx.policy.freeSchedule.impl.DefaultGetFreeSchedulePolicyImpl">
...
<property name="removeSchedulePolicy" ref="removeSchedulePolicy" />
</bean>
<bean id="dateGetFreeSchedulePolicy"
class="com.xx.xx.xx.policy.freeSchedule.impl.DefaultGetFreeSchedulePolicyImpl">
...
<property name="removeSchedulePolicy" ref="removeSchedulePolicy" />
</bean>
And bean removeSchedulePolicy has only one bean:
<bean id="removeSchedulePolicy"
class="com.xx.xx.xx.policy.freeSchedule.impl.DefaultRemoveSchedulePolicyImpl"></bean>
Base on information above, I expect that, Intellij IDEA can be as smart as human that, know which bean to go when I want to find the implement of the method, but it didn't:
Is it because I use Intellij IDEA in the wrong way? Is anywhere I can config such that Intellij IDEA can read the Spring bean definition then just show me the right bean method implement?
I have the following construct Spring XML (Spring 3.1):
<bean id="taskRunner" abstract="true" init-method="startThreads"
class="my.class.TaskRunner" />
...
<bean id="taskRunnerA" parent="taskRunner">
<constructor-arg name="foo">...</constructor-arg>
<property name="bar">...</property>
</bean>
And I am trying to separate out the init method into a higher level abstract bean:
<bean id="taskRunnerLauncher" abstract="true" init-method="startThreads" />
<bean id="taskRunner" abstract="true" depends-on="taskRunnerLauncher"
class="my.class.TaskRunner" />
...
<bean id="taskRunnerA" parent="taskRunner">
<constructor-arg name="foo">...</constructor-arg>
<property name="bar">...</property>
</bean>
Somehow this does not work, i.e. startThreads() is never invoked in the second case. Does anybody know why? Does Spring support nested abstract beans?
My idea for doing this is so I can override "taskRunnerLauncher" in unit tests and set it to "mock" or "java.lang.Object" and suppress startThreads() call (which starts new thread and making it a pain to test).
Does anybody know why?
The taskRunnerLauncher bean is set to be abstract. This means it will only act as a template for other beans. Spring will not actually create a bean for it. Therefore there won't be any invocation of startThreads because there is nothing to invoke it on.
Found the problem. I mistakenly used depends-on instead of parent attribute on taskRunner bean.
I've got a MyAppConversionServiceFactoryBean which I'm registering like:
<bean id="conversionService" class="com.MyProject.MyAppConversionServiceFactoryBean">
<property name="messageSource" ref="messageSource"/>
<property name="converters">
<set>
<bean class="com.MyProject.XRepresentationConverter" />
<bean class="com.MyProject.YRepresentationConverter" />
<bean class="com.MyProject.ZRepresentationConverter" />
</set>
</property>
</bean>
I can continue to list every converter we write into this list, but I'd love to be able to configure it such that this isn't necessary and that converters will automatically register themselves somehow with my factory.
Sidebar 1: If that's not possible with a custom factory, is it possible with the default spring one?
Sidebar 2: If neither the first part nor Sidebar 1 is possible, is it possible to #Autowired the conversionService into the converters (so they can easily call one another)? Attempting to #Autowired ConversionService conversionService has previously given me issues due to not being able to wire the conversionService into an object while it's still busy creating the service.
Note: We're using Spring, but not Spring MVC. I have no control over that, so any solutions on that route will be unfortunately unusable. I can change pretty much anything else about the configuration and Java classes, just not the overarching tools.
#Vikdor's comment on the question pointed me in the right direction.
Spring is apparently capable (and no one I asked in person knew this) of gathering collections of beans through the scanning process with #Autowired annotations. Here's what I needed to achieve the same effect I got from the configuration in the post:
applicationContent.xml must have:
<context:component-scan base-package="com.MyProject"/>
<bean id="conversionService" class="com.MyProject.MyAppConversionServiceFactoryBean" />
MyAppConversionServiceFactoryBean.java:
public class MyAppConversionServiceFactoryBean implements
FactoryBean<ConversionService>, InitializingBean {
#Autowired
private Set<BaseConverter> converters;
}
And then all of my converters now have the #Component annotation.
Relevant Docs on #Autowired do briefly mention that it can be used to collect all beans of a type, but I wouldn't have known that it could be done into any collection type without this thread by Grzegorz Oledzki which addresses the generic form of my question, but takes it down a philosophical route.
Can someone explain ProxyFactoryBean in simple terms?
I see this being quoted lot of places.
ProxyFactoryBean is used to apply interceptor logic to an existing target bean, so that when methods on that bean are invoked, the interceptors are executed before-and-after that method call. This is an example of Aspect Oriented Programming (AOP).
This is best explained using a simple example. A classic use-case for AOP is to apply caching to the result of a method call. This could be wired up using ProxyFactoryBean as follows:
<bean id="targetService" class="com.x.MyClass"/>
<bean id="cachingInterceptor" class="com.x.MyCachingInterceptor"/>
<bean id="cachedService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="targetService"/>
<property name="interfaces">
<list>
<value>com.x.MyService</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>cachingInterceptor</value>
</list>
</property>
</bean>
We have a bean targetService of type com.x.MyClass, which implements the interface com.x.MyService. We also have a interceptor bean called cachingInterceptor, which implements the interface org.aopalliance.intercept.MethodInterceptor.
This config will generate a new bean, called cachedService, which implements the MyService interface. Any calls to the methods on that object will first be passed through the cachingInterceptor object's invoke() method, which in this case would look for the results of previous method calls in its internal cache. It would either return the cached result, or allow the method call to proceed to the appropropriate method on targetService.
targetService itself knows nothing of this, it's completely unaware of all this AOP stuff going on.
ProxyFactoryBean is heavily used internally within Spring to generate proxies for a variety of reasons (e.g. remoting stubs, transaction management), but it's perfectly suitable for use in application logic also.
The ProxyFactoryBean applies aspects to an existing bean. You start out with your existing bean (the target bean), which spring "wraps" to add the aspects you provide. The returned bean has the same interface as your original bean, but with the additional aspects weaved around the target bean's methods.
I have two xml files defining beans for the springframework (version 2.5.x):
containerBase.xml:
<beans>
<bean id="codebase" class="com.example.CodeBase">
<property name="sourceCodeLocations">
<list>
<value>src/handmade/productive</value>
</list>
</property>
</bean>
</beans>
... and
containerSpecial.xml:
<beans>
<import resource="containerBase.xml" />
</beans>
Now I want to adjust the property sourceCodeLocations of bean codebase within containerSpecial.xml. I need to add a second value src/generated/productive.
A simple approach is to override the definition of codebase in containerSpecial.xml and add both values, the one from containerBase.xml and the new one:
containerSpecial.xml:
<beans>
<import resource="containerBase.xml" />
<bean id="codebase" class="com.example.CodeBase">
<property name="sourceCodeLocations">
<list>
<value>src/handmade/productive</value>
<value>src/generated/productive</value>
</list>
</property>
</bean>
</beans>
Is there a way to extend the list without redefining the bean?
EDIT 2009-10-06:
The purpose of this is to have a shared standard container containerBase that is used by a lot of different projects. Each project can override/extend some properties that are special for that project in its own containerSpecial. If the project doesn't override, it's using the defaults defined in containerBase.
You could use a BeanFactoryPostProcessor to change the bean's metadata before the Spring container instantiates the CodeBase bean. For example:
public class CodebaseOverrider implements BeanFactoryPostProcessor {
private List<String> sourceCodeLocations;
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
CodeBase codebase = (CodeBase)beanFactory.getBean("codebase");
if (sourceCodeLocations != null)
{
codebase.setSourceCodeLocations(sourceCodeLocations);
}
}
public void setSourceCodeLocations(List<String> sourceCodeLocations) {
this.sourceCodeLocations = sourceCodeLocations;
}
}
Then in contextSpecial.xml:
<beans>
<import resource="context1.xml" />
<bean class="com.example.CodebaseOverrider">
<property name="sourceCodeLocations">
<list>
<value>src/handmade/productive</value>
<value>src/generated/productive</value>
</list>
</property>
</bean>
</beans>
Yes. A bean definition can have a "parent" attribute that references a parent bean definition. The new "child" definition inherits most of the properties of the parent and any of those properties can be overridden.
See Bean Definition Inheritance
Also you can use Collection Merging to merge the list property definition from the parent and child bean definitions. This way you can specify some list items in the parent bean definition and add more items to it in the child bean definition.
Is there a way to define the list in a properties or other configuration before hand?
It seems like the app configuration and wiring are tightly coupled. From my experience, if it is hard to do something in Spring, likely there is a different easier way to do it.
3 approaches:
Simple: have two lists defaultSourceCodeLocations and additionalSourceCodeLocations and have your accessor methods check both of these (or combine them). I've seen this done in some frameworks - a default list of handlers is populated then additional user created ones are added...
More complicated but keeps the original class clean: You could then create a CodeBaseModifier class. This would have a init-method to alter an injected instance of the bean.
<bean id="codebaseModifier" class="com.example.CodeBase" init-method="populateCodeBase">
<property name="sourceCodeLocations" ref="codebase"/>
<property name="additionalSourceCodeLocations">
<list>
<value>src/handmade/productive</value>
</list>
</property>
</bean>
If you wanted to make this really generic you could make a bean modifier that would do this by reflection. Be careful of the ordering if use this approach. Dependent beans of CodeBase would have to make sure this class was instantiated first (with depends on)
3 A variation on 2... Instead of directly creating a CodeBase class instead create a factory that returns a populated bean. This factory could then be configured with Spring in a similar fashion to 2. Have a defaultSourceCodeLocations and additionalSourceCodeLocations
Unless you need a lot of extensible properties I would go with option 1.
In Spring 3.0, you can specify merge="true" on the 'list' tag. See http://forum.springsource.org/archive/index.php/t-97501.html for details.