General Rules:
- All exceptions and messages require a translation method in the @MessageBundle.
- All info and higher messages being logged require a translation method in the @MessageLogger.
- Messages in both the @MessageBundle and @MessageLogger should have an id. Note though there are cases, specifically some methods in the @MessageBundle, that do not need id's. These typically include messages that are not being used in exceptions.
- All logged messages should use a static logger from the @MessageLogger interface. This includes debug and trace messages.
- The project code should be the same for across all @MessageLogger's and @MessageBundle's
Passing the cause:
Both @MessageLogger's and @MessageBundle's can except a java.lang.Throwable type as a parameter to either log the exception or intialize the exception return types cause. This is done by annotating the parameter with @Cause.
StartException unableToStart(@Cause Throwable cause);
Creating Exception Return Types:
Most @MessageBundle's methods will be returing exceptions. Some exceptions require a special constructor to be used or require a property/field to be set on the exception. JBoss Logging has 3 separate annotations for these requirements.
@Param - Is used for exception constructor.
SAXParseException invalidAttribute(@Param Locator locator, String attributeName, String tagName);
@Field({name=fieldName}) - Is used to set an instance variable.
XAException invalidTransaction(@Field Integer errorCode);
@Propert({name=propertyName}) - Is used to set a property via it's setter method.
Exception createException(@Property StackTrace[] stackTrace);
Examples:
Example Messages:
package org.jboss.logging.example;
import org.jboss.logging.Logger.Level;
import org.jboss.logging.Messages;
import org.jboss.logging.annotations.Cause;
import org.jboss.logging.annotations.Field;
import org.jboss.logging.annotations.LogMessage;
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.Message.Format;
import org.jboss.logging.annotations.MessageBundle;
import org.jboss.logging.annotations.Param;
import org.xml.sax.Locator;
import org.xml.sax.SAXParseException;
import java.io.File;
import java.io.IOException;
import javax.transaction.xa.XAException;
@MessageBundle(projectCode = "JBOSS")
interface ExampleMessages {
/**
* The messages.
*/
ExampleMessages MESSAGES = Messages.getBundle(ExampleMessages.class);
@Message(id = 12, value = "Could not write to file %s.")
IOException writeError(@Cause Throwable cause, File file) throws RuntimeException;
@Message(id = 13, "Attribute %s is not valid for tag %s.")
SAXParseException invalidAttribute(@Param Locator locator, String attributeName, String tagName);
@Message(id = 14, "Transaction is invalid")
XAException invalidTransaction(@Field Integer errorCode);
}
Example Logger:
package org.jboss.logging.example;
import org.jboss.logging.BasicLogger;
import org.jboss.logging.Logger;
import org.jboss.logging.Logger.Level;
import org.jboss.logging.annotations.Cause;
import org.jboss.logging.annotations.LogMessage;
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger;
@MessageLogger(projectCode = "JBOSS")
interface ExampleLogger extends BasicLogger {
/**
* The default logger.
*/
ExampleLogger LOGGER = Logger.getMessageLogger(ExampleLogger.class, DefaultLogger.class.getPackage().getName());
@LogMessage(level = Level.INFO)
@Message(id = 1, value = "Replacing '%s' value of '%s' with '%s'")
void replacingPropertyValue(String key, Object oldValue, Object newValue);
}
Before:
package org.jboss.logging.example;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import org.jboss.logging.Logger;
public class ConfigWriter {
private static final Logger LOGGER = Logger.getLogger(ConfigWriter.class.getPackage().getName());
private final File configFile;
private final Properties properties;
public ConfigWriter(final File configFile) {
this.configFile = configFile;
this.properties = new Properties();
}
public ConfigWriter(final File configFile, final Properties properties) {
this.configFile = configFile;
this.properties = properties;
}
public void add(final String key, final Object value) {
if (properties.contains(key)) {
LOGGER.infof("Replacing '%s' value of '%s' with '%s'", key, properties.get(key), value);
}
properties.put(key, value);
}
public void writeConfig() throws Exception {
final FileWriter writer = new FileWriter(configFile);
try {
properties.store(writer, "Configuration");
} catch (IOException e) {
throw new IOException("Could not write to file " + configFile, e);
}
}
}
After:
package org.jboss.logging.example;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class ConfigWriter {
private final File configFile;
private final Properties properties;
public ConfigWriter(final File configFile) {
this.configFile = configFile;
this.properties = new Properties();
}
public ConfigWriter(final File configFile, final Properties properties) {
this.configFile = configFile;
this.properties = properties;
}
public void add(final String key, final Object value) {
if (properties.contains(key)) {
ExampleLogger.LOGGER.replacingPropertyValue(key, properties.get(key), value);
}
properties.put(key, value);
}
public void writeConfig() throws Exception {
final FileWriter writer = new FileWriter(configFile);
try {
properties.store(writer, "Configuration");
} catch (IOException e) {
throw ExampleMessages.MESSAGES.writeError(e, configFile);
}
}
}
Setting Up the Logging Tools Processor
Refer to https://community.jboss.org/wiki/JBossLoggingTooling#How_to_set_it_up_in_your_project
Comments