You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@cxf.apache.org by "Peter Palaga (Jira)" <ji...@apache.org> on 2023/11/04 15:53:00 UTC
[jira] [Comment Edited] (CXF-8911) Allow creating a custom CXFHttpAsyncResponseConsumer
[ https://issues.apache.org/jira/browse/CXF-8911?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17782899#comment-17782899 ]
Peter Palaga edited comment on CXF-8911 at 11/4/23 3:52 PM:
------------------------------------------------------------
Sorry for the late response and thanks for the ideas, [~reta] and [~dufoli]!
{quote}
{code}
public interface AsyncResponseListenerFactory {
AsyncResponseListener create();
}
public interface AsyncResponseListener {
void onBeforeReceived(HttpResponse response);
void onAfterReceived(HttpResponse response);
}
CXFResponseCallback responseCallback = new CXFResponseCallback() {
@Override
public void responseReceived(HttpResponse response) {
listener.onBeforeReceived(response);
setHttpResponse(response);
listener.onAfterReceived(response);
}
};
{code}
{quote}
I think this would not work, because I need to "be on the stack" of the code called by {{setHttpResponse(response);}}.
But your earlier proposal with {{interface AsyncResponseCallbackFactory}} would work. I could do something like
{code}
class AsyncResponseCallbackFactory implements AsyncResponseCallbackFactory {
AsyncResponseCallback create() {
ThreadContext threadContext = Arc.container().select(ThreadContext.class).get();
/*
* We need to call this threadContext.contextualConsumer() here in the constructor to store the context
* because consumeResponse() is called from another thread where the context is not available anymore
*/
BiConsumer<HttpResponse, CXFResponseCallback> contextualConsumer =
threadContext.contextualConsumer(
(HttpResponse response, CXFResponseCallback callback)
-> callback.responseReceived(response));
return new MyAsyncResponseCallback(contextualConsumer);
}
}
class MyAsyncResponseCallback implements AsyncResponseCallback {
final BiConsumer<HttpResponse, CXFResponseCallback> contextualConsumer;
MyAsyncResponseCallback(BiConsumer<HttpResponse, CXFResponseCallback> contextualConsumer) {
this.contextualConsumer = contextualConsumer;
}
void responseReceived(HttpResponse response, CXFResponseCallback callback) {
contextualConsumer.accept(response, callback);
}
}
{code}
Could you perhaps draft a CXF pull request so that I can check that it really works?
was (Author: ppalaga):
Sorry for the late response and thanks for the ideas, [~reta] and [~dufoli]!
{quote}
{code}
public interface AsyncResponseListenerFactory {
AsyncResponseListener create();
}
public interface AsyncResponseListener {
void onBeforeReceived(HttpResponse response);
void onAfterReceived(HttpResponse response);
}
CXFResponseCallback responseCallback = new CXFResponseCallback() {
@Override
public void responseReceived(HttpResponse response) {
listener.onBeforeReceived(response);
setHttpResponse(response);
listener.onAfterReceived(response);
}
};
{code}
{quote}
I think this would not work, because I need to "be on the stack" of the code called by {{setHttpResponse(response);}}.
But your earlier proposal with {{interface AsyncResponseCallbackFactory} }} would work. I could do something like
{code}
class AsyncResponseCallbackFactory implements AsyncResponseCallbackFactory {
AsyncResponseCallback create() {
ThreadContext threadContext = Arc.container().select(ThreadContext.class).get();
/*
* We need to call this threadContext.contextualConsumer() here in the constructor to store the context
* because consumeResponse() is called from another thread where the context is not available anymore
*/
BiConsumer<HttpResponse, CXFResponseCallback> contextualConsumer =
threadContext.contextualConsumer(
(HttpResponse response, CXFResponseCallback callback)
-> callback.responseReceived(response));
return new MyAsyncResponseCallback(contextualConsumer);
}
}
class MyAsyncResponseCallback implements AsyncResponseCallback {
final BiConsumer<HttpResponse, CXFResponseCallback> contextualConsumer;
MyAsyncResponseCallback(BiConsumer<HttpResponse, CXFResponseCallback> contextualConsumer) {
this.contextualConsumer = contextualConsumer;
}
void responseReceived(HttpResponse response, CXFResponseCallback callback) {
contextualConsumer.accept(response, callback);
}
}
{code}
Could you perhaps draft a CXF pull request so that I can check that it really works?
> Allow creating a custom CXFHttpAsyncResponseConsumer
> ----------------------------------------------------
>
> Key: CXF-8911
> URL: https://issues.apache.org/jira/browse/CXF-8911
> Project: CXF
> Issue Type: New Feature
> Reporter: Peter Palaga
> Priority: Major
>
> We recently got a [bug report|https://github.com/quarkiverse/quarkus-cxf/issues/947] in Quarkus CXF complaining about non-working context propagation with CXF HC5 client.
> The problem was that if the client is called in context of a Quarkus REST endpoint, whose vert.x thread has the request context setup properly, the request scoped beans are then not accessible e.g. from ContainerRequestFilters which run in in a different thread.
> To make it work, we would need wrap the creation of CXFHttpAsyncResponseConsumer in some code storing the context of the creation thread into a wrapping method that can then be executed by some other thread. I was able to do this by overriding some default classes. What I did can be seen around here: https://github.com/quarkiverse/quarkus-cxf/pull/950/files#diff-568a3d75d004f9f41c6130854755ebb2beae2f30308cc45aa98492d09bac2ecc
> This solution is by no means elegant and I wonder whether it would be feasible to implement some new API to allow creating custom CXFHttpAsyncResponseConsumers?
> Maybe we could introduce some kind of CXFHttpAsyncResponseConsumerFactory?
> I am quite new to CXF internals, so I'd be thankful for any hints how to proceed.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)