[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