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.
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.
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.
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:
- 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. - 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. - If it hasn't been discarded, the message is passed to all
handlers associated with its
<logger>
, including those in the<root-logger>
. Set theuse-parent-handlers
attribute of<logger>
to "false" to override this behavior. - If the handler has no
<level>
threshold defined, as is the case for the FILE handler below, the message is logged. - 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