handling http calls from within an EJB transaction - ejb-3.0

This is the code I have:
//EJB
beanclass 1{
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public String method1(){
method2();
DBupdates();
return "";
}
}
//plain java class
class 2{
method 2(){
//call which may take a long time (but dont want to wait for it to complete)
makes http calls to an external URL method();
}}
The issue is: the Http call may take a long time. However the response of the call decides the next steps in method1 -> db updates and response.the response needs to go back to the end-user, and i cannot make the end-user wait for ever.
i can handle this situation in two ways:
move method2 into the EJB and put TransactionAttributeType.NEVER, so that the http call is not in the transaction, and the transaction of method1 is not waiting on it. In this case, the container manages the transaction of method1 and does no db updates and returns null if it didnt hear back from method2. How long does the method1's transaction wait before "returning"?
i can use JBoss annotation and put a TransactionTimeout of 2 minutes on method1(): in this case, if http call does not complete within 2 minutes, method1 can return null and do no DB updates.
Which of these two methods is advisable and fault-proof?
Thanks for your insights.

When you use TransactionAttributeType.NEVER, the transaction isn't propagated further.
You can use #Asynchronous annotation for a method which returns Future<V> object. Then you can invoke get(timeout, unit) on the object to get the result type V which waits for the given time for manipulation, but it's EJB-3.1 specific.
Can try JBoss specific annotation #TransactionTimeout at method or class level. Also can configure it in jboss.xml or jboss-service.xml depending on your server version. This will be fine with EJB-3.0, but will loose portability of application.

Related

How to use Spring WebClient to make multiple calls sequentionaly?

I read the topic
How to use Spring WebClient to make multiple calls simultaneously? , but my case is a bit different. I'm calling 2 different external services using webclient, let's say from method Mono < Void > A() , followed by Mono < Void > B (). My goal is to extract data from A(), then pass it to B(). Is there correct way to avoid:
asynchronous call (which leads to Illegal arg exception, since B requesting args BEFORE A() complete);
blocking call, cause the system is reactive.
Is there are a standart way to achieve it?
First scenario:
Mono<> a = getFromAByWebClient();
and you want to send this data to call service B via a post or put request,
here, since mono is one object and you want to send it through api in a post or method, so must have that data with you, here you should wait until data is not come from first service, else it will hit the api with blank data or will result an exception.
Second scenario:
Since B is dependent on A, why not to call A service inside B service and get data.
Since in Spring reactive everything is stream, so can do operation with one data until others are on their way, but that operations which will be performed should have data.
Well, I was told how to refactor the code. The problem was fixed and for memorizing, here is the solution:
the original code returns
Mono.fromRunnable(()->apply(param param));
method 'apply' subscribes on call of external resource:
apply(param param) {
service.callRemote(val x).subscribe();
<---some bl --->
};
So,it seems Like when first beanA.process() followed beanB.process(), reactive pipeline falls apart, and lambda from runnable() branches into separate thread.
What was changed:
beanA and beanB methods apply return logic -
Mono.just.flatMap(service.callRemote(val x)).then();
apply() has been removed, remote call wrapped into flatMap() and integrated into pipeline. Now it works as expected, sequentionally calling remote resource.

use spring jpaRepository in scheduled task without wrapping in transaction

Is it possible to use a jpaRepository to perform CRUD operations within a scheduled Task (annotated with #Scheduled) without wrapping the scheduled method with #Transactional?
Use Case:
We have a scheduler to pop jobs and each job has certain operations to perform and fetches + saves data accordingly.
private void processJob(T job) throws Exception {
updateJobToTaken(job);
internalProcess(job); //calls a service to run the job operations
updateJobToDone(job);
}
1- If we don't wrap the method with #Transactional, all operations done within the internalProcess() are not saved to the DB. So we added #Transactional(propagation.REQUIRES_NEW)
2- This caused a regressions on our dryRun flag: We added a dryRun flag that is passed to the internalProcess method. If the flag is true, we skip calling repository.save(entities) and expected that none of the work was saved. So we simply logged the changes to the console.
if (!dryRun) {
setupsGroupRepository.save(setupsGroup);
}
But since the method is transactional, Spring committed the changes and everything was committed.
What we would like?
Controlling DB access explicitly. Meaning if I don't call repository.save(), i'm not expecting anything to be committed. And vice versa, when i call repository.save(), i'm expecting my updates to be committed fully to the DB.
When we call the internalProcess method directly without having a scheduledTask, everything runs perfectly. but now, it feels that spring transaction management gets in the way at every turn.

Write call/transaction is dropped in TransactionalEventListener

I am using spring-boot(1.4.1) with hibernate(5.0.1.Final). I noticed that when I try to write to the db from within #TransactionalEventListener handler the call is simply ignored. A read call works just fine.
When I say ignore, I mean there is no write in the db and there are no logs. I even enabled log4jdbc and still no logs which mean no hibernate session was created. From this, I reckon, somewhere in spring-boot we identify that its a transaction event handler and ignore a write call.
Here is an example.
// This function is defined in a class marked with #Service
#TransactionalEventListener
open fun handleEnqueue(event: EnqueueEvent) {
// some code to obtain encodeJobId
this.uploadService.saveUploadEntity(uploadEntity, encodeJobId)
}
#Service
#Transactional
class UploadService {
//.....code
open fun saveUploadEntity(uploadEntity: UploadEntity, encodeJobId: String): UploadEntity {
// some code
return this.save(uploadEntity)
}
}
Now if I force a new Transaction by annotating
#Transactional(propagation = Propagation.REQUIRES_NEW)
saveUploadEntity
a new transaction with connection is made and everything works fine.
I dont like that there is complete silence in logs when this write is dropped (again reads succeed). Is there a known bug?
How to enable the handler to start a new transaction? If I do Propogation.Requires_new on my handleEnqueue event, it does not work.
Besides, enabling log4jdbc which successfully logs reads/writes I have following settings in spring.
Thanks
I ran into the same problem. This behavior is actually mentioned in the documentation of the TransactionSynchronization#afterCompletion(int) which is referred to by the TransactionPhase.AFTER_COMMIT (which is the default TransactionPhase attribute of the #TransactionalEventListener):
The transaction will have been committed or rolled back already, but the transactional resources might still be active and accessible. As a consequence, any data access code triggered at this point will still "participate" in the original transaction, allowing to perform some cleanup (with no commit following anymore!), unless it explicitly declares that it needs to run in a separate transaction. Hence: Use PROPAGATION_REQUIRES_NEW for any transactional operation that is called from here.
Unfortunately this seems to leave no other option than to enforce a new transaction via Propagation.REQUIRES_NEW. The problem is that the transactionalEventListeners are implemented as transaction synchronizations and hence bound to the transaction. When the transaction is closed and its resources cleaned up, so are the listeners. There might be a way to use a customized EntityManager which stores events and then publishes them after its close() was called.
Note that you can use TransactionPhase.BEFORE_COMMIT on your #TransactionalEventListener which will take place before the commit of the transaction. This will write your changes to the database but you won't know whether the transaction you're listening on was actually committed or is about to be rolled back.

Heavy REST Application

I have an Enterprise Service Bus (ESB) that posts Data to Microservices (MCS) via Rest. I use Spring to do this. The main Problem is that i have 6 Microservices, that run one after one. So it looks like this: MCS1 -> ESB -> MCS2 -> ESB -> ... -> MCS6
So my Problem looks like this: (ESB)
#RequestMapping(value = "/rawdataservice/container", method = RequestMethod.POST)
#Produces(MediaType.APPLICATION_JSON)
public void rawContainer(#RequestBody Container c)
{
// Here i want to do something to directly send a response and afterwards execute the
// heavy code
// In the heavy code is a postForObject to the next Microservice
}
And the Service does something like this:
#RequestMapping(value = "/container", method = RequestMethod.POST)
public void addDomain(#RequestBody Container container)
{
heavyCode();
RestTemplate rt = new RestTemplate();
rt.postForObject("http://134.61.64.201:8080/rest/rawdataservice/container",container, Container.class);
}
But i dont know how to do this. I looked up the post for Location method, but i dont think it would solve the Problem.
EDIT:
I have a chain of Microservices. The first Microservice waits for a Response of the ESB. In the response the ESB posts to another Microservice and waits for a response and the next one does the same as the first one. So the Problem is that the first Microservice is blocked as long as the complete Microservice Route is completed.
ESB Route
Maybe a picture could help. 1.rawdataService 2.metadataservice 3.syntaxservice 4.semantik
// Here i want to do something to directly send a response and afterwards execute the
// heavy code
The usual spelling of that is to use the data from the http request to create a Runnable that knows how to do the work, and dispatch that runnable to an executor service for later processing. Much the same, you copy the data you need into a queue, which is polled by other threads ready to complete the work.
The http request handler then returns as soon as the executor service/queue has accepted the pending work. The most common implementation is to return a "202 Accepted" response, including in the Location header the url for a resource that will allow the client to monitor the work in progress, if desired.
In Spring, it might be ResponseEntity that manages the codes for you. For instance
ResponseEntity.accepted()....
See also:
How to respond with HTTP 400 error in a Spring MVC #ResponseBody method returning String?
REST - Returning Created Object with Spring MVC
From the caller's point of view, it would invoke RestTemplate.postForLocation, receive a URI, and throw away that URI because the microservice only needs to know that the work as been accepted
Side note: in the long term, you are probably going to want to be able to correlate the activities of the different micro services, especially when you are troubleshooting. So make sure you understand what Gregor Hohpe has to say about correlation identifiers.

Laravel IoC and singleton pattern

I'm trying to use Laravel IoC by creating a singleton object. I'm following the pattern from tutorial as below. I have put a Log message into object (Foobar in this example) constructor and I can see that object is being created every time I refresh page in browser. How is the singleton pattern meant for Laravels IoC? I understood that its shared object for entire application but its obviously being created every time its requested by App:make(...) Can someone explain please. I thought I would use the singleton pattern for maintaining shared MongoDB connection.
App::singleton('foo', function()
{
return new FooBar;
});
What has been said in Laravel Doc
Sometimes, you may wish to bind something into the container that
should only be resolved once, and the same instance should be returned
on subsequent calls into the container:
This is how you can bind a singleton object and you did it right
App::singleton('foo', function()
{
return new FooBar;
});
But, the problem is, you are thinking about the whole process of the request and response in the wrong way. You mentioned that,
I can see that object is being created every time I refresh page in
browser.
Well, this is normal behaviour of HTTP request because every time you are refreshing the page means every time you are sending a new request and every time the application is booting up and processing the request you've sent and finally, once the application sends the response in your browser, it's job is finished, nothing is kept (session, cookie are persistent and different in this case) in the server.
Now, it has been said that the same instance should be returned on subsequent calls, in this case, the subsequent calls mean that, if you call App::make(...) several times on the same request, in the single life cycle of the application then it won't make new instances every time. For example, if you call twice, something like this
App::before(function($request)
{
App::singleton('myApp', function(){ ... });
});
In the same request, in your controller, you call at first
class HomeController {
public function showWelcome()
{
App::make('myApp'); // new instance will be returned
// ...
}
}
And again you call it in after filter second time
App::after(function($request, $response)
{
App::make('myApp'); // Application will check for an instance and if found, it'll be returned
});
In this case, both calls happened in the same request and because of being a singleton, the container makes only one instance at the first call and keeps the instance to use it later and returns the same instance on subsequent calls.
It is meant to be used multiple times throughout the applications instance. Each time you refresh the page, it's a new instance of the application.
Check this out for more info and practical usage: http://codehappy.daylerees.com/ioc-container
It's written for L3, but the same applies for L4.

Resources