« Posts under Jboss

Using Jboss System Properties

So if I have a jboss application set up on different environments, is there an easy way for me to load environment specific properties on a per instance basis?

Yes there is, read on.

So normally, in most applications you might end up with some property values you’ll want to override based on the environment. For example, login credentials to some third party service, environment specific file locations, environment specific jnp servers, or properties that flag the application’s mode as test or production environments.

It’s generally a good idea for an application to have properties bundled within the deployable artifact so that during deployment you can avoid running into “property not found” type of exceptions. Defaults are always a good idea, and since a deployable artifact should be completely self contained, bundling properties during a deploy is a naturally good practice. But what if you want to override these properties with an environmentally dependent set of values?

We can use the jboss “conf” directory. Because jboss uses an instance style of configuration, you can stick your properties in the “/jboss-install-dir/server/configured-instance/conf” directory, and access them easily from within your code. In a nutshell you can ask the System.properties object for the URL location of the “conf” directory, then load your properties file into a local Properties object as a resource. If your property file is not in the “conf” directory, you can then choose to load from the bundled properties (deployed with your archive) the regular way.

Lets take a look at some of the properties jboss loads into System.properties – on startup if you have jboss set up to output debugging during boot, you will eventually see a system property dump like this:



06:34:04,070 INFO [ServerInfo] Java version: 1.6.0_0,Sun Microsystems Inc.
06:34:04,071 INFO [ServerInfo] Java Runtime: OpenJDK Runtime Environment (build 1.6.0_0-b14)
06:34:04,072 INFO [ServerInfo] Java VM: OpenJDK Client VM 14.0-b08,Sun Microsystems Inc.
06:34:04,072 INFO [ServerInfo] OS-System: Linux 2.6.29.4-167.fc11.i686.PAE,i386
06:34:04,074 DEBUG [ServerInfo] Full System Properties Dump
06:34:04,075 DEBUG [ServerInfo] java.vendor: Sun Microsystems Inc.
06:34:04,076 DEBUG [ServerInfo] sun.java.launcher: SUN_STANDARD
06:34:04,076 DEBUG [ServerInfo] sun.management.compiler: HotSpot Client Compiler
06:34:04,076 DEBUG [ServerInfo] os.name: Linux
06:34:04,076 DEBUG [ServerInfo] user.name: jboss
06:34:04,076 DEBUG [ServerInfo] jboss.bind.address: 192.168.1.252
06:34:04,076 DEBUG [ServerInfo] jboss.home.dir: /jboss/jboss-5.1.0.GA
06:34:04,076 DEBUG [ServerInfo] jboss.home.url: file:/jboss/jboss-5.1.0.GA/

06:34:04,076 DEBUG [ServerInfo] java.version: 1.6.0_0
06:34:04,076 DEBUG [ServerInfo] jboss.server.home.dir: /jboss/jboss-5.1.0.GA/server/standard
06:34:04,077 DEBUG [ServerInfo] jboss.server.home.url: file:/jboss/jboss-5.1.0.GA/server/standard/
06:34:04,077 DEBUG [ServerInfo] jboss.server.config.url: file:/jboss/jboss-5.1.0.GA/server/standard/conf/

06:34:04,077 DEBUG [ServerInfo] jboss.common.lib.url: file:/jboss/jboss-5.1.0.GA/common/lib/
06:34:04,078 DEBUG [ServerInfo] java.home: /usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0/jre
06:34:04,078 DEBUG [ServerInfo] java.endorsed.dirs: /jboss/jboss-5.1.0.GA/lib/endorsed*
06:34:04,079 DEBUG [ServerInfo] jboss.lib.url: file:/jboss/jboss-5.1.0.GA/lib/
06:34:04,079 DEBUG [ServerInfo] bind.address: 192.168.1.252
06:34:04,080 DEBUG [ServerInfo] jboss.server.temp.dir: /jboss/jboss-5.1.0.GA/server/standard/tmp
06:34:04,080 DEBUG [ServerInfo] user.home: /home/jboss
06:34:04,080 DEBUG [ServerInfo] jboss.common.base.url: file:/jboss/jboss-5.1.0.GA/common/
06:34:04,080 DEBUG [ServerInfo] jboss.server.log.dir: /jboss/jboss-5.1.0.GA/server/standard/log
06:34:04,081 DEBUG [ServerInfo] java.io.tmpdir: /tmp
06:34:04,081 DEBUG [ServerInfo] jboss.server.data.dir: /jboss/jboss-5.1.0.GA/server/standard/data
06:34:04,081 DEBUG [ServerInfo] java.rmi.server.hostname: 192.168.1.252
06:34:04,082 DEBUG [ServerInfo] user.dir: /jboss/jboss-5.1.0.GA/bin
06:34:04,082 DEBUG [ServerInfo] java.vm.name: OpenJDK Client VM
06:34:04,082 DEBUG [ServerInfo] jboss.server.base.dir: /jboss/jboss-5.1.0.GA/server
06:34:04,082 DEBUG [ServerInfo] jboss.server.base.url: file:/jboss/jboss-5.1.0.GA/server/
06:34:04,082 DEBUG [ServerInfo] file.encoding: UTF-8
06:34:04,082 DEBUG [ServerInfo] jboss.server.name: standard


Note the bolded entries. You can access these properties by saying something like this:

String serverConfUrl = System.getProperty("jboss.server.config.url")

A more complete solution that would check the server conf directory before loading the bundled properties could look something like this:

String propertiesFileName = "application.properties";

Properties props = new Properties();
String path = System.getProperty("jboss.server.config.url")+propertiesFileName;
URL url = new URL(path);

if(new File(url.toURI()).exists()) {
	props.load(url.openStream());
	log.info("loaded application properties from file: " + path);
} else {
	props.load(MyClass.class.getResourceAsStream("/" + propertiesFileName));
	log.info("loaded application properties: /"+propertiesFileName);
}

There you have it. An easy to use environment specific properties definition strategy with bundled fail over defaults. Try saying that three times.

External deploy directories in JBoss

Why not use the default jboss deploy directory?

Out of the box, jboss has a bunch of .sar, .war, and .jar deployment artifacts as well as a bunch of xml files in the default deploy directory (whose path is “jboss-install-dir/server/configured-server-instance/deploy”). For the sake of being neat and cautious, I prefer to break out any deployment artifacts that are constantly in development to a separate external directory where I would never be able to “accidentally” delete all the other important configuration files required by jboss to run. Something like that never happened to me, but a friend. Yeah, a friend. About the only thing I feel ok with leaving in the default deploy directory are the “-ds” files that map the database configurations for the instance. These database settings rarely if ever change so it abides by the “deploy moving targets to an external directory” school of thought.

Ok, I want to deploy and external directory. How do I set it up?

Well, the answer depends on which version of JBoss you are running. In general, the process is twofold: first we’ll want to locate the deployment folder configuration and then add our own entry to the list of directories JBoss inspects for deployable artifacts. If we hardcode this location, we won’t need a second step. If we want this external directory to be parameterized though, we’ll need to make sure the edits we make to the configuration match the input parameter’s name for substitution.

JBoss 5.1

Open up the profile.xml file:

[root@bedrock ~]# vim /jboss-root/server/instance/conf/bootstrap/profile.xml

You’re going to want to add a line like the following:

<bean name="BootstrapProfileFactory" 
class="org.jboss.system.server.profileservice.repository.StaticProfileFactory">
...
<property name="applicationURIs">
	<list elementClass="java.net.URI">
		<value>${jboss.server.home.url}/deploy</value>
		<value>file:/c:/external/location/deploy/directory/path</value>
		<value>${external.deploy.dir}/deploy</value>
	</list>
</property>
...
</bean>

You’ll notice the two ant script like looking variables in the list. The first one ${jboss.server.home.url}, declares the JBoss server’s default deploy location. The other one ${external.deploy.dir}, is a parameterized version of an externalized deploy directory. If you use this second style, you’ll need to make sure to pass in a parameter in the format “-Dexternal.deploy.dir=file:/c:/external/location”. This will pass in the value so the substitution will provide a fully qualified URL to scan for deployments. Note, however if the parameterized version does not satisfy a reachable location, JBoss will continuously attempt to deploy that location if you have hot deploy and/or deployment scanner enabled (these services will attempt to periodically attempt to scan deployment directories for new deployments).

Save the file, and fire up jboss, and you’re good to go.

Set up Jboss 5.1 as a service

Run JBoss not as root

First off, you’ll need to add a user named jboss to your system. Do this so you wont have to run jboss as root. Running anything as root is usually dangerous and is usually never recommended. Its very easy to break stuff if you don’t know what you’re doing. To add jboss to the sudoers file, open it by doing the following:

[root@bedrock ~]# vi /etc/sudoers

Scroll down some then add this entry somewhere near where the root user is listed:

## Services
Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig
...
...
...
## Allow root to run any commands anywhere
root    ALL=(ALL) ALL
jboss   ALL = NOPASSWD: SERVICES

This essentially allows the jboss user to run any command listed as the SERVICE command alias (as shown above).

Make changes to the red had startup script “jboss_init_red_hat.sh” found in the jboss/bin directory.

You’ll want to edit some relevant variables like JBOSS_HOME and JBOSS_BIND to fit your actual setup. by default jboss will bind to 127.0.0.1 (localhost), if you’re setting up a server that you want to listen to every possible url, you want it to bind to 0.0.0.0, otherwise, bind it to the url you want:

-b some.domain.com
-b 0.0.0.0
-b 127.0.0.1

Lets start off with the red hat script and start making some changes:

[root@bedrock ~]# vi jboss_install_directory/bin/jboss_init_red_hat.sh

#define where jboss is - this is the directory 
#containing directories log, bin, conf etc
JBOSS_HOME=${JBOSS_HOME:-"/server/jboss"}

#define the user under which jboss will run, or use 
#'RUNASIS' to run as the current user
JBOSS_USER=${JBOSS_USER:-"RUNASIS"}

#make sure java is in your path
JAVAPTH=${JAVAPTH:-"/usr/lib/jvm/jre/bin"}

#configuration to use, usually one of 'minimal', 'default', 'all'
JBOSS_CONF=${JBOSS_CONF:-"services"}

#if JBOSS_HOST specified, use -b to bind jboss services to that address
JBOSS_BIND_ADDR=${JBOSS_BIND_ADDR:-"-b 0.0.0.0"}

I also made some changes so the server.log file is renamed with a time stamp so when jboss fires up its free to create a new server.log file:

case "$1" in
start)

    echo JBOSS_CMD_START = $JBOSS_CMD_START

    echo "moving old log file to server.log.$(date +%Y-%m-%d-%H%M%S)"
    mv "$JBOSS_LOG_DIR/server.log" 
    	"$JBOSS_LOG_DIR/server.log.$(date +%Y-%m-%d-%H%M%S)"

    cd $JBOSS_HOME/bin

...

Once you’re done, you’ll probably want to set this up s a service daemon so it will always be running. add the chkconfig metadata at the top of jboss_init_red_hat.sh in comments

# chkconfig: - 35 64 36
# description: Starts and stops the jboss backend daemon that handles 
#              all database requests.
# processname: jboss

Then you’ll want to save the file as /etc/init.d/jboss and fix permissions and ownership. you’ll want it to be owned by root, and give it 0755 permissions to make it look like everyone else in that init.d folder. then run chckconfig to add it to the service list. The full script I’m using right now is linked at the end of this article.

[root@bedrock ~]# chkconfig –add jboss

run the jboss service.

[root@bedrock ~]# service jboss start

finally, make sure its listening off the right bind address.

[root@bedrock ~]# netstat -ntalp | grep java

...
tcp      0      0 0.0.0.0:8080        0.0.0.0:*       LISTEN      1894/java
...

JBoss will add other entries, not just this one but this particular line means some java proc (must be jboss) is bound to the 8080 port, which is means our jboss is up and running.

if you’ve set up the iptable firewall rules to listen in on port 8080, you should be good to go.

Resources:
The complete service script can be found here