Small question for SpringBoot, and how to configure the bean using @Qualifier please.
I have a very straightforward piece of code:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/>
</parent>
<groupId>com.question</groupId>
<artifactId>language</artifactId>
<version>1.1</version>
<name>language</name>
<description>Spring Boot</description>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.question;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class LanguageApplication {
public static void main(String[] args) {
SpringApplication.run(LanguageApplication.class, args);
}
}
package com.question.service;
public interface LanguageService {
String process(String name);
}
package com.question.service;
import org.springframework.stereotype.Service;
@Service("french")
public class FrenchLanguageServiceImpl implements LanguageService {
@Override
public String process(String name) {
return "Bonjour " + name;
}
}
package com.question.service;
import org.springframework.stereotype.Service;
@Service("english")
public class EnglishLanguageServiceImpl implements LanguageService {
@Override
public String process(String name) {
return "Welcome " + name;
}
}
package com.question.controller;
import com.question.service.LanguageService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
@RestController
public class LanguageController {
private final LanguageService languageService;
@Value("${configuration}")
public String configuration;
public LanguageController(@Qualifier(configuration) LanguageService languageService) {
this.languageService = languageService;
}
@GetMapping("/test")
public String test(@RequestParam String name) {
return languageService.process(name);
}
}
Expected:
What I hope to achieve is equally straightforward. I would like to pass some sort of configuration to application.properties, something like configuration=french or configuration=english.
At the controller layer, to use (@Qualifier(configuration) LanguageService languageService) And the correct concrete service will be used.
Actual:
Unfortunately,
@Qualifier(configuration) + @Value("${configuration}") public String configuration;
will yield Attribute Value must be constant.
Is there a way we can configure the concrete Bean via a configurable @Qualifier please?
I understand there is a way to workaround this by using ApplicationContext getBean.
But having this construct: @Qualifier(configuration) makes the code clean and easily understandable. How to achieve this please?
Thank you
If you only need 1 of the
LanguageServicebeans active at a time, then you can use@ConditionalOnPropertyon each of them, each using a uniquehavingValue. Like this (warning, untested code written from memory):With that, you don't need any qualifiers, just set the
my.app.prefix.languageproperty in your config (application.properties or application.yaml) to the value you want, and there will just oneLanguageServicebean in the context. You can inject that bean wherever you need it without needing a qualifier.