Question

I am using xml configuration in my Spring Application. Now i would like to convert the existing classes to use annotation(like @service, @Repository etc) instead of xml configuration.

Business Logic(Irrelevant for this question, just for understanding): Sevice connnects to Americas database and find the skus(products) and deactivates the skus. Sevice connnects to EMEA database and find the skus(products) and deactivates the skus.

Here is the sample code.

/* Service code, which has 2 instances of SkuDAO, one connecting to US database and one connecting to EMEA database */

public class DeactivationService {

    private static final Logger LOG = Logger.getLogger(DeactivationService.class);

    private SkuDAO amerdao; //Dependency Injection Amer
    private SkuDAO emeadao; //Dependency Injection EMEA

    public DeactivationService(SkuDAO amerdao,SkuDAO emeadao) {
        this.amerdao=amerdao;
        this.emeadao=emeadao;
    }

    /*
     * Step 1: find inactive sku in americas skudao1.find()
     * Step 2: find inactive sku in emea skudao2.find()
     * Step 3: deactivate sku in americas
     * Step 4: deactivate sku in emea
 */
    public void deactivateSku() {
        List<Sku> totalList = new ArrayList<Sku>();
        List<Sku> amerList = amerdao.find();
        List<Sku> emeaList = emeadao.find();
              amerdao.deactivate(amerList);
        emeaList.deactivate(emeaList);
        }

}

/* DAO interface */

public interface SkuDAO {
     public List<Sku> find();
     public void deactivate(List<Sku>);
}

/* DAO Implementation
   Here one constructor in which DataSource is injected

 */

    public class SkuDAOImpl implements SkuDAO {

        private DataSource datasource; //Dependency injection
        private JdbcTemplate jdbcTemplate;

        public SkuDAOImpl(DataSource datasource) {
            this.datasource=datasource;
        }

        public List<Sku> find() {
            //some processing to find the sku, purposely left empty as it is a sample code
        }

        public void deactivate(List<Sku>) {
            //some processing to deactivate the sku, purposely left empty as it is a sample code
            }
    }

Spring Configuration:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:property-placeholder location="file:${dbconfiguration}"/>

    <bean id="AmericasDataSource" class="dell.harmony.data.HarmonyBasicDataSource" destroy-method="close" >
       <property name="url"><value>${HarmonyAmericasDb.url}</value></property>
       <property name="driverClassName"><value>${HarmonyAmericasDb.driverClassName}</value></property>
       <property name="username"><value>${HarmonyAmericasDb.username}</value></property>
       <property name="password"><value>${HarmonyAmericasDb.password}</value></property>
       <property name="initialSize"><value>${HarmonyAmericasDb.initialSize}</value></property>
       <property name="maxActive"><value>${HarmonyAmericasDb.maxActive}</value></property>
       <property name="maxWait"><value>${HarmonyAmericasDb.maxWait}</value></property>
       <property name="maxIdle"><value>${HarmonyAmericasDb.maxIdle}</value></property>
       <property name="minIdle"><value>${HarmonyAmericasDb.minIdle}</value></property>
       <property name="removeAbandoned"><value>${HarmonyAmericasDb.removeAbandoned}</value></property>
       <property name="removeAbandonedTimeout"><value>${HarmonyAmericasDb.removeAbandonedTimeout}</value></property>
    </bean>

    <bean id="EMEADataSource" class="dell.harmony.data.HarmonyBasicDataSource" destroy-method="close" >
       <property name="url"><value>${HarmonyEMEADb.url}</value></property>
       <property name="driverClassName"><value>${HarmonyEMEADb.driverClassName}</value></property>
       <property name="username"><value>${HarmonyEMEADb.username}</value></property>
       <property name="password"><value>${HarmonyEMEADb.password}</value></property>
       <property name="initialSize"><value>${HarmonyEMEADb.initialSize}</value></property>
       <property name="maxActive"><value>${HarmonyEMEADb.maxActive}</value></property>
       <property name="maxWait"><value>${HarmonyEMEADb.maxWait}</value></property>
       <property name="maxIdle"><value>${HarmonyEMEADb.maxIdle}</value></property>
       <property name="minIdle"><value>${HarmonyEMEADb.minIdle}</value></property>
       <property name="removeAbandoned"><value>${HarmonyEMEADb.removeAbandoned}</value></property>
       <property name="removeAbandonedTimeout"><value>${HarmonyEMEADb.removeAbandonedTimeout}</value></property>

    </bean>

     **<!--  Sku Deactivation  -->**
     <bean id="SkuAmerDao" class="dell.harmony.service.skudeactivation.dao.SkuDAOImpl">
        <constructor-arg index="0"><ref bean="AmericasDataSource"/></constructor-arg>
     </bean>

     <bean id="SkuEMEADao" class="dell.harmony.service.skudeactivation.dao.SkuDAOImpl">
        <constructor-arg index="0"><ref bean="EMEADataSource"/></constructor-arg>
     </bean>

     <bean id="ServiceManager" class="dell.harmony.service.skudeactivation.service.DeactivationService">
        <constructor-arg index="0"><ref bean="SkuAmerDao"/></constructor-arg>
        <constructor-arg index="1"><ref bean="SkuEMEADao"/></constructor-arg>
     </bean>    

</beans>

Now i want to convert the above classes to highlighted inside xml("Sku Deactivation") , into annodation.

My code for convertion is as follows:

@Service
public class DeactivationService {

    private static final Logger LOG = Logger.getLogger(DeactivationService.class);

    private SkuDAO amerdao; //Dependency Injection Amer
    private SkuDAO emeadao; //Dependency Injection EMEA

    @Autowired(required=true)
    public DeactivationService( @Qualifier("SkuAmerDao") SkuDAO amerdao, @Qualifier("SkuEMEADao") SkuDAO emeadao) {
        this.amerdao=amerdao;
        this.emeadao=emeadao;
    }

}

In the above constructor, now 'amerdao' instance, should be injected with AmericasDataSource and 'emeadao' with EMEADataSource, how to do that?

Please note, i dont have a setter in the SkuDAOImpl. Also there is only one datasource instance inside the SkuDAOImpl.

  1. can you given sample code of SkuDAOImpl with annodation.
  2. Any suggestion, to improve the coding from service to dao , if it can be done in a better way. (Not required to answer this)

EDITED NOW: just to be clear with question 1, I would like to remove the below two lines in Spring xml and use annotation instead my DeactivationService. Is it possible?

 <bean id="SkuAmerDao" class="dell.harmony.service.skudeactivation.dao.SkuDAOImpl">
    <constructor-arg index="0"><ref bean="AmericasDataSource"/></constructor-arg>
 </bean>

 <bean id="SkuEMEADao" class="dell.harmony.service.skudeactivation.dao.SkuDAOImpl">
    <constructor-arg index="0"><ref bean="EMEADataSource"/></constructor-arg>
 </bean>
Était-ce utile?

La solution

What about:

@Service
public class DeactivationService {

    private static final Logger LOG = Logger.getLogger(DeactivationService.class);

    @Autowired  
    @Qualifier("SkuAmerDao")
    private SkuDAO amerdao; //Dependency Injection Amer

    @Autowired 
    @Qualifier("SkuEMEADao")
    private SkuDAO emeadao; //Dependency Injection EMEA

    // no constructor needed.
}

public abstract class BaseDao implements SkuDAO {

    private final JdbcTemplate jdbcTemplate;       

    protected BaseDao() {
        this.jdbcTemplate = new JdbcTemplate(getDataSource());
    }

    protected abstract DataSource getDataSource();

    public List<Sku> find() {
        //some processing to find the sku, purposely left empty as it is a sample code
    }

    public void deactivate(List<Sku>) {
        //some processing to deactivate the sku, purposely left empty as it is a sample code
    }
}

@Repository("SkuAmerDao")
public class SkuAmerDAOImpl extends BaseDao {
    @Autowired 
    @Qualifier("AmericasDataSource")
    private DataSource datasource; //Dependency injection

    @Override
    protected DataSource getDatasource() {
        return dataSource;
    }
}

@Repository("SkuEMEADao")
public class SkuEMEADAOImpl extends BaseDao {
    @Autowired 
    @Qualifier("EMEADataSource")
    private DataSource datasource; //Dependency injection

    @Override
    protected DataSource getDatasource() {
        return dataSource;
    }
}

Always the same principle:

  • class is made a bean by an annotation @Service, @Component, @Repository (those annotations can take the name of the bean as value)
  • injection of dependency is made on fields with @Autowired and if there are more than one corresponding bean (in your case you have two DataSources), add a @Qualifier to specify which one.

Full documentation here.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top