Accessing Injected @RequestScoped objects from different threads

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Accessing Injected @RequestScoped objects from different threads

Paul Carter-Brown-3
Hi,

I have a scenario as follows:

1) JAX-RS request comes into TomEE 8.0.0 and hits a stateless EJB of mine
2) The EJB has an object called UserContext injected which is @RequestScoped
3) userContext in turn injects HttpServletRequest with @Context
4) I use userContext fine. All is good and it can access the
HttpServletRequest
5) My EJB does a rest call to another system. This rest call uses asynhttp
with reactive programming and returns a CompletionStage.
6) my EJB code does a .thenAccept on the completionstage and in this code
we try and use the injected UserContext. Here we get an error when
UserCOntext tries to use HttpServletRequest.

java.lang.IllegalStateException: No CXF message usable for JAX-RS
@Context injections in that thread so can't use interface
javax.servlet.http.HttpServletRequest


I believe this is due to the completionstage being executed on a different
thread. E.g.. steps 1-5 use TomEE-Exec-1 while step 6 uses async-http-3-3.

To resolve this I got UserContext to eagerly load the data it needs
from HttpServletRequest
in step 3 so that at step 6 no calls to HttpServletRequest are needed. It
seems though that the userContext is proxied by webbeans and I get a
different instance on the different thread and this new instance has none
of my eagerly loaded data in it.

Does anyone know how to resolve this issue. Basically I want to somehow get
step 6 to use the exact instance of UserContext as step 2 even though they
are on different threads.

Paul Carter-Brown
Director
Jini Guru
m: +27 (0) 83 442 7179 <+27834427179>
a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
  Johannesburg, South Africa
w: jini.guru  e: [hidden email]

Disclaimer: This message and/or attachment(s) may contain
privileged, confidential and/or personal information. If you are not the
intended recipient you may not disclose or distribute any of
the information contained within this message. In such case you must
destroy this message and inform the sender of the error. Jini Guru may not
accept liability for any errors, omissions, information and viruses
contained in the transmission of this message. Any opinions, conclusions
and other information contained within this message not related to Jini
Guru official business is deemed to be that of the individual only and is
not endorsed by Jini Guru.
Reply | Threaded
Open this post in threaded view
|

Re: Accessing Injected @RequestScoped objects from different threads

jgallimore
Hi Paul

You able to create an as small as possible sample, maybe based on
https://github.com/apache/tomee/tree/master/examples/async-servlet? I'm
struggling a little to picture the code in my head. It sounds likely
related to the two different threads. I'm sure we can at least help figure
out a workaround.

Jon

On Mon, Oct 7, 2019 at 1:01 PM Paul Carter-Brown
<[hidden email]> wrote:

> Hi,
>
> I have a scenario as follows:
>
> 1) JAX-RS request comes into TomEE 8.0.0 and hits a stateless EJB of mine
> 2) The EJB has an object called UserContext injected which is
> @RequestScoped
> 3) userContext in turn injects HttpServletRequest with @Context
> 4) I use userContext fine. All is good and it can access the
> HttpServletRequest
> 5) My EJB does a rest call to another system. This rest call uses asynhttp
> with reactive programming and returns a CompletionStage.
> 6) my EJB code does a .thenAccept on the completionstage and in this code
> we try and use the injected UserContext. Here we get an error when
> UserCOntext tries to use HttpServletRequest.
>
> java.lang.IllegalStateException: No CXF message usable for JAX-RS
> @Context injections in that thread so can't use interface
> javax.servlet.http.HttpServletRequest
>
>
> I believe this is due to the completionstage being executed on a different
> thread. E.g.. steps 1-5 use TomEE-Exec-1 while step 6 uses async-http-3-3.
>
> To resolve this I got UserContext to eagerly load the data it needs
> from HttpServletRequest
> in step 3 so that at step 6 no calls to HttpServletRequest are needed. It
> seems though that the userContext is proxied by webbeans and I get a
> different instance on the different thread and this new instance has none
> of my eagerly loaded data in it.
>
> Does anyone know how to resolve this issue. Basically I want to somehow get
> step 6 to use the exact instance of UserContext as step 2 even though they
> are on different threads.
>
> Paul Carter-Brown
> Director
> Jini Guru
> m: +27 (0) 83 442 7179 <+27834427179>
> a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>   Johannesburg, South Africa
> w: jini.guru  e: [hidden email]
>
> Disclaimer: This message and/or attachment(s) may contain
> privileged, confidential and/or personal information. If you are not the
> intended recipient you may not disclose or distribute any of
> the information contained within this message. In such case you must
> destroy this message and inform the sender of the error. Jini Guru may not
> accept liability for any errors, omissions, information and viruses
> contained in the transmission of this message. Any opinions, conclusions
> and other information contained within this message not related to Jini
> Guru official business is deemed to be that of the individual only and is
> not endorsed by Jini Guru.
>
Reply | Threaded
Open this post in threaded view
|

Re: Accessing Injected @RequestScoped objects from different threads

Paul Carter-Brown-3
Hi Jon,

Not easy to create a working example but hopefully this will help explain:

@Stateless
public class myEJb() {
    @Inject
    private UserContext userContext;

    // Gets called from a JAX-RS context
    public void go(AsyncResponse asyncResponse) {
        CompletionStage<Foo> cs1 = userContext.doSomething();
        cs1.thenAccept((Foo foo) -> {
            ... this is now on a different thread to the previous threads

            CompletionStage<Bar> cs2 = userContext.doSomethingElse(foo) ...
this gets IllegalStateException
            cs2.thenAccept((Bar bar) -> {
                asyncResponse.resume(bar);
            });
        });
    }
}

@RequestScoped
public class UserContext {

    @Context
    private HttpServletRequest httpRequest;

    private Object someVal;

    public CompletionStage<Foo> doSomething() {
        ...
        ...
        Use httpRequest ... all OK
        someVal = httpRequest.getAttribute("someVal");
        ...
    }

    public CompletionStage<Bar> doSomethingElse(Foo foo) {
        ...
        ...
        if (someVal == null) {
            // will go in here as someVal is null
            someVal = httpRequest.getAttribute("someVal"); ...
java.lang.IllegalStateException: No CXF message usable for JAX-RS @Context
injections in that thread so can't use interface
javax.servlet.http.HttpServletRequest
        }
        ...
    }
}

Paul Carter-Brown
Director
Jini Guru
m: +27 (0) 83 442 7179 <+27834427179>
a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
  Johannesburg, South Africa
w: jini.guru  e: [hidden email]

Disclaimer: This message and/or attachment(s) may contain
privileged, confidential and/or personal information. If you are not the
intended recipient you may not disclose or distribute any of
the information contained within this message. In such case you must
destroy this message and inform the sender of the error. Jini Guru may not
accept liability for any errors, omissions, information and viruses
contained in the transmission of this message. Any opinions, conclusions
and other information contained within this message not related to Jini
Guru official business is deemed to be that of the individual only and is
not endorsed by Jini Guru.



On Mon, Oct 7, 2019 at 2:29 PM Jonathan Gallimore <
[hidden email]> wrote:

> Hi Paul
>
> You able to create an as small as possible sample, maybe based on
> https://github.com/apache/tomee/tree/master/examples/async-servlet? I'm
> struggling a little to picture the code in my head. It sounds likely
> related to the two different threads. I'm sure we can at least help figure
> out a workaround.
>
> Jon
>
> On Mon, Oct 7, 2019 at 1:01 PM Paul Carter-Brown
> <[hidden email]> wrote:
>
> > Hi,
> >
> > I have a scenario as follows:
> >
> > 1) JAX-RS request comes into TomEE 8.0.0 and hits a stateless EJB of mine
> > 2) The EJB has an object called UserContext injected which is
> > @RequestScoped
> > 3) userContext in turn injects HttpServletRequest with @Context
> > 4) I use userContext fine. All is good and it can access the
> > HttpServletRequest
> > 5) My EJB does a rest call to another system. This rest call uses
> asynhttp
> > with reactive programming and returns a CompletionStage.
> > 6) my EJB code does a .thenAccept on the completionstage and in this code
> > we try and use the injected UserContext. Here we get an error when
> > UserCOntext tries to use HttpServletRequest.
> >
> > java.lang.IllegalStateException: No CXF message usable for JAX-RS
> > @Context injections in that thread so can't use interface
> > javax.servlet.http.HttpServletRequest
> >
> >
> > I believe this is due to the completionstage being executed on a
> different
> > thread. E.g.. steps 1-5 use TomEE-Exec-1 while step 6 uses
> async-http-3-3.
> >
> > To resolve this I got UserContext to eagerly load the data it needs
> > from HttpServletRequest
> > in step 3 so that at step 6 no calls to HttpServletRequest are needed. It
> > seems though that the userContext is proxied by webbeans and I get a
> > different instance on the different thread and this new instance has none
> > of my eagerly loaded data in it.
> >
> > Does anyone know how to resolve this issue. Basically I want to somehow
> get
> > step 6 to use the exact instance of UserContext as step 2 even though
> they
> > are on different threads.
> >
> > Paul Carter-Brown
> > Director
> > Jini Guru
> > m: +27 (0) 83 442 7179 <+27834427179>
> > a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
> >   Johannesburg, South Africa
> > w: jini.guru  e: [hidden email]
> >
> > Disclaimer: This message and/or attachment(s) may contain
> > privileged, confidential and/or personal information. If you are not the
> > intended recipient you may not disclose or distribute any of
> > the information contained within this message. In such case you must
> > destroy this message and inform the sender of the error. Jini Guru may
> not
> > accept liability for any errors, omissions, information and viruses
> > contained in the transmission of this message. Any opinions, conclusions
> > and other information contained within this message not related to Jini
> > Guru official business is deemed to be that of the individual only and is
> > not endorsed by Jini Guru.
> >
>
Reply | Threaded
Open this post in threaded view
|

Re: Accessing Injected @RequestScoped objects from different threads

Paul Carter-Brown-3
Hi Jon,

I've created a basic example of the issue as attached. 

mvn install -Prun

then:


Paul Carter-Brown
Director
Jini Guru
m:<a href="tel:+27834427179" value="+27832837000" style="color:rgb(17,85,204)" target="_blank">+27 (0) 83 442 7179
a:1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
 Johannesburg, South Africa
w:jini.guru  e: [hidden email]

Disclaimer: This message and/or attachment(s) may contain privileged, confidential and/or personal information. If you are not the intended recipient you may not disclose or distribute any of the information contained within this message. In such case you must destroy this message and inform the sender of the error. Jini Guru may not accept liability for any errors, omissions, information and viruses contained in the transmission of this message. Any opinions, conclusions and other information contained within this message not related to Jini Guru official business is deemed to be that of the individual only and is not endorsed by Jini Guru.




On Mon, Oct 7, 2019 at 3:02 PM Paul Carter-Brown <[hidden email]> wrote:
Hi Jon,

Not easy to create a working example but hopefully this will help explain:

@Stateless
public class myEJb() {
    @Inject
    private UserContext userContext;

    // Gets called from a JAX-RS context
    public void go(AsyncResponse asyncResponse) {
        CompletionStage<Foo> cs1 = userContext.doSomething();
        cs1.thenAccept((Foo foo) -> {
            ... this is now on a different thread to the previous threads        
            CompletionStage<Bar> cs2 = userContext.doSomethingElse(foo) ... this gets IllegalStateException
            cs2.thenAccept((Bar bar) -> {
                asyncResponse.resume(bar);
            });
        });      
    }
}

@RequestScoped
public class UserContext {

    @Context
    private HttpServletRequest httpRequest;

    private Object someVal;

    public CompletionStage<Foo> doSomething() {
        ...
        ...
        Use httpRequest ... all OK
        someVal = httpRequest.getAttribute("someVal");
        ...
    }

    public CompletionStage<Bar> doSomethingElse(Foo foo) {
        ...
        ...
        if (someVal == null) {
            // will go in here as someVal is null
            someVal = httpRequest.getAttribute("someVal"); ... java.lang.IllegalStateException: No CXF message usable for JAX-RS @Context injections in that thread so can't use interface javax.servlet.http.HttpServletRequest
        }
        ...
    }
}

Paul Carter-Brown
Director
Jini Guru
m:<a href="tel:+27834427179" value="+27832837000" style="color:rgb(17,85,204)" target="_blank">+27 (0) 83 442 7179
a:1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
 Johannesburg, South Africa
w:jini.guru  e: [hidden email]

Disclaimer: This message and/or attachment(s) may contain privileged, confidential and/or personal information. If you are not the intended recipient you may not disclose or distribute any of the information contained within this message. In such case you must destroy this message and inform the sender of the error. Jini Guru may not accept liability for any errors, omissions, information and viruses contained in the transmission of this message. Any opinions, conclusions and other information contained within this message not related to Jini Guru official business is deemed to be that of the individual only and is not endorsed by Jini Guru.




On Mon, Oct 7, 2019 at 2:29 PM Jonathan Gallimore <[hidden email]> wrote:
Hi Paul

You able to create an as small as possible sample, maybe based on
https://github.com/apache/tomee/tree/master/examples/async-servlet? I'm
struggling a little to picture the code in my head. It sounds likely
related to the two different threads. I'm sure we can at least help figure
out a workaround.

Jon

On Mon, Oct 7, 2019 at 1:01 PM Paul Carter-Brown
<[hidden email]> wrote:

> Hi,
>
> I have a scenario as follows:
>
> 1) JAX-RS request comes into TomEE 8.0.0 and hits a stateless EJB of mine
> 2) The EJB has an object called UserContext injected which is
> @RequestScoped
> 3) userContext in turn injects HttpServletRequest with @Context
> 4) I use userContext fine. All is good and it can access the
> HttpServletRequest
> 5) My EJB does a rest call to another system. This rest call uses asynhttp
> with reactive programming and returns a CompletionStage.
> 6) my EJB code does a .thenAccept on the completionstage and in this code
> we try and use the injected UserContext. Here we get an error when
> UserCOntext tries to use HttpServletRequest.
>
> java.lang.IllegalStateException: No CXF message usable for JAX-RS
> @Context injections in that thread so can't use interface
> javax.servlet.http.HttpServletRequest
>
>
> I believe this is due to the completionstage being executed on a different
> thread. E.g.. steps 1-5 use TomEE-Exec-1 while step 6 uses async-http-3-3.
>
> To resolve this I got UserContext to eagerly load the data it needs
> from HttpServletRequest
> in step 3 so that at step 6 no calls to HttpServletRequest are needed. It
> seems though that the userContext is proxied by webbeans and I get a
> different instance on the different thread and this new instance has none
> of my eagerly loaded data in it.
>
> Does anyone know how to resolve this issue. Basically I want to somehow get
> step 6 to use the exact instance of UserContext as step 2 even though they
> are on different threads.
>
> Paul Carter-Brown
> Director
> Jini Guru
> m: +27 (0) 83 442 7179 <+27834427179>
> a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>   Johannesburg, South Africa
> w: jini.guru  e: [hidden email]
>
> Disclaimer: This message and/or attachment(s) may contain
> privileged, confidential and/or personal information. If you are not the
> intended recipient you may not disclose or distribute any of
> the information contained within this message. In such case you must
> destroy this message and inform the sender of the error. Jini Guru may not
> accept liability for any errors, omissions, information and viruses
> contained in the transmission of this message. Any opinions, conclusions
> and other information contained within this message not related to Jini
> Guru official business is deemed to be that of the individual only and is
> not endorsed by Jini Guru.
>

basic-service.zip (19K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Accessing Injected @RequestScoped objects from different threads

jgallimore
Awesome, thanks for this. Haven't had a chance to look at this yet, but
I'll have a go with it tomorrow.

Jon

On Mon, Oct 7, 2019 at 9:07 PM Paul Carter-Brown
<[hidden email]> wrote:

> Hi Jon,
>
> I've created a basic example of the issue as attached.
>
> mvn install -Prun
>
> then:
>
> curl "http://localhost:8000/basic-service/basic/async?echo=111"
>
> Paul Carter-Brown
> Director
> Jini Guru
> m: +27 (0) 83 442 7179 <+27834427179>
> a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>   Johannesburg, South Africa
> w: jini.guru  e: [hidden email]
>
> Disclaimer: This message and/or attachment(s) may contain
> privileged, confidential and/or personal information. If you are not the
> intended recipient you may not disclose or distribute any of
> the information contained within this message. In such case you must
> destroy this message and inform the sender of the error. Jini Guru may not
> accept liability for any errors, omissions, information and viruses
> contained in the transmission of this message. Any opinions, conclusions
> and other information contained within this message not related to Jini
> Guru official business is deemed to be that of the individual only and is
> not endorsed by Jini Guru.
>
>
>
> On Mon, Oct 7, 2019 at 3:02 PM Paul Carter-Brown
> <[hidden email]> wrote:
>
>> Hi Jon,
>>
>> Not easy to create a working example but hopefully this will help explain:
>>
>> @Stateless
>> public class myEJb() {
>>     @Inject
>>     private UserContext userContext;
>>
>>     // Gets called from a JAX-RS context
>>     public void go(AsyncResponse asyncResponse) {
>>         CompletionStage<Foo> cs1 = userContext.doSomething();
>>         cs1.thenAccept((Foo foo) -> {
>>             ... this is now on a different thread to the previous threads
>>
>>             CompletionStage<Bar> cs2 = userContext.doSomethingElse(foo)
>> ... this gets IllegalStateException
>>             cs2.thenAccept((Bar bar) -> {
>>                 asyncResponse.resume(bar);
>>             });
>>         });
>>     }
>> }
>>
>> @RequestScoped
>> public class UserContext {
>>
>>     @Context
>>     private HttpServletRequest httpRequest;
>>
>>     private Object someVal;
>>
>>     public CompletionStage<Foo> doSomething() {
>>         ...
>>         ...
>>         Use httpRequest ... all OK
>>         someVal = httpRequest.getAttribute("someVal");
>>         ...
>>     }
>>
>>     public CompletionStage<Bar> doSomethingElse(Foo foo) {
>>         ...
>>         ...
>>         if (someVal == null) {
>>             // will go in here as someVal is null
>>             someVal = httpRequest.getAttribute("someVal"); ...
>> java.lang.IllegalStateException: No CXF message usable for JAX-RS @Context
>> injections in that thread so can't use interface
>> javax.servlet.http.HttpServletRequest
>>         }
>>         ...
>>     }
>> }
>>
>> Paul Carter-Brown
>> Director
>> Jini Guru
>> m: +27 (0) 83 442 7179 <+27834427179>
>> a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>>   Johannesburg, South Africa
>> w: jini.guru  e: [hidden email]
>>
>> Disclaimer: This message and/or attachment(s) may contain
>> privileged, confidential and/or personal information. If you are not the
>> intended recipient you may not disclose or distribute any of
>> the information contained within this message. In such case you must
>> destroy this message and inform the sender of the error. Jini Guru may not
>> accept liability for any errors, omissions, information and viruses
>> contained in the transmission of this message. Any opinions, conclusions
>> and other information contained within this message not related to Jini
>> Guru official business is deemed to be that of the individual only and is
>> not endorsed by Jini Guru.
>>
>>
>>
>> On Mon, Oct 7, 2019 at 2:29 PM Jonathan Gallimore <
>> [hidden email]> wrote:
>>
>>> Hi Paul
>>>
>>> You able to create an as small as possible sample, maybe based on
>>> https://github.com/apache/tomee/tree/master/examples/async-servlet? I'm
>>> struggling a little to picture the code in my head. It sounds likely
>>> related to the two different threads. I'm sure we can at least help
>>> figure
>>> out a workaround.
>>>
>>> Jon
>>>
>>> On Mon, Oct 7, 2019 at 1:01 PM Paul Carter-Brown
>>> <[hidden email]> wrote:
>>>
>>> > Hi,
>>> >
>>> > I have a scenario as follows:
>>> >
>>> > 1) JAX-RS request comes into TomEE 8.0.0 and hits a stateless EJB of
>>> mine
>>> > 2) The EJB has an object called UserContext injected which is
>>> > @RequestScoped
>>> > 3) userContext in turn injects HttpServletRequest with @Context
>>> > 4) I use userContext fine. All is good and it can access the
>>> > HttpServletRequest
>>> > 5) My EJB does a rest call to another system. This rest call uses
>>> asynhttp
>>> > with reactive programming and returns a CompletionStage.
>>> > 6) my EJB code does a .thenAccept on the completionstage and in this
>>> code
>>> > we try and use the injected UserContext. Here we get an error when
>>> > UserCOntext tries to use HttpServletRequest.
>>> >
>>> > java.lang.IllegalStateException: No CXF message usable for JAX-RS
>>> > @Context injections in that thread so can't use interface
>>> > javax.servlet.http.HttpServletRequest
>>> >
>>> >
>>> > I believe this is due to the completionstage being executed on a
>>> different
>>> > thread. E.g.. steps 1-5 use TomEE-Exec-1 while step 6 uses
>>> async-http-3-3.
>>> >
>>> > To resolve this I got UserContext to eagerly load the data it needs
>>> > from HttpServletRequest
>>> > in step 3 so that at step 6 no calls to HttpServletRequest are needed.
>>> It
>>> > seems though that the userContext is proxied by webbeans and I get a
>>> > different instance on the different thread and this new instance has
>>> none
>>> > of my eagerly loaded data in it.
>>> >
>>> > Does anyone know how to resolve this issue. Basically I want to
>>> somehow get
>>> > step 6 to use the exact instance of UserContext as step 2 even though
>>> they
>>> > are on different threads.
>>> >
>>> > Paul Carter-Brown
>>> > Director
>>> > Jini Guru
>>> > m: +27 (0) 83 442 7179 <+27834427179>
>>> > a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>>> >   Johannesburg, South Africa
>>> > w: jini.guru  e: [hidden email]
>>> >
>>> > Disclaimer: This message and/or attachment(s) may contain
>>> > privileged, confidential and/or personal information. If you are not
>>> the
>>> > intended recipient you may not disclose or distribute any of
>>> > the information contained within this message. In such case you must
>>> > destroy this message and inform the sender of the error. Jini Guru may
>>> not
>>> > accept liability for any errors, omissions, information and viruses
>>> > contained in the transmission of this message. Any opinions,
>>> conclusions
>>> > and other information contained within this message not related to Jini
>>> > Guru official business is deemed to be that of the individual only and
>>> is
>>> > not endorsed by Jini Guru.
>>> >
>>>
>>
Reply | Threaded
Open this post in threaded view
|

Re: Accessing Injected @RequestScoped objects from different threads

Paul Carter-Brown-3
Hi Jon,

I've attached a new version with an implementation that works along with the one that fails.

I got it to work by getting the injected class to implement a method as follows:

public SomeContext getForAsync() {
        return this;
}

That in combination with eagerly loading the required data from context injected variables at @PostConstruct means that so long as the instance obtained from getForAsync() is used, then when subsequent threads invoke the object, there is no proxy in the way and no need to access other injected classes that would complain about the different thread being used.

Works for my use case.

Paul Carter-Brown
Director
Jini Guru
m:<a href="tel:+27834427179" value="+27832837000" style="color:rgb(17,85,204)" target="_blank">+27 (0) 83 442 7179
a:1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
 Johannesburg, South Africa
w:jini.guru  e: [hidden email]

Disclaimer: This message and/or attachment(s) may contain privileged, confidential and/or personal information. If you are not the intended recipient you may not disclose or distribute any of the information contained within this message. In such case you must destroy this message and inform the sender of the error. Jini Guru may not accept liability for any errors, omissions, information and viruses contained in the transmission of this message. Any opinions, conclusions and other information contained within this message not related to Jini Guru official business is deemed to be that of the individual only and is not endorsed by Jini Guru.




On Tue, Oct 8, 2019 at 12:42 AM Jonathan Gallimore <[hidden email]> wrote:
Awesome, thanks for this. Haven't had a chance to look at this yet, but
I'll have a go with it tomorrow.

Jon

On Mon, Oct 7, 2019 at 9:07 PM Paul Carter-Brown
<[hidden email]> wrote:

> Hi Jon,
>
> I've created a basic example of the issue as attached.
>
> mvn install -Prun
>
> then:
>
> curl "http://localhost:8000/basic-service/basic/async?echo=111"
>
> Paul Carter-Brown
> Director
> Jini Guru
> m: +27 (0) 83 442 7179 <+27834427179>
> a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>   Johannesburg, South Africa
> w: jini.guru  e: [hidden email]
>
> Disclaimer: This message and/or attachment(s) may contain
> privileged, confidential and/or personal information. If you are not the
> intended recipient you may not disclose or distribute any of
> the information contained within this message. In such case you must
> destroy this message and inform the sender of the error. Jini Guru may not
> accept liability for any errors, omissions, information and viruses
> contained in the transmission of this message. Any opinions, conclusions
> and other information contained within this message not related to Jini
> Guru official business is deemed to be that of the individual only and is
> not endorsed by Jini Guru.
>
>
>
> On Mon, Oct 7, 2019 at 3:02 PM Paul Carter-Brown
> <[hidden email]> wrote:
>
>> Hi Jon,
>>
>> Not easy to create a working example but hopefully this will help explain:
>>
>> @Stateless
>> public class myEJb() {
>>     @Inject
>>     private UserContext userContext;
>>
>>     // Gets called from a JAX-RS context
>>     public void go(AsyncResponse asyncResponse) {
>>         CompletionStage<Foo> cs1 = userContext.doSomething();
>>         cs1.thenAccept((Foo foo) -> {
>>             ... this is now on a different thread to the previous threads
>>
>>             CompletionStage<Bar> cs2 = userContext.doSomethingElse(foo)
>> ... this gets IllegalStateException
>>             cs2.thenAccept((Bar bar) -> {
>>                 asyncResponse.resume(bar);
>>             });
>>         });
>>     }
>> }
>>
>> @RequestScoped
>> public class UserContext {
>>
>>     @Context
>>     private HttpServletRequest httpRequest;
>>
>>     private Object someVal;
>>
>>     public CompletionStage<Foo> doSomething() {
>>         ...
>>         ...
>>         Use httpRequest ... all OK
>>         someVal = httpRequest.getAttribute("someVal");
>>         ...
>>     }
>>
>>     public CompletionStage<Bar> doSomethingElse(Foo foo) {
>>         ...
>>         ...
>>         if (someVal == null) {
>>             // will go in here as someVal is null
>>             someVal = httpRequest.getAttribute("someVal"); ...
>> java.lang.IllegalStateException: No CXF message usable for JAX-RS @Context
>> injections in that thread so can't use interface
>> javax.servlet.http.HttpServletRequest
>>         }
>>         ...
>>     }
>> }
>>
>> Paul Carter-Brown
>> Director
>> Jini Guru
>> m: +27 (0) 83 442 7179 <+27834427179>
>> a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>>   Johannesburg, South Africa
>> w: jini.guru  e: [hidden email]
>>
>> Disclaimer: This message and/or attachment(s) may contain
>> privileged, confidential and/or personal information. If you are not the
>> intended recipient you may not disclose or distribute any of
>> the information contained within this message. In such case you must
>> destroy this message and inform the sender of the error. Jini Guru may not
>> accept liability for any errors, omissions, information and viruses
>> contained in the transmission of this message. Any opinions, conclusions
>> and other information contained within this message not related to Jini
>> Guru official business is deemed to be that of the individual only and is
>> not endorsed by Jini Guru.
>>
>>
>>
>> On Mon, Oct 7, 2019 at 2:29 PM Jonathan Gallimore <
>> [hidden email]> wrote:
>>
>>> Hi Paul
>>>
>>> You able to create an as small as possible sample, maybe based on
>>> https://github.com/apache/tomee/tree/master/examples/async-servlet? I'm
>>> struggling a little to picture the code in my head. It sounds likely
>>> related to the two different threads. I'm sure we can at least help
>>> figure
>>> out a workaround.
>>>
>>> Jon
>>>
>>> On Mon, Oct 7, 2019 at 1:01 PM Paul Carter-Brown
>>> <[hidden email]> wrote:
>>>
>>> > Hi,
>>> >
>>> > I have a scenario as follows:
>>> >
>>> > 1) JAX-RS request comes into TomEE 8.0.0 and hits a stateless EJB of
>>> mine
>>> > 2) The EJB has an object called UserContext injected which is
>>> > @RequestScoped
>>> > 3) userContext in turn injects HttpServletRequest with @Context
>>> > 4) I use userContext fine. All is good and it can access the
>>> > HttpServletRequest
>>> > 5) My EJB does a rest call to another system. This rest call uses
>>> asynhttp
>>> > with reactive programming and returns a CompletionStage.
>>> > 6) my EJB code does a .thenAccept on the completionstage and in this
>>> code
>>> > we try and use the injected UserContext. Here we get an error when
>>> > UserCOntext tries to use HttpServletRequest.
>>> >
>>> > java.lang.IllegalStateException: No CXF message usable for JAX-RS
>>> > @Context injections in that thread so can't use interface
>>> > javax.servlet.http.HttpServletRequest
>>> >
>>> >
>>> > I believe this is due to the completionstage being executed on a
>>> different
>>> > thread. E.g.. steps 1-5 use TomEE-Exec-1 while step 6 uses
>>> async-http-3-3.
>>> >
>>> > To resolve this I got UserContext to eagerly load the data it needs
>>> > from HttpServletRequest
>>> > in step 3 so that at step 6 no calls to HttpServletRequest are needed.
>>> It
>>> > seems though that the userContext is proxied by webbeans and I get a
>>> > different instance on the different thread and this new instance has
>>> none
>>> > of my eagerly loaded data in it.
>>> >
>>> > Does anyone know how to resolve this issue. Basically I want to
>>> somehow get
>>> > step 6 to use the exact instance of UserContext as step 2 even though
>>> they
>>> > are on different threads.
>>> >
>>> > Paul Carter-Brown
>>> > Director
>>> > Jini Guru
>>> > m: +27 (0) 83 442 7179 <+27834427179>
>>> > a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>>> >   Johannesburg, South Africa
>>> > w: jini.guru  e: [hidden email]
>>> >
>>> > Disclaimer: This message and/or attachment(s) may contain
>>> > privileged, confidential and/or personal information. If you are not
>>> the
>>> > intended recipient you may not disclose or distribute any of
>>> > the information contained within this message. In such case you must
>>> > destroy this message and inform the sender of the error. Jini Guru may
>>> not
>>> > accept liability for any errors, omissions, information and viruses
>>> > contained in the transmission of this message. Any opinions,
>>> conclusions
>>> > and other information contained within this message not related to Jini
>>> > Guru official business is deemed to be that of the individual only and
>>> is
>>> > not endorsed by Jini Guru.
>>> >
>>>
>>

basic-service.zip (19K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Accessing Injected @RequestScoped objects from different threads

jgallimore
This makes sense, you're keeping the state that the async part needs. I was
going to suggest something similar. I'll check this against the specs and
make sure we don't have a bug here.

Jon

On Wed, Oct 9, 2019 at 12:00 AM Paul Carter-Brown
<[hidden email]> wrote:

> Hi Jon,
>
> I've attached a new version with an implementation that works along with
> the one that fails.
>
> I got it to work by getting the injected class to implement a method as
> follows:
>
> public SomeContext getForAsync() {
>         return this;
> }
>
> That in combination with eagerly loading the required data from context
> injected variables at @PostConstruct means that so long as the instance
> obtained from getForAsync() is used, then when subsequent threads invoke
> the object, there is no proxy in the way and no need to access other
> injected classes that would complain about the different thread being used.
>
> Works for my use case.
>
> Paul Carter-Brown
> Director
> Jini Guru
> m: +27 (0) 83 442 7179 <+27834427179>
> a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>   Johannesburg, South Africa
> w: jini.guru  e: [hidden email]
>
> Disclaimer: This message and/or attachment(s) may contain
> privileged, confidential and/or personal information. If you are not the
> intended recipient you may not disclose or distribute any of
> the information contained within this message. In such case you must
> destroy this message and inform the sender of the error. Jini Guru may not
> accept liability for any errors, omissions, information and viruses
> contained in the transmission of this message. Any opinions, conclusions
> and other information contained within this message not related to Jini
> Guru official business is deemed to be that of the individual only and is
> not endorsed by Jini Guru.
>
>
>
> On Tue, Oct 8, 2019 at 12:42 AM Jonathan Gallimore <
> [hidden email]> wrote:
>
>> Awesome, thanks for this. Haven't had a chance to look at this yet, but
>> I'll have a go with it tomorrow.
>>
>> Jon
>>
>> On Mon, Oct 7, 2019 at 9:07 PM Paul Carter-Brown
>> <[hidden email]> wrote:
>>
>> > Hi Jon,
>> >
>> > I've created a basic example of the issue as attached.
>> >
>> > mvn install -Prun
>> >
>> > then:
>> >
>> > curl "http://localhost:8000/basic-service/basic/async?echo=111"
>> >
>> > Paul Carter-Brown
>> > Director
>> > Jini Guru
>> > m: +27 (0) 83 442 7179 <+27834427179>
>> > a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>> >   Johannesburg, South Africa
>> > w: jini.guru  e: [hidden email]
>> >
>> > Disclaimer: This message and/or attachment(s) may contain
>> > privileged, confidential and/or personal information. If you are not the
>> > intended recipient you may not disclose or distribute any of
>> > the information contained within this message. In such case you must
>> > destroy this message and inform the sender of the error. Jini Guru may
>> not
>> > accept liability for any errors, omissions, information and viruses
>> > contained in the transmission of this message. Any opinions, conclusions
>> > and other information contained within this message not related to Jini
>> > Guru official business is deemed to be that of the individual only and
>> is
>> > not endorsed by Jini Guru.
>> >
>> >
>> >
>> > On Mon, Oct 7, 2019 at 3:02 PM Paul Carter-Brown
>> > <[hidden email]> wrote:
>> >
>> >> Hi Jon,
>> >>
>> >> Not easy to create a working example but hopefully this will help
>> explain:
>> >>
>> >> @Stateless
>> >> public class myEJb() {
>> >>     @Inject
>> >>     private UserContext userContext;
>> >>
>> >>     // Gets called from a JAX-RS context
>> >>     public void go(AsyncResponse asyncResponse) {
>> >>         CompletionStage<Foo> cs1 = userContext.doSomething();
>> >>         cs1.thenAccept((Foo foo) -> {
>> >>             ... this is now on a different thread to the previous
>> threads
>> >>
>> >>             CompletionStage<Bar> cs2 = userContext.doSomethingElse(foo)
>> >> ... this gets IllegalStateException
>> >>             cs2.thenAccept((Bar bar) -> {
>> >>                 asyncResponse.resume(bar);
>> >>             });
>> >>         });
>> >>     }
>> >> }
>> >>
>> >> @RequestScoped
>> >> public class UserContext {
>> >>
>> >>     @Context
>> >>     private HttpServletRequest httpRequest;
>> >>
>> >>     private Object someVal;
>> >>
>> >>     public CompletionStage<Foo> doSomething() {
>> >>         ...
>> >>         ...
>> >>         Use httpRequest ... all OK
>> >>         someVal = httpRequest.getAttribute("someVal");
>> >>         ...
>> >>     }
>> >>
>> >>     public CompletionStage<Bar> doSomethingElse(Foo foo) {
>> >>         ...
>> >>         ...
>> >>         if (someVal == null) {
>> >>             // will go in here as someVal is null
>> >>             someVal = httpRequest.getAttribute("someVal"); ...
>> >> java.lang.IllegalStateException: No CXF message usable for JAX-RS
>> @Context
>> >> injections in that thread so can't use interface
>> >> javax.servlet.http.HttpServletRequest
>> >>         }
>> >>         ...
>> >>     }
>> >> }
>> >>
>> >> Paul Carter-Brown
>> >> Director
>> >> Jini Guru
>> >> m: +27 (0) 83 442 7179 <+27834427179>
>> >> a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and Leslie
>> >>   Johannesburg, South Africa
>> >> w: jini.guru  e: [hidden email]
>> >>
>> >> Disclaimer: This message and/or attachment(s) may contain
>> >> privileged, confidential and/or personal information. If you are not
>> the
>> >> intended recipient you may not disclose or distribute any of
>> >> the information contained within this message. In such case you must
>> >> destroy this message and inform the sender of the error. Jini Guru may
>> not
>> >> accept liability for any errors, omissions, information and viruses
>> >> contained in the transmission of this message. Any opinions,
>> conclusions
>> >> and other information contained within this message not related to Jini
>> >> Guru official business is deemed to be that of the individual only and
>> is
>> >> not endorsed by Jini Guru.
>> >>
>> >>
>> >>
>> >> On Mon, Oct 7, 2019 at 2:29 PM Jonathan Gallimore <
>> >> [hidden email]> wrote:
>> >>
>> >>> Hi Paul
>> >>>
>> >>> You able to create an as small as possible sample, maybe based on
>> >>> https://github.com/apache/tomee/tree/master/examples/async-servlet?
>> I'm
>> >>> struggling a little to picture the code in my head. It sounds likely
>> >>> related to the two different threads. I'm sure we can at least help
>> >>> figure
>> >>> out a workaround.
>> >>>
>> >>> Jon
>> >>>
>> >>> On Mon, Oct 7, 2019 at 1:01 PM Paul Carter-Brown
>> >>> <[hidden email]> wrote:
>> >>>
>> >>> > Hi,
>> >>> >
>> >>> > I have a scenario as follows:
>> >>> >
>> >>> > 1) JAX-RS request comes into TomEE 8.0.0 and hits a stateless EJB of
>> >>> mine
>> >>> > 2) The EJB has an object called UserContext injected which is
>> >>> > @RequestScoped
>> >>> > 3) userContext in turn injects HttpServletRequest with @Context
>> >>> > 4) I use userContext fine. All is good and it can access the
>> >>> > HttpServletRequest
>> >>> > 5) My EJB does a rest call to another system. This rest call uses
>> >>> asynhttp
>> >>> > with reactive programming and returns a CompletionStage.
>> >>> > 6) my EJB code does a .thenAccept on the completionstage and in this
>> >>> code
>> >>> > we try and use the injected UserContext. Here we get an error when
>> >>> > UserCOntext tries to use HttpServletRequest.
>> >>> >
>> >>> > java.lang.IllegalStateException: No CXF message usable for JAX-RS
>> >>> > @Context injections in that thread so can't use interface
>> >>> > javax.servlet.http.HttpServletRequest
>> >>> >
>> >>> >
>> >>> > I believe this is due to the completionstage being executed on a
>> >>> different
>> >>> > thread. E.g.. steps 1-5 use TomEE-Exec-1 while step 6 uses
>> >>> async-http-3-3.
>> >>> >
>> >>> > To resolve this I got UserContext to eagerly load the data it needs
>> >>> > from HttpServletRequest
>> >>> > in step 3 so that at step 6 no calls to HttpServletRequest are
>> needed.
>> >>> It
>> >>> > seems though that the userContext is proxied by webbeans and I get a
>> >>> > different instance on the different thread and this new instance has
>> >>> none
>> >>> > of my eagerly loaded data in it.
>> >>> >
>> >>> > Does anyone know how to resolve this issue. Basically I want to
>> >>> somehow get
>> >>> > step 6 to use the exact instance of UserContext as step 2 even
>> though
>> >>> they
>> >>> > are on different threads.
>> >>> >
>> >>> > Paul Carter-Brown
>> >>> > Director
>> >>> > Jini Guru
>> >>> > m: +27 (0) 83 442 7179 <+27834427179>
>> >>> > a: 1st Floor, Golf House, Design Quarter, Cnr. William Nicol and
>> Leslie
>> >>> >   Johannesburg, South Africa
>> >>> > w: jini.guru  e: [hidden email]
>> >>> >
>> >>> > Disclaimer: This message and/or attachment(s) may contain
>> >>> > privileged, confidential and/or personal information. If you are not
>> >>> the
>> >>> > intended recipient you may not disclose or distribute any of
>> >>> > the information contained within this message. In such case you must
>> >>> > destroy this message and inform the sender of the error. Jini Guru
>> may
>> >>> not
>> >>> > accept liability for any errors, omissions, information and viruses
>> >>> > contained in the transmission of this message. Any opinions,
>> >>> conclusions
>> >>> > and other information contained within this message not related to
>> Jini
>> >>> > Guru official business is deemed to be that of the individual only
>> and
>> >>> is
>> >>> > not endorsed by Jini Guru.
>> >>> >
>> >>>
>> >>
>>
>