0
votes

I want to use the Spring ConversionService with custom Converter implementations to convert values from Spring XML config.

I configure a bean through xml config like this:

<bean name="A1" class="com.example.MyClass">
    <constructor-arg name="time" value="10"/>
</bean>

The associated class:

import java.time.Duration;

public class MyClass {
    public MyClass(Duration time) {
        System.out.println("TIME: " + time);
    }
}

The converter that should perform the conversion is:

public class StringToDurationInSecondsConverter implements Converter<String, Duration> {
    @Override
    public Duration convert(String source) {
        int seconds = Integer.valueOf(source);
        return Duration.ofSeconds(seconds);
    }
}

The config looks like this:

@SpringBootApplication
public class Application {

    @Bean
    public ConversionService conversionService(
            Set<Converter<?, ?>> converters,
            ConversionServiceFactoryBean factory) {
        factory.setConverters(converters);
        return factory.getObject();
    }

    @Bean
    public ConversionServiceFactoryBean conversionServiceFactoryBean() {
        return new ConversionServiceFactoryBean();
    }

    @Bean
    public StringToDurationInSecondsConverter stringToDurationInSecondsConverter() {
        return new StringToDurationInSecondsConverter();
    }
    // ...
}

The converters are injected as expected into conversionService method, so that the conversionService should be properly initialized. But the conversion of the parameter time in the xml config could not be performed. The error message is:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'A1' defined in resource loaded through SAX InputSource: Unsatisfied dependency expressed through constructor parameter 0: Could not convert argument value of type [java.lang.String] to required type [java.time.Duration]: Failed to convert value of type 'java.lang.String' to required type 'java.time.Duration'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.time.Duration': no matching editors or conversion strategy found

If I set a breakpoint into my convert method it is never reached. So it looks like the converter is never called.

Even If I inject the ConversionService directly to the (modified) MyClass and call the convert method within the constructor ...

public class MyClass {
    public MyClass(String time, ConversionService conversionService) {
        final Duration duration = conversionService.convert(time, Duration.class);
        System.out.println(duration);
    }
}

... I get the exception:

ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.time.Duration]

The core of the application is configured with Springs Java config, but there is some more "volatile" config that is read from a file by another bean (what works apart from the conversion).

Is it possible to use Spring's ConversionService with custom Converters to convert values in a Spring xml config? How?

1
it seems to be failing to create the bean instance of A1. what is the code for class MyClass and what is the type of time in that class. from the error stack it looks like time is of type java.time.Duration to which you are trying to assign 10 as string literal while bean creation.madteapot
The type of time is java.time.Duration. And I'm indeed passing the String "10" to this constructor, but it should be converted to Duration in between. I've added my example class to the question.deamon
I don't think that the way you are trying to use converterService is in correct context. The converterServices are for you to use in your code NOT in a way so spring automatically convert the argument types when instantiating a bean. Take a look at official documentation at docs.spring.io/spring/docs/current/spring-framework-reference/…madteapot
But even If I inject the converter directly, no appropriate converter is found.deamon
i don't think adding the converter to spring context is enough. You need to register it to the converterService refer to accepted answer on stackoverflow.com/questions/25628063/… and official doc docs.spring.io/spring/docs/current/spring-framework-reference/…madteapot

1 Answers

0
votes

Thanks to the comment of Sotirios Delimanolis (on another question) I came to the following solution:

@Bean
public ConversionService conversionService(Set<Converter<?, ?>> converters) {
    final ConversionServiceFactoryBean factory = new ConversionServiceFactoryBean();
    factory.setConverters(converters);
    factory.afterPropertiesSet(); // necessary
    return factory.getObject();
}

Converting attribute values from XML works fine now.