JBoss.orgCommunity Documentation

Chapter 12. JBoss AS Crash Course

12.1. Introduction

The JBoss Application Server (AS7) is the foundation upon which Immutant is built. You can go a long way with Immutant without knowing anything about the administration of JBoss AS, but for advanced applications, it's worth knowing something about how AS is configured and extended. Feel free to skip this section if you're just getting started with Immutant, and use it as a reference later.

You'll see references below to $JBOSS_HOME. Use the env subtask of the lein-immutant plugin to find yours.

For more detailed documentation, please read the official AS7 docs.

12.2. Configuring

In AS7, all server configuration is kept in two folders, one for each runtime mode: standalone and domain. Administrative tasks are simplified from previous releases because all configuration is in one folder and, in standalone mode, in a single file.

./images/jboss-server.png

Immutant uses standalone mode by default but can be run in domain mode as well.

JBoss AS 7 uses a modular architecture - libraries common to all server configurations are kept under the modules/ directory. Configuration files are stored inside $JBOSS_HOME/standalone/configuration/ and $JBOSS_HOME/domain/configuration/ folders.

Both standalone and domain modes have a common folder structure, including the following directories: configuration/, deployments/, and lib/. In general, it isn't a good idea to remove anything from these directories that you didn't put there yourself.

./images/jboss-standalone-mode.png

Some additional directories are created automatically at runtime, as needed: tmp/, data/, and log/. Though not typically necessary, you may safely delete these when the server is not running to clear its persistent state.

12.3. Running

The $JBOSS_HOME/bin/ directory contains the main JBoss entry point, standalone.sh (or standalone.bat), along with its config file, standalone.conf. Running the JBoss server is simple:

$ $JBOSS_HOME/bin/standalone.sh

In fact, this is exactly what the lein-immutant plugin's run task does.

Use the --server-config option to specify a different configuration. For example, to put JBoss in "clustered" mode:

$ $JBOSS_HOME/bin/standalone.sh --server-config=standalone-ha.xml

The lein plugin's --clustered option is shorthand for the above:

$ lein immutant run --clustered

You may set Java system properties using the -D option. Pass -h for a list of all the available options.

Permanent runtime configuration of JBoss should go in $JBOSS_HOME/bin/standalone.conf. For example, your application may require more memory (RAM) than the default allocated. Edit standalone.conf to increase the value of -Xmx to something reasonable.

In production you may prefer to control JBoss via a Unix "init script", examples of which may be found beneath $JBOSS_HOME/bin/init.d/. Feel free to tweak one for your particular OS.

12.4. Deploying

Each runtime mode has a deployments/ subdirectory, the contents of which determine the applications and services JBoss runs. These apps and services are represented as archives, "exploded" folders, or text files called "deployment descriptors". The JBoss deployment scanner operates in two different modes: auto-deploy and manual deploy (the default).

Auto-deploy mode works like in previous releases of AS, in that a resource will be redeployed every time its timestamp changes. The scanner creates a marker file with a ".deployed" suffix, and if the resource gets deleted the scanner will not trigger an undeployment.

In manual deploy mode the scanner will rely on addition or removal of a marker files. To learn more about this deployment method, see the marker files section of the administrator guide.

./images/jboss-deploy.png

The lein-immutant Leiningen plugin provides commands to create and copy a deployment descriptor for your Clojure application to $JBOSS_HOME/standalone/deployments/ along with the required deployment markers. See Deployment for more details.

12.5. Logging

The recommended way to integrate your applications with JBoss logging is to use clojure.tools.logging, which will discover and use the JBoss configuration automatically when your app is deployed on Immutant. You'll find your log messages in $JBOSS_HOME/standalone/log/server.log.

JBoss provides a very sophisticated logging system that nobody completely understands. It's possible to configure hierarchical, categorized log message routing, complex file rotation, syslog integration, SMTP notifications, SNMP traps, JMS, JMX and much more. Obviously, most of that is far beyond the scope of this document.

All JBoss log messages have an associated category, which clojure.tools.logging defaults to the current namespace, and level, e.g. DEBUG, INFO, WARN, ERROR, or FATAL. Levels are ordered by increasing severity, e.g. FATAL is higher than ERROR, which is higher than WARN, etc. Logging configuration rules determine where messages are logged according to their category and level. For standalone mode, these rules are contained in the logging subsystem element of standalone/configuration/standalone.xml. By default, you will see INFO (and higher, i.e. more severe) messages on the console (the shell where you start Immutant) and written persistently to standalone/log/server.log.

Anything written to stdout or stderr is interpreted as an INFO log message and will therefore also be displayed on the console and written to standalone/log/server.log.

12.5.1. JBoss Logging Configuration

The default AS7 configuration is shown below. It includes two handlers (one for the CONSOLE and one for the FILE), some loggers and a root logger. When a message is logged, here's what happens:

  1. The message's category is compared to any defined <logger> elements. If a match is found, the message's level must be greater than or equal to that of the <logger>, else it's discarded.
  2. If no matching <logger> is found, the message's level must be greater than or equal to the level of the <root-logger>, else it's discarded.
  3. If it hasn't been discarded, the message is passed to all handlers associated with its <logger>, including those in the <root-logger>. Set the use-parent-handlers attribute of <logger> to "false" to override this behavior.
  4. If the handler has no <level> threshold defined, as is the case for the FILE handler below, the message is logged.
  5. If the handler has a <level> threshold defined, as is the case for the CONSOLE handler below, the message's level must be greater than or equal to that threshold to be logged.

Here's the default config from standalone/configuration/standalone.xml:

<subsystem xmlns="urn:jboss:domain:logging:1.2">
    <console-handler name="CONSOLE">
        <level name="INFO"/>
        <formatter>
            <pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
        </formatter>
    </console-handler>
    <periodic-rotating-file-handler name="FILE" autoflush="true">
        <formatter>
            <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
        </formatter>
        <file relative-to="jboss.server.log.dir" path="server.log"/>
        <suffix value=".yyyy-MM-dd"/>
        <append value="true"/>
    </periodic-rotating-file-handler>
    <logger category="com.arjuna">
        <level name="WARN"/>
    </logger>
    <logger category="org.apache.tomcat.util.modeler">
        <level name="WARN"/>
    </logger>
    <logger category="org.jboss.as.config">
        <level name="DEBUG"/>
    </logger>
    <logger category="sun.rmi">
        <level name="WARN"/>
    </logger>
    <logger category="jacorb">
        <level name="WARN"/>
    </logger>
    <logger category="jacorb.config">
        <level name="ERROR"/>
    </logger>
    <root-logger>
        <level name="INFO"/>
        <handlers>
            <handler name="CONSOLE"/>
            <handler name="FILE"/>
        </handlers>
    </root-logger>
</subsystem>

One thing to note about the default logging configuration is that your DEBUG messages won't show up anywhere. You could lower the default level for the root logger to DEBUG, but that results in DEBUG messages for every other category that doesn't match any of the loggers, potentially a lot of messages. A better solution is to define a <logger> specifically for your namespace:

<logger category='your.awesome.namespace'>
  <level name='DEBUG'/>
</logger>

This will result in log messages written to the FILE handler, but not the CONSOLE, since its threshold level is still set at INFO.

For many applications, it's usually better to take advantage of the hierarchical nature of categories and refer only to the top-level namespace component so that any messages logged from a child namespace will match. For example, this rule will cause debug messages logged from both your.awesome and your.awesome.namespace:

<logger category='your'>
  <level name='DEBUG'/>
</logger>

For more information, see the official JBoss logging documentation.

12.5.2. Per-application Logging Configuration

In addition to adjusting the logging settings globally in the xml configuration, you can also provide a log4j.properties, log4j.xml, or logging.properties file on the effective classpath for an application (i.e. in resources/, src/, etc.). These settings will only affect the logging for the application that provides the file.

For example, the following log4j.properties will cause all log messages from within the application (and from any Immutant namespaces called by the application) to be written to ~/my-app.log:

log4j.rootCategory=INFO, F

log4j.appender.F=org.apache.log4j.FileAppender
log4j.appender.F.append=true
log4j.appender.F.file=${user.home}/my-app.log
log4j.appender.F.layout=org.apache.log4j.PatternLayout
log4j.appender.F.layout.ConversionPattern=%d %-5p %c: %m%n

Note: due to a known issue with the logging system in the application server, configuring a console appender in log4j.properties/.xml won't work - no messages will be written to the console. The current workaround is to use a logging.properties file instead.

The following logging.properties will do the same as the above log4j.properties, but also display the messages in the console:

# Additional loggers to configure (the root logger is always configured)
loggers=

logger.level=INFO
logger.handlers=CONSOLE,FILE

handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
handler.CONSOLE.level=TRACE
handler.CONSOLE.formatter=PATTERN
handler.CONSOLE.properties=autoFlush,target,enabled
handler.CONSOLE.autoFlush=true
handler.CONSOLE.target=SYSTEM_OUT
handler.CONSOLE.enabled=true

handler.FILE=org.jboss.logmanager.handlers.FileHandler
handler.FILE.level=ALL
handler.FILE.formatter=PATTERN
handler.FILE.properties=append,autoFlush,enabled,suffix,fileName
handler.FILE.constructorProperties=fileName,append
handler.FILE.append=true
handler.FILE.autoFlush=true
handler.FILE.enabled=true
handler.FILE.fileName=${user.home}/my-app.log

formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
formatter.PATTERN.properties=pattern
formatter.PATTERN.constructorProperties=pattern
formatter.PATTERN.pattern=%d %-5p %c: %m%n
Immutant 1.1.4