Moshe Katz
Moshe Katz

Reputation: 16863

@Autowired using the wrong implementation despite @ConditionalOnProperty

I followed a tutorial I found online to use @ConditionalOnProperty with @Bean to choose an implementation for @Autowired.

For completeness (though it isn't relevant to the issue), the purpose of this is to choose an "ICE Server List" provider - either as configured locally in a config file or using the Twilio API to get a list of STUN and TURN servers for WebRTC.

Here is the relevant code:

application.properties

ice.provider = twilio

Controller.java

@ComponentScan
@RestController
@EnableAutoConfiguration
@EnableWebSocket
public class Controller {

    @Autowired
    private IceProvider iceProvider;

    @Bean
    @ConditionalOnProperty(name = "ice.provider", havingValue = "local")
    public IceProvider localIceProvider() {
        logger.info("Creating ICE server provider - LOCAL");
        return new LocalIceProvider();
    }

    @Bean
    @ConditionalOnProperty(name = "ice.provider", havingValue = "twilio")
    public IceProvider twilioIceProvider() {
        logger.info("Creating ICE server provider - TWILIO");
        return new TwilioIceProvider();
    }
}

IceProvider.java

public interface IceProvider {
    List<ICEServer> getIceServers(String username);
}

LocalIceProvider.java

@Component
public class LocalIceProvider implements IceProvider {

    private final static Logger logger = Logger.getLogger(LocalIceProvider.class);

    @PostConstruct
    void init() {
        logger.info("Reading local ICE Server list config file");

        // ...
    }

    @Override
    public List<ICEServer> getIceServers(String username) {
        logger.info("Returning locally configured ICE servers");

        // ...    
    }
}

TwilioIceProvider.java

@Component
public class TwilioIceProvider implements IceProvider {

    private final static Logger logger = Logger.getLogger(TwilioIceProvider.class);

    @Override
    public List<ICEServer> getIceServers(String username) {
        logger.info("Doing Twilio API call and returning result");

        // ...
    }
}

Despite the application.properties setting to use the twilio provider, the application is using the local provider. However, only the twilioIceProvider factory method is being called, not the localIceProvider method.

Here is a snippet from the logs:

On application start

Both the @PostConstruct method of LocalIceProvider and the factory method of TwilioIceProvider are called, but not the factory method of LocalIceProvider

...
[2017-12-31 21:11:53 INFO ] [localhost-startStop-1] [ice.LocalIceProvider] Reading local ICE Server list config file
...
[2017-12-31 21:11:55 INFO ] [main] [com.example.Controller] Creating ICE server provider - TWILIO
...

On a request from the client that calls iceProvider.getIceServers()

[2017-12-31 21:14:40 INFO ] [http-nio-9083-exec-5] [ice.LocalIceProvider] Returning locally configured ICE servers

Since only the twilioIceProvider factory method is being called and the localIceProvider method is not, why is the LocalIceProvider being @Autowired?

Upvotes: 1

Views: 152

Answers (1)

Behrang Saeedzadeh
Behrang Saeedzadeh

Reputation: 47913

Remove the @Component annotations from your IceProvider implementations. You are already declaring them as beans using @Bean on the bean definition methods.

Upvotes: 1

Related Questions