Mariusz Jaskółka
Mariusz Jaskółka

Reputation: 4482

Spring MVC Converters doesn't work at all

I'm very new to Spring MVC and Java EE at all (I came from PHP+Zend2). My english is poor too. I use NetBeans. My problem is that my custom converter does not work. Here's some code:

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

<bean id="universalDAO" class="dao.UniversalDAO"/>
<bean id="sessionManager" class="utils.SessionManager"/>

<bean id="idToEntityConverterFactory" class="utils.IdToEntityConverterFactory">
    <property name="dao" ref="universalDAO"/>
</bean>

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <ref bean="idToEntityConverterFactory" />
            <bean id="temp" class="utils.TempConverter" />
        </list>
    </property>
</bean>

<bean name="universalService" class="service.UniversalService">
    <property name="universalDAO" ref="universalDAO"/>
</bean>

<bean name="sessionApplicationService" class="service.SessionApplicationService">
    <property name="universalDAO" ref="universalDAO"/>
    <property name="sessionManager" ref="sessionManager"/>
</bean>

<bean name="systemUserApplicationService" class="service.SystemUserApplicationService">
    <property name="universalDAO" ref="universalDAO"/>
</bean>

<aop:aspectj-autoproxy />
<bean id="loggerAspect" class="aspect.LoggerAspect"/>

</beans>

I also have tried version with:

class="org.springframework.format.support.FormattingConversionServiceFactoryBean"

IdToEntityConverterFactory is a ConverterFactory created with this tutorial but it is not important now. I wrote simpler one not to do mess.

TempConverter.java

package utils;

import entity.Role;
import org.springframework.core.convert.converter.Converter;

public class TempConverter implements Converter<String, Role> {

    @Override
    public Role convert(String id) {
        return new Role();
    }
}

Here is .jsp fragment:

    <form:select path="${names[item.index]}" items="${valueOptions[names[item.index]]}" />

When I submit the form there appears an error:

Failed to convert property value of type java.lang.String[] to required type java.util.List for property roleList; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [entity.Role] for property roleList[0]: no matching editors or conversion strategy found

I found solution to similar problem here . It has something to do with

<mvc:annotation-driven>

but I don't use such tag anywhere in my application (should I?).

My question is how to make any converter work while binding form data to Java object.

EDIT:

I figured out some workaround. I have overriden initBinder method in my Controller:

@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
    binder.setConversionService(conversionService);
}

conversionService had to be previously set in Controller of course:

private ConversionService conversionService;
//...
public void setConversionService(ConversionService conversionService) {
    this.conversionService = conversionService;
}

dispatcher-servlet.xml:

<bean class="controller.SystemUserFormController" p:applicationService-ref="systemUserApplicationService" p:sessionManager-ref="sessionManager" p:conversionService-ref="conversionService" />

It works now but it is kind of inconvenience because:

Kindest regards!

Upvotes: 1

Views: 1761

Answers (2)

Pavel Horal
Pavel Horal

Reputation: 18204

Your questions:

I have to add extra code p:conversionService-ref="conversionService" in every Controller I need converter to be used.

  • You can use @Autowired to inject ConversionService.
  • You can implement common parent class for your controllers with @InitBinder
  • You can use abstract parent bean definition <bean abstract="true" ...>

It works out-of-the-box in every toutorial I found on the internet but not for me. I am just curious what am I doing different.

Just use <mvc:annotation-driven>. This easy-to-use configuration is there so that you don't need to configure stuff manually.


How to do it

You can implement WebBindingInitializer. This bean needs to be set up on handler adapter.

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="webBindingInitializer" ref="yourBindingInitializer" />
</bean>

However this approach is kind of painful if you are not already defining hanlder adapter yourself. When you define this bean it disables some DispatcherServlet's default behavior. So you might need to do a bit more than to define this bean.


Off-topic advice

Problem with Spring is that the internet is full of obsolete tutorials. Please use the official guide and reference app. Start using namespace (or even Java) config, autowiring, @Controller components and @RequestMapping.

Upvotes: 2

Mariusz Jask&#243;łka
Mariusz Jask&#243;łka

Reputation: 4482

I belive there is not such think as mvc:annotation-config. There are 2 other things:

  • context:annotation-config
  • mvc:annotation-driven

Please tell me if I am wrong

I have tried both and both doesn't work. Here's what what have I done:

  • Removed p:conversionService-ref="conversionService" from my Controller bean
  • Added @Autowired annotation to my setter

    @Autowired public void setConversionService(ConversionService conversionService) { this.conversionService = conversionService; }

  • Added context:annotation-config/ (or mvc:annotation-driven/) to applicationContext.xml

Unfortunately setter has never been executed!

My source is here

Quote: "When Spring finds an @Autowired annotation used with setter methods, it tries to perform byType autowiring on the method."

I also have tried using setter with exactly the same type as bean class - still nothing.

Upvotes: 0

Related Questions