Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

managing two or more implementations of one Spring interface With @PROFILE

Tags:

java

spring

We want to have two implementation of an interface for production and development mode:

Consider an interface:

public interface AccountList {
        public List<Account> getAllAccounts(String userID) ;
}

With two implementations:

The base implementation

 @Service
 public AccountListImp1 interface AccountList { ... }

and some development implementation

 @Service
 @Profile("Dev") 
 public AccountListImp2 interface AccountList { ... }

When I try to use the bean:

public class TransferToAccount{
    @Autowired
    private AccountServices accountServices;

}

I get this error:

No qualifying bean of type [AccountList] is defined: expected single matching bean but found 2: coreSabaAccountList,dummyAccountList

During the development, we set the spring.profiles.active to dev as below:

<context-param>
    <param-name>spring.profiles.active</param-name>
    <param-value>Dev</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

I assumed that setting the profile name, will make spring to categorize beans with different profiles, and use them base on profile name.

Can you please let me know how can I solve this? I can use @Primary, or change the applicationContext.xml, but I think the @profile should solve my problem.

like image 671
Alireza Fattahi Avatar asked Oct 12 '13 11:10

Alireza Fattahi


1 Answers

I think that your problem is that your base class AccountListImp1 is not marked for any profile. I think that you are expecting that if no active profile is defined the beans without profile specification will run but when you define profile the beans that have such specification will override beans that implement the same interface and do not have profile definition. This does not work this way.

When working with active profile X spring starts all beans that are not targeted for any profile and beans targeted for current profile. In your case this causes clash between your 2 implementations.

I think that if you want to use profiles you should define at least 2: Dev and Prod (the names are taken just for example.)

Now mark AccountListImp1 as Prod and AccountListImp2 as Dev:

@Service
@Profile("Prod") 
public AccountListImp1 interface AccountList { ... }
and some development implementation

@Service
@Profile("Dev") 
public AccountListImp2 interface AccountList { ... }

I believe that this configuration will work. Good luck. I'll be glad to know if this was helpful.

like image 192
AlexR Avatar answered Sep 18 '22 14:09

AlexR