Design: Background thread with a Spring service - spring

I have Spring service which after performing some tasks,initiates a background Async tasks. The task itself I have defined as a component.
Now, If I have to use some method belonging to my the service which initiated the thread. I can Autowire the service in the thread(Component) and it will work. Problem is...The design. It brings in kind of circular dependency?
How can we tackle such issue?
ServiceA-> Starts a ThreadA component->ThreadA Needs to call a method in the ServiceA.

What about using an #Async annotated method as described here
A non tested example:
#Service
public class MyService {
private final RestTemplate restTemplate;
public String mySyncMethod(){
return "Hello World";
}
#Async
public Future<String> myAsyncMethod() throws InterruptedException {
return new AsyncResult<>(mySyncMethod());
}
}

Related

How to call #Scheduled method in only one instance using #PostConstruct

There is job that needs to be done on cron schedule
The same logic as in the job must be performed at the start of the spring boot application, therefore #PostConstruct method is used
Shedlock is used, since it is planned to run the application in multiple instances
The question is: how to make the logic from the #PostConstruct method be called in only one instance and not called in others?
An example of my code:
#Component
#AllArgsConstructor
public class TestJob {
private TestService testService;
#PostConstruct
public void init() {
testService.upload();
}
#Scheduled(cron = "${cron}")
#SchedulerLock(name = "uploadJob", lockAtMostFor = "${lockAtMostFor}")
public void execute() {
testService.upload();
}
}
It should work if you put the #PostConstruct method to a different service and call the execute() method.
The reason is that ShedLock by default uses Spring AOP which wraps each method marked by #SchedulerLock in an aspect that does the locking. And Spring AOP usually does not get applied if you call another method in the same class.

Server Sent Event with SQL Database connection using Spring Boot

I want to implement Server Sent Events in Spring Boot. The data is there in SQL database, It is resulting in blocking connection. Web Flux is an option but it is supported only for some NoSQL database.
Yes, you right WebFlux framework doesn't SQL databases in the non blocking mode because reactive drivers does not exist.
But WebFlux provides some instruments to avoid blocking our main threads while we are making blocking long queries to a database.
1) Create configuration with Scheduler where count of threads equals to pool size:
#Configuration
public class SchedulerConfiguration {
#Value("${spring.datasource.maximum-pool-size}
private final Integer connectionPoolSize;
#Bean
#Qualifier("jdbcScheduler")
public Scheduler jdbcScheduler() {
return Schedulers.fromExecutor(Executors.newFixedThreadPool(connectionPoolSize));
}
}
2) Inject your "jdbcScheduler" to the service class:
#Service
public class DataService {
#Autowired
private final DataRepository jdbcRepository;
#Autowired #Qualifier("jdbcScheduler")
private final Scheduler scheduler;
public Mono<String> findById(long id) {
return async(() -> repository.findById(id));
}
private <T> Mono<T> async(Callable<T> callable) {
return Mono.fromCallable(callable).publishOn(scheduler);
}
}
Wrap your blocking method by Mono.fromCallable and delegate from main thread to your "scheduler" via Mono.publishOn
More about schedulers you can read here: Threading and Schedulers
Yes you can achieve asynchronous processing in spring without flux by using their inbuilt #Async processing, here how you can achieve it.
Step1: Enable Aysnc and define a bean for Executor. You can define separate configuration or directly under Main application class.
#SpringBootApplication
#EnableAsync
public class Application {
public static void main(String[] args) {
// close the application context to shut down the custom ExecutorService
SpringApplication.run(Application.class, args).close();
}
#Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("GithubLookup-");
executor.initialize();
return executor;
}
STEP2:
Following is the simple way to configure a method with void return type to run asynchronously, You can also invoke method by retrieve the result of the asynchronous process using the Future object.
#Async
public void asyncMethodWithVoidReturnType() {
System.out.println("Execute method asynchronously. "
+ Thread.currentThread().getName());
}
For more information, You can visit Spring official guide Spring Async

Stateless Service Layer in Spring

These days im working on a Web project and i just want to clarify couple of things regarding Spring bean scopes and best practices for Spring based developments. Here i am using a scenario using a sample code
I have a Web Controller as below
#Controller
Public class JobController{
private JobService jobService;
#Autowired
public void setJobService(JobService jobService ) {
this.jobService = jobService ;
}
public void run(){
Job job = new Job();
-- Setting the properties for the Object
jobService.run(job);
}
}
Then I have the Service as below
#Service
Public class JobService {
public void run(Job job){
-- perform the business logic
}
}
In Here i want to make the JobService class stateless so i can define JobService as singleton hence reduce the unnecessary object creation. As per my understanding in-order make a class stateless we do not want to keep instance properties.In This scenario i pass different Job objects to the service. Does this make this JobService statefull because JObservice process different different job objects? Can you please help me to understand
Thanks,
Keth
Passing different objects does not make your service stateful.
Consider this for example.
#Service
Public class JobService {
private Job currentJob;
public void setJob(Job job) {
currentJob = job;
}
public void run(){
-- perform the business logic on currentJob
}
}
This would make the bean 'stateful' and cause unexplained behavior.
The execution of the method in your singleton by multiple controller/threads will not collide and can be assumed to be safe.

Spring Microservices issue with #HystrixCommand

We are facing a problem with Hystrix Command in a Spring Boot / Cloud microservice. We have a Spring Component containing a method annotated with #RabbitListener. When a new message arrives, the method delegates the invocation to NotificationService::processNotification().
The NotificationService is a bean annotated with #Service. The method processNotification() can request third party applications. We want to wrap the invocation of third party applications using #HystrixCommand to provide fault tolerance, but due to some reasons the Hystrix Command annotated method is not working.
If we invoke a Controller and the Controller delegates the invocation to a Service method, which in turns have a Hystrix Command , everything works perfectly. The only problem with Hystrix Command arises when the microservices consume a messages and it seems to be Hystrix Command doesn’t trigger the fallback method.
Here is the non-working code:
#Component
public class MessageProcessor {
#Autowired
private NotificationService notificationService;
#RabbitListener(queues = "abc.xyz-queue")
public void onNewNotification(String payload) {
this.notificationService.processNotification(payload);
}
}
#Service
public class NotificationService {
public void processNotification(String payload) {
...
this.notifyThirdPartyApp(notificationDTO);
...
}
#HystrixCommand(fallbackMethod = "notifyThirdPartyAppFallback")
public void notifyThirdPartyApp(NotificationDTO notificationDTO) {
//Do stuff here that could fail
}
public void notifyThirdPartyAppFallback(NotificationDTO notificationDTO) {
// Fallbacl impl goes here
}
}
#SpringBootApplication
#EnableCaching
#EnableCircuitBreaker
#EnableDiscoveryClient
#EnableRabbit
public class NotificationApplication {
public static void main(String[] args) {
SpringApplication.run(NotificationApplication.class, args);
}
}
I'm not sure about your problem without looking at the code.
As another approach you can take: instead of describing this calls with annotations in your service, just extend HystrixCommand and implement api calling logic in it (read more):
public class CommandHelloWorld extends HystrixCommand<String> {
private final String name;
public CommandHelloWorld(String name) {
super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
this.name = name;
}
#Override
protected String run() {
// a real example would do work like a network call here
return "Hello " + name + "!";
}
}

Spring #Async #Autowired null in only one method

I am encountering a NullPointerException in my Spring application when calling a method on an autowired object. The class in question looks like the following:
#Component
public class Listener {
#Autowired
TemplateService templateService;
#Async
#EventListener
private Future<String> listener1(Event1 event) {
System.out.println(templateService);
return new AsyncResult<>(null);
}
#Async
#EventListener
public Future<String> listener2(Event2 event) {
System.out.println(templateService);
return new AsyncResult<>(null);
}
}
When I publish an event that triggers listener1, a null value is printed, but when I publish an event that triggers listener2, the toString() method of TemplateService is called (as I would expect). I'm probably misunderstanding some aspect of how #Async affects #Autowired objects, but I haven't been able to determine what that would be. Am I misusing #Async? Am I misunderstanding how to use #Autowired objects in a multithreaded environment?
Change the visibility of your listener1 method to be at least protected (package visibility , protected or public). This is because Spring creates a proxy which is a subclass of your component. It overrides your #Async annotated methods in order to add new logic to execute your code in a separate thread. However because it uses inheritance it can only override methods which are visible to the subclass.
This explains why listener2 method which is public works.
Change your method to
#Async
#EventListener
public Future<String> listener1(Event1 event) {
System.out.println(templateService);
return new AsyncResult<>(null);
}
Spring needs an interface to create a proxy class. It's this proxy class that gets called every time you call the method, and it's through this method that the whole asynchronous execution happens. Without an interface Spring can't autowire, scan or make methods execute asynchronously.
public interface Listener {
public Future<String> listener1(Event1 event);
public Future<String> listener2(Event2 event);
}
#Component
public class ListenerImpl {
#Autowired
private TemplateService templateService;
#Async
#Override
public Future<String> listener1(Event1 event) {
System.out.println(templateService);
return new AsyncResult<>(null);
}
#Async
#Override
public Future<String> listener2(Event2 event) {
System.out.println(templateService);
return new AsyncResult<>(null);
}
}
It's also worth noting that Spring can't run private methods asynchronously.

Resources