Sun compiler silently accepts annotation syntax error
Today I experienced another strange thig with the eclipse compiler. I coded some annotations that contain some syntax error which I wasn’t aware of since the IDE didn’t highlight it. The @@ManagedOperationParameters( { @ManagedOperationParameter(name = "category", description = "Logger category"), }) annotation is not correct, trying to compile it with the Sun compiler fails (can you spot it?).
@ManagedOperation(description = "Get the logging level for a category")
@ManagedOperationParameters( { @ManagedOperationParameter(name = "category", description = "Logger category"), })
public String getLoggerLevel(String category) {
return LogManager.getLogger(category).getLevel().toString();
}
After reporting this a a eclipse JDT bug I was pointed at that this is allowed syntax (see JLS) but the sun compiler does not properly implement syntax checking! So I should rather see to report this against the Sun compiler. Still it is strange that this syntax is allowed at all!!!
Hibernate isPersistent Element
Rarely you need to be able to detect whether some class or property is managed by Hibernate (i.e. it is mapped) or not. In this case SessionFactory.getClassMetdata helps with this problem.
It returns mapping information or throws an exception if it is not mapped!
Imagebin – A place to slap up your images
Just by chance I noticed an interesting image service. Imagebin allows you to temporarily post any image up to 1MB for up to 7 days (depending on the current capacity – only a total of 1000 images is allowed to be stored at anby time).
eclipse 3.3 and WAR file imports
eclipse 3.3.1.1 has an annoying bug. Try to import a WAR file that contains class files in WEB-INF/classes. Thes class files are not imported into the right folder in the imported project structure.
Importing a WAR file gets you a special folder ImportedClasses which is supposed to contain the package/folder structure for imported classes. Due to a bug in the eclipse WAR importer they are copied to ImportedClasses/WEB-INF/classes. As a result, starting a deployed web application presents plenty of ClassNotFoundExceptions and the like.
Today I tried this again with eclipse 3.4-M4 and was glad to see this bug fixed, I was already preparing to file a bug. Until 3.4 is released the classes must be moved manually to the right folder!
Change log4j logging level at runtime using JMX/Spring
Monitoring application servers is a daunting task. Without the right instrumentation of your code it is even impossible. I try to use log4j as much as possible and in general I’m very generous regarding logging levels. But occasionally the console just gets flooded with logging output. Typically then I would modify the logging configuration files and restart the server which may be very time consuming and unnecessary.
In the past I had used JMX to switch logging levels at runtime for various projects. The first time now I have tried this with the Spring framework and it worked like a charm (did you expect anything else). I’m making the solution public in case I need this for future projects and to document the steps required!
First, a bean is required that uses the logging API (here log4j) to manage the logging level.
/*
* Copyright 2002-2008 Martin Ahrer.
*
* $Id$
*/
package at.martinahrer.blueprint.log4j;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedOperationParameter;
import org.springframework.jmx.export.annotation.ManagedOperationParameters;
import org.springframework.jmx.export.annotation.ManagedResource;
/**
* @author Martin Ahrer
*
*/
@ManagedResource(objectName = "at.martinahrer.blueprint.log4j:name=Logging", description = "Logging", log = true, logFile = "jmx.log", currencyTimeLimit = 15, persistPolicy = "OnUpdate", persistPeriod = 200, persistLocation = "logging", persistName = "logging")
public class Logging {
@ManagedOperation(description = "Set the logging level for a category")
@ManagedOperationParameters( { @ManagedOperationParameter(name = "category", description = "Logger category"),
@ManagedOperationParameter(name = "level", description = "Logging level") })
public void setLoggerLevel(String category, String level) {
LogManager.getLogger(category).setLevel(Level.toLevel(level));
}
@ManagedOperation(description = "Get the logging level for a category")
@ManagedOperationParameters( { @ManagedOperationParameter(name = "category", description = "Logger category") })
public String getLoggerLevel(String category) {
return LogManager.getLogger(category).getLevel().toString();
}
}
It’s been annotated with Spring JMX annotations to provide JMX meta data. Next, we need to export the bean as a JMX Bean. This is supported very well by the Springframework’s MBeanExporter.
Finally to connect to the MBeanServer using jconsole the JVM (running the MBean) must be started with the system property -Dcom.sun.management.jmxremote set.
Create FacesMessage within a get-method
Lately I had problems with displaying a FacesMessage. I suspected that it was due to creating it inside a property get-method. As a proof I created a simple demo application.
public class CreateFacesMessageController {
public String newFacesMessage() {
new FacesMessageSupport().error("TEST");
return "success"
}
public String getFacesMessage() {
System.out.println("get-method");
return newFacesMessage();
}
}
The class above contains an action method that creates FacesMessage instance and adds it to the FacesContext through some helper class. A get-method (for pseudo property facesMessage) calls this action method.
A JSP view is using these methods to show the effect described.
The JSP contains a button that triggers the action method, every time it is clicked a faces message is shown.
It also shows the property facesMessage which is bound to the method getFacesMessage.
So one would think that every time the view is show, it also produces a faces message on top of the form – it doesn’t. Here is why:
- getFacesMessage gets called (typically) during the phase RENDER_RESPONSE
- The messages tag is at the very top of the form whereas the outputText element that is bound to the facesMessage property is somewhere below
As a result the messages have alread been rendered when the new faces message is created. You only have 2 choices to remedy. Either you move the messages tag to the very bottom of the form or you make sure that any method that is possibly creating a faces message is invoked in an earlier phase than the RENDER_RESPONSE phase!

