Accessing application code from overridden Tomcat class - java

I'm currently creating my own JDBCRealm and more specifically, I'm overriding the Authenticate method. The override was no problem, and I got it to work using SHA authentication.
The problems starting arising when I needed to access a different column that isn't covered by Tomcat's own methods, like getPassword(username) and getPrincipal(username).
I have a Hibernate method that retrieves a user based on their username and it looks like:
UsersDTO user = UsersDAO.getUser(username);
The problem is, that because the code is part of the Tomcat library and not the application, calling the method doesn't work. It throws no exceptions and nothing gets logged to catalina.out, it just presents me with a 500 HTTP error.
I have tried numerous things, but I'm at a loss at the moment. Can anyone shed a light on my problem?

You cannot call classes loaded by the app classloader from classes loaded by the server classloader.
You should deploy your jars in a way that all the invocations are done between classes loaded by the same classloader, or from classes loaded by a lower level classloader to classes loaded by a higher level classloader.
Take a look at this. It's related to Weblogic, but the same concepts apply to Tomcat.
http://docs.oracle.com/cd/E24329_01/web.1211/e24368/classloading.htm

Tomcat is implemented with Apache Commons Logging library. So with proper implementation of that logging library in your code, tomcat should be able to log your error properly.
see reference here

Related

log4j.logger.org.jasig.cas not got emitted into application logs

We are using cas-client-core-3.3.3.jar for providing single sign on functionality in our application and we are trying to emit this jar library logs into our appliation logs.
Our application is a weblogic based application and we are using log4j for logging.
So to get cas-client-core-3.3.3.jar logs in our application log we have added this property in our log4j.properties
log4j.logger.org.jasig.cas=DEBUG
but we are not getting the logs which are expected from org.jasig.cas classes. I am attaching sample log here which is expected
2015-05-13 10:00:17,798 DEBUG [org.jasig.cas.client.validation.Saml11TicketValidator.<constructValidationUrl>] - Placing URL parameters in map.
2015-05-13 10:00:17,801 DEBUG [org.jasig.cas.client.validation.Saml11TicketValidator.<constructValidationUrl>] - Calling template URL attribute map.
2015-05-13 10:00:17,802 DEBUG [org.jasig.cas.client.validation.Saml11TicketValidator.<constructValidationUrl>] - Loading custom parameters from configuration.
2015-05-13 10:00:17,803 DEBUG [org.jasig.cas.client.validation.Saml11TicketValidator.<validate>] - Constructing validation url:
Disclaimer: I've never worked with Web Sphere but worked a lot with different logging systems, so my answer is based on my experience in this area.
First off, cas uses slf4j under the hood which is great.
Slf4j is only an interface (slf4j-api jar), and if you want to use it with log4j which is a concrete implementation of logging system that knows nothing about slf4j apis you should provide an implementation of sfl4j interfaces that will delegate the calls to log4j loggers.
So you should also include such an adapter in classpath as well Here is the link.
Now if this doesn't work, then probably the log4j.properties are not configured correctly, for example, the logger doesn't have any associated appenders/wrong appenders.
I've found the best way to check this is just to place a breakpoint on the logger's call (inside cas library) and see the following:
Which implementation of slf4j interface is actually used (as I've said before org.sl4j.Logger is just an interface and it has to be instantiated with real implementation object somehow, you know)
See the associated appenders to the underlying implementation.
Regarding the second item, depending on technology/frameworks you have, you might be able to get this information via JMX or some kind of web admin interface. Debugging is a "hardcore" general way to figure this out.

Issue with jetty, log4j and parentloaderPriority

I am using jetty 6.
I am using a library which requires me to set parentloaderPriority to true. However this messes up my log4j and for some reason I cannot log to my log file anymore (the file appender doesn't work). I don't know if this a known and documented issue? All I googled seems to imply that it's better with parentloaderPriority to true! whereas I have the exact opposite, if I set it back to false, my log4j file gets logged in again. Anything I should be checking in particular?
The WebAppContext.parentLoaderPriority property is for embedded Jetty users only.
All it does is flip the classloader priority from:
Servlet API Mandated Behavior
WebAppContext.setParentLoaderPriority(false)
When a WebApp attempts to resolve a class or resource, the webapp's own ClassLoader is used first, then the parent classloader (which in the case of Jetty is the server classloader)
to
Java Default Behavior
WebAppContext.setParentLoaderPriority(true)
When a class or resource is resolved, use the parent classloader first, then the child classloader.

Jersey 2.5: How can a resource access external classes instances

I have embedded Jetty container inside my main server and I also use Jersey 2.5 for handling REST resources.
everything seems to work well and now I would like to pass my server's context class into each of my REST resources.
I'm having hard time understanding how to do that...
If someone can provide full code example - it could be awesome!
Many thanks
What exactly do you mean when you say you have a Jetty container inside your "main server"? Are you programmatically executing Jetty within the application? Also, when you say "context" are you referring to the ServletContext?

Provider oracle.j2ee.ws.client.ServiceFactoryImpl not found

I am writing an application that invokes an Oracle web service. The web service client code was provided me.
This application uses a custom subclass of URLClassLoader to load jars at run-time. Running the unit tests from my local machine works fine, however when I deploy the application on the server and run it, I get the following error. Other classes/jars are loading fine through the custom ClassLoader.
Not sure why this is happening? Maybe FactoryFinder is using a separate ClassLoader instance? Any help is appreciated. Thanks!
javax.xml.rpc.ServiceException: Provider oracle.j2ee.ws.client.ServiceFactoryImpl not found
at javax.xml.rpc.FactoryFinder.newInstance(FactoryFinder.java:44)
at javax.xml.rpc.FactoryFinder.find(FactoryFinder.java:137)
at javax.xml.rpc.ServiceFactory.newInstance(ServiceFactory.java:69)
at com.mycomp.myapp.oracle.client.TSClient.<init>(TSClient.java:34)
at com.mycomp.myapp.oracle.LaborHours.update(LaborHours.java:92)
at com.mycomp.myapp.oracle.OracleConnection.updateMetrics(OracleConnection.java:73)
at com.mycomp.myapp.Project.crawl(Project.java:150)
at com.mycomp.myapp.Main.main(Main.java:302)
This is the conclusion I came up with.
ServiceFactory uses it's own class loading mechanism (which apparently is a different instance than my custom class loader).
I had to use this hack http://forums.sun.com/thread.jspa?threadID=300557 to add the jars to the system class loader's class path.

Logging Java web applications?

I am planning to implement logging into a web application that I am currently working on but I am struggling with some of the details. What is the best way to go about logging a Java web application?
Specifically;
Where does the configuration file go in .war package file?
Where do people log to, relative or absolute path flat file, or a database?
Does Log4J logging go directly into the application server log file automatically or is that something you have to set up? In this case I am using Tomcat, but I often use Jrun.
Any other gotchas I should be aware of for web application logging?
Currently I am using Log4J but I imagine that the best practices would apply universally to all logging implementations.
EDIT:
One addition to the questions up top.
Where do you initilize the log
configuration?
In a traditional app, I do this at the entry point;
DOMConfigurator.configureAndWatch("log4j.xml");
What would the web application equivalent be?
I would recommend you to use SLF4J. This is simple logging facade which supports most of popular logging systems (Log4j, commons-logging, Java Logging API and Logback).
Using it, you will able to replace your underline logging system to any other, by simple CLASSPATH update.
The other benefit of SLF4J are parameterized calls, which reduces ugly logging code.
Actually, they recommends to use SLF4J with Logback.
Logback is a successor of Log4J. And it was designed by the same author.
Where does the configuration file go in .war package file?
Root of the classpath.
Where do people log to, relative or absolute path flat file, or a database?
Depends on the need. It's always better to use relative paths. Databases are good if you implement another application which will fetch logs from it and send them using email/sms
Does Log4J logging go directly into the application server log file automatically or is that something you have to set up? In this case I am using Tomcat, but I often use Jrun.
If you use Console appender, yes, it's going to be logged in your servlet container log file.
Any other gotchas I should be aware of for web application logging?
If you are logging from different threads use logback, it's thread-safe and it exposes parameterized log messages.
Logging to a DB adds another failure point. We had a situation where the prod servers logged to a DB and someone ran an expensive query on that DB that slowed it so much that the prod servers got very, very slow. Logging to a file can cause issues if you run out of space but it seems less likely to slow down the whole app.
I place my configuration on the default package: src/
and log to files using the ${catalina.home} system property:
log4j.appender.???.file=${catalina.home}/logs/system.log
It might be a good idea to place the config file somewhere where an admin can modify it without rebuilding your web app (e.g., so they can turn on detailed logging without waking you up in the middle of the night).
Unfortunately, there's no "official" way for locating externalized resources from a web app (correct me if I'm wrong). The most common way of doing it I've seen is to look through the directories in the classpath.
The excellent paper How to Do Application Logging Right has a bunch of gotchas.
I believe that your other questions have been answered by other people on this page.
I also recommend that you use SLF4J.
One last thing: having speakable representations of objects can save some time.
I recommend to call log API (log4j) via slf4j. Even if you use log4j, web container or depending modules may use different log API such as Java.util.logging or Jakarta commons logging. Slf4j provides bridge modules that redirect them to slf4j API. As a result, all log messages are written by log4j in that case.
put the log4j in the container (server) and create proper appenders per application
relative to server path, but that depends on your needs
we use appenders which log to different files, depends on your needs, e.g. one file for hibernate info/statistics, one for application only, etc.
don't log to much, it slows the application down
Personally I put the log4j.properties in the WEB-INF directory and use an init servlet with the following code :
public class InitServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
private static final String LOG4J_FILE = "WEB-INF/log4j.properties";
public InitServlet() {
super();
}
#Override
public void init() throws ServletException {
super.init();
PropertyConfigurator.configure(getServletContext().getRealPath(LOG4J_FILE));
LogFactory.getLog(InitServlet.class).info("LOG 4J configured");
}
}
Where does the configuration file go in .war package file?
At the root of the classpath but... Don't put the configuration file in the war package. You don't want to repackage and redeploy the application if you change the logging configuration, do you ? A better practice would be to put the configuration file somewhere in the classpath outside the war.
Where do people log to, relative or absolute path flat file, or a database?
I usually log to the file system on a separate partition (log files can grow very fast and should never block the application or the operating system if they become too big). I use most of time an absolute path based on the following model: /var/projects/<PROJECT_NAME>/<PRODUCT>/<CLUSTER_NAME>/logs/<INSTANCE_NAME>.log where <PROJECT_NAME> is the project name, <PRODUCT> can be Apache, Tomcat, Weblogic,..., <CLUSTER_NAME> the name of the cluster and <INSTANCE_NAME> the name of the instance inside the cluster. Logging to the file system is faster than in a database. The drawback is that logs aren't centralized if you are using several instances and physical machines. But merging can easily be done with a script.
Does Log4J logging go directly into the application server log file automatically or is that something you have to set up? In this case I am using Tomcat, but I often use Jrun.
Application server logs are application server logs, not application logs. Don't write to them but set up a logger tool (e.g. log4j) and write to application logs (understand dedicated).
Any other gotchas I should be aware of for web application logging?
If you are using log4j, don't forget to use the isDebugEnabled() before to log:
if(logger.isDebugEnabled()) {
logger.debug("Bla Bla Bla");
}
Where does the configuration file go in .war package file?
Usually, I do not place any logging configuration into the application, rather leaving that to the appserver admins to configure logging server-wide. In the rare cases I want the log4j configuration deployed with a webapp, WEB-INF is the usual path.
Where do people log to, relative or absolute path flat file, or a database?
Again, depends on appserver settings. One common log file for a appserver and rotating on a daily basis is the usual setup. If there are any app-specific needs, the admin may configure a separate logfile for an app (distinguished by package / class names).
Does Log4J logging go directly into the application server log file automatically or is that something you have to set up? In this case I am using Tomcat, but I often use Jrun.
See above. For tomcat used for development purposes, I'd just look for its logging (log4j) configuration and add app-specific specific there.
Any other gotchas I should be aware of for web application logging?
Performance. Limit the ,log level to a minimum (i.e. WARN or ERROR) once you go live. Use
if (log.isDebugEnabled()) { log.debug("..."); } and alike constructs in your code.
Note that if you just need a bit of logging, the servlet standard specifies that you can get the ServletContext and use the log methods there. That is the generic servlet equivalent of System.out.println.

Categories