1 Reply Latest reply on Apr 12, 2005 10:54 AM by errant01

    Problem changing Log4j config without restart

    errant01

      I have no idea where best to post this question , so I'll post it here.

      I have multiple applications running on one appserver instance. Each one of these requires its own log4j config. To accomplish this, I've subclassed RepositorySelector as below to be able to use different configs for different contexts.

      I'm trying to enable dynamic reloading of the log4j config. Log4j supposedly supports this with the Configurator.configureAndWatch() method. However, the API is not available for DOM objects coupled with the RepositorySelector extension. So, I exposed the config loading code to a servlet call (not very secure, but sufficient for the immediate term).

      Here's the problem. When the config info is reloaded, it does not actually replace the old config in the jboss memory structures. So, where is the log4j config being stored in jboss? Is it a bug that its not replacing the config? If not, is there a facility for getting around this, or even a suggested hack?

      Thanks for your help.



      /**
      * This RepositorySelector is for use with web applications. It assumes that
      * your log4j.xml file is in the WEB-INF directory.
      *
      * The essentials are that this RepositorySelector replaces the standard one. This one maintains
      * a hashmap of LoggerRepositories keyed by context ClassLoader. Each web app should have
      * a different ClassLoader. If the classloader asking for a repository is not one of the ones
      * stored in the hashmap, then the std default jboss one is returned.
      *
      * @author Stan Silvert (original)
      */
      public class RDRepositorySelector implements RepositorySelector
      {
      private static boolean initialized = false;
      private static Object guard = new Object();

      private static Map repositories = new HashMap();
      private static LoggerRepository defaultRepository;

      /**
      * Register your web-app with this repository selector.
      */
      public static synchronized void init(ServletConfig config)
      throws ServletException {

      loadLog4j(config.getServletContext());
      }

      public static void loadLog4j (ServletContext ctx) throws ServletException {
      if( !initialized ) // set the global RepositorySelector
      {
      defaultRepository = LogManager.getLoggerRepository();
      RepositorySelector theSelector = new RDRepositorySelector();
      LogManager.setRepositorySelector(theSelector, guard);
      initialized = true;
      }
      Hierarchy hierarchy = new Hierarchy(new RootCategory(Level.DEBUG));
      loadLog4JConfig(ctx, hierarchy);
      ClassLoader loader = Thread.currentThread().getContextClassLoader();
      repositories.put(loader, hierarchy);
      }

      // load log4j.xml from WEB-INF
      private static void loadLog4JConfig(ServletContext ctx,
      Hierarchy hierarchy)
      throws ServletException {
      try {
      String log4jFile = "/WEB-INF/log4j.xml";

      // Original method of getting stream as ByteArrayInputStream
      // InputStream log4JConfig =
      // ctx.getResourceAsStream(log4jFile);

      // Getting InputStream from file directly instead of thru resource loader.
      String log4jPath = ctx.getRealPath(log4jFile);
      InputStream log4JConfig =
      new FileInputStream(log4jPath);

      Document doc = DocumentBuilderFactory.newInstance()
      .newDocumentBuilder()
      .parse(log4JConfig);
      DOMConfigurator conf = new DOMConfigurator();
      conf.doConfigure(doc.getDocumentElement(), hierarchy);
      } catch (Exception e) {
      throw new ServletException(e);
      }
      }

      private RDRepositorySelector() {
      }

      public LoggerRepository getLoggerRepository() {
      ClassLoader loader = Thread.currentThread().getContextClassLoader();

      // get repository from hashmap
      LoggerRepository repository = (LoggerRepository)repositories.get(loader);

      if (repository == null) {
      return defaultRepository;
      } else {
      return repository;
      }
      }
      }