I've managed to implement this. Thanks Jonathan for raising this, and thank you David for the guidance. PRs incoming and I'll file a JIRA ticket.
Jon On Fri, Aug 11, 2023 at 12:34 AM Jonathan S. Fisher <exabr...@gmail.com> wrote: > 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 <dblev...@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 <exabr...@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 | exabr...@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 | exabr...@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. >