I'm following this scheme in a Spring application.
I asked in this other question what was the best way to prepare the object before populate the params of the request. The answer was that the best way was to use a conversion service instead of doing it in a @ModelAtribute annotated method or with an editor in the initBinder.
So I have tried to use a converter, but I haven't found a similar example and I'm a little stuck. I have written a code like the one below: In the init binder I register the conversion service. So before populating the values on the User object convert() method is invoked to load the object from the database. The problem is that this configuration doen't work because it is converting the id (username field) of the Object User into an Object user, but then it tries to make a setUsername() with the object so I get a "java.lang.IllegalArgumentException: argument type mismatch".
Can anyone give me a clue or an example of the way of using the ConversionService to get the desired behaviour?
Thanks.
@Autowired
private ConversionService conversionService;
@InitBinder("user")
public void initBinder(@RequestParam("username")String username, WebDataBinder binder){
binder.setConversionService(conversionService);
}
@RequestMapping(value="/user/save", method=RequestMethod.POST)
public String save(@ModelAttribute("user") User user, Model model) {
...
}
with something like:
@Component
public class UserConversionService implements ConversionService{
...
@Override
public Object convert(Object name, TypeDescriptor arg1, TypeDescriptor arg2) {
return userService.find((String)name);
}
}
You're trying to implement a ConversionService
to do the conversion between Strings and User objects. However, it's Converter
implementations that do this part. What you want to do is:
Your converter would be something like:
final class UserConverter implements Converter<String, User> {
...
public User convert(String username) {
return userService.find(username);
}
}
You then need to register that converter. You can either write your own ConversionServiceFactoryBean or override the default:
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="example.UserConverter"/>
</list>
</property>
</bean>
If you want to use the ConversionService explicitly, as you have, just leave it as something that can be autowired. Spring and that factorybean definition will take care of the rest.
If, however, you're already using the <mvc:annotation-driven>
tag in your context, you can use its conversion-service
attribute to reference your ConversionServiceFactoryBean. You then don't need to have InitBinder or ConversionService in your class at all: by simply having a parameter of a @RequestMapping have your target type, User, the conversion will take place without you having to intervene.