Spring boot environment property returns null - spring-boot

I have a spring boot 2 app. I am trying to access my application properties file properties through spring Environment as well as #Value property, neither of them works.
#Autowired
Environment env;
logger.info(env.getProperty("app.environment"));
#Value("${app.environment}")
private String _env;
logger.info(_env);
app.environment=LOCAL
Looks like spring boot is not detecting application.properties file at all.
What am I doing wrong here, Thanks in advance

If the injected property is null, it most probably means your bean has not been created yet. Spring boot injects values to bean properties only after the bean has been created.
Here's a simple experiment to demonstrate this behavior:
#Value("${spring.application.name}")
private String instanceApplicationName;
public UserController(#Value("${spring.application.name}") String appNameInConstructor) {
System.out.println("Constructor app name: " + appNameInConstructor);
System.out.println("Instance application name: " + this.instanceApplicationName);
}
Which property would be null? instanceApplicationName or appNameInConstructor?
Yes, it's the instanceApplicationName property that's null because, the constructor is called first and the instance property has not been initialized yet. The appNameInConstructor correctly logs the application name.
So, where you reference the injected properties and how you inject them, both matter.
You can check the entire project here: https://github.com/nkumashi/springboot-webmvc-demo.

Related

How to get the effective Properties in Spring Boot application regardless of where it is defined?

suppose I define a property when starting my Spring Boot application from command line by passing -Dmy.property=314 to JVM, and also I define this property in the application.properties :
my.property=318
to my knowledge the command line one has higher priority and when I inject the value of my.property in a bean I get 314. is there any API that I can get properties regardless of where it is defined and respect this priority? I mean I get the property that will be injected in beans by Spring.
If you don't want to inject the property via other mechanisms like #Value or bindings like #ConfigurationProperties, you can get it via Environment
#Autowired
private Environment env;
...
env.getProperty("xxx.yyy");

Creating a custom FactoryBean in Sprint Boot 2.3/Spring 5

I've got a spring-boot web application that's mostly working; my DataSource is properly configured by an external application.properties file.
Now I want to add properties to that file to help me instantiate and configure two instances of a class in my app. I have a APNsFactory that I currently instantiate manually and configure using JNDI, but I want to get away from JNDI calls:
#Bean
public
APNsFactory
apnsFactory()
throws
javax.naming.NamingException
{
sLogger.info("Configuring APNsFactory");
InitialContext ctx = new InitialContext();
APNsFactory f = new APNsFactory();
f.setProductionKeystorePath((String) ctx.lookup("java:comp/env/apns/prod/keystorePath"));
f.setProductionKeystorePassword((String) ctx.lookup("java:comp/env/apns/prod/keystorePassword"));
f.setDevelopmentKeystorePath((String) ctx.lookup("java:comp/env/apns/dev/keystorePath"));
f.setDevelopmentKeystorePassword((String) ctx.lookup("java:comp/env/apns/dev/keystorePassword"));
return f;
}
When running before in a standalone webapp container, Spring properly called that method and the JNDI context from the container’s <env-entry> tags was available.
I'm trying to update my APNsFactory to be a proper Spring FactoryBean<>, and I’ve given it a couple of #Autowire String variables that I want to be set by Spring Boot from the application.properties file.
For bonus points, I want this to be usable both in Spring Boot and in a standalone container like Tomcat or Resin.
For the life of me, I can't figure out how to get Spring to do this. There are dozens of examples for DataSources and other Beans already implemented by Spring, but none for a completely custom one, using application.properties, in a Spring Boot web environment.
I've seen some examples that use an XML config file, but I'm not sure how to do that with Spring Boot.
I don't think you need a factory bean here.
You already have spring boot that can read application.properties out-of-the-box:
So try the following:
Create key/values in the application.properties file:
myapp.keystore.path=...
myapp.keystore.passwd=...
// the same for other properties
Create ConfigurationProperties class
#ConfigurationProperties(prefix="myapp.keystore")
public class MyAppKeyStoreConfigProperties {
private String path; // the names must match to those defined in the properties file
private String passwd;
... getters, setters
}
In the class marked with #Configuration (the one where you create #Bean public APNsFactory apnsFactory()) do the following:
#Configuration
// Note the following annotation:
#EnableConfigurationProperties(MyAppKeyStoreConfigProperties.class)
public class MyConfiguration {
// Note the injected configuration parameter
#Bean public APNsFactory apnsFactory(MyAppKeyStoreConfigProperties config) {
APNsFactory f = new APNsFactory();
f.setProductionKeystorePath(config.getKeyPath());
and so on
}
}
I've intentionally didn't show the separation between production/dev stuff.
In spring boot you have profiles so that the same artifact (WAR, JAR whatever) can be configured to run with different profile and depending on that the corresponding properties will be read.
Example:
If you're running with prod profile, then in addition to application.properties that will be loaded anyway, you can put these keystore related definitions to application-prod.properties (the suffix matches the profile name) - spring boot will load those automatically. The same goes for dev profile of course.
Now I haven't totally understand the "bonus points" task :) This mechanism is spring boot proprietary way of dealing with configuration. In "standalone" server it should still have a WAR with spring boot inside so it will use this mechanism anyway. Maybe you can clarify more, so that I / our colleagues could provide a better answer

Spring boot #ConfigurationProperties not loading from external properties file or class path property file

Hi I am trying to use a reusable library that I have created using spring boot(2.0.5) from 2 applications I am able to bind properties from application.properties which is in my classpath to my bean as follows and I see the schemas being set through the setters in my debug in my first spring batch application which is also created with spring boot(2.0.5)
This is the property bean class in my library which holds some service api- this library is just a jar package created with spring boot.
package com.test.lib.config
#ConfigurationProperties("job")
#PropertySources({
#PropertySource(value = "${ext.prop.dir}", ignoreResourceNotFound = true),
#PropertySource(value = "classpath:application.properties", ignoreResourceNotFound = true)
})
public class ServiceProperties {
/**
* Schema for the service
*/
private String schema;
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
}
And the config bean for this library is as follows in the same package.
#Configuration
#EnableConfigurationProperties(ServiceProperties.class)
#ComponentScan("com.test.lib")
public class LibraryModuleConfig {
}
This code works perfectly fine when called from a sprint boot spring batch application which includes this library as a dependency and the corresponding setters are called and I can see the schema set when I add job.schema=testSchema in application.properties
I try to use this same library in an existing spring mvc web application started from a tomcat server with external files directory as launch arguments( This application was not created with spring boot) and added the appropriate context:component-scan to include the beans (java config beans) from the library in the application-context(appn-context.xml). The job.schema property is passed from both application.properties file and even a external file in C drive as given by the ${ext.prop.dir}" in the #propertySources annotation. The schema property in ServiceProperties Bean never gets set and even the setters never get called in the debug. Why will this libray config bean not work in an existing spring mvc application but work with the spring batch application. Both of them add the library as a dependency. I have been at this at a long time and except for the spring property binding the other functionality seem to work.
#EnableConfigurationProperties is a handy annotation that Spring Boot provides. (Spring MVC doesn't provides in default)
For a legacy Spring MVC app (specifically for Spring 3.x), you can use #Value annotation for the properties.
#Value annotation also works in Spring Boot so I guess you can make a change so that it works with older version (Spring 3.x) and newer version just works without changing anything at all.
Hope this helps! Happy Coding :)

Spring boot reading properties from a bean

I found an spring boot sample code in which properties are being injected directly with #Value.
The point is that those properties come from a bean which is not present actually in the code.
The annotations have this aspect:
#Value ("#{envPC['desktop.url']}")
private String url = "";
So I have a couple of questions:
1-how can I define env bean?
2-when defining the env bean, how can I modelate the correct structure for references like: desktop.url, desktop.port....
I hope the questions are clear.
Thanks in advance
Environment bean is implicitly defined within Spring context. Spring collects properties from multiple sources into this bean: JVM options, property files added via #PropertySource, etc.
Also it can be injected like any other bean:
#Autowired
private org.springframework.core.env.Environment environment;
More details can be found at https://docs.spring.io/ or in this nice article: http://www.baeldung.com/properties-with-spring

Spring mvc : Access properties file value in controller without #Value

I have a properties file for messages in my Spring application.I want to access these value directly in controller.How can i do this ?.
Note: I don't want to use #Value annotation to store data in another variable.
You can reference this question and answer regarding accessing files directly within controller.
It is what i used to implement mine.
Accessing multiple property files with #PropertyResource in spring
As M.Deinum suggested already, you should have a MessageSource bean definition if the purpose of the properties file is to externalize messages. A message source is automatically picked by the application context, meaning it is available for injection in every other bean. You can autowire it for example in your controller:
#Autowired
private MessageSource messageSource;
and then use its methods to access any message in any locale

Resources