Search code examples
javatomcatjboss5.xapache-commons-config

Cannot save to commons config in JBoss 5.1


I am writing a web application that uses Apache Commons config to read/write a system.properties file. The file itself is placed in WEB-INF/classes/config. Reading is no problem, and I can write to it when I deploy using Apache Tomcat. When I deploy the application using JBoss, however, I cannot write (using cofig.setProperty(...). I get the following error (JBoss only):

2012-01-06 12:53:48,879 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/flint].[flint]] (http-0.0.0.0-8080-1) Servlet.service() for servlet flint threw exception
java.net.UnknownServiceException: protocol doesn't support output
        at java.net.URLConnection.getOutputStream(URLConnection.java:792)
        at org.apache.commons.configuration.AbstractFileConfiguration.save(AbstractFileConfiguration.java:449)
        at org.apache.commons.configuration.AbstractFileConfiguration.save(AbstractFileConfiguration.java:377)
        at org.apache.commons.configuration.AbstractFileConfiguration.possiblySave(AbstractFileConfiguration.java:750)
        at org.apache.commons.configuration.AbstractFileConfiguration.clearProperty(AbstractFileConfiguration.java:789)
        at org.apache.commons.configuration.AbstractConfiguration.setProperty(AbstractConfiguration.java:481)
        at org.apache.commons.configuration.AbstractFileConfiguration.setProperty(AbstractFileConfiguration.java:782)
        at com.talecris.flint.server.config.SystemConfiguration.setResultInvalidColor(SystemConfiguration.java:571)
        at com.talecris.flint.controller.SystemAdminController.setSystemColors(SystemAdminController.java:496)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
        at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)

As I said, it all works fine in Tomcat. The system.properties permissions look fine (owner=Jboss). I even opened the permissions up to rw for everyone just to test, but I still get the same error. Is there some JBoss setting that is preventing my application from writing to the path in which it is deployed?

I can write files and subfolders to the deployment directory, but I cannot write changes to system.properties (via apache commons config).


Solution

  • The problem had to do with using VFSFileChangedReloadingStrategy when on JBoss.

    Here's a problem that frustrated me for a bit: When using Apache Commons Configuration under JBoss 5, I kept running into the following error when attempting to save to my configuration file (which was a resource under the deployed /classes path):

    ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/xxxx].[xxxx]] (http-0.0.0.0-8080-1) Servlet.service() for servlet flint threw exception java.net.UnknownServiceException: protocol doesn't support output at java.net.URLConnection.getOutputStream(URLConnection.java:792) at org.apache.commons.configuration.AbstractFileConfiguration.save(AbstractFileConfiguration.java:449)

    What the heck? This error happened every time I attempted to save to my configuration file. It worked fine in Tomcat 6.x, but any time I tested on JBoss, while I could read from the configuration file, the above error was thrown every time I attempted to write to it.

    JBoss 5.x VFS (virtual file abstraction) for the files that it deploys, and this causes problems with Commons Config's default FileChangedReloadingStrategy. So the fix is to do something like this instead:

    VFSFileChangedReloadingStrategy f = VFSFileChangedReloadingStrategy(); ((FileConfiguration) config).setReloadingStrategy(f);

    It turns out that we really want to use VFSFileChangedReloadingStrategy (which means using Apache Commons Config 1.7) . This also requires that the Apache Commons VFS API be on your classpath. The good news is that VFSFileChangedReloadingStrategy works well even with non-VFS deployments (i.e. plain old Tomcat and Jetty). Problem solved!