[prev in list] [next in list] [prev in thread] [next in thread]
List: openejb-development
Subject: Re: NotSerializableException with @Inject HttpServletRequest
From: "Jonathan S. Fisher" <exabrial () gmail ! com>
Date: 2023-08-10 23:34:17
Message-ID: CAJAC5uisorD=qNQqU7bNSQ6E=aYvCgC3XfS8_M+wGrZQex_LrA () mail ! gmail ! com
[Download RAW message or body]
Thanks David! I was actually experimenting with something similar,
extending the Supplier and Serializable interfaces and trying to pass a
function back and forth. I'll give this a shot and send a patch up.
In the meantime as a workaround, one can call externalContext.getRequest()
and cast to HttpServletRequest.
On Thu, Aug 10, 2023 at 5:58 PM David Blevins <dblevins@tomitribe.com>
wrote:
> Here's what I'd probably do:
>
> Replace these calls with dedicated classes for each proxy type
>
> if (systemInstance.getComponent(HttpServletRequest.class) == null)
> {
> systemInstance.setComponent(HttpServletRequest.class,
> Proxys.threadLocalProxy(HttpServletRequest.class,
> OpenEJBSecurityListener.requests, null));
> }
>
> To
>
> if (systemInstance.getComponent(HttpServletRequest.class) == null)
> {
> systemInstance.setComponent(HttpServletRequest.class,
> HttpServletRequestProxy.get());
> }
>
> The `HttpServletRequestProxy` would be an interface that extends
> HttpServletRequest and Serializable, like this one:
>
> -
> https://github.com/apache/tomee/blob/main/server/openejb-client/src/main/java/org/apache/openejb/client/EJBHomeProxy.java
>
> Unlike that interface, I'd put all the implementation code in the
> interface and add a static get() method. The stub would look something
> like this:
>
> public interface HttpServletRequestProxy extends Serializable,
> HttpServletRequest {
>
> public Object writeReplace() throws ObjectStreamException;
>
> public static HttpServletRequest get() {
> // return a proxy that implements this interface and uses our
> Handler inner-class
> }
>
> public static class Handler implements InvocationHandler {
> // move the relevant Handler code in here and forget Proxys
> // add code to handle the writeReplace() method and return an
> instance of Serialized
> }
>
> public static class Serialized implements Serializable {
> public Object writeReplace() throws ObjectStreamException {
> return HttpServletRequestProxy.get();
> }
> }
> }
>
> What will happen is that when the HttpServletRequest is serialized, an
> instance of Serialized will be written instead. On deserialization, the
> `Serialized` instance will replace itself again using the same
> `HttpServletRequestProxy.get()` call used to create the original proxy.
>
> I'd do that for all the proxy types (HttpSession). Each proxy type would
> have hardcoded references in their handler to the ThreadLocal static fields
> they need.
>
> Then I would try to delete every line of code from Proxys that we could.
>
> Incidentally, this looks like a bug:
>
> -
> https://github.com/apache/tomee/blob/tomee-8.x/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java#L362
>
>
> -David
>
> > On Aug 10, 2023, at 1:35 PM, Jonathan S. Fisher <exabrial@gmail.com>
> wrote:
> >
> > Hello TomEE friends, I was looking to patch a bug we encountered and
> could
> > use some advice from the other committers.
> >
> > Given this CDI Bean:
> >
> > @SessionScoped
> > @Named
> > public class MyPageBean implements Serializable {
> > @Inject private HttpServletRequest req;
> > ... use the bean somewhere in EL
> > }
> >
> > This will result in an exception when serializing the Session (For
> session
> > replication or passivation): java.lang.RuntimeException:
> > java.lang.RuntimeException: java.io.NotSerializableException:
> > org.apache.openejb.cdi.Proxys$ThreadLocalHandler
> >
> > Looking at the Proxys.java code, it contains a private static class
> called
> > ThreadLocalHandler, that is indeed not Serializable. For fun, I made
> > ThreadLocalHandler implement Serializable, but that just resulted in
> > another error because ThreadLocalHandler contains a ThreadLocal field
> which
> > is definitely not Serializable.
> >
> > ThreadLocalHandler for HttpServletRequest is invoked by
> > TomcatWebappBuilder.setComponentsUsedByCDI():
> >
> >
> https://github.com/apache/tomee/blob/tomee-8.x/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java#L358
>
> >
> > I'm at a bit of a loss on how to fix this. My assumption is the
> > ThreadLocalHandler was designed as a generic proxy object that defers to
> an
> > internal ThreadLocal object. I wonder if marking the ThreadLocal as
> > transient is sufficient, but I could use some input.
> >
> > Thank you,
> >
> > --
> > Jonathan | exabrial@gmail.com
> > Pessimists, see a jar as half empty. Optimists, in contrast, see it as
> half
> > full.
> > Engineers, of course, understand the glass is twice as big as it needs to
> > be.
>
>
--
Jonathan | exabrial@gmail.com
Pessimists, see a jar as half empty. Optimists, in contrast, see it as half
full.
Engineers, of course, understand the glass is twice as big as it needs to
be.
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic