Spring boot - custom variables in Application.properties - spring

I have spring boot client that consumes a restful api. Instead of hardcoding the IP address of the REST API in the java class, is there any key entry in the application.properties I can use?
And if not, can I create a custom entry?
Thanks

The infrastructure that Spring Boot uses can be used in your own project in the exact same way. You commented in #zmitrok answer about a "unknown property" warning. That is because your property has no meta-data so the IDE does not know about it.
I would strongly advice you not to use #Value if you can as it is rather limited compared to what Spring Boot offers (#Value is a Spring Framework feature).
Start by creating some POJO for your IP:
#ConfigurationProperties("app.foo")
public class FooProperties {
/**
* IP of foo service used to blah.
*/
private String ip = 127.0.0.1;
// getter & setter
}
Then you have two choices
Put #Component on FooProperties and enable the processing of configuration properties by adding #EnableConfigurationProperties on any of your #Configuration class (this last step is no longer necessary as of Spring Boot 1.3.0.M3)
Leave FooProperties as is and add #EnableConfigurationProperties(FooProperties.class) to any of your #Configuration class which will create a Spring Bean automatically for you.
Once you've done that app.foo.ip can be used in application.properties and you can #Autowired FooProperties in your code to look for the value of the property
#Component
public MyRestClient {
private final FooProperties fooProperties;
#Autowired
public MyRestClient(FooProperties fooProperties) { ... }
public callFoo() {
String ip = this.fooProperties.getIp();
...
}
}
Okay so your key is still yellow in your IDE. The last step is to add an extra dependency that will look your code and generate the relevant meta-data at build time. Add the following to your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
And voilà, your key is recognized, you have javadoc and the IDE gives you the default value (the value you initialized on the field). Once you've that you can use any type the conversion service handles (i.e. URL) and the javadoc on the field is used to generate documentation for your keys.
You can also add any JSR-303 constraint validation on your field (for instance a regex to check it's a valid ip).
Check this sample project and the documentation for more details.

Instead of hardcoding the IP into the properties file, you can start the application with
-Dmy.property=127.127.10.20
And Spring Boot will automatically pick it up with
#Value("${my.property}")
private String myProperty;

You can add your own entries to the application.properties. Just make sure that the property name does not clash with the common properties listed at http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties

Related

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

Split jackson configuration into separate properties

I'm using Spring Boot 2.2.5.RELEASE and would like to split my application.properties into separate files. There are already similar questions on StackOverflow but none of them seem to work for configuring Jackson.
My current non working solution is the following:
root/
- application.properties (without Jackson configuration)
- jackson-configuration.properties (includes Jackson configuration)
Jackson configuration class:
#Configuration
#PropertySource("/jackson-configuration.properties")
public class JacksonConfiguration {
}
Please note, I've tried different ways to specify the path including:
"/jackson-configuration.properties"
"jackson-configuration.properties"
"classpath:/jackson-configuration.properties"
"classpath:jackson-configuration.properties"
Spring Boot does not seem to use the configuration. If I copy it over into the application.properties - it works.
Content of jackson-configuration.properties:
spring.jackson.property-naming-strategy=SNAKE_CASE
spring.jackson.mapper.sort-properties-alphabetically=true
spring.jackson.deserialization.fail-on-unknown-properties=true
spring.jackson.parser.strict-duplicate-detection=true
spring.jackson.time-zone=Europe/Zurich
My application is annotated with #SpringBootApplication , so it should scan for additional properties.
/edit
I just realized the problem is the testing, not the productive code itself. If I start the application it works. What doess not work is testing with #JsonTest. I can fix this problem by adding the following line to my tests #ContextConfiguration(classes = {JacksonConfiguration.class}). But in turn, this causes the annotation #JsonComponent to stop working but only for the #JsonTest annotated classes.
See the documentation here. Here is an excerpt from the documentation
In order to resolve ${...} placeholders in definitions or
#Value annotations using properties from a PropertySource, you must
ensure that an appropriate embedded value resolver is registered in
the BeanFactory used by the ApplicationContext. This happens
automatically when using in XML. When
using #Configuration classes this can be achieved by explicitly
registering a PropertySourcesPlaceholderConfigurer via a static #Bean
method.
You need to create a bean like this
#Bean
public static PropertySourcesPlaceholderConfigurer devPropertyPlaceholderConfigurer() throws IOException {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setLocations(new PathMatchingResourcePatternResolver().getResources("file:pathtToFile"));
configurer.setIgnoreUnresolvablePlaceholders(true);
return configurer;
}

Using properties from application.properties while building bean in spring boot configuration annotated class?

We have properties defined in application.properties, is it appropriate to have the property pulled in a spring-boot #Configuration annotated class to be used for initializing the bean being created. Refer code snippet below
#Configuration
public class MyConfig {
#Value("${a.property.in.application.properties}")
public String aProperty;
#Bean
MyClass myClassInstance() {
return new MyClass(aProperty);
}
}
Simplest example would be creating a datasource instance with url, driver, username, password configured in the application.properties
Is it appropriate?
What could be the possible consequences of continuing to use in this manner?
I'm using this approach for different things like cors configurations. There are probably also disadvantages, but so far it has only had advantages for me. I think it's most times better to have config values outside of the code. That allows you, for example, to use different profiles (local/dev/int/prod). But I would recommend to encrypt things like passwords. I'm using Jasypt.

How to correctly using Spring profile on windows

I am trying to maintain different Spring profiles for development and production, for which I have created a folder(web skeleton) on my desktop with my Spring Boot project, application-dev.properties and application-prod.properties.
However, I am unable to import the profile into my project. The code that I use to import it to my project is as follows.
#Configuration
#Profile("dev")
#PropertySource("file:///${user.home}/web skeleton/application-dev.properties")
public class DevelopmentConfig {
#Bean
public EmailService emailService(){
return new MockEmailService();
}
Can someone tell me if this is the right way to use PropertySource in Spring.
You can optionally define a custom source where we’re storing these properties, else the default location (classpath:application.properties) is looked up. So we now add the above annotations to the existing properties class:
#Configuration
#PropertySource("classpath:configprops.properties")
#ConfigurationProperties(prefix = "dev")
public class ConfigProperties {
// previous code
}
Now any properties defined in the property file that has the prefix dev and the same name as one of the properties are automatically assigned to this object.
#Simple properties
dev.host=mailer#mail.com
dev.port=9000
Check this
I have done this kind of configuration too
Just add below code in your configuration class
#PropertySource("classpath:application-${spring.profiles.active}.properties")
And this propery in application.properties
spring.profiles.active=dev
you can change it to prod and cert as per you need.

spring boot setting up message.properties and errors.properties file in the project structure and reading file to code

I am new to spring boot. I want to add external properties files in project structure . Files are errors.properties, messages.propeties and sql.properties file which contains the all sql queries. I get it where to add it i.e \demo\src\main\resources\errors.properties file. Can Anyone of you give me insight how to read from these files to my java code .
The easiest way would be to leverage what Spring Boot already give you automatically. Anything you put into application.properties (under \demo\src\main\resources) is going to be added to your Environment. I would just take the keys from those three files and create unique entries in application.properites
errors.key1=value1
errors.key2=value2
sql.key1=value1
....
Then you can use the #ConfigurationProperties annotation to map those configurations to a class that encapsulates each type.
#Component
#ConfigurationProperties(prefix="errors")
public class ErrorSettings {
private String key1;
.....
//getter and setters
}
Now you have a Bean of type ErrorSettings that you can inject into any other Bean you declare and just call the getXXX() method of the configuration you want.
Reference doc:
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

Resources