[ 
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)

Reply via email to