I'm using SpringBatch but I cant find any document or tutorial about Spring's #Scheduled , showing it being used along side with some controller method (annotated with #GetMapping, #PostMapping).
For example, I have this controller method
#Scheduled(cron = "0 */5 * ? * *")
#PostMapping("/create-progress-data")
public ResponseEntity<?> createSomething(#Request Something request) { }
I can easily create another method that do the same thing as in the body of createSomething then put it in a #Component or a Service, but between doing that and just applying #Scheduled on top of the controller method, I don't know which one is better.
I can see that:
Using #Scheduled : code is minimal, works just find. But we're kind of using the controller method in the wrong way. However I don't see it violates Single responsibility point in design pattern.
Create another method and put it in other #Component or #Service: separate the duty of the controller method and the cron job but duplicate the code.
Ps: I need to implement it like this because we need to support two ways to trigger the job. Either via api call (controller method), or periodically (with #Scheduled).
Please notice in this case the code of controller method and the expected cron job is the same.
I believe it is better to separate the two ways of launching your jobs. You can use the controller for API-based on-demand job launches, and use the #Scheduled way for a background process that launches jobs on the defined schedule.
That said, you should take into consideration the concurrency policy for your job definitions. For example, what should your system do if a job launch request comes through the API and tries to launch the same job that has been launched by a schedule (which could be running at that time)?. There are other use cases, but those depend on your requirement.
Related
We have a Spring micro-service connected to Axon with an #Component and an #EventHandler function on this class. Like this:
#Component
#AllowReplay(false)
class AClass {
#EventHandler
fun on(someEvent: SomeEvent) {
...some handling here
}
}
The Event gets picked up normally and everything works fine but when we run multiple instances of our service only one instance of the service picks up the event. I userstand that this has to do with the way the event processors work (https://docs.axoniq.io/reference-guide/axon-framework/events/event-processors) but I need all instances of the service to pick up the event. How can I configure this?
It pretty much depends on how you are configuring and using it.
So, 'pick up' events, the way you describe, I assume that are events being handled.
In that case, and another assumption here that you are using some sort of Tracking Event Processor (TEP), this is where this logic and responsability is.
In essence, a TEP is responsible for 'tracking' which events it already received to not double react on those.
In your scenario, seems like your apps/instances are sharing the same database (hence sharing the same tokens) and that's why you see it.
About your 'workaround', you are just assigning names to a Processing Group (which can also be done using annotations like this: #ProcessingGroup("processing-group-name-you-want"). If you do not assign a name, the package is the default name used.
Every Processing Groups has a tracking token behind it. In this case, you get multiple tokens and 'react' to the same event multiple times.
For more info about Processing Groups, I recommend this answer.
The answer that works for me, although not the prettiest: Axon 'merges' processors based on package name so multiple instances of a service result in a single processor.
By using unique processing groups you can trick Axon into not 'merging' the different processors into one.
#Autowired
fun configure(configurer: EventProcessingConfigurer) {
configurer.assignProcessingGroup { t: String? -> "${t}_${UUID.randomUUID()}" }
}
What changes if I call
schedule->call(function() { .. do something ... })->daily()
and if I call
schedule->job(... my job class where handle do the same things... )->daily()
?
The job() method is there specifically for adding a Laravel job (i.e. a class that implements the Illuminate\Contracts\Queue\ShouldQueue interface) to a queue. Whereas the call() method would run a Closure or an invokable object synchronously at the scheduled time, the job() method would add the given job to a queue at the scheduled time. The queue worker would then process the job when it gets to the front of the queue which might not be immediately.
The $schedule->job(new Heartbeat)->everyFiveMinutes(); is then basically a shortcut for:
$schedule->call(function () {
Heartbeat::dispatch();
})->everyFiveMinutes();
It's practically the same thing.
$schedule->job() requires you to create a job class and add the logic there. This is an easy way to schedule a job without having to write the execution code yourself.
Where as $schedule->call() allows you to do any action directly in a callback. This removes the need to create a job class for simple actions.
job()
The job method may be used to schedule a queued job. This method
provides a convenient way to schedule jobs without using the call
method to manually create Closures to queue the job.
source :https://laravel.com/docs/5.8/scheduling#scheduling-queued-jobs
Basically, there is no significant difference for you. But writing complex code in the call method can become messy quite easily.
The main difference is that one has the code in-line and the other separates it out into its own class.
The in-line option is appropriate if the code is extremely short, readable, and in context.
The separate class option is appropriate if the code is more than a couple of lines long.
In general writing clean code to the SOLID principles would dictate using the separate class option in almost every case.
I am pretty new to Spring Boot, and working on developing a mini application for myself, that will able to implement a service that provides a set of APIs for managing a set of calendars for different users.
I am using STS IDE for this project and selected Apache Derby, JPA and Web dependencies for the same. I have created two Entity class for CalanderEvents and CalanderUser and the basic CRUD operation for both of them.
I have two questions:
1)I am using Postman app to implement CRUD operations and just cant figure out how to fetch Meeting time for Post master in STS so that I can create a background app that sends reminder 30 minutes prior to the meeting time.
Will #Async work here?
2) For user based authentication, I think JWT will do the work, but do I need to have a GUI just to implement token based authentication, or can I do it through postman?
I am not sure if I am able to clearly put up my query, please let me know if you think I need to add some more information.
Thanks.
Small precision -- you're not using Postman to implement CRUD; you're using Postman to test your implementation.
#Async is used to allow the execution of methods in an asynchronous manner (in other words, multiple methods can run at the same time). What you're looking for is probably #Scheduled.
#Scheduled allows you to schedule a task every X amount of time -- in your case, to schedule the execution of a method, you'd do something like that:
#Scheduled(fixedRate = 1800000)
public void sendMessagePeriodically() {
// ...
}
(1000ms * 60 * 30 = 1800000ms = 30min)
In order for the above to work, you can annotate a configuration class with #EnableScheduling:
#Configuration
#EnableScheduling
public class SchedulingConfiguration {
}
Alternatively, you can add #EnableScheduling on top of your main class (the one with #SpringBootApplication)
No, you don't need a GUI. All you need to do is implement an authentication system either with Spring Security (which would make your work much easier), or by using a controller. Then, you can simply communicate with that API using Postman in order to authenticate yourself.
Good luck.
Update
For instance, you can schedule a task that runs every minute and checks if there's any events scheduled in 30 minutes. If there is, then send a notification:
#Scheduled(fixedRate = 60000)
public void checkForUpcomingEvents() {
// get all events scheduled in ~30 minutes
List<Event> events = getEventsScheduledSoon();
for (Event event : events) { // for each event
event.notifyUsers(); // notify all users concerned
}
}
Note that it is important that you get all events that have an event in approximately 30 minutes (e.g. between 29 - 31), because while you can rely on #Scheduled to execute, you still need to consider potential delays. Following that logic, you also need to make sure that you don't notify the same person for the same event twice.
There are multiple variables to consider, for instance, how long does getting events take? How long does notifying the users take? Depending on those variables, you may need to adjust your configuration (e.g. run every 5 minutes instead of 1 minute).
There are really a lot of ways to go about this, your solution of using java's ExecutorService is also an excellent one, but as you have tagged your question with spring-boot and not java, I opted for the #Scheduled approach.
I'm trying to use spring cloud stream to send and receive messages on kafka. The examples for this use a simple example of using time stamps as the messages. I'm trying to go just one step further into a real world application when I ran into this blocker on the InboundChannelAdapter docs:
"A method annotated with #InboundChannelAdapter can't accept any parameters"
I was trying to use it like so:
#InboundChannelAdapter(value = ChannelManager.OUTPUT)
public EventCreated createCustomerEvent(String customerId, String thingId) {
return new EventCreated(customerId, thingId);
}
What usage am I missing? I imagine that when you want to create an event, you have some data that you want to use for that event, and so you would normally pass that data in via parameters. But "A method annotated with #InboundChannelAdapter can't accept any parameters". So how are you supposed to use this?
I understand that #InboundChannelAdapter comes from spring-integration, which spring-cloud-stream extends, and so spring-integration may have a different context in which this makes sense. But it seems un-intuitive to me (as does using an _INBOUND_ChannelAdapter for an output/producer/source)
Well, first of all the #InboundChannelAdapter is defined exactly in Spring Integration and Spring Cloud Stream doesn't extend it. That's false. Not sure where you have picked up that info...
This annotation builds something like SourcePollingChannelAdapter which provides a poller based on the scheduler and calls periodically a MessageSource.receive(). Since there is no any context and end-user can't effect that poller's behavior with his own arguments, the requirement for empty method parameters is obvious.
This #InboundChannelAdapter is a beginning of the flow and it is active. It does its logic on background without your events.
If you would like to call some method with parameters and trigger with that some flow, you should consider to use #MessagingGateway: http://docs.spring.io/spring-integration/reference/html/messaging-endpoints-chapter.html#messaging-gateway-annotation
How are you expecting to call that method? I think there was a miscommunication with your statement "stream extends integration" and Artem probably understood that we extend #InboundChannelAdatper
So, if you are actively calling this method, as it appears since you do have arguments that are passed to it, why not just using your source channel to send the data?
Usually sources do not require arguments as they are either push like the twitter stream that taps on twitter, listen for events and pushes them to the source channel, or they are polled, in which case, they are invoked on an interval defined via a poller.
As Artem pointed, if your intention is to call this method from your business flow, and deal with the return while triggering a message flow, then check his link from the docs.
I need to implement this functionality but I dont know to design and proceed on this.Please help me.
I have to import csv file from web ui. I used struts2(mvc)+spring(object injector)
I have done this task. But now the i have to import asynchronously i.e at a time many imports it should support. How can I do it?
I have done R&D. I found quartz. But can i use this?
Consider, I have two buttons. Clicking on first button it will go to first page there i can able to import cat1 type csv file containing 20k items. Clicking on second button it will go to another page there i can import cat2 type csv file containg 20k items.
How do i can implement it. Now its happening like at a time only one import can be done. but i want this to be asynchronous.
Judging from your requirements, I don't think Quartz will be needed. Quartz is a scheduler and what you need is a Spring asynchronous task execution facilities.
Essentially, what is done, upon first call of async bean, control is immediately returned and the called async bean is handed off to Spring's TaskExecutor which further on controls the execution of the given method logic.
High-level overview of your options is as follows: you will need to inject a TaskExecutor bean implementation into Spring context and your asynchronous method logic will have to somehow perform the handoff either by
(XML-config) wiring TaskExecutor as a collaborator inside your Spring bean containing method which you intend to execute asynchronously and calling execute() method of TaskExecutor, or
(annotation-config) by marking the intended method with #Async annotation. Be advised, TaskExecutor implementation must be injected into Spring context.
Also, take note that should you want to return something from your asynchronous task, the return type must be an implementation of Java's Future<T> interface, which is a requirement since TaskExecutor is built on java.concurrent.util.Executor interface.
I can't comment on Struts, though, as I've never worked with it, but as far as I can tell, Struts should have no part in realizing asynchronicity - the heavy lifting is done by Spring alone.
For a more thorough and complete look on mentioned subject, I suggest starting with the following links:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#scheduling
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/
http://docs.oracle.com/javase/1.5.0/docs/api/index.html?java/util/concurrent/Executor.html