Using Spring #Transactional processiong only 8 threads parallelly - spring

We are using Jetty+Spring. My WebService HostService receives N requests in parallel (Logged the time as soon as request arrived to my webservice) but when tried calling Transactional add method, something similar to below snippet
#Component
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ClassA {
#Transactional
public Host add(Host host) {
//logging time
Thread.sleep(100);
}
}
Now From code service I made the call to ClassA's add method, and logged the time, only 8 out of 100 request are reaching here at a time, and then when one finishes other starts.
I have already tries removing Thread.sleep with actual webservice call and a local process call, that doesn't help. But when I remove #Transactional, all requests comes at the same time to the add method, so problem is with #Transactional.
I want to understand
how #Transactional actually works, and why it limits to 8 calls in a batch, can I change this batch to some higher number.
All my classes are of scope prototype, so on what its trying to grab the lock on?
What should I do, to process all the requests in parallel, as my app in not db dependent it just calling other webservices(3), I don't need any lock, I just need the thread level lock, so that I can rollback if one of the webservice fails.

Related

How to run blocking codes on another thread and make http request return immediately

We started a new project with Quarkus and Mutiny, and created a bunch of endpoints with Quarkus #Funq, everything has been working fine so far. Now we want to process something very time-consuming in one of the endpoints, and what we are expecting is, once user clicks a button to send the http request from frontend and hits this specific endpoint, we are going to return 202 Accepted immediately, leaving the time-consuming operation processing in another thread from backend, then send notification email accordingly to user once it completes.
I understand this can be done with #Async or CompletableFuture, but now we want to do this with Mutiny. Based on how I read Mutiny documentation here https://smallrye.io/smallrye-mutiny/guides/imperative-to-reactive, runSubscriptionOn will avoid blocking the caller thread by running the time-consuming method on another thread, and my testing showed the time-consuming codes did get executed on a different thread. However, the http request does not return immediately, it is still pending until the time-consuming method finishes executing (as I observe in the browser's developer tool). Did I misunderstand how runSubscriptionOn works? How do I implement this feature with Mutiny?
My #Funq endpoint looks like this
#Inject
MyService myService;
#Funq("api/report")
public Uni<String> sendReport(MyRequest request) {
ExecutorService executor = Executors.newFixedThreadPool(10, r -> new Thread(r, "CUSTOM_THREAD"));
return Uni.createFrom()
.item(() -> myService.timeConsumingMethod(request))
.runSubscriptionOn(executor);
}
Edit: I found the solution using Uni based on #Ladicek's answer. After digging deeper into Quarkus and Uni I have a follow-up question:
Currently most of our blocking methods are not returning Uni on Service level, instead we create Uni object from what they return (i.e. object or list), and return the Uni on Controller level in their endpoints like this
return Uni.createFrom().item(() -> myService.myIOBlockingMethod(request)).
As #Ladicek explained, I do not have to use .runSubscriptionOn explicitly as the IO blocking method will automatically run on a worker thread (as my method on Service level does not return Uni). Is there any downside for this? My understanding is, this will lead to longer response time because it has to jump between the I/O thread and worker thread, am I correct?
What is the best practice for this? Should I always return Uni for those blocking methods on Service level so that they can run on the I/O threads as well? If so I guess I will always need to call .runSubscriptionOn to run it on a different worker thread so that the I/O thread is not blocked, correct?
By returning a Uni, you're basically saying that the response is complete when the Uni completes. What you want is to run the action on a thread pool and return a complete response (Uni or not, that doesn't matter).
By the way, you're creating an extra thread pool in the method, for each request, and don't shut it down. That's wrong. You want to create one thread pool for all requests (e.g. in a #PostConstruct method) and ideally also shut it down when the application ends (in a #PreDestroy method).

Make Asynchronous RepositoryRestResource

With springboot is there a way to make the default crud methods provided by the #RepositoryRestResource annotation asynchronous(with mongodb)? Meaning for example when i make 1000 save or find method(database) request, the thread doesnt wait for every single request to complete, it makes a new thread for each save() request, instead of executing each database request sequentially on one thread.

Implementing a background service that sends out reminders based on the reminder time and user authentication using a token-based mechanism.

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.

Why does Hibernate not support nested transactions outside of Spring?

I am using Hibernate4 but not Spring. In the application I am developing I want to log a record of every Add, Update, Delete to a separate log table. As it stands at the moment my code does two transactions in sequence, and it works, but I really want to wrap them up into one transaction.
I know Hibernate does not support nested transactions, only in conjunction with Spring framework. I´ve read about savepoints, but they´re not quite the same thing.
Nothing in the standards regarding JPA and JTA specification has support for nested transactions.
What you most likely mean with support by spring is #Transactional annotations on multiple methods in a call hierarchie. What spring does in that situation is to check is there an ongoing transaction if not start a new one.
You might think that the following situation is a nested transaction.
#Transactional
public void method1(){
method2(); // method in another class
}
#Transactional(propagation=REQUIRES_NEW)
public void method2(){
// do something
}
What happens in realitiy is simplified the following. The type of transactionManager1 and transactionManager2 is javax.transaction.TransactionManager
// call of method1 intercepted by spring
transactionManager1.begin();
// invocation of method1
// call of method 2 intercepted by spring (requires new detected)
transactionManager1.suspend();
transactionManager2.begin();
// invocation of method2
// method2 finished
transactionManager2.commit();
transactionManager1.resume();
// method1 finished
transactionManager1.commit();
In words the one transaction is basically on pause. It is important to understand this. Since the transaction of transactionManager2 might not see changes of transactionManager1 depending on the transaction isolation level.
Maybe a little background why I know this. I've written a prototype of distributed transaction management system, allowing to transparently executed methods in a cloud environment (one method gets executed on instance, the next method might be executed somewhere else).

Spring Declarative transaction management with hibernate using #Transactional

My requirement is to save data in 5 tables through 5 methods .
These 5 methods are wrapped under single parent method which is annotated with #Transactional.
Am calling this parent method 100 times in a loop.
Constraints are
Transaction has to be rolled back even if one method fails in one iteration.(i.e 5 methods has to be saved without exception) and the flow should continue for next iteration.
One iteration fail should not rollback all the other iterations. I.,e In 100 iterations if 5th iteration fails and all the other iterations are succeeded, then all the 99 iteration's operations should get committed.
It is OK if transaction is committed after successfully executing all the 5 methods in one iteration.
Issue is
If, 5th iteration is failed, then in next iteration, old values are showing in the entity.
I have used session.clear() method in catch block to avoid that. is that correct? But the issue is,
even after successful insertion of five methods in next iteration, the transaction is getting rolled-back. And all the previous 4 iteration's data state in session is getting cleared.
am using Spring 3.2, Hibernate3, HibernateTransactionManager
I forgot to write the caller method and calling method in different beans. Hence it is getting rolled back. Spring Transaction uses AOP. A proxy is created for the methods which are annotated with #Transactional. This bean method should be called from another bean, which I got form the Spring documentation
You want your iterations succeed or fail independently one from another. You want a failure in any of the 5 steps of the individual iteration to fail entire iteration and to roll back the corresponding transaction.
It is clear that you want to have transaction boundary at the level of the service call that corresponds to a single iteration. Now, the rule of the thumb is to allocate a Hibernate session per transaction. So, a Hibernate session should be created at the beginning of each iteration and be disposed of at the end. That would prevent random junk, like entites that failed to be persisted to the database in the previous trnsactions, from showing up in the Hibernate session.
Hope this helps.
Have a look into propagation levels of spring transactions here and choose whatever best suits your requirements. An example which does what you need is as follow (you may mark myService as #Transactional as well) but you might like to have a look at other levels.
public void myService() {
// call myTaskCaller as many times as you like
}
#Transactional(propagation=Propagation.REQUIRES_NEW)
public void myTaskCaller() {
task1();
task2();
task3();
task4();
task5();
}
private void task1(){}
private void task2(){}
private void task3(){}
private void task4(){}
private void task5(){}

Resources