Long running job Spring - java

I want to create a web page which takes a string as an input and start a process. The process will run for long time. I need to email the results after processing.
Which spring API should I use ?
The user will close the browser once he makes the request . I am a newbie to Java EE and spring .
Can anyone say the architecture that is needed to accomplish this ?

You could use some executor service:
#Bean
public ExecutorService executorService() {
return Executors.newCachedThreadPool();
}
Then
executorService.execute(yourLongRunningTaskRunnable);
in your controller, where yourLongRunningTaskRunnable is, of course, a Runnable. This like schedules your task for execution. The task could send an email if needed in the end.
This is not a Spring API, but it seems suitable for such a task.

Related

how to make spring web flux wait until specified condition met in server and then return the response

I'm a starter in Spring Web-Flux. i want to have a reactive service for example named isConfirmed and this service must wait until another service of my server is called for example named confirm. both services are located in my server and the first reactive service must wait until the second service (confirm) is called and then return the confirm message. i want no threads to be blocked in my server until the second service is called. like an observer pattern. is it possible with spring web flux?
update: can we have this feature while server using distributed cache?
I think you could use a CompletableFuture between your 2 services, something like that:
CompletableFuture<String> future = new CompletableFuture<>();
public Mono<String> isConfirmed() {
return Mono.fromFuture(future);
}
public void confirm(String confirmation) {
future.complete(confirmation);
}

Using Java Executor Service In Online Application

I have one functionality in online application. I need to mail receipt to customer after generate receipt. My problem is mail function takes more time nearly 20 to 30 seconds, customer could not wait for long time during online transaction.
So i have used java ExecutorService to run independently mail service [sendMail] and return response PAGE to customer either mail sent or not.
Is it right to use ExecutorService in online application [Http request & Response]. Below is my code. Kindly advice.
#RequestMapping(value="/generateReceipt",method=RequestMethod.GET)
public #ResponseBody ReceiptBean generateReceipt(HttpServletRequest httpRequest,HttpServletResponse httpResponse) {
// Other codes here
...
...
I need run below line independently, since it takes more time. so commeneted and wrote executor service
//mailService.sendMail(httpRequest, httpResponse, receiptBean);
java.util.concurrent.ExecutorService executorService = java.util.concurrent.Executors.newFixedThreadPool(10);
executorService.execute(new Runnable() {
ReceiptBean receiptBean1;
public void run() {
mailService.sendMail(httpRequest, httpResponse, receiptBean);
}
public Runnable init(ReceiptBean receiptBean) {
this.receiptBean = receiptBean1;
return(this);
}
}.init(receiptBean));
executorService.shutdown();
return receiptBean;
}
You can do that, although I wouldn't expect this code in a controller class but in a separate on (Separation of Concerns and all).
However, since you seem to be using Spring, you might as well use their scheduling framework.
It is fine to use Executor Service to make an asynchronous mail sending request, but you should try to follow SOLID principles in your design. Let the service layer take care of running the executor task.
https://en.wikipedia.org/wiki/SOLID
I agree with both #daniu and #Ankur regarding the separation of concerns u should follow. So just create a dedicated service like "EmailService" and inject it where needed.
Moreover you are leveraging the Spring framework and u can take advantage of its Async feature.
If u prefer to write your own async code then I'll suggest to use maybe a CompletableFuture instead of the ExecutorService to better handling failure (maybe u want store messages not sent into a queue for achieving retry feature or some other behaviour).

Java: How to handle an API call that can take around 10 seconds

I have a requirement and I am bit confused about its design.
Requirement: iOS makes a call to backend(java), backend makes a call to the cloud API which return a token for future calls. The cloud API might take approximately 6 to 10 seconds to return the actual result, so instead of waiting for 6 to 10 seconds it gives a token back and let the caller(in my case the backend java server) to pull the results.
Current Approach: iOS calls the backend(java server), the backend calls cloud API and get's the token, then it sleeps the thread for 1 second and once the thread is invoked it hit the cloud API to get the status, if the status is not completed thread.sleep is invoked again and this continues till the cloud API call give's the complete result. Once the cloud API returns the result the backend returns the result to iOS.
The approach is not scalable and was done to test the cloud API but now we need a more scalable approach.
This is what I am thinking about iOS calls backend, backend calls the API and send back the result to iOS(it displays some static screen just to keep users engaged) and in the mean time it puts the object in Spring Thread pool Executor. The executor hits the API every one second and update the iOS through push notification and this continues till we get the final result from cloud API.
This is better then existing approach but even this doesn't look scalable and thread pool executor will get exhausted after some time(making it slow) and also thread.sleep is also not a good option.
I thought about using AWS SQS but it doesn't provide real time processing and running background jobs every 1 second doesn't seem to be a good option.
I am also exploring Apache Kafka and trying to understand whether it can fit to my use case.
Let me know if someone has tacked the similar kind of use case.
Here #EventListener in tandem with #Scheduled can be utilized, if Spring 4.2 (or newer) version is used.
First Create an event object say APIResult which will hold the API result
public class APIResult extends ApplicationEvent {
public APIResult(Object result) {
super(source);
}
}
Next register a listener for the event published as APIResult
#Component
public class MyListener {
#EventListener
public void handleResult(APIResult result) {
// do something ...
}
}
Next create a scheduled process which will hold the token(s) for which result is not yet retrieved
#Component
public class MyScheduled {
private final ApplicationEventPublisher publisher;
private List<String> tokens = new ArrayList<>();
#Autowired
public MyScheduled (ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
#Scheduled(initialDelay=1000, fixedRate=5000) // modify it as per requirement
public void callAPIForResult() {
// call the API and get result for each token(s) ....
this.publisher.publishEvent(new APIResult(result));
}
// method to add & remove tokens
}
The overall process flow should be like
Application submit a request to API and collect the respective token.
Token is passed to scheduled service to fetch the result.
In its next run the scheduled service iterates over the available token(s) and call API to fetch the results (if result is available publish the event else continue)
The published event is intercepted by registered listener; which itself process the result or delegates as applicable
This approach will transparently fetch results without messing with the business logic and at same time leveraging the standard framework features viz. scheduling and asynchronous event publishing & processing.
Although I have not tested this but it should work, at least giving an idea on how to implement. The setup is tested with Spring boot ver. 1.5.1.RELEASE which is backed by Spring's 4.3.6.RELEASE
Do let know in comments if any further information is required.
Reference - Application Event in Spring (link)
I am thinking about using Spring ConcurrentTaskExecutor(let's call it cloudApiCall) and as soon as I received the token from Cloud API, I will submit a future job to the executor and return the token to the Mobile Client. The thread associated with ConcurrentTaskExecutor will pick the job, call the Cloud API and submit the response to the another ConcurrentTaskExecutor(let's call it pushNotification) which will be responsible for pushing the silent notification to the Mobile client. The thread associated ConcurrentTaskExecutor(cloudApiCall), will also check the status of the call, if the future call is required, it will submit the job back to ConcurrentTaskExecutor(cloudApiCall). This will continue till we get the complete response.

What's the recommended way to run processes in the background with Spring?

I'm working on a web app with Spring (Boot, MVC) and there will be some things that will need to run in the background so I don't block the request.
Currently I was thinking in having a Spring Batch job that runs every 5mins and checks in a table (jobs_queue) in the DB if there are things to do and then run the tasks (based on what each row in the table requires).
Obviously this is not a good scalable solution (I think) as I will only have one worker (if there are too many jobs in the queue this single worker might not be able to handle the load) and it will also make at least one DB query every 5 mins (too see if there are jobs in queue).
What is a better way of doing this?
Adding to #kotabek's answer, Spring Batch has the ability to launch jobs via messages. So you can have the JobLaunchingMessagHandler listen for requests to launch a job and run it accordingly. This allows you to handle this use case both locally (with direct channels) or remotely (via some messaging middleware like Rabbit). You can read more about it in the documentation here: http://docs.spring.io/spring-batch/reference/htmlsingle/#launching-batch-jobs-through-messages
If you are using Spring 4, Have a look at #Scheduled annotation.
Example:
#Component
public class ScheduledTasks {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
#Scheduled(fixedRate = 5000)
public void reportCurrentTime() {
System.out.println("The time is now " + dateFormat.format(new Date()));
}
}
Code reference - https://spring.io/guides/gs/scheduling-tasks/
A small note: Don't forget to add #EnableScheduling in your config.
I recommend you use RabbitMQ or ActiveMQ. So you can write you tasks in query and when somebody or something add task your job will work. I think you can integrate it with db and listen insert events.

callback function do background jobs after the completing the action in java spring

I am new to Java Spring Framework, I am Rails developer I have requirement in java spring like I need to do background jobs but after the response send to the end User. It should not wait for the jobs to complete. But the jobs should run every time action completes.
Is a webservice app. We have Service, Bo and DAO layers and we are logging any exceptions occurred while processing the user data in database before response send to user, but now we want to move(Exception handling) after response send to user to increase the performance.
I remember in rails we have callbacks/filters after the action executed it calls the methods we want to executed. Same is available in java Spring?
Thanks,
Senthil
I assume the use case is something like a user requests a long-running task, and you want to return a response immediately and then launch the task in the background.
Spring can help with this. See
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/scheduling.html
In particular see the #Async annotation.
With respect to the client getting a response back following the async processing (exception or otherwise), you can do it, but it's extra work.
Normally the immediate response would include some kind of ID that the client could come back with after some period of time. (For example, when you run a search against the Splunk API, it gives you a job ID, and you come back later with that job ID to check on the result). If this works, do that. The client has to poll but the implementation is the simplest.
If not, then you have to have some way for the client to listen for the response. This could be a "reply-to" web service endpoint on the client (perhaps passed in with the original request as a custom X-Reply-To HTTP header), or it could be a message queue, etc.

Categories

Resources