Spring boot load data to sql before start api - java

I'm trying to implement quartz scheduler for email scheduling. So everything is set up but tha main problem is dump for quartz trigers. After downloading script for postgre i mannualy run it from terminal using '\i path to scrpt'. I want that spring automatically run this script when api starts up.
I try to copy this script to resources and try to change some properties but nothing works yet
# Hibernate properties
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto= update
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation = false
# QuartzProperties
spring.quartz.job-store-type = jdbc
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#spring.quartz.jdbc.schema=classpath:org/quartz/impl/jdbcjobstore/tables_postgres.sql
org.quartz.jobStore.dataSource = default
spring.quartz.properties.org.quartz.threadPool.threadCount = 5

if you are using spring boot you can use #EnableScheduling inna your Application class like this:
#SpringBootApplication
#EnableScheduling
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
Then, you can use #Scheduled in your class jobs, for example:
#Component
public class MyJob {
#Scheduled(fixedDelay= 1000 * 60 * 24)
public void execute() {
System.out.println("Your job here!");
}
}
if you want a delay on start use initialDelay.

Solved, add prop: spring.datasource.initialization-mode=always. I need to do job only once and at the fixed time, so i need to use quartz.

Related

Time Scheduling in Spring Boot

I have the List of the requested user and I want to upload the list of the user every day at 7 pm on each day. how can i do that using Spring Boot.And yes, it should also check whether the list is available or not.
You can achieve this with #Scheduled annotation in one of your methods of the bean. In order to enable scheduling you need to put #EnableScheduling annotation in one of your config classes, can be the main class:
#SpringBootApplication
#EnableScheduling
public class TestingApplication {
public static void main(String[] args) {
SpringApplication.run(TestingApplication.class, args);
}
}
Then you create a class, annotate it with #Component and create a method with #Scheduled annotation with a cron statement inside:
#Component
public class MyWorkerComponent {
#Autowired
private MyListChecker myListChecker;
#Scheduled(cron = "0 0 19 * * ?")
public void doTheListThingy() {
if (myListChecker.isTheListAvailable()) {
// your task logic
}
}
}
First,you should make a descition when your application have more than one instance the task need to executed once or can executed more than once.
If the task can executed more than once,the method provided by #Pijotrek and #mkjh is good. If the task must executed only once you must use Quartz Scheduler or other framework support distribute scheduling task sysytem.more information you can get from here

How to load h2 data in spring boot test before component initialization

I have a #Component with #Scheduled method which runs every x mins (fixed delay)
While running my integration #SpringBootTest, this component gets initialized with application context, and then executes my test methods
The scheduler polls DB periodically and executes some logic. So as soon as application-context is loaded, it requires data pre-loaded in h2 database
#Component
public class MyScheduler {
...
...
#Scheduled(fixedDelayString = "${poll.interval:300}")
public void testXYZ() throws Exception {
dbService.fetchRecords();
//do blah blah
}
}
How can I pre-load initial data in h2 before #SpringBootTest application-context is loaded ?
I want to perform data assertions based on few #Scheduled periodic runs once the service comes up in my integration test
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class MyIntegrationTest{
...
#Test
#Sql(scripts={"classpath:data/data.sql"},
config=#SqlConfig(transactionMode = TransactionMode.ISOLATED),
executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
testMySchedulerLogic() {
assertTrue(isProcessed(), true);
}
}
Create import.sql file in test resources with the data you need.
In addition, a file named import.sql in the root of the classpath is executed on startup if Hibernate creates the schema from scratch (that is, if the ddl-auto property is set to create or create-drop). This can be useful for demos and for testing if you are careful but is probably not something you want to be on the classpath in production. It is a Hibernate feature (and has nothing to do with Spring).
Source: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html

Spring Scheduled task does not start on application startup

I have a #Scheduled task in my application which is setup using CRON and run every 4 hours. The problem I face is that the CRON job does not start immediately after application startup but it starts only 4 hours after the application startup.
I tried to use a #PostConstruct method inside the task to invoke it, but that results in an error due to an uninitialized Spring context.
Please tell me how I can make the Scheduled task run immediately on application deployment and then on every 4 hours after the deployment.
EDIT:
I would not use a #PostConstruct since my scheduled method depends on other Beans , which are not initialized when this PostConstruct method runs for some reason.
By 0 */4 * * * you specify "At minute 0 past every 4th hour (0:00, 4:00, 8:00 etc.)", which is not at startup time and then every 4 hours as I think you want.
You can specify initial delay and rate by:
#Scheduled(initialDelay=0, fixedRate=4*60*60*1000)
If you are worried about hard-coded values, you can still provide config value:
#Scheduled(initialDelay=0, fixedRateString = "${some.config.string}")
I had #EnableScheduling in my app config. I had
#Scheduled(fixedDelay=5000) in my scheduled task class. Even then it didn't work.
I added #Service to my scheduled task class and everything worked fine.
I'm not sure if you have tried this but you can use #Scheduled with an initialDelay
For fixed-delay and fixed-rate tasks, an initial delay may be specified indicating the number of milliseconds to wait before the first execution of the method.
https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html#scheduling-annotation-support-scheduled
#Scheduled(initialDelay=0, fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
I assume this will execute your scheduled method when the application is run.
If is not possible to use initialDelay attribute with the cron rule and your intention is execute this Job after every restart, you can implement a CommandLineRunner on your application class:
#SpringBootApplication
public class MyApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
#Autowired
private TaskService taskService;
#Override
public void run(final String... args) throws Exception {
taskService.run();
}
}
It's not the best strategy, but works.
Just specify the method you want to run in the init_method attribute of the bean.
Java config: #Bean(init_method="methodWhichStartsTask")
XML config: <bean id="someId" class="com.example.Clazz" init-method="methodWhichStartsTask"/>
This will invoke the method just after the bean is properly initialized and if the method is scheduled, then it will be called afterwards every 4 hours.
Instead of cron inside #Scheduled, use fixedRate like below. By default initialDelay is -1, which will start immediately or you can set 0.
#Scheduled(fixedRate=4*60*60*1000)
public void test() {
System.out.println("helloworld");
}
I was having the same situation. I need to run cron scheduler every 1st day of the month and also when the application starts.
This is how I achieved using ApplicationListener.
import org.springframework.context.ApplicationListener;
import org.springframework.boot.context.event.ApplicationReadyEvent;
#Component
public class ApplicationReadyListner implements ApplicationListener<ApplicationReadyEvent> {
#Override
public void onApplicationEvent(ApplicationReadyEvent event) {
// callYourTask();
}
}
user #EnableScheduling annotation on your class which contains you1 scheduled method:
see spring document:
To enable support for #Scheduled and #Async annotations add
#EnableScheduling and #EnableAsync to one of your #Configuration
classes:
#Configuration
#EnableAsync
#EnableScheduling
public class AppConfig {
}
link : https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

Spring Boot, Scheduled task, double invocation

Got a pretty standard Spring Boot (1.3.5) application.
Enabled scheduling with #EnableScheduling (tried on main application entry point and a #Configuration annotated class.
Created a simple class with a #Scheduled method (simple fixedDelay schedule).
Scheduled task executes twice (always).
From what I have gathered so far, it is probably because two contexts are being loaded, and thusly picking up my beans twice.
Ok.
So how do I fix/prevent this double execution, since all the config is basically hidden Spring Boot magic?
Framework versions:
Spring Boot 1.3.5
Spring Cloud Brixton SR1
Main application:
#SpringBootApplication
#EnableDiscoveryClient
#EnableAsync
#EnableCircuitBreaker
public class AlertsApplication {
public static void main(final String[] args) {
SpringApplication.run(AlertsApplication.class, args);
}
}
My task class (HookCreateRequest list is pulled in from application.yml - I do not believe that to be relevant currently, but if required, can be provided):
#ConditionalOnProperty(name = "init.runner", havingValue = "InitRunner")
#ConfigurationProperties(prefix = "webhook")
public class InitRunner /*implements CommandLineRunner*/ {
private final List<HookCreateRequest> receivers = new ArrayList<>();
#Autowired
private WebHookService hookService;
#Scheduled (fixedRate = 300000)
public void run() throws Exception {
getReceivers().stream().forEach(item -> {
log.debug("Request : {}", item);
hookService.create(item);
});
}
public List<HookCreateRequest> getReceivers() {
return receivers;
}
}
There is zero xml configuration.
Not sure what else might be relevant?
EDIT 2016/07/04
I have modified to output the scheduled instance when it runs (I suspected that two different instances were being created). However, the logs seem to indicate it is the SAME instance of the task object.
logs:
15:01:16.170 DEBUG - scheduled.ScheduleHookRecreation - Schedule task running: scheduled.ScheduleHookRecreation#705a651b
...task stuff happening
...first run completes, then:
15:01:39.050 DEBUG - scheduled.ScheduleHookRecreation - Schedule task running: scheduled.ScheduleHookRecreation#705a651b
So it would seem it is the same task instance (#705a651b). Now why would in the name of sweet things would it be executed twice?
EDIT 2016/07/05
I added a #PostConstruct method to the class that carries the scheduled method, with just some logging output in. By doing that I could verify that the #PostConstruct method is being called twice - which seems to confirm that the bean is being picked up twice, which which presumably means it is fed to the scheduler twice. So how to prevent this?
Had the same problem, in my case the reason was in #Scheduled annotation's initialDelay parameter absence - method was called on application start.

disable scheduling with properties file

I would like to disable spring scheduling via an external config file. I have the config file setup and the task in the example below logs out the following.
INFO MainTaskScheduler:36 - scheduled task: Update converted bookings false. So im most of the way there.
What im looking to achieve is to not to have to put logic inside each task method to determine if scheduling properties has been enabled.
So something like this on my config file (this isn't valid code)
#EnableScheduling(${enable.scheduling})
My working snippets
AppConfiguration
#Configuration
#EnableTransactionManagement
#EnableScheduling
#ComponentScan( /*etc*/})
public class AppConfiguration {
}
MainTaskScheduler
#Component
public class MainTaskScheduler {
private Logger log = LoggerFactory.getLogger(getClass());
#Value("${enable.scheduling}")
private Boolean enableScheduling;
#Scheduled(fixedRate=300) // every 5 minutes -- check if any existing quotes have been converted to bookings
public void updateConvertedBookings() {
log.info("scheduled task: Update converted bookings "+enableScheduling);
// logic for class here
}
}
application.properties
enable.scheduling=false
If you are using spring boot, you can use #ConditionalOnExpression annotation to enable or disable scheduling:
#ConditionalOnExpression("'${enable.scheduling}'=='true'")

Resources