tomcat shared lib - (config) files context rules - java

Within Tomcat 6's lib (${catalina.home}/lib/) folder I have several shared JAR files such as Hibernate's.
When I debug my web app the console gets LOTs of output by Hibernate, unless I put logback.xml in ${catalina.home}/lib/.
Here's the question's highlight:
If I move that same logback.xml to my web app's /WEB-INF/lib/ folder it is ignored as if there is no file - I get all the output.
That's obviously related to context (on the Java level I presume), but I can't find info about it.
Please help me understand it better, the fundamentals.
Thank you!

I bet it isn't related with the context but rather the classpath hierarchy. Java infrastructure provides a mechanism (ClassLoader) to build classpath hierarchies and Tomcat (as many other servlet containers/application servers) use that to isolate the different JARs/class folders being used in a specific application.
The root class loader is the one that has less visibility inside the hierarchy, nested class loaders can look for a class inside their scope or ask a parent class loader for it if not found. Some application servers allow to configure the class loaders to ask first the parent and then look inside their own scope if the parent can't locate it. However, a parent class loader can't never load a class from a nested class loader.
NOTE: same happens with normal files, as with your logback.xml.
So, you have some hibernate libraries deployed in your Tomcat's lib folder, which is handled by the root class loader in the hierarchy. When you have your logback.xml file in that folder it actually is at the same classpath hierarchy level than your Hibernate JARs, so Hibernate (or the log mechanism being used by it) can load the file because it's within its scope.
In the other hand, the libraries used by your application (WEB-INF/lib) are handled by a different class loader which actually is nested to the previous mentioned one. When you move your logback.xml to your application's library folders you are actually moving it to a wider scope but, since Hibernate has been loaded by a parent class loader, it can not locate the file within its scope (remember, a parent class loader can't load classes or files from its children, just the children can ask the parent for those).

Related

Override classloading for a specifc java class file in a wildfly/jboss module

I want to overwrite a particular java class present in a JBoss/Wildfly module with my own customizations. If I use tomcat server, all I need to do, place the customized class files in WEB-INF/classes. Since classes present in WEB-INF/classes takes precedence over the class files present in a particular jar file under WEB-INF/lib. Is there any similar way available for Wildfly server?
One way I can think of is you can write your own class-loading logic.
URLClassLoader loader;
//create object and initialize URLClassLoader loader with the corrosponding classes or jar from //specific location
//Get the 'className' by iterating Jar or by listing class files
Class c = cl.loadClass(className);

where should I locate a common ESAPI.properties file used by multiple wars inside an ear?

I have two modules that will use ESAPI with the same properties files (ESAPI and validation.properties).
These modules output to wars that are contained in an ear.
I have the properties files inside one of the war files, where they are found at server start. The other war file seems to work fine and does not complain that it can't find the properties files in the log.
I am using ESAPI to sanitize html and url parameters - I wonder if I even need these property files to be accessible to the second module, or either one since there is no configuration and everything is being done with defaults.
First, let me describe how ESAPI 2.x goes about finding its ESAPI.properties file.
The reference implementation class for ESAPI's SecurityConfiguration interface is
org.owasp.esapi.reference.DefaultSecurityConfiguration
With this default implementation, resources like ESAPI.properties and
Validation.properties can be put in several locations, which are searched in the following order:
1) Inside a directory set with a call to SecurityConfiguration.setResourceDirectory(). E.g.,
ESAPI.securityConfiguration().setResourceDirectory("C:\myApp\resources");
Of course, if you use this technique, it must be done before any other ESAPI calls are made that use ESAPI.properties (which are most of them).
2) Inside the directory defined by the System property "org.owasp.esapi.resources". You can set this on the java command line as follows (for example):
java -Dorg.owasp.esapi.resources="C:\temp\resources" ...
You may have to add this to the start-up script that starts your web server. For example, for Tomcat, in the "catalina" script that starts Tomcat, you can set the JAVA_OPTS variable to the '-D' string above.
3) Inside the
System.getProperty( "user.home" ) + "/.esapi"
directory (supported for backward compatibility) or inside the
System.getProperty( "user.home" ) + "/esapi"
4) The first ".esapi" or "esapi" directory encountered on the classpath. Note this may be complicated by the fact that Java uses multiple class loaders and if you are have multiple applications in a given application server, they may be using different classpaths. For this reason, this option is not generally recommended, but is offered for reasons of backward compatibility with earlier ESAPI 1.4.x versions.
Once ESAPI finds a valid property file (e.g., ESAPI.properties) that it can read, it stops searching for others.
Now, that said, if you want to share a single ESAPI.properties file across all of your .war files, I would recommend going with option #2 and set the System property "org.owasp.esapi.resources" to some common secured directory that both of them can access. Also, you should use a full path name.
The answer was to place the esapi directory containing the properties files in
src/main/application
in one of the modules. This path puts it's contents at the root of the ear.
I'm running ESAPI on a maven project with java 1.8.0_71. I've put ESAPI.properties and validation.properties in
src/main/resources
This worked for me:
Attempting to load ESAPI.properties via the classpath.
SUCCESSFULLY LOADED ESAPI.properties via the CLASSPATH from '/ (root)' using current thread context class loader!
Attempting to load validation.properties via the classpath.
SUCCESSFULLY LOADED validation.properties via the CLASSPATH from '/ (root)' using current thread context class loader!

Access resource files in plugin jars from main application

I'm developing a main application whose features can be extended via jar files that contain plugins. When my application runs, it simply checks the folder for the plugins, and loads up the classes that it finds there and registers them with my application.
I'd like to develop a help / messages sub-system to my application that uses external resource files (HTML files if possible) to get the help content associated with various parts of the application and to get detailed info/warning/error messages to display to the user.
For all things that pertain to the main application, I can easily determine the relative path to the resource file since I'm keeping those resource files in the same jar as my application class files.
For external plugins, ideally the resource files pertaining to that plugin should live within the jar for that plugin. However, I'm not finding a consistent way to determine the path to those files in the dynamically loaded jars.
Would appreciate any insight into how I could consistently do that for both internal resources and externally provided resources to use the same help / messaging framework provided by the main application.
If you are trying to load the file from a different plugin, or from the main application code, you'll need an instance of the pluginManager from Spring:
InputStream in = pluginManager.getDynamicResourceAsStream(filename)
Ref: https://developer.atlassian.com/confdev/development-resources/confluence-developer-faq/what-is-the-best-way-to-load-a-class-or-resource-from-a-plugin

Log4J Event Viewer Problem

I am develloping 2 applications and publishing them on Websphere Aplication Server.
Since I need to write errors that occur on both applications on the event viewer I put the log4j JAR file on the lib folder of Websphere Aplication Server and the file os being loaded successfully.
I have also created the log4j.properties file under src root package of both applications with different variable names and source designation ("Application A" and "Application B").
When an execption is caught it is being logged to the Event Viewer for both cases.
The problem is that the source name presented is the same "Application A" even if the error occured on Application B...
Can anyone help?
Thanks
I'm not sure what you mean by "applications with different variable names and source designation" — that you use differently named loggers in both applications and direct output to different appenders?
Still, I see one problem with your configuration: when you put your log4j jar into WAS lib folder, it's loaded with the class loader common for both your applications (a bootstrap class loader or extension class loader, depending where this "lib" directory is) — and that means log4j is loaded only ONCE. Considering how log4j is initialized (with a static code section), it is also initialized ONCE, meaning that at most one log4j.properties is read.
Try removing log4j from the WAS lib directory and deploy it with every application, see where it gets you.

log4j properties file: how to configure?

My procedure for using log4j is this:
put a .properties file somewhere in a project folder
in an initialization method, that runs only once, invoke PropertyConfigurator.configure("path_to_file")
in every method we need to use logger we define a static logger variable and simply invoke getLogger(class)
Is this correct?
What happens if the initialization module is not defined? Where can I put the "log4j.properties" file such that I don't have to invoke propertyconfigurator.configure at all? If that's not possible, is it OK to invoke PropertyConfigurator.configure("path_to_file") in every method that uses a logger?
If you put it somewhere in the classpath, Log4J will automatically load it. A typical place for it is the source (or resource) root directory. That way it can get copied into the root directory of your jar too (if you create one from your class files).
The exact details for this depend on what build system you use. E.g. in Maven the convention is to put it in src/main/resources.
The default initialization procedure for log4j is documented in this section of the log4j tutorial. This explains in detail the steps that log4j takes to locate the logging configuration.
The simplest way to configure log4j is to put a the properties file somewhere that allows it to be found by the class loader using the name "/log4j.properties". There are other approaches that you can use as well that involve setting system properties, loading the properties file programmatically, or even instantiating the Loggers, Appenders and so on via the log4j APIs. (Not that the latter is a good idea ...)
(Putting the log4j properties file in "src/main/resources" in a Maven project is just one of a number of possible ways to get the file into your application's classpath root.)

Categories