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.
Related posts:
3:24 am, February 19, 2010Bharat Kumar Patel /
Hi
I have facing a problem with a webapplication, I am using JBoss 5.0. In my web application I want to load a xsl file to make some conversion, however, when I place the file in JBoss/default/conf dir I am unable to create a File object. I am using Maven. I am able to access the file if I place the file in jboss home. but not anywhere else. could you provide me a solution. I have follow the steps that you have given above but unfortunately it does not work. After some RD I think there is some security issue with JBoss and Java that the file is gettting locked in conf dir.
Thanks in advance
10:09 am, February 19, 2010Ant /
Hi Bharat,
Thanks for the question. In order to be able to write a file to any directory you must have the appropriate permissions. It sounds from your description that you might be running on linux and as the jboss user. This would mean you would automatically have “write” permissions on any files that jboss owns, like the jboss home directory. Check the permissions on your jboss install, if the jboss user is not the owner of the entire tree structure, you will run into file write permissions. One common thing is if jboss was installed as root and then run as jboss, jboss won’t have write permissions on the directory since the jboss user wont have as many permissions as root.
Actually, I think i misunderstood your question. If you are trying to “read” the file, but not letting you it sounds like its still some kind of OS/permissions related kind of thing. The same concept I just mentioned above still applies. In order for jboss to act on a file structure it needs to have the right permissions. In the “read” case, it needs “read”. If you’re on linux, it might help to try and set chmod on the tree structure to 0777/ugo=rwx. If you’re on windows, try setting read/write permissions to allow everyone. Then go back and limit permissions as necessary.
Usually, its not very useful to write to the conf directory anyway. You might want to create a separate directory unrelated to the jboss install in case you end up upgrading to a different version of jboss in the future. I would usually create a directory in the base of the disk drive with a path something like this:
/public/jboss/files
This way when you upgrade jboss, you wont have to reference a file structure tied to an outdated version of jboss.
Hope this helps.
2:24 pm, August 4, 2010ps /
SO can a solution like this be used for accessing JSP, and other files outside of JBoss deployment? I am facing an issue where all my JSPs /javascripts are in an outside location to jBoss deployment. But jboss cannot pick them based on relative paths. Right now I am having to cop with creating symlinks. Any thoughts?
3:16 pm, August 4, 2010Ant /
It sounds like you’re trying to include files local to the OS’s file system as linked files in your jsp or html files. Are they images, javascript files, or compile required jsps? These items would normally be packaged as part of the deployed artifact’s war file, and should not be accessed through the local OS’s filesystem
So the simple answer is: no. Not unless you want to load the jsp file into a java 1.6 dynamic compiler object, and compile all your jsp code yourself and then somehow hook into jboss’ servlet container framework so you can persist the compiled servlet. The method in this article gives you access to a directory, from which you can load items into a File object. This works well for reading into a Properties object, but not so much for compiling jsps.
In a nutshell if you end up needing to go outside the web application’s space, into say, a local /www httpd web directory, prefer the fully qualified local server/hostname instead of using the internal file structure of your OS. By trying to use the local file system instead of a dedicated web server, your application will collapse under load. Web servers are meant to handle much heavier stress than the OS’s file system – symbolic links included, as web servers implement much more rigorous caching mechanisms and access time saving techniques. You might also be breaking the j2ee paradigms by making your application installed base dependant, not making it easy to deploy into a new environment.
Can you describe your environment a little more? Its unusual that you’d have to stick all your jsps and resources somewhere other than a war file. There is definitely a better way than having to resort to symbolic links.
11:01 pm, August 4, 2010ps /
Well, I replaced JRun with jboss and added Apache mod_jk in the front to serve multiple jboss configs. The existing structure was that JSPs and JS files were kept in a storage location outside of deployment.
Jrun has a Apache module, so when Apache recieves a JSP request, it forwards it to jRun, which can pick it up from an outside storage structure and serve it simply based on a web.xml mapping (of relative paths)
Now, it seems to me, Apache mod_jk is serving relative paths and JBoss web cannot make sense of the path by looking at the web.xml. I looked at adding virtual directory definitions as part of Tomcat context, but JBoss 5.1.0 does not support it.
At this point, my option does not include redoing the existing structure or bringing files into the WAR.
How would I make Apache or JBoss serve/understand the real path and pick files up? I wld love to get rid of these symlinks.
12:32 am, August 5, 2010Ant /
OK – I think i understand what’s going on. Correct me if I’m wrong: you’re using jrun-web.xml to configure your web application using virtual-mapping as described in this problem:
http://community.jboss.org/message/192491#192491
and as described in JRun’s “jrun-web.xml” documentation here:
http://www.adobe.com/livedocs/jrun/4/Assembly_and_Deployment_Guide/descriptors4.htm
There is a major different between web.xml and jrun-web.xml in that web.xml is server/vendor implementation agnostic and will thus deploy in any j2ee compliant server while jrun-web.xml is much like jboss-web.xml, and weblogic.xml in that they are vendor specific deployment descriptors and are therefore unusable on any other app servers. It’s like trying to speak Korean to an Icelandic person, they won’t understand what’s being described by the descriptors.
It appears from that unanswered JBoss post that it has never been addressed. The use of virtual-mapping is not part of the j2ee standard, and is therefore not implemented in JBoss. It appears the closest thing you can do is configure a jboss external directory as a context as described in this article:
http://community.jboss.org/wiki/ExternalDirectories
Essentially you end up creating a mapped context to a local directory. I think this still takes the compilation of JSPs off the table as there is no way for JBoss to dynamically load in those files and compile them into servlets.
Its important to know a little bit about how jboss works with deployments – JBoss takes each deployable artifact and copies them into the instance/tmp directory. As JBoss loads them into the instance/tmp directory they all get loaded into ram and if configured to auto detect file updates, will reload the modified file on demand. JSPs are a litlte different – these guys are read in and compiled into servlet code and then written to disk in the instance/work directory, one folder for every mapped domain served by the instance. In order for external JSP directories to work as they do in the JRun implementation there would need to be some kind of connector that would snap on to the web.xml parsing engine which would figure out how to load local configured directories into the JBoss servlet container – compiling those jsps and then saving them into that instance/work directory. Such a connector does not exist as far as I know.
5:05 pm, August 5, 2010ps /
Yes, I think your what you say is correct. It the connector which does it. But then I dont understand how to achieve this in jBoss. Any thoughts would be very helpful
6:17 pm, August 5, 2010Ant /
Unfortunately there is no direct equivalent in JBoss. The closest you can get is a hosted contextual mapping to a local directory as explained in this article: http://community.jboss.org/wiki/ExternalDirectories, but it will only serve up static content, no jsps or dynamically compiled resources. One purpose of the j2ee spec is to formulate some kind of standard so that multiple vendors can deploy a standard enterprise application and you can migrate. If your application uses custom descriptors however, you roll the dice if you ever want to explore the idea of migrating to a different vendor. That’s the choice you end up with – either stick to the standards or risk locking yourself into a single vendor’s platform. I’ve been in your situation before, and I’ve been burned before by it so I tend to lean towards using the standard.
12:25 am, September 27, 2011uday kiran reddy /
hi
i am using j-boss 3.2.8 and unable to load images located in a folder out side jboss on to html even after configuring j-boss properties can any one give me some idea
and one more thing is that i am going to add images to this folder in run time
1:16 am, September 27, 2011Ant /
If I understand your question correctly, you generally don’t want to do this kind of file IO yourself. J2EE deployment folders are meant to block access to the filesystem directly because it breaks application portability – so you can’t access an images file in a folder outside of your deployment via a URL through the server on purpose. You might be able to create an external empty war deployment, and work it that way but you’re still working within a deployable artifact attached to a context. I’d recommend taking a look at something like webdav to offload images to an exterior non deployment dependent location. I should mention that jboss 3.2.8 is way out of date – 7 is out and sticking with 3.x… Well – it’d definitely be worth trying your deployment on 7 and seeing what breaks. If you’ve done it right your deployments should be minimally impacted. Stick as closely as you can to the specs so server upgrades don’t break your application.
2:44 am, September 27, 2011uday kiran reddy /
i am first time visiting this forum and thanks a lot for above mentioned link it helped me a lot
http://community.jboss.org/wiki/ExternalDirectories
in detail 20 days of my searching came to an end
8:11 am, September 27, 2011uday kiran reddy /
@Ant
hi ant ,thanks for u r valuable information we are about to change version of our j boss soon
and coming to my case i dont know wether i am going in right way or not my complete senario is like this
i need to show images on html for that i am getting them from db and saving them on a location on j-boss …..jboss-3.2.8.SP1\server\*\* and for showing it on html i added that location at deploy\jbossweb-tomcat50.sar\server.xml
at context tag along with some path (/images) and giving that path to html dynamically using setsrc method of dom.html.imageelement and every thing is working fine for now and i am restricted from using url tags so planned this way
plz let me know in detail as i am only 10months old in industry
hardly
Thanks in advance