You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Krzysztof Jamróz (Jira)" <ji...@apache.org> on 2021/01/29 11:00:00 UTC

[jira] [Created] (CAMEL-16111) Bean reference by name in properties not working when there are custom property converters

Krzysztof Jamróz created CAMEL-16111:
----------------------------------------

             Summary: Bean reference by name in properties not working when there are custom property converters
                 Key: CAMEL-16111
                 URL: https://issues.apache.org/jira/browse/CAMEL-16111
             Project: Camel
          Issue Type: Bug
    Affects Versions: 3.7.1
            Reporter: Krzysztof Jamróz


Bean reference by name ({{#bean:name syntax}}) in properties not working when there are custom converters registered in Spring Boot Application. I use Spring Boot 2.4.2 and Camel 3.7.1 to create Quartz component with manally defined scheduler via property:

{{camel.component.quartz.scheduler=#quartzScheduler}}

This causes error:
{quote}Failed to bind properties under 'camel.component.quartz.scheduler' to org.quartz.Scheduler:

Property: camel.component.quartz.scheduler
 Value: #quartzScheduler
 Origin: class path resource [application.properties] - 93:34
 Reason: No converter found capable of converting from type [java.lang.String] to type[org.quartz.Scheduler]
{quote}
Previously, in Spring Boot 2.3.0 and Camel 3.3.0 it worked ok.


 Debugging shows that problem is caused by the fact that:
 * {{QuartzComponentConverter}} registers itself only in {{ApplicationConversionService.getSharedInstance}}
 * {{QuartzComponentConverter}} is _not_ a bean in Spring context
 * {{org.springframework.boot.context.properties.ConversionServiceDeducer.Factory.create()}} creates separate instance of {{ApplicationConversionService}} if there are any custom converters (which indeed are present in application configuration)

Quick workaround is to add custom property converter similar to {{QuartzComponentConverter}} that will be picked by the {{ConversionServiceDeducer}}:

{code:java}
@ConfigurationPropertiesBinding
@Component
public class QuartzComponentPropertyConverter implements GenericConverter {
    @Autowired
    private ApplicationContext applicationContext;

    public Set<ConvertiblePair> getConvertibleTypes() {
        Set<ConvertiblePair> answer = new LinkedHashSet<>();
        answer.add(new ConvertiblePair(String.class, org.quartz.Scheduler.class));
        answer.add(new ConvertiblePair(String.class, org.quartz.SchedulerFactory.class));
        return answer;
    }

    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        if (source == null) {
            return null;
        }
        String ref = source.toString();
        if (!ref.startsWith("#")) {
            return null;
        }
        ref = ref.startsWith("#bean:") ? ref.substring(6) : ref.substring(1);
        switch (targetType.getName()) {
        case "org.quartz.Scheduler":
            return applicationContext.getBean(ref, org.quartz.Scheduler.class);
        case "org.quartz.SchedulerFactory":
            return applicationContext.getBean(ref, org.quartz.SchedulerFactory.class);
        }
        return null;
    }

}
{code}




--
This message was sent by Atlassian Jira
(v8.3.4#803005)