Read application.properties value from Spring boot main class - spring-boot

In my spring boot app, I have variable value set in application.properties.
I want to read it in the main java class. How can I do that? following code returns null.
#SpringBootApplication
public class MyApplication {
#Value( "${spring.shutdown.sleep.time}" )
private static String shutdownSleepTime;
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(MysApplication.class, args);
System.out.println("sleep time : " + shutdownSleepTime);

You can read the property from the applicationContext.
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(MysApplication.class, args);
String shutdownSleepTime = applicationContext.getEnvironment().getProperty("spring.shutdown.sleep.time");
}

I recommend it
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(MysApplication.class, args);
}
#Component
public static class CmdRunner implement CommandLineRunner {
#Value( "${spring.shutdown.sleep.time}" )
private static String shutdownSleepTime;
public void run(String... args) throws Exception {
System.out.println("sleep time : " + shutdownSleepTime);
}
}

So you want to print something when the application context is created.
For that You can use event listeners:
#SpringBootApplication
public class MyApplication {
#Value( "${spring.shutdown.sleep.time}" )
private String shutdownSleepTime; // not static
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext =
SpringApplication.run(MysApplication.class, args);
}
#EventListener
public void onAppContextStarted(ApplicationStartedEvent e) {
System.out.println("sleep time : " + shutdownSleepTime);
}
}

Related

How do I get Environment variables in the main method of a spring boot application? [duplicate]

I am trying to get the value of a property
hello.world=Hello World
in MainApp class
#SpringBootApplication
public class MainApp {
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
This didn't work as its the main method.
#Value("${hello.world}")
public static String helloWorld;
Maybe its possible to load by
Properties prop = new Properties();
// load a properties file
prop.load(new FileInputStream(filePath));
Is there any other better way to get the properties using Spring in the main method of SpringBoot before SpringApplication.run
ConfigurableApplicationContext ctx =
SpringApplication.run(MainApp.class, args);
String str = ctx.getEnvironment().getProperty("some.prop");
System.out.println("=>>>> " + str);
You have declared the variable helloWorld as static. Hence you need to use Setter Injection and not Field Injection.
Injecting a static non-final field is a bad practice. Hence Spring doesn't allow it. But you can do a workaround like this.
public static String helloWorld;
#Value("${hello.world}")
public void setHelloWorld(String someStr) {
helloWorld = someStr
}
You can access this variable helloWorld at any point in the class, if its any other class. But if you want to do it in the main class. You can access the variable only after this line
SpringApplication.run(MainApp.class, args);)
i.e only after the application has started.
Don't do this. Its better to use CommandLineRunner.
Thanks to this you can have a non static method that Spring Boot will run for you automatically:
#SpringBootApplication
public class SimulatorApplication implements CommandLineRunner {
#Value("${my-value}")
private myValue;
public static void main(String[] args) {
SpringApplication.run(SimulatorApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
// here you can access my-value
}
}
#SpringBootApplication
public class MainApp {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(MainApp.class);
springApplication.addListeners(new VersionLogger());
springApplication.run(args);
}
// The VersionLogger Class
public class VersionLogger implements ApplicationListener<ApplicationEnvironmentPreparedEvent>{
#Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEvent) {
String helloWorld = applicationEvent.getEnvironment().getProperty("hello.world");
}
}
ApplicationEnvironmentPreparedEvent
Event published when a SpringApplication is starting up and the Environment is first available for inspection and modification.
ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
String applicationPropertyVersion=applicationContext.getEnvironment().getProperty("application.property.version");
LOGGER.info("RELEASE CODE VERSION {} and applicationProperty Version {} ", LcoBuildVersion.version,
applicationPropertyVersion);
We can't read values into static fields . Here is the explanation gives a better insight How to assign a value from application.properties to a static variable?

spring boot "#ComponentScan(nameGenerator = CustomGenerator.class)" not working jpaRepository bean

#ComponentScan(nameGenerator = CustomGenerator.class)
#SpringBootApplication
public class SampleApplication {
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
}
if you do it with the above code, the name of jpa Repository Bean will not be changed
#SpringBootApplication
public class SampleApplication {
public static void main(String[] args) {
new SpringApplicationBuilder()
.beanNameGenerator(new CustomGenerator())
.sources(SampleApplication.class)
.run();
}
}
If the code is used above, the name of the jpa Repository bean will be changed, but the CustomGenerator will not be injected during the test
what should i do!! helppppp
it is the same as above!!

Passing constructor args for Spring CommandLineRunner

I have an application that uses a class myClass that implements Spring CommanLineRunner:
#SpringBootApplication
#ComponentScan({ . . . } )
public class myClass implements CommandLineRunner {
. . .
public myClass() { . . . }
public myClass( String anArg ) { . . . }
public static void main(String[] args) {
SpringApplication application = new SpringApplication( myClass.class );
application.setWebEnvironment( false );
application.run( args );
}
#Override
public void run(String... args) {
. . .
}
}
this in the run method is bound to an instance of myClass that Spring constructs automagically. My problem is that for this constructing, I want to use the non-default constructor that takes an argument
and I want to pass to that argument one of the command line args.
How do I tell Spring to use the non-default constructor, and how do I supply a value to the constructor argument anArg?
In order to be able to pass other instances to CommandLineRunner it is recommended to separate your application class from the CommandLineRunner interface. So, your main class would look like this:
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication .class, args);
}
In the other hand we should instanciate the CommandLineRunner as a component:
#Component
public class MyCommandLineRunner implements CommandLineRunner {
private MyOtherComponent otherComponent
#Autowired
public MyCommandLineRunner(MyOtherComponent otherComponent) {
this.otherComponent = otherComponent;
}
public void run(String... args) {
otherComponent.setArg(arg[0]);
}
}
A more convenient way is to create a bean by passing a lambda function to it:
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
#Bean
CommandLineRunner initialize(MyOtherComponent otherComponent) {
return args -> {
otherComponent.setArg(arg[0]);
};
}
}

How can I Spring-ify my stand-alone (non Web Service) application?

I have a working stand-alone application, which uses Postgres, with the following
rough structure:
class myClass {
public myClass( String filePath ) {...}
public void calculate( ...args... ) {...}
public static void main(String[] args) {
...process args...
new myClass(...).calculate(...)
}
}
I am trying to convert this to a Spring Boot application to take advantage of
Spring JDBC. Here's the rough structure, a modification of the above:
#SpringBootApplication
class myClass implements implements CommandLineRunner {
public myClass( String filePath ) {...}
public void calculate( ...args... ) {...}
public static void main(String[] args) {
SpringApplication.run( myClass.class, args);
}
#Override
public void run(String... args) throws Exception {
...process args...
new myClass(...).calculate(...)
}
}
When I try running this from Eclipse, I get the following error message:
Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
Why is this happening, what can I do to fix it? And, why is it even complaining about "WebApplication",
since I do not include anything having to do with Web or Controller in my build.gradle.
I was able to find a solution to the error above by slightly modifying how I structured my main method:
#SpringBootApplication
class myClass implements implements CommandLineRunner {
public myClass( String filePath ) {...}
public void calculate( ...args... ) {...}
public static void main(String[] args) {
SpringApplication application = new SpringApplication( myClass.class );
application.setWebEnvironment( false );
application.run( args );
}
#Override
public void run(String... args) throws Exception {
...process args...
this.calculate(...) <<<=== Note change here, too
}
}

Spring Boot application to read a value from properties file in main method

I am trying to get the value of a property
hello.world=Hello World
in MainApp class
#SpringBootApplication
public class MainApp {
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
This didn't work as its the main method.
#Value("${hello.world}")
public static String helloWorld;
Maybe its possible to load by
Properties prop = new Properties();
// load a properties file
prop.load(new FileInputStream(filePath));
Is there any other better way to get the properties using Spring in the main method of SpringBoot before SpringApplication.run
ConfigurableApplicationContext ctx =
SpringApplication.run(MainApp.class, args);
String str = ctx.getEnvironment().getProperty("some.prop");
System.out.println("=>>>> " + str);
You have declared the variable helloWorld as static. Hence you need to use Setter Injection and not Field Injection.
Injecting a static non-final field is a bad practice. Hence Spring doesn't allow it. But you can do a workaround like this.
public static String helloWorld;
#Value("${hello.world}")
public void setHelloWorld(String someStr) {
helloWorld = someStr
}
You can access this variable helloWorld at any point in the class, if its any other class. But if you want to do it in the main class. You can access the variable only after this line
SpringApplication.run(MainApp.class, args);)
i.e only after the application has started.
Don't do this. Its better to use CommandLineRunner.
Thanks to this you can have a non static method that Spring Boot will run for you automatically:
#SpringBootApplication
public class SimulatorApplication implements CommandLineRunner {
#Value("${my-value}")
private myValue;
public static void main(String[] args) {
SpringApplication.run(SimulatorApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
// here you can access my-value
}
}
#SpringBootApplication
public class MainApp {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(MainApp.class);
springApplication.addListeners(new VersionLogger());
springApplication.run(args);
}
// The VersionLogger Class
public class VersionLogger implements ApplicationListener<ApplicationEnvironmentPreparedEvent>{
#Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEvent) {
String helloWorld = applicationEvent.getEnvironment().getProperty("hello.world");
}
}
ApplicationEnvironmentPreparedEvent
Event published when a SpringApplication is starting up and the Environment is first available for inspection and modification.
ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
String applicationPropertyVersion=applicationContext.getEnvironment().getProperty("application.property.version");
LOGGER.info("RELEASE CODE VERSION {} and applicationProperty Version {} ", LcoBuildVersion.version,
applicationPropertyVersion);
We can't read values into static fields . Here is the explanation gives a better insight How to assign a value from application.properties to a static variable?

Resources