Introduction
The JBoss logging tools are used to create internationalized log statements and exceptions.
Getting Started
To get started you need to include three dependencies in your project.
| Required at compile time and runtime. | |
| Required at compile time only. | |
| Required at compile time only. | 
If you’re using maven here is an example pom.xml snippet:
<dependencies>
    <!-- Required by the annotation processor and will be used at runtime -->
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging</artifactId>
    </dependency>
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging-annotations</artifactId>
        <version>2.2.1.Final</version>
        <!-- This is a compile-time dependency of this project, but is not needed at compile or runtime by other
              projects that depend on this project.-->
        <scope>provided</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging-processor</artifactId>
        <version>2.2.1.Final</version>
        <!-- This is a compile-time dependency of this project, but is not needed at compile or runtime by other
              projects that depend on this project.-->
        <scope>provided</scope>
        <optional>true</optional>
    </dependency>
</dependencies>Once your project is configured you can create either a message bundle interface or a message logger interface. For detailed information see the JavaDocs for the annotations.
Message Bundle Interfaces
Message bundle interfaces provide a way to internationalize exceptions or strings. A message bundle interface is
annotated with @MessageBundle. Each method in must be annotated with @Message
which will be used to determine the String used for either the return type or the message for the exception being
returned.
The value for a @Message may contain an expression.
| Expressions are in the form of ${key:defaultValue}. If the key is prefixed withsys.a system property is
used. If the key is prefixed withenv.an environment variable is used. In all other cases the properties are resolved
from theorg.jboss.logging.tools.expressionPropertiespath. If the key is not found in the properties the default
value will be used. | 
| Expressions are processed at compile time. The values will be hard-coded in the generated source files. | 
The following constraints are placed on methods in a message bundle:
- 
The return type must be one of the follow - 
A java.lang.String
- 
A java.lang.Throwableor a subtype ofjava.lang.Throwable
- 
A java.lang.function.Supplierwho’s return type fits one of the other two constraints above.
 
- 
- 
The method must be annotated with @Messageor a message must be inheritable.
- 
A method can have only one @Causeparameter.
- 
A method can only have one @Producerparameter.
| A message is inheritable if the two methods have the same name and same number of format parameters. | 
| A format parameter is a parameter that has no annotations or is annotated with one of the following annotations; @FormatWith,@Posor@Transform. | 
Example Message Bundle
@MessageBundle(projectCode = "CW") (1)
public interface ErrorMessages {
    ErrorMessages MESSAGES = Messages.getBundle(ErrorMessages.class);
    @Message("Version %d.%d.%d.%s") (2)
    String version(int major, int minor, int macro, String rel);
    @Message(id = 1, value = "Value '%s' is invalid")
    IllegalArgumentException invalidValue(Object value);
    @Message(id = 2, value = "Failure closing %s") (3)
    CloseException closeFailure(@Cause Throwable cause, @Param @Pos(1) Closeable c);
    CloseException closeFailure(@Cause Throwable cause, @Param @Pos(1) Closeable c, @Suppressed Throwable... errors);
    @Message(id = 3, value = "Parameter %s cannot be null")
    Supplier<String> nullParam(String name);
    @Message(id = 4, value = "Operation %s failed.")
    <T extends RuntimeException> T operationFailed(@Producer Function<String, T> fn, String name); (4)
    <T extends RuntimeException> T operationFailed(@Producer BiFunction<String, IOException, T> fn, @Cause IOException cause, String name);
}| 1 | The projectCodewill be prepended to messages which have anidspecified. For example withid = 1the message will be prepended withCW000001. You can control the number padding with thelengthproperty on the annotation. | 
| 2 | No idis specified for this message which means no id will be prepended on this message. | 
| 3 | The @Paramannotation tells the generator that the parameter should be used to construct theCloseException. The@Pos(1)annotation indicates the parameter should also be used when formatting the message. | 
| 4 | The @Producerannotation indicates that theFunctionshould be used to create the exception being returned. | 
| Message bundle interfaces can also contain valid message logger methods. | 
Message Logger Interfaces
Logger interfaces provide a way to internationalize log messages. A logger interface is an interface annotated with
@MessageLogger. Each method in must be annotated with @Message which will
be used to determine the message to be logged.
The value for a @Message may contain an expression.
| Expressions are in the form of ${key:defaultValue}. If the key is prefixed withsys.a system property is
used. If the key is prefixed withenv.an environment variable is used. In all other cases the properties are resolved
from theorg.jboss.logging.tools.expressionPropertiespath. If the key is not found in the properties the default
value will be used. | 
| Expressions are processed at compile time. The values will be hard-coded in the generated source files. | 
The following constraints are placed on methods in a message logger:
- 
The method must have a voidreturn type
- 
The method must be annotated with @LogMessage
- 
The method must be annotated with @Messageor a message must be inheritable.
- 
A method can have only one @Causeparameter.
| A message is inheritable if the two methods have the same name and same number of format parameters. | 
| A format parameter is a parameter that has no annotations or is annotated with one of the following annotations; @FormatWith,@Posor@Transform. | 
A message logger interface may also extend the org.jboss.logging.BasicLogger. This allows the logging interface to be usable for standard logging. For example AppLogger.LOGGER.debugf("Initializing %s", this);
Example Message Logger
@MessageLogger(projectCode = "CW") (1)
public interface AppLogger extends BasicLogger {
    AppLogger LOGGER = Logger.getMessageLogger(AppLogger.class, AppLogger.class.getPackage().getName());
    @LogMessage
    @Once (2)
    @Message("%s version %d.%d.%d.%s") (3)
    void appVersion(CharSequence name, int major, int minor, int macro, String rel);
    @LogMessage(level = Logger.Level.ERROR) (4)
    @Message(id = 100, value = "Failure while closing %s")
    void closeFailure(@Cause Throwable cause, Object obj);
    @LogMessage(level = Logger.Level.WARN)
    @Message(id = 101, value = "Encoding %s could not be found. Defaulting to %s.")
    void encodingNotFound(String encoding, Charset dft);
    @LogMessage
    @Message(id = 102, value = "Cache size changed to '%d'")
    void cacheSizeChanged(@Transform(Transform.TransformType.SIZE) Collection<String> c);
    @LogMessage
    void cacheSizeChanged(@Transform(Transform.TransformType.SIZE) String... array);
    @LogMessage
    void cacheSizeChanged(@Transform(Transform.TransformType.SIZE) Map<String, Object> map);
}| 1 | The projectCodewill be prepended to messages which have anidspecified. For example withid = 100the message will be prepended withCW000100. You can control the number padding with thelengthproperty on the annotation. | 
| 2 | Ensures the log message is only written once. | 
| 3 | No idis specified for this message which means no id will be prepended on this message. | 
| 4 | Overrides the default level to ERRORto indicate an error message should be logged. | 
Reports
There are currently two types of reports that can be generated. The options are adoc or asciidoc for asciidoc and xml for XML.
The reports contain the following data:
- 
The formatted message id. 
- 
A possible link to a resolution document for the error. 
- 
The unformatted message. 
- 
The log level, if applicable. 
- 
The return type, if applicable. 
Annotations
Two annotations can be used to assist withing linking resolution documents for messages.
- 
- 
This annotation can be used on a type to define the base URL for linking resolution documents. This annotation is not required for links to be created on reports. 
 
- 
- 
- 
This annotation is used to define information about the resolution document for creating links. If placed on an interface all methods that have a defined id will have a link generated. This can also be placed individually on the method to only generate links for specific id’s. 
 
- 
Example Use Cases
Below are some example use case snippets from the examples.
/**
 * Writes the value of the object to the file.
 *
 * @param value the value to write, cannot be {@code null}
 *
 * @throws UncheckedIOException if an error occurs writing the data
 */
public void write(final Object value) {
    AppLogger.LOGGER.appVersion("ContentWriter", 1, 0, 0, "Beta1"); (1)
    Objects.requireNonNull(value, ErrorMessages.MESSAGES.nullParam("value")); (2)
    write(Objects.requireNonNull(value, ErrorMessages.MESSAGES.nullParam("value")).toString());
}
/**
 * Writes the value to the file.
 *
 * @param value the value to write, cannot be {@code null} or an {@linkplain String#isEmpty() empty string}.
 *
 * @throws UncheckedIOException if an error occurs writing the data
 */
public void write(final String value) {
    AppLogger.LOGGER.appVersion("ContentWriter", 1, 0, 0, "Beta1");
    if (Objects.requireNonNull(value, ErrorMessages.MESSAGES.nullParam("value")).isEmpty()) {
        throw ErrorMessages.MESSAGES.invalidValue(value); (3)
    }
    try {
        synchronized (outputLock) {
            writer.write(value);
            writer.newLine();
            if (autoFlush) {
                flush();
            }
        }
    } catch (IOException e) {
        throw ErrorMessages.MESSAGES.operationFailed(UncheckedIOException::new, e, "write"); (4)
    }
}
@Override
public void close() {
    try {
        synchronized (outputLock) {
            writer.close();
        }
        AppLogger.LOGGER.tracef("ContentWriter %s was successfully closed.", this);
    } catch (Exception e) {
        throw ErrorMessages.MESSAGES.closeFailure(e, this);
    }
}
/**
 * Safely close this writer logging any errors that occur during closing.
 */
public void safeClose() {
    try {
        synchronized (outputLock) {
            writer.close();
        }
        AppLogger.LOGGER.tracef("ContentWriter %s was successfully closed.", this);
    } catch (Exception e) {
        AppLogger.LOGGER.closeFailure(e, this); (5)
    }
}| 1 | Logs the application version. Note this uses the @Once annotation to indicate this should only be logged once regardless of which writemethod is used. | 
| 2 | The ErrorMessages.nullParam()returns ajava.lang.function.Supplier. This allows the message to be lazily formatted only if thevalueisnull. | 
| 3 | Throws a message if the valueis an empty string. | 
| 4 | Uses a java.lang.function.BiFunctionto create a newUncheckedIOExceptionwith the caught exception set as the cause. | 
| 5 | Logs the caught exception instead of throwing a new exception. | 
Translation Property Files
The translation properties files must exist in the same directory structure as the interface. The name of the properties file InterfaceName.i18n_language_country_variant.properties. For example if you have a class named org.jboss.logging.tools.examples.ErrorMessages and you want to translate this into French you create a properties file called ErrorMessages.i18n_fr.properties in a directory org/jboss/logging/tools/examples.
Annotation Processor Options
You can pass options to an annotation processor with the -A compiler option. For example to disable generating the @Generated annotation from being placed on the generated source files you would pass -Aorg.jboss.logging.tools.addGeneratedAnnotation=false to the compiler command.
General
| Option | Description | 
|---|---|
| 
 | This option turns on debug logging for the processor | 
| 
 | This option allows you to define a path where, at compile-time, expressions in messages can be resolved. | 
| 
 | If set to  | 
| In Java 9 the @javax.annotation.Generatedwas moved to@javax.annotation.processor.Generated. The processor attempts to determine which annotation to use by attempting to find the@javax.annotation.Generatedfirst. If it fails the@javax.annotation.processor.Generatedis attempted. If neither can be found no annotation will be placed on the generated implementations. | 
| Expressions are in the form of ${key:defaultValue}. If the key is prefixed withsys.a system property is
used. If the key is prefixed withenv.an environment variable is used. In all other cases the properties are resolved
from theorg.jboss.logging.tools.expressionPropertiespath. If the key is not found in the properties the default
value will be used. | 
| Expressions are processed at compile time. The values will be hard-coded in the generated source files. | 
Translation Options
| Option | Description | 
|---|---|
| 
 | The base path for the translated properties files. This defaults to the location where new class files are placed. | 
| 
 | If set to  | 
| 
 | If defined this indicates the path a skeleton file should be generated for the interface. The generated skeleton file will be placed in a directory that matches the package with a name that matches the interface with a  | 
| 
 | Sets the maximum level to include in the generated skeleton files. For example if set to  | 
| 
 | By default when generating a skeleton translation file an index will be appended to the format pattern. For example  | 
Report Options
| Option | Description | 
|---|---|
| 
 | Indicates the type of report that should be generated. The current report types are  | 
| 
 | The path where the generated reports should be placed. This defaults to the location where new class files are placed. | 
| 
 | An optional title for the report. For asciidoc this defaults to  |