#Configuration class with empty #Value - java

I have a Maven Spring Boot application with an external configuration.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
I have a config class with #PropertySource annotation, which uses both #Value and Environment:
#Configuration
#PropertySource("file:/etc/koshka/application.properties")
public class Config
{
#Autowired
private Environment env;
#Bean
public static PropertySourcesPlaceholderConfigurer configurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Value("${socmess.pass}")
private String pass;
public String getUser() {
return env.getProperty("socmess.user");
}
public String getPass() {
return pass;
}
}
In the nutshell, I need just #Value, but I tested Environment option as well.
I have configuration file in the appropriate folder:
$ cat /etc/koshka/application.properties
socmess.user="testuser"
socmess.pass="testpass"
In the controller I'm instantiating the configuration:
#RestController
public class Sender {
private final Logger logger;
public Sender()
{
logger = (Logger)LogManager.getLogger("KoshkaBot");
}
#GetMapping("/vk")
#CrossOrigin(origins = "*")
public ResponseEntity<String> vk(
#RequestParam(value="username") String username,
#RequestParam(value="password") String password
) {
Config conf = new Config();
logger.info(conf.getUser());
logger.info(conf.getPass());
return ResponseEntity.ok().body("OK");
}
}
Unfortunately, I see nulls in the log.

Don't create new Config() object. This one is managed by spring container and as such you should, at most, inject it.
Recap
Spring is dependency injection framework, meaning that if you need some dependency, it is provided to you by the container and you shouldn't create it. Those dependencies are generally spring beans, objects that spring know how to create and manage.
Back to us
#Configuration is annotation that spring uses to define beans, through #Bean annotation that can be, later on, used by other components using the #Inject annotation. What I would do is define a pojo like:
public class User(){
private String username;
private String password;
//getters,setters etc ...
}
and then in the Config class define the bean like:
#Bean
public User getUser(){
//..load user and password
return new User(user, password);
}
and finally when you need to use the user you can do:
#Inject User user;
//now the properties will be not-null

Related

Java Spring Boot #Autowired values are null

When I try to print the variable that I have autowired, it prints "null" instead of the value I set it to, "Example." I can't quite figure out what I'm missing
In my AppConfig class I have:
#Configuration
public class ApplicationConfiguration {
#Bean
public String tableName(){
return "Example";
}
}
In my other class, DAOMethods, that I want to autowire the variable in:
#Component
public class DAOMethods {
#Autowired
private String tableName;
public void print(){
System.out.println(tableName);
}
}
They exist in different packages; With AppConfig living in a config
folder and DAOMethods in client->dynamodb->util folder. Config and
Client are folders under the main->java folder
The added #Configuration annotation scans for the beans in the current and its subpackages. You need to explicitly tell the application to scan the required packages. So you can do:
#SpringBootApplication (scanBasePackages = {"config", "client"})
OR,
You need to keep the config and other classes which uses that config in same root package. You can put the config folder and client folder under same package, say com.application and then add the following in your main class:
#SpringBootApplication(scanBasePackages = "com.application")
Now run the application.
You problem have many solutions
F.e. you can create config-class with required set of parameters and next autowire it (Injecting values with #Value annotation from application configuration file is good practice):
#Component
public class CustomConfiguration {
#Value("${table.name}")
private String tableName;
#Value("${some.value}")
private Integer someValue;
public String getTableName() {
return tableName;
}
public Integer getsomeValue() {
return someValue;
}
}
And you application.properties will looks like:
some.value=1
table.name=Example
Or you can simply inject single value from configuration with #Value annotation
One of solutions is using bean name in #Value annotation:
#Configuration
public class ApplicationConfiguration {
#Bean
public String tableName(){
return "Example";
}
}
#Component
public class DAOMethods {
#Value(#{tableName})
private String tableName;
}
More examples you can see in this question: Autowire a string from Spring #Configuration class?

Spring Boot: custom AutoConfiguration class fails to find properties

I have a library for a FooService.
Here's it's AutoConfiguration class:
#Configuration
#EnableConfigurationProperties(FooProperties.class)
public class FooServiceAutoConfigure {
#Autowired
FooProperties config;
#Bean
public FooService getFooService() throws Exception {
return new FooService(config.username, config.password)
}
}
Here's the FooProperties class:
#ConfigurationProperties(prefix = "foo")
public class FooProperties {
String username;
String password;
}
In resources/META-INF/spring.factories I have the following line:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.my.company.FooServiceAutoConfigure
In my main project (which is a #SpringBootApplication), I have:
A Maven dependency to this library.
foo.username and foo.password in application.properties
Some #Autowired FooService.
I can see in the logs that Spring Boot is trying to instantiate FooService but the config.username and config.password are nulls. Why?
Solved.
I'll answer for future readers:
There weren't setters for FooProperties

Unable to Inject Configuration in normal utility classes Play Framework 2.5.x

I am unable to Inject Configuration in normal utility classes ,it works fine in controller class.
#Inject
Configuration configuration
public class EmailService {
public static boolean sendEmail(final AppUser appUser,final String mailString,String subject) {
final Properties props = new Properties();
final String auth = Play.application().configuration().getString("mail.smtp.auth‌​")
final String starttls = Play.application().configuration().getString("mail.smtp.star‌​ttls.enable");
}
}
Actually I want to remove Depricated Play.application() and want to use Configuration for that I want to Inject Configuration in this class.
Dependency injection frameworks inject dependencies when constructing instances of objects, so if you want a method to use an injected component it has to be non-static.
You want to do something like this, making your sendEmail method non-static, and providing an interface:
#ImplementedBy(EmailServiceImpl.class)
public interface EmailService {
void sendEmail(AppUser appUser, String mailString, String subject);
}
#Singleton
public class EmailServiceImpl implements EmailService {
private final Configuration config;
#Inject
public EmailServiceImpl(Configuration config) {
this.config = config;
}
public void sendEmail(AppUser appUser, String mailString, String subject) {
final Properties props = new Properties();
final String auth = config.getString("mail.smtp.auth‌​")
final String starttls = config.getString("mail.smtp.star‌​ttls.enable");
}
}
Then inject an EmailService instance into your controller constructors.
Note: this uses #ImplementedBy for simplicity but you could also configure the binding in your Guice module, allowing you to mock it in tests.

How to inject config settings into autowired spring beans?

I have a bean for an webservice client in my project which requires some configuration settings to be injected. We are using Spring 3.1. Currently the best idea that came up was using the #Value annotation like this:
#Service
public class MyWebServiceClient {
private String endpointUrl;
#Required
#Value("${mywebserviceClient.endpointUrl}")
public void setEndpointUrl(String endpointUrl) {
this.endpointUrl = endpointUrl;
}
}
However I don't really like hardcoding the property name into the class. It also has the problem that there is no way to have more than one client with different settings in the same context (as there is only one property and this is hardcoded). Is there a more elegant way of doing this with autowiring or should I resort to plain old xml configuration for doing this?
I would use JavaConfig to do this.
More specifically, I would use JavaConfig to create multiple instances of MyWebServiceClient, and have the config be #Value'd with the proper endpoint property keys.
Something like this:
#Configuration
public class MyWebServiceConfig {
#Required
#Value("${myWebserviceClient1.endpointUrl")
private String webservice1Url;
#Required
#Value("${myWebserviceClient2.endpointUrl")
private String webservice2Url;
#Required
#Value("${myWebserviceClient3.endpointUrl")
private String webservice3Url;
#Bean
public MyWebServiceClient webserviceClient1() {
MyWebServiceClient client = createWebServiceClient();
client.setEndpointUrl(webservice1Url);
return client;
}
#Bean
public MyWebServiceClient webserviceClient2() {
MyWebServiceClient client = createWebServiceClient();
client.setEndpointUrl(webservice2Url);
return client;
}
#Bean
public MyWebServiceClient webserviceClient3() {
MyWebServiceClient client = createWebServiceClient();
client.setEndpointUrl(webservice3Url);
return client;
}
}
With this, you should have 3 instances of MyWebServiceClient in your ApplicationContext available via the names of the methods annotated with #Bean.
Here is some more documentation to JavaConfig for your convenience.

Creating #Autowire like annotation for injecting properties

I am using Spring 3 and also heavily utilize the well known #Autowire annotation. I would like to create a new annotation, let's call it #Property that autowires Java properties from set by .property files or vm arguments.
Considering the following class
class A {
#Property("my.a")
private int a;
}
if the property my.a is present, the property A.a is set.
Is such an annotation maybe already existing? If not I am aiming to create one, as mentioned above. Are the utilities given by spring to achieve my goal? I think about creating a BeanPostProcessor ...
Thanks for your hints!
There's already such an annotation - #Value
You should just define a PropertyPlaceHolderConfigurer, and configure it to resolve system properties.
Refer http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/
you can use #ImportResource to import XML configuration files. Then use context:property-placeholder to load properties
#Configuration
#ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {
private #Value("${jdbc.url}") String url;
private #Value("${jdbc.username}") String username;
private #Value("${jdbc.password}") String password;
public #Bean DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
}
properties-config.xml
<beans>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>
jdbc.properties
jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
jdbc.username=sa
jdbc.password=
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
TransferService transferService = ctx.getBean(TransferService.class);
// ...
}

Categories