Unable to read application.properties in spring boot application - java

I am unable to read application.properties value in my project in classes that are injected as a bean from another project. My project is using another project which has classes which needs to read configuration from application.properties.
Mine is a maven project and a spring boot application having application.properties in src/main/resources folder and those properties values are defined in it.
What is it that I am missing that it is unable to read file values? Or is there is any other mechanism for setting these properties for classes loaded via component-scan
Below line of code works fine, it is able to read value from the application.properties:
#PostConstruct
void init() throws ClassNotFoundException, IOException {
System.out.println(context.getEnvironment().getProperty("env.host",
"default value"));
}
Now there is another project which I am using in mine. When loading the classes those beans are getting initialized as dependency of another class, there also it tries to read same value in constants file as
static final String HOST_PROPERTY = "${env.host}";
There this value is not getting initialized to value from applictaion.properties

If you want to get application.properties values,you have to two option.
1) you can autowire Environment class and use its getProperty() method as
#Autowired
Environment env;
env.getProperty("${env.host}");
2)#Value annotation
#Value("${env.host}")
String HOST_PROPERTY;

Related

jhipster java tests failing - application properties

I have generated a jhipster monolithic app. I have created a class to connect with the AWS S3 and upload a file there. I defined the properties in .yml file. Here everything works fine.
When I am trying to run the provided tests, most of them are failing with the following error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 's3AutoConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'aws.endpoint.url' in value "${aws.endpoint.url}"
S3AutoConfig is the class which uses the properties.
I checked jhipster's documenation and several posts, like the one below:
Adding applicationproperties in Jhipster
which mention that you should provide the properties in the ApplicationProperties class (seems a bit redundant).
I defined the properties also in the java class, but the tests are still failing with the same error above.
How should I define the properties, so they are picked up by the tests? Is it necessary to provide them also in the java class as some posts suggest?
Your implementation cannot work because you are defining Aws class within ApplicationProperties which means that your AWS properties will be prefixed by application, so for example application.aws.endpoint.url which does not match your application*.yml structure and this is why you get this error.
You should extract Aws class and its inner classes to its own file (Aws.java) and use prefix "aws".
Also, it would probably better named as AwsProperties.
#ConfigurationProperties(prefix = "aws", ignoreUnknownFields = false)
public class Aws {
Then the second point about tests is that they are using a different classpath than main class so you should ensure that you define these properties also in src/test/resources/config/application.yml

Spring Boot App not picking up application.properties from dependent jar

I have two spring boot apps. The first is an API library that's pulled into the second (a web application) as a dependent jar.
The first, is an API library that houses functions to create "cases" in an IBM solution. It's a standalone type jar that has a service class that exposes methods like getCaseXMLForDocId(String docId) or createCaseForAgreementNumber(String agreementNumber)
The first library called CaseInvocationAPI has an application.properties file which has several properties. For example:
caseinvocation.query.fetchNonProcessedCaseXml=SELECT Id, CaptureSource, AgreementNumber, CaptureSourceID FROM CaseInvocation WHERE ProcessIndicator IN (0, 2)
The service class has a method which makes a query, grabbing that query string from a member variable that's populated with a property from the application.properties file:
#Value("${caseinvocation.query.fetchNonProcessedCaseXml}")
private String selectNonProcessedQueryString;
The second SpringBoot app is a webapplication that has REST controllers. These controllers expose endpoints that call the CaseInvocationAPI library, specifically the CaseInvocationService class.
The problem I am having is that when the SpringBoot WEBAPPLICATION starts up, the context configuration blows up with the following error:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'caseinvocation.query.fetchNonProcessedCaseXml' in string value "${caseinvocation.query.fetchNonProcessedCaseXml}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:219)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:193)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:813)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1039)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:349)
... 45 common frames omitted
It appears that when the WebApp starts up, when it's trying to build the classes from the dependent jar, those properties are not being found.
I didn't think I had to copy each and every property out of the dependent jar application.properties file into an application.properties file in the Webapp project.
Why isn't the WebApp project (CaseInvocationWebApp) picking up the application.properties file from the dependent jar file (CaseInvocationAPI)?
I checked the compiled jar file (CaseInvocationAPI) and the application.properties file is there in the jar.
Looks like the problem was related to the fact that both the child jar and the webapp have application.properties files. I wasn't aware that the parent WebApp application.properties sort of overwrites the others (ignoring all others really).
Special thanks to Paschoal for his response.
You can see details on the answer here:
Adding multiple application.properties files
There are 3 ways (that I can think of) you can approach this:
The dependency, API library, should not have an application.properties since it's a library and not an executable Spring boot application in itself. You only define the properties in your web application's application.properties, even for the API library.
But, here the assumption is that you have access to the API library jar.
You can redefine all the properties in web application's application.properties essentially overriding them.
Explicitly configure the Spring boot application to use both the application.properties files, each for different set of properties.
Caveat: The file names must be different, as config location is classpath for both.
#SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplicationBuilder(WebApplication.class)
.properties("spring.config.location=classpath:api-application.properties,classpath:application.properties")
app.run(args);
}
}

Override a single property in a parent project of a application.properties defined in child project?

I have a project, let's call it BaseProject, which contains a properties file defining different configurations. One of those properties could be security.password.minlength=4.
Now I have a ProjectA which builds up on BaseProject and there for depends on it.
ProjectA
|
|--BaseProject
Now in ProjectA I would like to have a default security.password.minlength of 8.
If I simply add a application.properties file to my ProjectA, containing security.password.minlength=8 and the specific property is set to 8. Al tough all the other properties form my BaseProject are ignored now, giving me the exception: java.lang.IllegalArgumentException: Could not resolve placeholder
I still would like to use all properties defined in BaseProject but solely set the security.password.minlength to a different value. How can I achieve this?
Update
Currently I let Spring do the handling of the application.properties file. Inside my application, I simply get the values from the Spring environment.
If you are using the default property handling of Spring Boot, you can make use of profiles. E.g. you could use a profile named projecta for your derived project and specify your properties in a file named application-projecta.properties. This will automatically be picked up when you specify the profile to be active (see here: http://www.baeldung.com/spring-profiles)
I found the following solution for me:
BaseProject has a application.properties which contains all the default values.
ProjectA has a projectA.properties which is I integrate with
#PropertySource("projectA.properties")
public class ProjectA {
public static void main(String[] args) {
SpringApplication.run(ProjectA .class, args);
}
}
This allows me to override any property from the BaseProject project in the projectA.properties file. The properties which I don't define in projectA.properties are still taken from the application.properties of the BaseProject`.

How can I access 'spring.application.name' when defined in bootstrap.properties?

I have the following spring-boot 1.4.2.RELEASE sample app
#SpringBootApplication
public class Application {
#Value("${spring.application.name}")
private String applicationName;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And I have the following configuration defined in bootstrap.properties:
spring.application.name=sample-app
When run it I get the following error:
java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.application.name' in string value "${spring.application.name}"
Any hint on why it fails to inject 'spring.application.name'?
Need to define it there to support other spring boot cloud.
The first answer is correct. The default properties file is application.properties or application.yml.
The bootstrap file is properly for Spring Cloud.
See http://projects.spring.io/spring-cloud/spring-cloud.html#_the_bootstrap_application_context
If you are using spring cloud, and the bootstrap file is not working, you need to enable the "cloud" Spring profile.
For example using:
./gradlew -Dspring.profiles.active=cloud bootrun
or
./mvnw spring-boot:run -Dspring.profiles.active=cloud
By default, if you don't specify any properties source, spring boot will lookup for your property in the file application.properties. Therefore, you should rename your property file to that default name or manually specify a properties source for your bootstrap.properties

Getting Spring #Value annotations working with Grails

I have trouble getting #Value annotations working with a Spring bean in a Grails 2.3.4 app.
I have a separate jar as a Grails dependency. The jar has annotated beans:
#Named
public class Bean {
#Value("${client.environment}")
private String environment;
....
}
I have setup the property in Config.groovy.
...
client.environment = "DEV"
...
When I run Grails in IntelliJ IDEA the property works and the #Value annotated variable is populated automatically. But when I deploy the war to a standalone Jetty instance the same property has not been initialized and its value is instead "${client.environment}".
I have tried for hours to check all production and development settings so they don't change anything. I've also tried multiple solutions to load properties in Grails and even tried to setup a propertyPlaceholderConfigurer in resources.groovy but nothing helps.
The #Value annotation from Spring needs single quotes in order to work (Tested on Grails 4):
import org.springframework.beans.factory.annotation.Value;
public class Bean {
#Value('${client.environment}')
String environment;
...
}
So I got the bean working as inteded by following these instructions. First I read the property from the property file and explicitly set it to the bean variable using the last method in the following URL (using beans in Config.groovy)
http://softnoise.wordpress.com/2013/07/29/grails-injecting-config-parameters/

Categories

Resources