Is there any way in spring that we can send response immediately.
I want to create a thread which will do a job. But I don't want to make the user to wait till that job completed.
There is multiple way of doing so in Spring.
Here is their article.
If you want to make the operations asynchronously, the easiest way is to use the #Asyn annotation from Spring.
Here is a simple example :
// Interface definition for your async operation here
public interface AsyncOperator {
#Async
void launchAsync(String aBody);
}
And a simple implementation that uses the interface
// Need to be a bean managed by Spring to be async
#Component
class SimpleAsync implements AsyncOperator {
#Override
public void launchAsync(String aBody){
// Your async operations here
}
}
Then you need for Spring to configure how the async works. Using Spring boot a simple configuration class like this works:
#Configuration
#EnableAsync
public class AsyncConfiguration {
}
Then you can call your method and it will return right away and do the treatments asynchronously :
#Component
public class AController {
private final AsyncOperator async;
public AController(AsyncOperator async){
this.async = async;
}
public String aMethod(String body){
// here it will return right after call
this.async.launchAsync(body);
return "Returned right away !!";
}
}
The only downsides of this method is that all your classes for async operations must be managed by Spring.
Related
I am having troubles invoking a method asynchronously in Spring, when the invoker is an embedded library receiving notifications from an external system. The code looks as below:
#Service
public class DefaultNotificationProcessor implements NotificationProcessor {
private NotificationClient client;
#Override
public void process(Notification notification) {
processAsync(notification);
}
#PostConstruct
public void startClient() {
client = new NotificationClient(this, clientPort);
client.start();
}
#PreDestroy
public void stopClient() {
client.stop();
}
#Async
private void processAsync(Notification notification) {
// Heavy processing
}
}
The NotificationClient internally has a thread in which it receives notifications from another system. It accepts a NotificationProcessor in its constructor which is basically the object that will do the actual processing of notifications.
In the above code, I have given the Spring bean as the processor and attempted to process the notification asynchronously by using #Async annotation. However, it appears the notification is processed in the same thread as the one used by NotificationClient. Effectively, #Async is ignored.
What am I missing here?
#Async (as well as #Transactional and other similar annotations) will not work when the method is invoked via this (on when #Async is used for private methods*), as long as you do not use real AspectJ compiletime or runtime weaving.
*the private method thing is: when the method is private, then it must been invoked via this - so this is more the consequence then the cause
So change your code:
#Service
public class DefaultNotificationProcessor implements NotificationProcessor {
#Resource
private DefaultNotificationProcessor selfReference;
#Override
public void process(Notification notification) {
selfReference.processAsync(notification);
}
//the method must not been private
//the method must been invoked via a bean reference
#Async
void processAsync(Notification notification) {
// Heavy processing
}
}
See also the answers for: Does Spring #Transactional attribute work on a private method? -- this is the same problem
I use Camunda as bpmn engine in my spring boot application
Main idea:
The first process is started in the controller, and after the response is returned to the client, the Second process should start.
I do this using #Async(spring framework) to start the second process and I have two bpmn diagrams:
firstProcess
secondProcess
Simple implementation of the idea:
#RestController
public class SimpleController {
#Autowired
private CustomService asyncService;
#Autowired
private CustomService syncService;
#GetMapping(value = "/request")
public ResponseEntity<String> sendQuestion() {
//start process described in first.bpmn
syncService.startProcess("firstProcess");
//start process described in second.bpmn asynchronously
//controller responses to client without waiting for ending secondProcess
asyncService.startProcess("secondProcess");
return new ResponseEntity<>("OK", HttpStatus.OK);
}
}
#Service
public class AsyncService implements CustomService {
#Autowired
private RuntimeService runtimeService;
#Async
public void startProcess(String key) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
//
}
runtimeService.startProcessInstanceByKey(key);
}
}
Questions:
Is there a way to do these two processes in one process (as shown at both processes)?
How should I implement this in the spring boot app?
bothProcess
You need use Call Activity Task specifying BPMN as CallActivity Type and corresponding process ids in Called Element field on the properties panel.
Also don't forget uncheck Startable checkbox for your subprocesses.
I have a Spring boot Application connecting to SQL Server Database. I need some help in using caching in my application. I have a table for CodeCategory which has a list of codes for Many codes. This table will be loaded every month and data changes only once in a month.
I want to cache this entire table when the Application starts. In any subsequent calls to the table should get value from this cache instead of calling the Database.
For Example,
List<CodeCategory> findAll();
I want to cache the above DB query value during application startup. If there is a DB call like List<CodeCategory> findByCodeValue(String code) should fetch the code result from the already Cached data instead of calling the Database.
Please let me know how this can be achieved using spring boot and ehcache.
As pointed out, It takes some time for ehcache to setup and it is not working completely with #PostConstruct. In that case make use of ApplicationStartedEvent to load the cache.
GitHub Repo: spring-ehcache-demo
#Service
class CodeCategoryService{
#EventListener(classes = ApplicationStartedEvent.class )
public void listenToStart(ApplicationStartedEvent event) {
this.repo.findByCodeValue("100");
}
}
interface CodeCategoryRepository extends JpaRepository<CodeCategory, Long>{
#Cacheable(value = "codeValues")
List<CodeCategory> findByCodeValue(String code);
}
Note: There are multiple ways as pointed by others. You can choose as per your needs.
My way is to define a generic cache handler
#FunctionalInterface
public interface GenericCacheHandler {
List<CodeCategory> findAll();
}
And its implementation as below
#Component
#EnableScheduling // Important
public class GenericCacheHandlerImpl implements GenericCacheHandler {
#Autowired
private CodeRepository codeRepo;
private List<CodeCategory> codes = new ArrayList<>();
#PostConstruct
private void intializeBudgetState() {
List<CodeCategory> codeList = codeRepo.findAll();
// Any customization goes here
codes = codeList;
}
#Override
public List<CodeCategory> getCodes() {
return codes;
}
}
Call it in Service layer as below
#Service
public class CodeServiceImpl implements CodeService {
#Autowired
private GenericCacheHandler genericCacheHandler;
#Override
public CodeDTO anyMethod() {
return genericCacheHandler.getCodes();
}
}
Use the second level hibernate caching to cache all the required db queries.
For caching at the application start-up, we can use #PostContruct in any of the Service class.
Syntax will be :-
#Service
public class anyService{
#PostConstruct
public void init(){
//call any method
}
}
Use CommandLineRunner interface.
Basically , you can create a Spring #Component and implement CommandLineRunner interface. You will have to override it's run method. The run method will be called at the start of the app.
#Component
public class DatabaseLoader implements
CommandLineRunner {
#override
Public void run(.... string){
// Any code here gets called at the start of the app.
}}
This approach is mostly used to bootstrap the application with some initial data.
Let's imagine a scenario where I have a Spring Boot app (in a controller/service/repository pattern) which contains controller for cars. Now I would like to create paths that look for example like this:
"/api/cars/bmw"
"/api/cars/mercedes"
"/api/cars/audi"
And so on. And for each of these car producers I would like to have multiple endpoints, some of them common for all car producers (not sure if it really matters but just for the sake of it lets say for example "/order" and "/cancelOrder"), but some of them different.
Now what would be the proper way to implement this scenario? Is there a way to make a CarController for the /car/{producer} path which would be a proxy for other controllers like AudiController handling /car/audi requests? Having 3 car producers in one controller and a service for each car producer is ok, but having 30 would make a lot of injected dependencies (30 services injected into the controller) if I would have only one CarController.
I believe node.js Express framework would allow us to do this in the car "controller" script (not sure if they are called controllers in express or what):
var app = express();
app.use('/audi', '{path to audi controller script}');
Is there a similar possibility in Spring? Or is this maybe a bad idea, an antypattern?
Another idea that is quite simple but seems not that elegant is to skip the CarController and implement a:
AudiController with the #RequestMapping("/api/cars/audi")
BmwController with the #RequestMapping("/api/cars/bmw")
MercedesController with the #RequestMapping("/api/cars/mercedes")
etc.
So, what would be the best idea here?
Spring has #PathVariable for this, which can be used in the following way:
#RestController
#RequestMapping("/api/cars/")
public class MyController {
#GetMapping
#RequestMapping("{producer}/cancelOrder")
public String cancelOrder(#PathVariable String producer) {
return "Cancel order for " + producer;
}
}
We can call this endpoint like this: http://localhost:8080/api/cars/Mercedes/cancelOrder
There is no such thing as child controller in Spring. If you want to create a separate controller for every producer having some common functionality, you can use inheritance:
Parent controller class (please note that this does not have any Controller annotation):
#RequestMapping("/api/cars/")
public class BaseCarController {
#GetMapping("/common")
public String common() {
return "Common stuff";
}
}
Child controller classes:
#RestController
public class MercedesController extends BaseCarController{
private MercedesService mercedesService;
// Spring will autowire this by default, no need to add #Autowired
public MercedesController(MercedesService mercedesService) {
this.mercedesService = mercedesService;
}
#GetMapping
#RequestMapping("Mercedes/cancelOrder")
public String cancelOrder() {
return "Cancel order for Mercedes.";
}
}
#RestController
public class AudiController extends BaseCarController{
private AudiService audiService;
// Spring will autowire this by default, no need to add #Autowired
public AudiController(AudiService audiService) {
this.audiService = audiService;
}
#GetMapping
#RequestMapping("Audi/cancelOrder")
public String cancelOrder() {
return "Cancel order for Audi.";
}
}
We can call the produces specific endpoints like this:
http://localhost:8080/api/cars/Mercedes/cancelOrder or http://localhost:8080/api/cars/Audi/cancelOrder. Moreover we can call the common endpoint in the following way: http://localhost:8080/api/cars/common
I'm not sure where to open my Transaction object. Inside the service layer? Or the controller layer?
My Controller basically has two services, let's call them AService and BService. Then my code goes something like:
public class Controller {
public AService aService = new AService();
public BService bService = new BService();
public void doSomething(SomeData data) {
//Transaction transaction = HibernateUtil.getSession().openTransaction();
if (data.getSomeCondition()) {
aService.save(data.getSomeVar1());
bService.save(data.getSomeVar2());
}
else {
bService.save(data.getSomeVar2());
}
//transaction.commit(); or optional try-catch with rollback
}
}
The behavior I want is that if bService#save fails, then I could invoke a transaction#rollback so that whatever was saved in aService would be rolled back as well. This only seems possible if I create one single transaction for both saves.
But looking at it in a different perspective, it looks really ugly that my Controller is dependent on the Transaction. It would be better if I create the Transaction inside the respective services, (something like how Spring #Transactional works), but if I do it that way, then I don't know how to achieve what I want to happen...
EDIT: Fixed code, added another condition. I am not using any Spring dependencies so the usage of #Transactional is out of the question.
You can accomplish what you're asking with another layer of abstraction and using composition.
public class CompositeABService {
#Autowired
private AService aservice;
#Autowired
private BService bservice;
#Transactional
public void save(Object value1, Object value2) {
aservice.save( value1 );
bservice.save( value2 );
}
}
public class AService {
#Transactional
public void save(Object value) {
// joins an existing transaction if one exists, creates a new one otherwise.
}
}
public class BService {
#Transactional
public void save(Object value) {
// joins an existing transaction if one exists, creates a new one otherwise.
}
}
This same pattern is typically used when you need to interact with multiple repositories as a part of a single unit of work (e.g. transaction).
Now all your controller needs to depend upon is CompositeABService or whatever you wish to name it.