Hi Ceki, See comments inline below...
At 12:09 PM 12/13/2002 +0100, you wrote:
Looks like Mark made it so that the selectors package is separate from the core log4j.jar. I guess that is fine. Users will simply have to be diligent about making sure that the selectors.jar (or whatever it will be called) and log4j.jar are always next to each other. The big gotcha is when log4j.jar is in, for instance, common/lib, but then the user also includes the log4j.jar in the webapp WEB-INF/lib. Because of the way the servlet-2.3 spec defines the reverse classloading behavior, the log4j.jar that will get loaded will be inAt 21:04 12.12.2002 -0600, Jacob Kjome wrote:MW> I would also like to say that I have proposed that we include servlet/web
MW> application support in v1.3 of log4j. This would include an init servlet,
MW> context listeners, configuration via a servlet, etc. Jacob has proposed to
MW> include his servlet as a start (<hint>Maybe Jacob would like to lead the
MW> effort...</hint>). If anyone has other ideas/submissions, we'd like to hear
MW> about them. We want to make log4j as useful as possible "out of the box" so
MW> that folks don't have to re-invent the wheel each time.
+1Does that mean an init servlet in general or the one I created?I meant in general. [snip]Yep, exactly. It is cumbersome and confusing for developers not used to dealing with classloader issues. If they can't see each other then the configuration breaks. If Log4jCRS was included in log4j.jar, then there wouldn't be any chance that a user could mess this up.
Indeed, the user would have one less step to follow. One less possibility of messing up. However, asking users to have log4j.jar and Log4jCRS.jar next to each other is not an impossible requirement. I don't feel strongly either way.
WEB-INF/lib instead of the parent classloader, which would be the normal Java2 way to load classes. If the user now forgets to also put a copy of the selectors.jar in WEB-INF/lib and is using Log4jCRS (now called ContextClassLoaderSelector) in their initialization servlet or servlet context listener, then they will get an exception because Log4jCRS, existing in the parent classloader, cannot access log4j.jar sitting in the child classloader.
However, given that this stuff is Container-behavior-dependent, it probably does makes sense to not include it in the official log4j.jar distribution. I'd still be happy if it was, but I'll defer to yours and Mark's wisdom.
[snip]So, Ceki, Mark, do you have any ideas for improving upon the flexibility of Log4jCRS? If you provide the suggestions, I'll definitely try to implement those suggestions and drive this thing as you were hoping. However, I'll need some code review to let me know where things could be more optimized, made more flexible, and conform to the standards of the classes included in Log4j.Will do so in a next email.
I look forward to it!
Now, when you say "explicit container support", are you saying that it would have to be implemented by the container or do you just mean that it depends on the behavior of the container. In the case of Log4jCRS, the container does not need to know about it at all. The only way it is connected to the container is that Log4jCRS assumes that the classloaders are implemented a certain way.The classloader based approach has one severe limitation. Without explicit Container support, it kinda breaks down for applications with multiple classloaders. For example, in an EJB applicaiton, beans have their own classloader, web-applications have another class loader, and JSPs have yet another even if they all live in the same application (EAR file). See the problem?
The independence of Log4jCRS and the Container is beautiful. Let me also thank you for writing Log4jCRS. I have been theorizing about it for a while, you have actually done it. Kudos.
Thank you very much :-)
Regarding Tomcat 4.x, let me note that JSPs in a web-app have aYou guessed correctly. Since I use the Barracuda framework along with XMLC, I never use JSP. Thank you for pointing out the fact that the JSP classloader is a child of the WebappClassLoader. Its behavior must follow standard Java2 in the way it loads classes where it looks in the WebappClassLoader first for classes before looking in its own classloader. Of course, the normal Java2 classloading behavior would stop at the point of the WebappClassLoader since it, preferentially, loads classes from itself before looking to a parent classloader. Very interesting. I wasn't aware of this at all.
different class loader then that of servlets. The JSP classloader is
of type org.apache.jasper.servlet.JasperLoader. It is the child of the
classloader (of type WebappClassLoader) that loads servlets. To
convince yourself run the following JSP file and the following
servlet from within the same web-applicaiton.
----------------- BEGIN JSP file
<%@ page language="java" %>
<% ClassLoader cl = this.getClass().getClassLoader(); out.println("
");
out.println("-----CL.jsp : "+cl);
out.println("-----CL.jsp parent: "+cl.getParent());
out.println("");
%>
</body>
</html>
--------------------END JSP----
------------------- BEGIN servlet
import java.io.*;
import javax.servlet.*;
public class XServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><body><pre>");
out.println("-----XServlet"+this.getClass().getClassLoader());
out.println("</pre></body></html>");
}
}
------------------- ENF servlet
I suppose that Log4jCRS was not tested with JSPs.
One way to allow JSPs and servlets to use the *same* logger-repository is to check whether the type of the TCL (thread context classloader) is org.apache.jasper.servlet.JasperLoader and if so to key on the parent class loader. But then, Log4jCRS becomes Tomcat specific. It would not work with Resin or Jetty. We could of course write a Jetty specific Log4jCRS or Resin specific Log4jCRS. More importantly, assuming all containers follow some sort of classloader structure, we could write a Log4jCRS for each container *without* the involvement of Jetty, Resin, or Tomcat developers. The bottom line is that we can do it and we do not need permission!
Yep, gotta like that :-)
Yes, that does seem like a very viable solution since all containers are required to implement JNDI.>As of right now, Log4jCRS has been tested to work with Tomcat-4.1.x >standalone (should work fine in 4.0.x as well). Since Tomcat is not an >EJB container, EJB's are not a consideration and niether Log4jCRS not >log4j.jar would see the EJB container at all even if there was some >connection being made between Tomcat and an EJB container because they'd >be in separate JVM's. You'd have two separate logger configurations >anyway in this case. Most Servlet Containers can be embedded within application servers. JBoss for example can embed both jetty and tomcat. Websphere and Weblogic embed their own servlet container which might even be tomcat. (I don't know and I don't care.) >The big exception would be a case with something like JBoss which, >currently, implements some sort of Single ClassLoader architecture, which >I'm not completely familiar with. So, when you use the JBoss+Tomcat >integration, the web container should be able to see classes in the EJB >container and vice-versa (at least in the non-WebappClassLoaders), unless >I am mistaken. However, since servlet-2.3 defines a ClassLoader >architecture exactly opposite of the normal Java2 architecture (classes in >the WebappClassLoader check first with itself for classes instead of >immediately delegating to the parent), then there should still be a >separate classloader for webapps. And if the WebappClassLoader is used as >the key for logger repositories and EJB's can see Log4j (and >Log4jCRS...both in a parent classloader, not in WEB-INF/lib) in the same >way that servlets can, then they should all still be able to use a logging >configuration initialized via servlets with an application specific logger >repository. This is purely speculative, though, because I haven't >actually tried it. The advantage of JNDIRS is that it would work for all containers regardless of their classloader architecture. It would work uniformly across JSPs, Servlets and EJBs. JNDIRS does not require anything new from Containers. It just leverages the existing infrastructure. I think JNDIRS solves the "voluntary logging separation" problem quite nicely. It would be further refined to solve the "mandatory logging separation" problem introduced by Costin Manolache: One comment: application isolation is not a voluntary thing. If we want to isolate the loggers you can't allow the application to specify what logger it wants in web.xml and hope they'll not use the same name. He even suggests a solution. The container could (on demand) place a prefix on the name of the logger repository. I'll modify http://qos.ch/logging/sc.html to explain this more in detail.
Thanks again, and thanks for including my Log4jCRS (ContextClassLoaderSelector) in Log4j. It is quite an honor :-)[snip] >Yes, they are all loaded in the WebappClassLoader defined by the >servlet-2.3 spec (see my ramblings above). In fact, jsp's are just >servlets in the end anyway. If they were loaded by another classloader (a >parent classloader such as the shared or common classloaders) they they >wouldn't be able to load classes in the WebappClassLoader unless they did >some trickery like using the thread context classloader. I'm nearly 100% >positive that they are all loaded via the WebappClassLoader. Maybe Yoav >Shapira can verify this? Unless they have a parent child relationship. Please see above. Anyway, I very much like the way you bypassed the requirement to have the Container initialize the repository selector and delegated the responsibility to Log4jCRS/web-apps.
Jake
-- Ceki -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>