Scheduling a function in Spring boot - spring-boot

I am trying to schedule the following function to run every 10seconds. But it tells that it needs a void function. Is there any way to schedule the following function?
#Scheduled(fixedRate = 10000)
public FtpOutboundGateway getFiles() {
FtpOutboundGateway gateway = new FtpOutboundGateway(sf(), "mget", "payload");
gateway.setAutoCreateDirectory(true);
gateway.setLocalDirectory(new File("./downloads/"));
gateway.setFileExistsMode(FileExistsMode.REPLACE_IF_MODIFIED);
gateway.setFilter(new AcceptOnceFileListFilter<>());
gateway.setOutputChannelName("fileResults");
return gateway;
}

Since #Scheduled method is called internally by the threads in thread pool in a given interval or time, the annotation expect it to be void because it doesn't make sense to return values. if you want to track down the response the extract it to another method and call it from the #Scheduled method as well as from other services.

For this, we need to do the following things.
First put this Annotation #EnableScheduling at the class level.
then at the function which needs to be scheduled should be marked with #Scheduled.
The function that we are trying to schedule should not return anything.
#EnableScheduling
class <ClassName>{
//def
#Scheduled(fixedDelayString = "10000")
public void fxnName() {
//def
}
}

Related

Programmatically trigger a #Scheduled method?

I'm working on a Springboot app that includes a task that's executed on a schedule. It typically takes about two to three minutes to run.
#Scheduled(cron = "* */30 * * * *")
public void stageOfferUpdates() throws SQLException {
...
}
We have a requirement to be able to kick off the execution of that task at any time by calling a rest endpoint. Is there a way my #GET method can programmatically kick this off and immediately return an http 200 OK?
So you just want to trigger an async task without waiting for results. Because you are using Spring, the #Async annotation is an easy way to achieve the goal.
#Async
public void asyncTask() {
stageOfferUpdates();
}
Couldn't you just run the method in another Thread:
executor.execute(() -> {
stageOfferUpdates();
}
and then procede and return 200?

axon 4 snapshot in demand

I work with spring boot and axon example, i implement the snapshot feature, with the below code is working fine, after 3 events i found the data in the table snapshot_event_entry in the database
#Configuration
#AutoConfigureAfter(value = { AxonAutoConfiguration.class })
public class AxonConfig {
#Bean
public SnapshotTriggerDefinition catalogSnapshotTrigger(Snapshotter snapshotter) {
return new EventCountSnapshotTriggerDefinition(snapshotter, 3);
}
}
#Aggregate(snapshotTriggerDefinition = "catalogSnapshotTrigger")
public class CatalogAggregate { }
My question, is there a method to do a snapshot in demand? That means i want to implement an api to do the snapshot, not automatically after 3 events
there is nothing already in place.
One way to implement what you need is to create a dedicated Command, eg PerformShapshotCmd, that will carry the aggregateId information, and a #CommandHandler into your Aggregate. You could then let Spring autowire the Snapshotter instance bean, and call for the scheduleSnapshot(Class<?> aggregateType, String aggregateIdentifier) method.
Below some code snippet that could guide you.
data class PerformShapshotCmd(#TargetAggregateIdentifier val id: String)
#CommandHandler
public void handle(PerformShapshotCmd cmd, Snapshotter snapshotter) {
logger.debug("handling {}", cmd);
snapshotter.scheduleSnapshot(this.getClass(), cmd.getId());
}
You should also define one Bean of type Snapshotter into your config
#Bean
public SpringAggregateSnapshotterFactoryBean snapshotter() {
SpringAggregateSnapshotterFactoryBean springAggregateSnapshotterFactoryBean = new SpringAggregateSnapshotterFactoryBean();
//Setting async executors
springAggregateSnapshotterFactoryBean.setExecutor(Executors.newSingleThreadExecutor());
return springAggregateSnapshotterFactoryBean;
}
Please note that the first argument of your commandHandler needs to be the command, otherwise the framework will complain with an exception at startup time.

Spring Cloud - HystrixCommand - How to properly enable with shared libraries

Using Springboot 1.5.x, Spring Cloud, and JAX-RS:
I could use a second pair of eyes since it is not clear to me whether the Spring configured, Javanica HystrixCommand works for all use cases or whether I may have an error in my code. Below is an approximation of what I'm doing, the code below will not actually compile.
From below WebService lives in a library with separate package path to the main application(s). Meanwhile MyWebService lives in the application that is in the same context path as the Springboot application. Also MyWebService is functional, no issues there. This just has to do with the visibility of HystrixCommand annotation in regards to Springboot based configuration.
At runtime, what I notice is that when a code like the one below runs, I do see "commandKey=A" in my response. This one I did not quite expect since it's still running while the data is obtained. And since we log the HystrixRequestLog, I also see this command key in my logs.
But all the other Command keys are not visible at all, regardless of where I place them in the file. If I remove CommandKey-A then no commands are visible whatsoever.
Thoughts?
// Example WebService that we use as a shared component for performing a backend call that is the same across different resources
#RequiredArgsConstructor
#Accessors(fluent = true)
#Setter
public abstract class WebService {
private final #Nonnull Supplier<X> backendFactory;
#Setter(AccessLevel.PACKAGE)
private #Nonnull Supplier<BackendComponent> backendComponentSupplier = () -> new BackendComponent();
#GET
#Produces("application/json")
#HystrixCommand(commandKey="A")
public Response mainCall() {
Object obj = new Object();
try {
otherCommandMethod();
} catch (Exception commandException) {
// do nothing (for this example)
}
// get the hystrix request information so that we can determine what was executed
Optional<Collection<HystrixInvokableInfo<?>>> executedCommands = hystrixExecutedCommands();
// set the hystrix data, viewable in the response
obj.setData("hystrix", executedCommands.orElse(Collections.emptyList()));
if(hasError(obj)) {
return Response.serverError()
.entity(obj)
.build();
}
return Response.ok()
.entity(healthObject)
.build();
}
#HystrixCommand(commandKey="B")
private void otherCommandMethod() {
backendComponentSupplier
.get()
.observe()
.toBlocking()
.subscribe();
}
Optional<Collection<HystrixInvokableInfo<?>>> hystrixExecutedCommands() {
Optional<HystrixRequestLog> hystrixRequest = Optional
.ofNullable(HystrixRequestLog.getCurrentRequest());
// get the hystrix executed commands
Optional<Collection<HystrixInvokableInfo<?>>> executedCommands = Optional.empty();
if (hystrixRequest.isPresent()) {
executedCommands = Optional.of(hystrixRequest.get()
.getAllExecutedCommands());
}
return executedCommands;
}
#Setter
#RequiredArgsConstructor
public class BackendComponent implements ObservableCommand<Void> {
#Override
#HystrixCommand(commandKey="Y")
public Observable<Void> observe() {
// make some backend call
return backendFactory.get()
.observe();
}
}
}
// then later this component gets configured in the specific applications with sample configuraiton that looks like this:
#SuppressWarnings({ "unchecked", "rawtypes" })
#Path("resource/somepath")
#Component
public class MyWebService extends WebService {
#Inject
public MyWebService(Supplier<X> backendSupplier) {
super((Supplier)backendSupplier);
}
}
There is an issue with mainCall() calling otherCommandMethod(). Methods with #HystrixCommand can not be called from within the same class.
As discussed in the answers to this question this is a limitation of Spring's AOP.

spring boot batch-- How can we read Jobperameters from ItemReader<>?

need to fetch the job parameters in ItemReades from jobLancher.run(job, parameters); in to ItemReader<>
Spring Boot------
i did like below.
i created listener where i can monitor after/before batch job running.
in listener i created static method which is return JobExecution entity where as we can find job related parameters like below.
public class MyListener extends Job***Listener**{
private static Jobexceution jobExecution1;
#Override
p v beforeJob(Jobexceution jobExecution){
this.jobExecution1=jobExecution;
}
p s JobExecution getJobExecution (){
return jobExecution1;
}
}

spring scheduling a job with fixed delay and initial delay

I am trying o schedule a method call. I want to schedule this method call as soon as server starts and then after every 30 seconds.
Below code:
#Configuration
#EnableScheduling
#EnableTransactionManagement
public class Schedular implements SchedulingConfigurer {
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(poolScheduler());
taskRegistrar.addTriggerTask(new Runnable() {
#Override
public void run() {
testScheduling();
}
}, new Trigger() {
#Override
public Date nextExecutionTime(TriggerContext triggerContext) {
Calendar nextExecutionTime = Calendar.getInstance();
nextExecutionTime.add(Calendar.SECOND, <some value from database>);
return nextExecutionTime.getTime();
}
});
}
#Bean
public TaskScheduler poolScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("poolScheduler");
scheduler.setPoolSize(10);
return scheduler;
}
public void testScheduling(){
System.out.println("Scheduling Testing");
}
}
The code below schedule the method code after 30 seconds after the server started BUT NOT just after server started. I know I need to do some other config to schedule the method call just after server start and then after every 30 seconds (or whatever time I want to).
I am using spring boot. Could anyone please suggest.
Also, is it possible to get both initial and fixeddelay/fixedrate value from database. I want to set the initial value as well from database
Thanks in advance.
let me know if this worked for you
#PostConstruct
#Scheduled(fixedDelay=30000)
public void testScheduling(){
System.out.println("Scheduling Testing");
}
Use the #PostConstuct annotation to start the method after the application starts.
You can use like below. I had used Spring Boot version v2.2.7
#Scheduled(fixedRateString = "${echo.interval(milliseconds)}", initialDelayString = "${echo.initialDelay(milliseconds)}")
The properties should be mentioned in "application.properties" file for the Spring Boot to detect and inject the values of the fixed rate and initial delay into the Scheduler.

Resources