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

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?

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?

How to read it from the properties file in Springboot

application.properties file has:
my.greeting = Hello
ServiceClass file has:
#Value("${my.greeting}")
private String messageFromProperties;
MainAppfile:
public static void main(String[] args) {
SpringApplication.run(SpringBootApplicationConceptsApplication.class, args);
ServiceClass serv = new ServiceClass();`enter code here`
System.out.println(serv.getMessageFromProperties());//getting null
}
Please let me know what am i missing here. What all configuration is pending
You need to use #PropertySource to specify the source.
For example:
#PropertySource(value = "example.properties")
You can use the above-mentioned annotation with your main class.
For example:
#SpringBootApplication
#PropertySource(value = "example.properties")
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
Or, you can use them with classes annotated with #Configuration.
For example:
#Configuration
#PropertySource("example.properties")
public class ExampleConfiguration {
//code
}
If this doesn't help, I would advise you to share your complete code for everyone to understand what exactly the problem is.

How to pick spring option arguments at run time in java class

I want to know how to pick spring option arguments like
--server.port , --spring.config.name
in a java class.
Basically I want to know the value of this argument at run time to load some property
You can access them in your application's main() method. A great blog about this topic covers it in detail. Following is how you can do it.
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
for(String arg:args) {
System.out.println(arg);
}
SpringApplication.run(Application.class, args);
}
}
Please try using spring org.springframework.core.env.Environment,
public class MyService {
#Autowired
private Environment env;
public String getPropertyValue(String key) {
return env.getProperty(key);
}
}
OR
In application-<env>.propeties (if using spring.profiles)
else application.properties
myapp.property=007
In your class :
#Value("${myapp.property}")
private String myProperty;

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 with additional main() methods

I have a simple SpringBootApplication that sets up JPA and defines some Beans.
#SpringBootApplication
public class AnalysisApplication {
public static void main(String[] args) {
SpringApplication.run(AnalysisApplication.class, args);
}
#Autowired
SoftwareArchiveRepository swaRepository;
#Bean
SoftwareArchiveService swaService() {
return new SoftwareArchiveService(swaRepository);
}
#Bean
PlatformService platformService(#Autowired PlatformRepository platformRepository) {
return new JpaPlatformService(platformRepository);
}
// More Bean definitions omitted
}
I now want to use this context in a couple of classes that perform one time setup for my application that I will call manually. Although they use the defined beans, they are not really part of the application - basically I want to perform a one-off data load exercise.
public class DatabaseLoader {
ApplicationContext context;
public static void main(String[] args) {
DatabaseLoader loader = new DatabaseLoader();
loader.run();
}
private void run() {
context = ??????
PlatformService service = context.getBean("platformService");
// etc etc
}
What do I need to do to intialize a SpringBootApplication context so that all the SpringBoot autoconfiguration happens without actually calling SpringApplication.run(AnalysisApplication.class, args);

Resources