Service is stuck when using #CacheResult - java

I'm trying to cache some expensive db operations in my quarkus project.
But when I'm adding a #CacheResult annotation, the program is getting stuck before the method execution.
Class is annotated as #ApplicationScoped.
There's also #Transactional annotation.
Method looks like:
#Override
#CacheResult(cacheName = "some-chain")
public List<UUID> getChain(#CacheKey UUID someId){
// Call to the Spring Data repository and some additional logic
}
Thread dump shows that everything is in Waiting or Runnable state.
It looks like a deadlock. Dear community, please help me to solve it )
PS. When I remove request to DB from this method, everything works as expected.

Related

Quarkus: Blocking grpc service method running on event loop

I am implementing a gprc server in quarkus (1.8.3.Final).
My service is written in reactive style (smallrye mutiny)
This is my service class
#Singleton
#Blocking
#Slf4j
public class GrpcService extends MutinyGrpcServicesGrpc.GrpcServicesImplBase{
#Blocking
public Uni<MyResponse> executeMyLogic(MyRequest request) {
System.out.println("grpc thread name "+Thread.currentThread().getName());
...
}
}
Now the actual logic written inside executeMyLogic is a bit blocking and was resulting in blocked event loop warnings(and some other errors) by vertx.
So as mentioned in the quarkus grpc server guide(https://quarkus.io/guides/grpc-getting-started)
I annotated the method with #Blocking (io.smallrye.common.annotation.Blocking).
Before I added this annotation I get this log on sys.out
grpc thread name vert.x-eventloop-thread-0
which indicates that this logic is being run on a vertx event loop which seems to be causing the issue.
Now according to my understanding after adding this #Blocking annotation on executeMyLogic this should be running on some worker thread.
But its still running on vertx event loop.
It seems like this this annotation is not being honored by the framework.
Correct me if my understanding is wrong or else please help me get this working.
So as it turns out this was a bug in quarkus framework.
Earlier it didn't honor the #Blocking annotation.
It worked after upgrading to 1.10.2.Final
Here's a link to the PR that fixed it

JPA Repositories and blocking I/O

I'm having a problem where I need to perform several slow HTTP requests on a separate thread after having written to the database using a JpaRepository. The problem is that doActualJob() blocks while waiting for a series of futures to resolve. This seems to prevent the underlying Hibernate session from closing, causing the application to run out of connections shortly after.
How do I write this function so the database connection isn't kept open while doing the blocking I/O? Is it even possible using JpaRepositories, or do I need to use a lower level API like EntityManager/SessionFactory?
#Service
class SomeJobRunner {
private final SomeJobRepository mSomeJobRepository; //extends JpaRepository
#AutoWired
public SomeJobRunner(final SomeJobRepository someJobRepository) {
mSomeJobRepository = someJobRepository;
}
#Async
public void doSlowJob(final long someJobId) {
SomeJob someJob = mSomeJobRepository.findOne(someJobId);
someJob.setJobStarted(Instant.now());
mSomeJobRepository.saveAndFlush(someJob);
doActualjob(); // Synchronous job doing several requests using Unirest in series
someJob = mSomeJobRepository.findOne(someJobId);
someJob.setJobEnded(Instant.now());
mSomeJobRepository.saveAndFlush(someJob);
}
Well - non-blocking database IO is not possible in Java/JDBC world in a standard way .To put it simply - your Spring data repository would be eventually using JPA ORM Implementation ( likes of Hibernate) which in turn will use JDBC to interact with the database which is essentially blocking in nature. There is work being done on this currently by Oracle (Asynchronous Database Access API ) to provide a similar API as JDBC but non-blocking. They intend to propose this as a standard. Also there is an exciting and parallel effort by Spring guys on this namely R2DBC – Reactive Relational Database Connectivity. They have actually integrated this with Spring data as well (link) so that may help you integrate in your solution. A good tutorial by Spring on this can be found here.
EDIT: As of 2022 Hibernate has reactive option as well
I would suggest to write in the database using a separate JTA transaction. Do do so, define a methode like
#Transactional(Transactional.TxType.REQUIRES_NEW)
public void saveJobStart(final long someJobId) {
SomeJob someJob = mSomeJobRepository.findOne(someJobId);
someJob.setJobStarted(Instant.now());
mSomeJobRepository.saveAndFlush(someJob);
}
Of course it is not quite the same. If doActualjob() fails, in your case, the database won't persist the start date. In my proposal, it will persist it. To compensate, you need to remove the start date in a catch bloc in doSlowJob, within a new transaction, and then rethrow the exception.

Need a way to annotate service methods following repository pattern

I'm trying to refactor the existing code base of one of my project following Repository pattern, so that i can make the project more re-usable and testable.
I've written services, repositories, when I try to set Authentication, Authorization and Transactional annotation on service layer, I am facing issues.
These annotations works only on controller level, but not on service layer, so I want a way for annotate service methods.
Is it possible to do so?
It would be helpful, if someone points me samples using repository pattern on Play framework or better way to proceed further.
Authentication and authorization only make sense on a request, so sticking them on anything but a controller method is not going to work either way.
Transactional is just a helper annotation to wrap the entire request in a JPA transaction. It is usually advisable to do the wrapping yourself anyway, so you don't really need that. Example taken from the documentation:
#Inject
private JPAApi jpaApi;
public void updateSomething() {
// do something with the entity manager, per instance
// save, update or query model objects.
jpaApi.withTransaction(() -> {
EntityManager em = jpaApi.em();
Query query = em.createNativeQuery("update people set active = 1 where age > 18");
query.executeUpdate();
});
}

Spring boot response caching

I was trying to understand the caching that happens at the client side.
Unfortunately I am unable to find any resources that can help me out.
I have employee model objects which are fairly small in size.
Once a use a GET request to obtain an employee object, I want it to be cached at the client side
Now when the request comes again to obtain the same employee, I want to see if the actual object has been modified, if not, then serve from the client cache else return the modified object also adding it to the cache.
I am using Spring boot to create a REST endpoint.
What I have been able to figure out is that cache-control would be used some how, but I am not sure how the objects would be added here in spring.
Any help here is much appreciated!!!!
Thanks,
Amar
HTTP caching is not an easy topic. There are different ways to do it, and you should probably start by familiarizing yourself with the mechanisms, this seems to be a good starting resource: HTTP caching
Then, you will probably identify some common usage patterns you will want to reuse. One way to do that is to create custom annotations and write an interceptor that reacts on them.
For example, you could write such an annotation:
#Inherited
#Retention(RUNTIME)
#Target({METHOD, TYPE})
public #interface CacheFor {
long amount();
TimeUnit unit() default TimeUnit.SECONDS;
}
and use it on controller methods like this:
#CacheFor(amount=10, unit = MINUTES)
#RequestMapping(bla bla)
public FooBar serveMyData(){
// code here
}
and in your interceptor, you will need to look at the handler method, check whether it has this annotation, and if it does, set the appropriate headers.

Using findBy in transactional context

Given:
controller PersonController with a #Transactional action save
service PersonService with a method populateProperties(PersonInstance) being called from the controller action
I'd like to populate personInstance properties based on some data already persisted in the database, like this:
def personLookupData = PersonLookupData.findByUsername(personInstance.username)
personInstance.firstName = personLookupData.firstName
The findByUsername method flushes the hibernate session and in order to avoid it (because it has been giving me problems described here), I do this:
def personLookupData = PersonLookupData.withNewSession { PersonLookupData.findByUsername(personInstance.username) }
personInstance.firstName = personLookupData.firstName
This does what I want (lets me use findBy without flushing the session), and this is fine when there is only a couple of findBys to use, but given a deeper call stack (in terms of services) and more database lookups in different places, using withNewSession everywhere becomes a bit ugly.
Apart from making a PersonLookupService which will collect all the required data in one withNewTransaction block and return it, is there any other nice (groovy) way of doing this?
I think you should move #Transactional from PersonControlller to PersonService.
If you have more service calls to include in the same transaction, you need to use a Transaction boundary gateway, that's marked as #Transactional and calls all services you need for the current business case.
It's not the responsibility of the MVC components to control transactions. The transactions boundary are handled by the service layer.

Categories

Resources