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