commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From John Bollinger <thinma...@yahoo.com>
Subject Re: Fwd: commons-logging unsuited for cross-context webapplication invocation usage - migrating to slf4j?
Date Fri, 24 Apr 2009 14:56:47 GMT


Mark Thomas wrote:
> Ate Douma wrote:
> > When Pluto needs to "aggregate" the content of this TestPortlet, it
> > invokes it render(PortletRequest, PortletResponse) method using a
> > "cross-context" call from the Pluto web application to the "test" web
> > application.
> > The TestPortlet.render method receives the PortletRequest object (as
> > loaded from the Pluto WEB-INF/lib) and invokes its
> > PortletRequest.getPortletPreferences() method. If the PortletPreferences
> > class hasn't been accessed yet before, this will cause the ClassLoader
> > of PortletRequest, being the Pluto webapp ClassLoader, to now load the
> > PortletPreferences class.
> > But, because the current ContextClassLoader is the "test" webapp
> > ClassLoader, LogFactory will lookup the logger implementation from the
> > "test" webapp...
> > With as result that logging output for the PortletPreferences class will
> > end up in the target as specified by the "test" webapp, not in the one
> > (as expected) as configured for the Pluto webapp.

So, basically, the PortletRequest needs to see the ClassLoader for the context
in which it was created, rather than the one for the context in which it is used?
I think this can be achieved without changing the behavior of LogFactory, and
in a way that provides the same benefit to any other classes that depend on
the context ClassLoader to find resources.  (See below and attached.)

> I have seen similar issues in Tomcat's internal logging with
> java.util.logging, log4j and commons-logging. Why will this be any
> different with slf4j?
>
> > The only possible workaround I could come up with was extending
> > LogFactory itself and temporarily switching/enforcing the current
> > ContextClassLoader to that of the class itself, but obviously we didn't
> > even consider that as a real option.
>
> In Tomcat, the issue was (mainly) log objects for internal components
> being created and loaded by a web application class loader. This was a
> particular issue for Jasper, the JSP engine, as it interacts quite
> closely with web apps. We solved this by ensuring that the logs were
> created during Tomcat start.

I think the case of the server's internal classes is a bit different from the
cross-context case, in part because the a web application's (portlet
application's) expectations of its environment are largely defined by the
servlet (and portlet) spec, whereas the server's internal classes are
whatever the server needs.  That doesn't necessarily mean they need
different solutions, but there are some solutions that are viable for the server
that the server may not be reasonably demand of webapps.

I think there is a better solution for cross-context, which may also have some
use for internal server classes: instead of subclassing LogFactory or any
class of an external component, wrap the servlet / portlet spec objects
in dynamic proxies that manage the context switch on method invocation
and return.  As long as the wrapped objects are specified by Java interfaces,
the java.lang.reflect.Proxy class makes this pretty easy -- you don't even
need different methods or classes to handle it for different interfaces.  As long
as the cross-context invocation is mediated by the server, web / portlet
applications would not need to do anything special -- the server could ensure
that the objects belonging to one webapp would always see the appropriate
context classloader for that context.

See attached sample code for a class that would support this behavior.


John


      
Mime
View raw message