Spring batch with multiple main and scheduler - spring-boot

I am working on a Spring Batch project that has two Main classes with #SpringBootApplication in it. I also have to use the #Scheduler and associate it only with one Main class. But the issue here is no matter which class I run, the scheduler is getting executed. Snippets below,
MainApp1.java
#SpringBootApplication
#EnableScheduling
public class MainApp1{
public static void main(String[] args) {
SpringApplication.run(MainApp1.class, args);
}
}
MainApp2.java
#SpringBootApplication
public class MainApp2{
public static void main(String[] args) {
SpringApplication.run(MainApp2.class, args);
}
}
Scheduler.java
#Configuration
public class TmsBatchSenderScheduler {
#Scheduled(fixedDelay = 5000)
public void myScheduler() {
}
}
I think what's happening here is the scheduler is getting created for both mains because of the #Configuration annotation. Is there a way to achieve this? I want the scheduler to run only when the MainApp1 is run.
Thanks in advance :)

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 postconstruct not called when running java -jar

I have the following class which has postconstruct.. But it doesnt seem to call the postconstruct? But it works in the eclipse IDE? But when i call it via java -jar... nothing
#SpringBootApplication
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#PostConstruct
public void postcontruct() {
System.out.println("******************TEST ********");
}
}

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.

#SpringbootApplication does not scan components in default package

Hi I have my main class of spring boot app in package com
and two other beans defined in com.bbh.fx.pack1.
As per my understanding SpringBootApplication will autoscan all the components in its pakacge and childern package. But it is not scanning. Not sure what i am missing
**package com.bbh.fx.pack1;**
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
#Component
public class BeanA {
#PostConstruct
public void init() {
System.out.println("in BEANA");
}
}
**package com;**
#SpringBootApplication
public class MainApp{
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
}
You do not have a main in your MainApp your code should look like:
#SpringBootApplication
public class MainApp{
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
}
I usually like to start all new applications from https://start.spring.io/ you can choose your project name, build type (maven or gradle) and select any spring dependencies you'd like included in the application.
Use #ComponentScan to scan components.
#SpringBootApplication
#ComponentScan("com")
public class MainApp{
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
}

Shutting down after task completion

I have spring application written in the following way -
#SpringBootApplication
#Import({
ApplicationLoader.class
})
public class MyApplication {
#Bean
public Clock clock() {
return Clock.systemDefaultZone();
}
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
The ApplicationLoader class looks like below
public class ApplicationLoader {
private final MyService myService;
public ApplicationLoader(MyService myService) {
// create
this.myService = myService;
}
#PostConstruct
void startJob() {
// perform some long running task
myService.runLongRunningTask();
}
}
Once ApplicationLoader finishes its job, Spring Application continues to run while I want it to stop.
Is there a way I can introduce a stop to this entire application lifecycle which runs after the application is done performing the long running task? I don't mind a rewrite of ApplicationLoader or MyApplication if there is a better way. My aim is to instantiate MyService and run myService.runLongRunningTask() based on certain runtime conditions.

Resources