shardingsphere-elasticjob icon indicating copy to clipboard operation
shardingsphere-elasticjob copied to clipboard

DataSourceConfiguration.createDataSource,invoke setter method,When the setter method is overloaded and the parameter type is not String, throw java.lang.IllegalArgumentException: argument type mismatch

Open yyyhhx opened this issue 1 year ago • 1 comments

Bug Report

Please answer these questions before submitting your issue. Thanks!

Which version of ElasticJob did you use?:ElasticJob-Lite3.0.2,Spring Boot v2.3.4,druid1.2.8

Which project did you use? ElasticJob-Lite or ElasticJob-Cloud?:ElasticJob-Lite

Expected behavior:Application run success

Actual behavior : ERROR org.springframework.boot.SpringApplication : Application run failed

java.lang.IllegalArgumentException: argument type mismatch at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_301] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_301] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_301] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_301] at org.apache.shardingsphere.elasticjob.tracing.rdb.datasource.DataSourceConfiguration.createDataSource(DataSourceConfiguration.java:121) ~[elasticjob-tracing-rdb-3.0.2.jar:3.0.2] at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) ~[na:1.8.0_301] at org.apache.shardingsphere.elasticjob.tracing.rdb.datasource.DataSourceRegistry.getDataSource(DataSourceRegistry.java:65) ~[elasticjob-tracing-rdb-3.0.2.jar:3.0.2] at org.apache.shardingsphere.elasticjob.tracing.rdb.datasource.DataSourceConfiguration.getStorage(DataSourceConfiguration.java:102) ~[elasticjob-tracing-rdb-3.0.2.jar:3.0.2] at org.apache.shardingsphere.elasticjob.tracing.rdb.datasource.DataSourceConfiguration.getStorage(DataSourceConfiguration.java:43) ~[elasticjob-tracing-rdb-3.0.2.jar:3.0.2] at org.apache.shardingsphere.elasticjob.tracing.listener.TracingListenerFactory.getListener(TracingListenerFactory.java:56) ~[elasticjob-tracing-api-3.0.2.jar:3.0.2] at org.apache.shardingsphere.elasticjob.tracing.JobTracingEventBus.register(JobTracingEventBus.java:69) ~[elasticjob-tracing-api-3.0.2.jar:3.0.2] at org.apache.shardingsphere.elasticjob.tracing.JobTracingEventBus.(JobTracingEventBus.java:57) ~[elasticjob-tracing-api-3.0.2.jar:3.0.2] at org.apache.shardingsphere.elasticjob.lite.internal.schedule.LiteJobFacade.(LiteJobFacade.java:73) ~[elasticjob-lite-core-3.0.2.jar:3.0.2]

Reason analyze (If you can)

When the setter method is overloaded,findSetterMethod,Only the method name and only one parameter are judged. If there is a method overload and the parameter type is not String, an argument type mismatch exception will be thrown,It is necessary to judge that the parameter type of the setter method is String

Steps to reproduce the behavior.

Example codes for reproduce this issue (such as a github link).

private Optional<Method> findSetterMethod(final Method[] methods, final String property) {
    String setterMethodName = Joiner.on("").join(SETTER_PREFIX, CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, property));
    for (Method each : methods) {
        if (each.getName().equals(setterMethodName) && 1 == each.getParameterTypes().length) {
            return Optional.of(each);
        }
    }
    return Optional.empty();
}
@SneakyThrows(ReflectiveOperationException.class)
public DataSource createDataSource() {
    DataSource result = (DataSource) Class.forName(dataSourceClassName).getConstructor().newInstance();
    Method[] methods = result.getClass().getMethods();
    for (Entry<String, Object> entry : props.entrySet()) {
        if (SKIPPED_PROPERTY_NAMES.contains(entry.getKey())) {
            continue;
        }
        Optional<Method> setterMethod = findSetterMethod(methods, entry.getKey());
        if (setterMethod.isPresent()) {
            setterMethod.get().invoke(result, entry.getValue());
        }
    }
    Optional<JDBCParameterDecorator> decorator = findJDBCParameterDecorator(result);
    return decorator.isPresent() ? decorator.get().decorate(result) : result;
}

yyyhhx avatar Nov 24 '22 09:11 yyyhhx

Thanks for your feedback. Using reflection is not a good way to construct a DataSource. This should be refactored.

TeslaCN avatar Dec 12 '22 08:12 TeslaCN