Spring Boot Override Properties Externally - spring

I have a Spring Boot application that is getting deployed as a WAR to a Tomcat server. There is already a currently deployed Spring Boot application on Tomcat server that has an application.properties file on classpath that is overriding the one bundled in the WAR. I need to do the same thing for my application, but I can't use the name application.properties as it is already taken, and my application is trying to use the application.properties on the classpath from Tomcat, which is intended for the other Spring Boot application.
Is there a way I can tell Spring Boot to look for a properties file on the classpath called myapp.properties or something along those lines?
I tried doing the following, but it doesn't seem to work when being deployed as a WAR.
#SpringBootApplication
public class ParameterManagerApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(ParameterManagerApplication.class)
.properties("spring.config.name:parameter-portal")
.build()
.run(args);
}
}

By default, Spring Boot looks for the application.properties file in these locations.
/config subdir of the working directory
The working directory
config package in the classpath
classpath root
So, the following worked for us when we placed myserver.properties under any of these locations.
public static void main(String[] args){
System.setProperty("spring.config.name","myserver");
SpringApplication.run(Application.class,args);
}
Otherwise, You can try setting the spring.config.location as below.
new SpringApplicationBuilder(Application.class)
.properties("spring.config.name:application,myserver",
"spring.config.location:classpath:/external/myproperties/")
.build().run(args);

We can also 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

Related

Define properties in a custom file, for Spring data JPA

I have a custom properties file for my spring boot application for database configurations. I use spring data JPA for persistence, By default spring boot choose application.properties to load the configurations.
How to avoid it and use any custom file, to read the database configuration on application startup
Example : database-connection.properties
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://ip:5432/HP
spring.datasource.username=hpadmin
spring.datasource.password=hp#12345
Thank you
You will avoid future complications if you use just one and the classic application.properties.
Spring requires more than just database configurations so replace the entire application.properties by a simple database-connection.properties is not a good idea.
Anyway, if you need to add more properties alongside application.properties you could use
one of the following approaches:
PropertyPlaceholderConfigurer
You could load extra properties alongside the application.properties or replace it entirely if you delete the application.properties
In your main class:
#Configuration
public class PropertiesConfiguration {
#Bean
public PropertyPlaceholderConfigurer properties() {
final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setIgnoreResourceNotFound(true);
final List<Resource> resourceLst = new ArrayList<Resource>();
resourceLst.add(new ClassPathResource("database-connection.properties"));
ppc.setLocations(resourceLst.toArray(new Resource[]{}));
return ppc;
}
Shell
You could replace the entire application.properties file at the moment of run of your jar with spring parameter --spring.config.location
java -jar app.jar --spring.config.location=/foo/bar/database-connection.properties
PropertySource
Similar to PropertiesConfiguration but without java code, just #annotations
#PropertySources({#PropertySource(value = "classpath:database-connection.properties")})
public class Application {

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

Set default application server Spring Boot

I have multiple application servers on my classpath, namely Netty via spring-boot-starter-webflux and Tomcat through another dependency chain. How can I determine which application server to use in Spring Boot?
Currently, Tomcat is being started instead Netty.
Important note: I can't exclude any of them, Tomcat is used by CXF, Netty is used by WebClient.
Just use proper spring-boot-starter-package
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html
In your case it will be probably spring-boot-starter-reactor-netty
Also it would be wise to exclude multiple JEE embedded containers and remove those you don't need.
You can specify the application is reactive directly in you configuration at startup something like this
#Configuration
#EnableAutoConfiguration
public class Application {
public static void main(final String[] args) {
final SpringApplication springApplication = new SpringApplication(Application.class);
springApplication.setWebApplicationType(WebApplicationType.REACTIVE);
springApplication.run(args);
}
}

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.

Plugin System in Spring Boot for modular applications

I looking for dynamically loading jar in spring boot after compiling, for example I will put jars in some folder and when spring boot is started, all jars from this folder will be injected into spring boot app. I don't know how can I do this with spring boot, and if You know can help me with this, with some example.
I need this jars to have #Service, #Controller as this will be module (plugin), with adding capabilities to my spring boot app.
Is possible to do this with spring boot, and if it is possible, please provide me with some sample code.
Thanks in advance.
UPDATE:
I found something https://www.youtube.com/watch?v=F-sw2pFdcDw https://code.google.com/p/jspf/
UPDATE 2: I can't get #Controller bean from plugin jar registered in Spring Boot
Have a look at FlexiCore, an open-source framework that brings modularity to spring boot utilizing plugins(jars) loaded at runtime See wizzdi and FlexiCore.
for example FlexiCore allows you to create a project ( compiled into a seperate jar from your main application) that contains a spring bean as follows:
#Component
#Extension
public class HelloWorldService implements ServicePlugin{
public String hello() {
return "Hello World!";
}
}
it will be automatically be loaded once placed inside the designated plugins folder, it basically allows a full support for most(all) of spring boot features , so for example you can add a RestController bean to your jar as well , FlexiCore will automatically load that bean allowing you to call the controller as if it was in your main application jar:
#RestController
#Extension
public class TestEntityController implements Plugin {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#Autowired
private TestEntityService testEntityService;
#PostMapping("/createTestEntity")
public TestEntity createTestEntity(#RequestParam(name="name", required=false, defaultValue="Stranger") String name) {
return testEntityService.createTestEntity(name);
}
#GetMapping("{id}")
public TestEntity getTestEntity(#PathVariable("id")String id) {
return testEntityService.getTestEntity(id);
}
}
Disclaimer: I am the CTO of wizzdi, the company powering FlexiCore.
One option is definitely to just use broad #ComponentScan. If you add new jar to classpath the annotated classes from that jar will get discovered via #ComponentScan, #Controllers will get mapped etc.
The XML equivalent here would be placing xml configuration files somewhere to your classpath (META-INF folder being obvious choice) and import them all using wildcard. The idea is the same. If the plugin jar file is on classpath you will get the xml file imported and the beans (controllers, ...) will get loaded.
There are drawbacks to this approach like the modules not being isolated but its definitely option for simpler applications.
You can find a sample spring boot web project here.
By dynamically loading jars I assume you want to add dependencies to your project. For this you can update pom.xml of the sample project and put your dependencies here.

Resources