Spring MVC: disable DefaultAnnotationHandlerMapping - java

I'm using Spring MVC with <mvc:annotation-driven />
I've implemented my own mapping handler extending DefaultAnnotationHandlerMapping, but I'm not sure how to use it. I've declared it like this:
<bean class="es.kcsolutions.boulevard.DispatcherMappingHandler" />
It works, but, obviously, DefaultAnnotationHandlerMapping works too and always before mine. Is there a way to disable it and use only mine?
Thanks.

My advice would be to remove the <mvc:annotation-driven /> altogether. It doesn't really do anything particularly useful - most of the beans it declares are there already. And in cases where you want to declare your own handler mapping or handler adapter, it just gets in the way.
So take it out, declare your own DefaultAnnotationHandlerMapping bean, and it should work. No need to mess about with ordering in 99.9% of cases.

If you take out any explicit declarations of the DefaultAnnotationHandlerMapping then your custom mapper is supposed to replace it in the dispatcher. (according to javadoc) If you need/want more than one mapping, then you control them by setting their Order property. Lower order numbers execute first.
<bean class="es.kcsolutions.boulevard.DispatcherMappingHandler">
<property name="order" value="0"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="1"/>
</bean>

Related

How to inject an attribute using spring in a type handler?

I'm setting up an application which uses mybatis to map objects to/from the database.
In my mybatis file, I use a typehandler to map one of the objects being sent to the database.
In the typeHandler, I am injecting an attribute using spring #resource.
However, when the typehandler is called, the injected property is always null.
From my research, I have discovered that mybatis sets its configuration before spring loads. That means the bean is cannot be injected into the handler as it is created after.
Does anyone know a solution to this?
Should let spring manage customized type handler, like this:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="typeHandlers">
<array>
<bean class="com.example.YourCustomTypeHandler">
<!-- inject -->
<property name="property" ref="bean"/>
</bean>
</array>
</property>
</bean>

Nesting abstract beans in Spring and init-method does not seem to work

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.

Spring #transactional behaving strangely with mode=aspectj

I've been trying to get Spring transactions working properly in my application for days, and now I have nowhere to turn but to the community. Thanks in advance for your help.
My application has specific requirements where I need to annotate a protected overridden method with #Transactional and call this method from the abstract parent class. From what I've read, I can not use proxies, and must use mode=aspectj.
First, some configuration:
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="false" mode="aspectj" />
<context:load-time-weaver />
<bean name="ID_DataAccessor" class="dal.DataAccessor">
<constructor-arg ref="dataSource" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost" />
.....
<property name="defaultAutoCommit" value="true" />
</bean>
If I use the #Transactional annotation on a method in ID_DataAccessor, then the connection is transactional (DataSourceUtils.isConnectionTransactional(c, dataSource) == true). This is useless to me though, because the transaction commits as soon as the method is completed. When I use #Trasnactional on a method that calls a method in DataAccessor, the connection aquired in DataAccessor (from DataSourceUtils.getConnection(dataSource)) is NOT transactional. Additionally, I put a breakpoint in DataSourceTransactionManager.doGetTransaction(), and this is only called if the #Transactional annotation is directly on the method acquiring the connection. Forgive me for overloading the terminology, but it appears that the #Transactional annotation does not propagate up the stack.
I'm completely baffled. Please help! :)
I just about gave up on this one. It was quite non-obvious. Your problem is caused by using the EndOfDayProcess class in your entry point. It's a problem because it causes the class to be loaded, and more generally, it'll extend to any of your *Process and *EntryPoint classes. At that point in your code, Spring hasn't been started yet, so its load-time weaver isn't active, and the class gets loaded normally, without the transaction code woven into it. Of course, classes are only loaded once, so it's there to stay, and when you create the bean in Spring, it's a bean whose type doesn't have anything to do with transactions, except it has #Transactional annotations on it. By then, there's nobody there to see them anymore, though. I see two possible (good) solutions:
Switch to build-time weaving. Then it's impossible to load a class before it's woven.
Change the way you determine which *Process bean to use based on the entry point. Use anything you like except for something that causes the *Process class to be loaded.

conditional beans using spring

I am trying to write a ValidatorFactory which will give me a validator based on its type
public Validator getNewValidator(ValidatorType type){
switch:
case a : new Validator1();
break;
case b : new Validator2();
break;
}
I want to write using spring xml beans definition
I can use method injection but it will let me create only one object and the method does
not take any arguments.
I don't want to use FactoryBean.. I am just looking whether we can do this using spring xml
bean definition.
you can do conditional bean injection with plain xml. The "ref" attribute can be triggered by property values from a property file and thus create conditional beans depending on property values. This feature is not documented but it works perfect.
<bean id="validatorFactory" class="ValidatorFactory">
<property name="validator" ref="${validatorType}" />
</bean>
<bean id="validatorTypeOne" class="Validator1" lazy-init="true" />
<bean id="validatorTypeTwo" class="Validator2" lazy-init="true" />
And the content of the property file would be:
validatorType=validatorTypeOne
To use the property file in your xml just add this context to the top of your spring config
<context:property-placeholder location="classpath:app.properties" />
For complex cases (more complex than the one exposed), Spring JavaConfig could be your friend.
If you are using annotation (#Autowired, #Qualifier etc) instead of xml, you are not able to make conditional beans work (at least at current version 3). This is due to #Qualifier does not support expression
#Qualifier(value="${validatorType}")
More information is at https://stackoverflow.com/a/7813228/418439
I had an slightly different requirements. In my case I wanted to have encoded password in production but plain text in development. Also, I didn't have access to parent bean parentEncoder. This is how I managed to achieve that:
<bean id="plainTextPassword" class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder"/>
<bean id="shaPassword" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
<constructor-arg type="int" value="256"/>
</bean>
<bean id="parentEncoder" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource">
<bean class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg ref="${password.encoding}Password"/>
</bean>
</property>
</bean>
Of course, I defined password.encoding in a property file with possible values as sha or plainText.
You should be able to do this:
<bean id="myValidator" factory-bean="validatorFactory" factory-method="getNewValidator" scope="prototype">
<constructor-arg><ref bean="validatorType"/></constructor-arg>
</bean>
<bean id="validatorType" ... />
Of course, it uses an automatically configured FactoryBean underneath but you avoid any Spring dependency in your code.

How do I inject a single property value into a string using spring 2.5.x?

I would really like to annotate a method with a reference to a single property in a property file for injection.
#Resource("${my.service.url}")
private String myServiceUrl;
Of course, this syntax does not work ;) Thats why I'm asking here.
I am aware that I can inject the full properties file, but that just seems excessive, I dont want the property file - I want the configured value.
Edit: I can only see PropertyPlaceholderConfigurer examples where XML is used to wire the property to the given field. I still cannot figure out how this can be achieved with an annotation ?
I know it has been a while since the original post but I have managed to stumble across a solution to this for spring 2.5.x
You can create instances of "String" beans in the spring xml configuration which can then be injected into the Annotated components
#Component
public class SomeCompent{
#Autowired(required=true
#Resource("someStringBeanId")
private String aProperty;
...
}
<beans ....>
<context:component-scan base-package="..."/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
...
</bean>
<bean id="someStringId" class="java.lang.String" factory-method="valueOf">
<constructor-arg value="${place-holder}"/>
</bean>
</beans>
I've created a project which addresses this problem for Spring 2.5.*:
http://code.google.com/p/spring-property-annotations/
For Spring 3 you can use the #Value("${propery.key}") annotation.
There's a thread about this on the Spring forum. The short answer is that there's really no way to inject a single property using annotations.
I've heard that the support for using annotations will be improved in Spring 3.0, so it's likely this will be addressed soon.
you can do this if you use XML configuration. Just configure PropertyPlaceholderConfigurer and specify property value in configuration
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:com/foo/jdbc.properties</value>
</property>
</bean>
<bean ...>
<property name="myServiceUrl" value="${my.service.url}"/>
</bean>
You could try injecting value of property "my.service.url" to a filed in your bean.
Take a look at: http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-factory-placeholderconfigurer
HTH.

Categories

Resources