One of the biggest ongoing challenges I see with Maven lies in discovering the groupId and artifactId of various public libraries.
I recently stumbled upon a website that provides a robust search on top of the maven central repository.
www.mvnrepository.com provides search and browse capabilities on top of the Maven central repository.¬† They’ve got tag clouds and other features as well.¬† You can search by groupId, Artifact, or any part of the description.¬† I’ve had much success with this site on recent projects.
I see a lot of developers at my organization who are using Log4J incorrectly when it comes to logging exceptions.
Invariably, the desire is to log the error and get a meaningful message from the exception that is thrown.
Consider the following code:
Logger log = Logger.getLogger(ClassName.class);
//Some code here...
log.error("Some error has occurred");
This block of code sets up the context for our example.¬† We’ll just worry about the log.error statement from here on.
The most common errors I see in logging exceptions are:
log.error("An error has occurred: " + e.getMessage());
Unfortunately, neither of these calls will generate the output that the developer wants.
Ultimately, the developer wants to get a meaningful message that will help them identify and debug the problem.
Log4J does provide a simple way to generate a full stack trace for an exception in your logs:
log.error(String msg, Throwable e)
So you could modify the incorrect examples I listed above to do what you really want:
log.error("Some Error Message", e);
This code will generate an entry in the log that contains your error message AND a full stack trace for the exception that was caught.
I’ve been writing code for a long time and now that I’m an Architect at my company, people look at me funny when I ask them to review my code. Many folks think that I don’t need code reviews.
My feeling on the matter is that everyone needs a code review. Code reviews don’t have to be long formal meetings with code printouts and red pens to mark all the issues. A simple peer review before checking your changes into the Source Control System may be all that is needed in many cases.
Here’s a recent example of a quick change I made to code and pushed through to production. It was such a small change that I didn’t think to get it reviewed. Now, I wish I had as we’re having to make an off-cycle release of the code to fix the bug that I introduced. Continue reading Everyone needs a code review
I found a simple way to enable Remote Debugging in OC4J stand-alone version 10.1.3. I assume it will work on other versions.
I was looking at the startup script (oc4j.cmd on Windows) that is found in the bin directory of your OC4J install. I was looking for where exactly to add the necessary startup options in the script to enable remote debugging.
I found that the script reads from an environment variable OC4J_JVM_ARGS to look for additional startup parameters.
Rather than muck about with the canned startup script, I simply created an environment variable OC4J_JVM_ARGS which contains the following value:
This was picked up by OC4J and the container launched with remote debugging enabled on port 4000.
Now, I want to be able to easily turn remote debugging on and off, but I don’t want to have to remember the pesky parameters every time, so I took another step.
I created a second Environment Variable OC4J_DEBUG with the value set to
I then changed the OC4J_JVM_ARGS parameter to contain a value of %OC4J_DEBUG%
Now to turn debugging on and off, I simply modify the value of OC4J_JVM_ARGS and add or remove my %OC4J_DEBUG% variable. It’s less typing and easier to remember.
We had a thread leak on our production servers recently that caused downtime on multiple applications.¬† The culprit turned out to be an application that configured Log4J incorrectly.
How can Log4J bring down an application server?¬† I don’t think this one was Log4J’s fault so much as a developer who initialized it incorrectly.
As you may know, Log4J has a nice feature called ConfigureAndWatch which allows you to specify a configuration file and an interval.¬† Log4J will check the configuration file for updates on the specified interval and will update the configuration as needed. ¬† This is a very useful feature as it allows us to configure logging on the fly on our production servers.¬† Thus, when an app begins to misbehave, we can enable more detailed logging without having to restart the application (which would reset the app and potentially make the error disappear for awhile).
The danger with ConfigureAndWatch is that by its very nature, it must spawn a new thread when it is called.¬† This thread sleeps for a period of time, then wakes up to check the config file.¬† This works well if you initialize Log4J properly as it is only called once when the application starts up.¬† Unfortunately, a developer will occasionally embed a call to ConfigureAndWatch in the main execution path of the application.¬† In the case of a web application, this results in a new thread being spawned each time the application gets a hit.¬† The threads never die, they just keep going.¬† Because they sleep most of the time, they don’t show up on system load reports and such until the system eventually cannot allocate any more threads.
On our LINUX systems, java threads count as OS processes.¬† As the OS reached its process limit, the application crashed as did the container, and everything else that was owned by the same user.
I caught wind of the thread leak and someone involved mentioned that all the threads were running the FileWatchDog class which is the class used by Log4J to monitor files.¬† We were able to identify the offending app and issue a fix, but this should have never happened.
In general, developers should follow the following rules when developing application code:
- Shared libraries should not run any kind of Log4J initialization code.¬† This should be left to the applications that will use the library.
- If you don’t need the ability to change your logging configuration at run-time, you should allow Log4J to configure itself by simply including a log4j.properties or log4j.xml file in the application classpath.
- Never call ConfigureAndWatch in a way where it can be executed more than once during an application’s life.