Open Mapobo opened 2 years ago
Hi Mapobo, thanks for reaching out!
You are correct, the SDK filters currently don't support async. You could work around this by writing a custom filter that does it, but it is a lot of custom code and I'm not certain that it will work on Neo.
Could you elaborate on what SDK functionality you want to use inside the async operation? Because currently the SDK context will anyway be destroyed when the initial filter chain ends, i.e. when the initial request is processed & answered. Thus, passing it on to a long-living thread doesn't really work. We are working on an improvement to make this work, but I can't give a timeline yet on when that will be available, and if it will work on Neo..
I think I have misunderstood the concept of thread context. Reviewing the documentation the thread context saves the tenant, the user and the JSON JWT token. In my asynchronous process I use a destination to get the data but with the technical user and thread context it is not necessary (principal propagation is not necessary). So I understand that it is not necessary to use the thread context. is it correct ? I saw asynchronous process and try to implement this hahaha.
What do you think about using in new thread instead of creating the asynchronous filter? I have read that using new thread in servlet is discouraged because of memory access issues.
Do you think saving the zip file and json information as an attribute on the session object is adequate?
Okay, so when using a destination the thread context may or may not be needed. It depends if your destination is related to a specific tenant or user. Is this the case, or is your destination defined on the "provider tenant" i.e. the account you are running the app with? In the provider case, the thread context should not be needed.
I have read that using new thread in servlet is discouraged because of memory access issues.
Yes, because threads may be re-used so you should clean up any state you are creating on the thread. Also, accessing the request of the servlet from another Thread is a problem, because that may also be recycled.
I'd think that if you have some "simple" logic that doesn't do these things you should be fine, but for sure you would have to read up on that and cross check with your implementation that there are no side effects.
Do you think saving the zip file and json information as an attribute on the session object is adequate?
I don't really know. If you store it on the session, it will have the same lifecycle as the session. That may depend on your configuration, how long those last. Also, in case your app crashes or a re-login happens you may lose the data. Not sure how impactful that is. E.g. if the computation takes a long time you may want to store the data in a database instead in order to recover in a case of failure.
Also, I'm not sure what the exact interaction between async threads and sessions are. E.g. you may have to ensure that there is no race condition, where two threads write to the same session at the same time.
Hello again.
First of all thanks for your help.
I have done a series of "stress" tests with multiple calls at the same time and the service works fine :)
At the end I have called the asynchronous functionality with the code you suggested as an example.
ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(new Runnable() {
@Override
public void run() {
logger.info("doPost:: Hilo Async:" + Thread.currentThread().getName());
try {
logger.info("doPost:: Generando CVs");
cvManager.init();
} catch (Exception e) {
e.printStackTrace();
}
executor.shutdown();
}
});
The information saved in the session only remains there for a few seconds, (when the second call is called it comes back and is deleted). It is not possible to overwrite the information because one uuid is generated per call/file.
I think we are on the right track But I have another question.
Is it possible to use in neo a standard servlet (without sdk) and startAsync functionality? In this case i wouldn´t use the destination but i could call directly the provider data service . It would be possible?
Thanks for all.
Happy to hear that it works for your use case! WRT the async servlet support, this seems to be supported: https://answers.sap.com/questions/9831334/servlet-30-async-support.html
Maybe just give it a try :)
Not sure if I should open a new issue, but since you already talk about async here, I'll give it a try:
We also faced an async issue, we needed the cloud-sdk to be async-compatible so that we can work with JWT tokens in async servlets for server-side-events.
For our surprise, all we had to do is remove the cloud-sdk package from componentscan and provide a copy of your RequestAccessorFilter
with the only change, that we set asyncSupported to true:
@WebFilter(filterName = "RequestAccessorFilter", urlPatterns = "/*", asyncSupported = true)
.
It seems that at least this filter works fine asyncronously. If you think there is no other problem that we maybe have overseen, could this be added to the sdk diredctly?
This is very good news, could you please detail the process? I hope they can be added to the SDK soon.
Thanks to all of you.
I've just added asyncSupported = true
to the WebFilter annotation in RequestAccessorFilter.
The code in RequestAccessorFilter seems to be working fine asynchronously, the filter is just rejected in async servlets as long as asyncSupported is not set to true. At least for our server-side-events, we can access the auth details in the thread context without issues.
Hi colleagues,
I'm the product owner of SAP Cloud SDK. We're planning to address the async support for our servlet Filter
soon in Q4/2022.
The reason for not immediately fixing this, is that we need the time to check all potential use-cases. If we miss something here, then we could potentially silently break SAP Cloud SDK for other customers. For today a workaround is available.
We will also update this ticket as soon as there is an update :+1:
Kind regards Alexander
Issue Description
Important information:
Hi all! I am trying to create an asynchronous service to generate document's employees with sap cloud sdk for neo environment.
The process is the following:
First an external application sends a post request with a body similar to this:
{ "Empleados": ["XXXX", "YYYY", "EEEEE"], "Secciones": ["1", "2", "3", "4", "5", "6","7","9","10","11","12","13","14","15","16"] }
Empleados contains the employees reference and Secciones contains the sections to print.
Then the service returns the following body :
Then, a background process generates documents and saves the json string info and a zip file with documents in two differents attributes of session object to be obtained later (once all documents are generated). Is it correct to save this info in attribute of session Object?
this.session.setAttribute(this.uniqueIdpdf, ByteArrayOutputStream);
An UUID is generated by the service to identify the request and other properties (success -> process finished flag, total -> total employee/docs to generate, procesados -> count of documents generated).
In the meantime, the external App call every second the service with the following get request (you can review the UUID parametter to identify the process)
GetCvs?UUID=3315ac6e-fa10-4ccf-a4f6-d6eb7452787a
and retrieve the same json info but the property "Procesados" increase while the generator process gen docs.
The only way to make this process works It is adding a new thread to execute it in background.
Rigth now the following code is working correctly.
After I tested a similar code with normal servlet (no created with sdk) and apache tomcat server 7.0 . I could use async support and created a asyncContext similar to this.
` final AsyncContext asyncContext = request.startAsync(request, response);
However, I tried to use asyncContext with sdk servlet and the following error is displayed. com.sap.cloud.sdk.cloudplatform.thread.exception.ThreadContextExecutionException: java.lang.IllegalStateException: A filter or servlet of the current chain does not support asynchronous operations..
I tried to add assync-supported in
@WebServlet
and in web.xml but always appear this error. Exist some incompatibility with sdk and asynchronous process?I saw Multitenancy, Thread Context and async Operations in the documentation and i tried to implement that but always execute in same thread and the post request return body when all docs are generated.
`ThreadContextExecutor executor = new ThreadContextExecutor(); Callable operationWithContext = () -> executor.execute(() -> operation());
invokeAsynchronously(operationWithContext);`
And I dont find or understand invokeAsyncronously.
What Is the better way to implement this aproach?
Sorry for my java knowledge. I new in that.
Thank you for your help.
Impact / Priority
Affected development phase: e.g. Getting Started, Development, Release, Production
Impact: e.g. No Impact, Inconvenience, Impaired, Blocked
Timeline: e.g. Go-Live is in 12 weeks.
Error Message
Error Output when try used request.startAsync
Project Details
Checklist