Last Updated
Viewed 25 Times

I wrote the follow piece of code and It works but i'm not sure why. What I wanted is to customize the jdbc configuration of spring-data-jdbc and I extended the configuration with another, what really happen in the IoC Container?

JdbcConfiguration is @Configuration annotated bean that instantiates a JdbcCustomConversions and i'm able to override this behavior subclassing the whole configuration and specifying ma own method, but i'm not really sure why.

@Configuration
public class CustomJdbcConfiguration extends JdbcConfiguration{

    @Override
    protected JdbcCustomConversions jdbcCustomConversions() {
        return new JdbcCustomConversions(Collections.singletonList(CLobToStringConverter.INSTANCE));
    }

    @ReadingConverter
    enum CLobToStringConverter implements Converter<Clob, String>{

        INSTANCE;

        @Override
        public String convert(Clob source) {

            try {
                return IOUtils.toString(source.getCharacterStream());
            } catch (IOException | SQLException e) {
                throw new RuntimeException(e);
            }
        }

    }
}

in my web application developped with GWT, Hibernate ans Spring, I encounter when setting the jobClass bean in the application-context.xml file.

I get this error at runtime :

Error 500 Error creating bean with name 'schedulerFactory' defined in class path resource [application-context.xml]:
Cannot resolve reference to bean 'cronTrigger' while setting bean property 'triggers' with key [0];

nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'cronTrigger' defined in class path resource [application-context.xml]:
Cannot resolve reference to bean 'exampleJob1' while setting bean property 'jobDetail';

nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'exampleJob1' defined in class path resource [application-context.xml]:
Initialization of bean failed;

nested exception is org.springframework.beans.TypeMismatchException:
Failed to convert property value of type [fr.web.utils.ExampleJob] to required type [java.lang.Class] for property 'jobClass';

nested exception is java.lang.IllegalArgumentException:
Cannot convert value of type [fr.web.utils.ExampleJob] to required type [java.lang.Class] for property 'jobClass':
PropertyEditor [org.springframework.beans.propertyeditors.ClassEditor] returned inappropriate value

Here is my Java class :


public class ExampleJob extends QuartzJobBean {
    private AbsenceDao absenceDao; 
    @Override
    protected void executeInternal(JobExecutionContext context)
    throws JobExecutionException {
        List untreatedDemands = new ArrayList();
        untreatedDemands = absenceDao.getDemandsAskedNotValidated();
    }
    public AbsenceDao getAbsenceDao() {
        return absenceDao;
    }
    public void setAbsenceDao(AbsenceDao absenceDao) {
        this.absenceDao = absenceDao;
    }
}

and here is my application-context.xml :

    <!-- variables d'environnement - fichier properties -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="placeholderconfig">
        <property name="fileEncoding" value="UTF-8"/>
        <property name="locations">
            <list>
                <value>classpath:internal.properties</value>
            </list>
        </property>
    </bean>

    <!-- Configuration du crontrigger -->
    <bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="cronTrigger" />
            </list>
        </property>
    </bean>
    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail">
            <ref local="exampleJob1" />
        </property>

        <property name="cronExpression">
            <util:constant static-field="fr.web.utils.APP_VAR.CRON_EXPRESSION" />
        </property>
    </bean>

    <bean id="jobClass" class="fr.web.utils.ExampleJob">
        <property name="absenceDao" ref="absenceDao"/>
    </bean>

    <bean id="exampleJob1" class="org.springframework.scheduling.quartz.JobDetailBean">
        <property name="jobClass" ref="jobClass" />
        <property name="jobDataAsMap">
            <map>
                <entry key="timeout" value="5" />
            </map>
        </property>
    </bean>

    <tx:annotation-driven transaction-manager="hibernateTransactionManager"/>

    <!-- Bean containing all the properties of the application -->
    <bean class="fr.web.utils.ApplicationProperties" id="applicationProperties" lazy-init="true" scope="singleton">
        <constructor-arg index="0" value="classpath:internal.properties"/>
    </bean>

    <!-- Bean DAO -->
    <bean abstract="true" id="abstractDao">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    <bean class="fr.web.dao.AbsenceDao" id="absenceDao" parent="abstractDao"/>

    </bean>
</beans>

I'm trying to understand Spring Java based configuration. Typically I might have an XML configuration containing something like:

<context:property-placeholder location="jdbc.properties"/>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
  p:driverClassName="${jdbc.driverClassName}"
  p:ur="${jdbc.url}"
  p:username="${jdbc.username}"
  p:password="${jdbc.password}"/>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
        p:dataSource-ref="dataSource" />

My effort to produce an equivalent but using Spring Java based configuration has stalled. I'm not sure what to do when trying to inject my dataSource into a jdbcTemplate:

@PropertySource("classpath:jdbc.properties")
@Configuration
public class Config {

  @Bean
  public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
  }

  @Bean(name = "dataSource")
  public DataSource dataSource(
    @Value("${jdbc.driverClassName}") final String driverClassName,
    @Value("${jdbc.url}") final String url,
    @Value("${jdbc.username}") final String username,
    @Value("${jdbc.password}") final String password) {
    BasicDataSource datasource = new BasicDataSource();
    datasource.setDriverClassName(driverClassName);
    datasource.setUrl(url);
    datasource.setUsername(username);
    datasource.setPassword(password);
    return datasource;
  }

  @Bean(name = "jdbcTemplate")
  public JdbcTemplate jdbcTemplate() {
    return new JdbcTemplate(
      /* Property 'dataSource' is required and needs to be referenced
       * What goes here?
       */
    );
  }

}

My guess is there isn't a direct equivalent and I may need to go about things in a subtly different way?

I have below bean configuration in Spring XML that reads some property files. Then I use the bean serverPropertyLoader as factory-bean to create another bean serverProperties of type java.util.Properties by factory-method. I pass the bean serverProperties to org.springframework.context.support.PropertySourcesPlaceholderConfigurer in the next configuration to allow spring handle the property injection.

<bean name="serverPropertyLoader" class="com.xxx.utils.ServerPropertyLoader">
    <constructor-arg name="propertyFiles">
        <list>
            <value>config.properties</value>
        </list>
    </constructor-arg>
</bean>

<bean id="serverProperties" factory-bean="serverPropertyLoader" factory-method="getProperties" />

<bean id="propertyPlaceholder" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
    <property name="propertiesArray">
        <list>
            <ref bean="serverProperties" />
            <ref bean="databaseProperties" /> <!-- Another Type of Properties -->
        </list>
    </property>
</bean>

Now I want to use either serverPropertyLoader or serverProperties inside Spring Java Configuration to read some property while creating a bean as below.

@Configuration
public class DataAccessConf {

    @Autowired
    private ServerPropertyLoader serverPropertyLoader;

    @Autowired
    private Properties serverProperties;

    @Bean(name = "dataSource")
    public javax.sql.DataSource datasource() {

        // want to use serverPropertyLoader or serverProperties here

        return new DataSource(...);
    }
}

Both serverPropertyLoader and serverProperties are null. How can I autowire one of them. Spring Version: 4.1.6.RELEASE

Similar Question 8 (3 solutions) : Spring Bean (Mis-)Configuration

cc