Blog

JMX und WebSphere Application Server 5

Meindert Deen

Aktualisiert Oktober 23, 2025
8 Minuten
Die Java Management eXtensions sind sehr gut geeignet, um das Verhalten Ihrer Anwendung dynamisch zu verändern. Die JMX-API ist in Java 5 Standard, aber wenn Sie mit einer alten Version arbeiten, müssen Sie eine eigene entwickeln oder eine vorhandene API verwenden. In WAS 5 können Sie die WebSphere API problemlos integrieren. In diesem Beitrag wird beschrieben, wie Sie das tun können. Ich werde dies anhand eines Beispiels tun, wie Sie eine JMX Managed Log4J Konfiguration in WAS 5 erhalten. Die Integration in WAS 5 erfolgt, indem Sie eine XML-Beschreibung Ihrer verwalteten Bohne (MBean) erstellen und die Implementierung von com.ibm.websphere.management.RuntimeCollaborator erweitern lassen. Die implementierende Klasse muss die Methoden enthalten, die in der XML definiert sind. Die XML muss auf der MbeanDescriptor.dtd (im Anhang) basieren und kann MBeans mit Attributen, Operationen und Benachrichtigungen enthalten.
  • Ein Attribut ist eine schreibgeschützte Information, auf die über die MBean zugegriffen werden kann.
  • Eine Operation ist auf der MBean aufrufbar
  • Eine Benachrichtigung ist ein Ereignis, das von der MBean ausgelöst wird
Die Logging MBean besteht aus drei Attributen und einer Operation:
  1. Attribut: version (die log4j-Version)
  2. Attribut: aktuelle Logger (alle aktuellen Log4j-Logger)
  3. Attribut: identification (Der Name des Root-Loggers)
  4. Operation: reload (Laden Sie die Logging-Konfigurationsdatei neu)
Das XML der MBean:




    
    
    
    
        
        
    

Und die Umsetzung:

import com.ibm.websphere.management.RuntimeCollaborator;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.xml.DOMConfigurator;
import java.net.URL;
import java.util.Enumeration;
public class LoggingCollaborator extends RuntimeCollaborator {
  private Logger logger;
  private URL configurationLocation;
  private static final Logger LOG = Logger.getLogger(LoggingCollaborator.class);
  public LoggingCollaborator(Logger root, URL configurationLocation) {
  if (root == null) {
  throw new IllegalArgumentException("root logger darf nicht null sein.");
  } sonst {
  logger = root;
  }
  if (configurationLocation == null) {
  throw new IllegalArgumentException("configurationLocation darf nicht null sein.");
  } sonst {
  this.configurationLocation = configurationLocation;
  }
  }
  public String getIdentification() {
  if (LOG.isDebugEnabled())
  LOG.debug("Identifikation holen " + logger.getName());
  return logger.getName();
  }
  public String getCurrentLoggers() {
  StringBuffer loggers = new StringBuffer(200);
  Enumeration enum = LogManager.getCurrentLoggers();
  boolean first = true;
  while (enum.hasMoreElements()) {
  Logger log = (Logger) enum.nextElement();
  wenn (zuerst)
  first = false;
  sonst
  loggers.append(", ");
  loggers.append(log.getName());
  if (log.getEffectiveLevel() != null)
  loggers.append("=").append(log.getEffectiveLevel());
  }
  return loggers.toString();
  }
  public String getVersion() {
  return LogManager.class.getPackage().getImplementationVersion();
  }
  public void reload() throws NamingException {
  LOG.info("Konfigurationsdatei über URL neu laden: " + configurationLocation ");
  new DOMConfigurator().doConfigure(configurationLocation, logger.getLoggerRepository());
  LOG.info("Konfigurations-URL: " + configurationLocation + " wird neu geladen");
  }
}
Wir haben jetzt eine MBean-Beschreibung und ihre Implementierung. Die Implementierung benötigt den Speicherort der log4j.xml und den Root-Logger in ihrem Konstruktor, um zu funktionieren. Damit WAS weiß, dass wir eine benutzerdefinierte MBean haben, müssen wir die MBean in WAS registrieren. Dies kann auf verschiedene Weise geschehen: Die Bean kann im Abschnitt "Extension MBean Providers" eines WAS-Servers in der Admin-Konsole definiert werden (siehe Ref. 3) und sie kann automatisch beim Start des Servers gestartet werden. (siehe Referenz 3). Da Log4j (zumindest bei mir) auf Anwendungsbasis und nicht auf Serverbasis funktioniert, werde ich es etwas anders machen. Ich werde die MBean programmatisch registrieren und die XML-Beschreibung im Klassenpfad der Anwendung ablegen. (Ein Wort der Warnung: Die von der Anwendung bereitgestellte MBean-XML ergibt für den Server definierte "Extension MBean Providers" mit normalem Classloading: "PARENT_FIRST". Um die MBean zu registrieren, verwende ich einen ServletContextListener (die vollständige Klassenimplementierung finden Sie am Ende dieses Blogs), den ich in der web.xml meiner Webanwendung definiere, so dass die MBean beim Starten meiner Anwendung registriert wird und ich sie beim Beenden meiner Anwendung wieder abmelden kann.

private void startJMXLog4j(String applicationName, URL configurationURL) {
  // Initialisieren Sie die MBean
  MBeanFactory factory = AdminServiceFactory.getMBeanFactory();
  LoggingCollaborator collab = new LoggingCollaborator(LogManager.getRootLogger(), configurationURL);
  String loggingMBeanName = applicationName + "LoggingMBean";
  Logger logger = Logger.getLogger(Log4JInitializer.class);
  logger.info("Aktiviere MBean mit Namen [" + loggingMBeanName
  + "] in der Klasse handle [" + getClass().hashCode()
  + "] für Version "
  + LogManager.class.getPackage().getImplementationVersion());
  versuchen {
  ObjectName foundName = factory.findMBean(loggingMBeanName);
  logger.info("Name " + loggingMBeanName
  + " bereits existiert, deaktivieren Sie es jetzt ....");
  factory.deactivateMBean(foundName);
  if (logger.isDebugEnabled()) {
  logger.debug("Deaktivierte MBean mit Namen " + applicationName + ".");
  }
  } catch (InstanceNotFoundException e1) {
  logger.debug("Keine Instanz gefunden für Name " + Anwendungsname);
  } catch (AdminException e) {
  logger.error("Fehler beim Deaktivieren der Bean, es wird versucht, eine neue Bean mit dem Namen " + applicationName, e) hinzuzufügen;
  }
  versuchen {
  ObjectName objName = factory.activateMBean(LOGGING_TYPE, collab, loggingMBeanName, LOGGING_XML_CONFIG);
  logger.info("Die mbean wurde dem Server hinzugefügt, objectName=[" + objName + "]");
  } catch (AdminException e) {
  if (e.getCause() instanceof InstanceAlreadyExistsException) {
  logger.error("Instanz existiert bereits für " + loggingMBeanName + ", Entfernung muss fehlgeschlagen sein.");
  }
  logger.error("Exception activating MBean for " + loggingMBeanName, e);
  e.printStackTrace();
  throw new IllegalStateException(e.toString());
  }
}
Und nun gibt es eine funktionierende MBean-Erweiterung. Um die MBean zu manipulieren, können wir die Anwendung wsadmin verwenden. Die folgenden JACL-Befehle können verwendet werden (dies ist eine Teilmenge): [code] # Holen Sie sich alle Logger set loggers [$AdminControl queryNames type=Log4JLogger,*] # Holen Sie sich das erste Log set log [lindex $loggers 0] # Holen Sie sich alle Attribute des Logs $AdminControl getAttributes $log # Laden Sie das Logging des Logs neu $AdminControl invoke $log reload {} [/code] Referenzen:
  1. JMX Erläuterung
  2. MBean Erklärung
  3. Developerwork Tutorial
Vollständige ServletContextListener-Klasse:

import java.net.URL;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.ObjectName;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.xml.DOMConfigurator;
importieren Sie LoggingCollaborator;
import com.ibm.websphere.management.AdminServiceFactory;
import com.ibm.websphere.management.MBeanFactory;
import com.ibm.websphere.management.exception.AdminException;
/**
* Der ServletContextListener initialisiert die Log4J-Konfiguration mit einer URL von
  * das JNDI-Repository und startet eine JMX-MBean, um dynamische Änderungen an der
  * Log4J-Konfiguration.
  */
public class Log4JInitializer implements ServletContextListener {
  private static final String LOGGING_XML_CONFIG = "LoggingMBean.xml";
  private static final String LOGGING_TYPE = "Logger";
 
/**
  * Loggername zur Überprüfung, ob die Protokollierung bereits initialisiert ist
  */
  private static final String LOGGING_INITIALIZED_KEY = "INITIALIZED";
 
/**
  * Anwendungsname für diese Instanz
  */
  private String applicationName;
 
/**
  * Erweiterung des Anwendungsnamens für diese Instanz
  */
  private static final String LOGGING_MBEAN_NAME_EXTENSION = "LoggingMBean";
 
/**
  * Initialisieren Sie Log4J mit einem Serice-Anbieter für den Anwendungsnamen und initialisieren Sie die mBean
  *
  * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
  */
  public void contextInitialized(ServletContextEvent event) {
  LogLog.debug("Log4JInitializer wird initialisiert");
  Logger existingLog = LogManager.exists(LOGGING_INITIALIZED_KEY);
  if (existingLog != null) {
  existingLog
  .info("Die Protokollierung ist bereits initialisiert. Sie wird nicht erneut initialisiert");
  zurück;
  }
  versuchen {
  // Wenn Sie den Anwendungsnamen abrufen, kann es zu einer Exception kommen.
  Anwendungsname = Anwendungsname.getAnwendungsname();
  } catch (Throwable e) {
  // Listener zeigen keine Stack Traces in WAS an. Verwenden Sie LogLog 
  LogLog
  .error(
  "Log4JInitializer - Fehler beim Abrufen des Anwendungsnamens aufgrund von ERROR",
  e);
  throw new IllegalStateException(
  "Es konnte kein ApplicationName-Anbieter gefunden werden, die Protokollierung konnte nicht gestartet werden. Ursache: "
  + e.getMessage());
  }
  LogLog.debug("Log4JInitializer - Anwendungsname gefunden ist: "
  + applicationName);
  if (anwendungsname == null || anwendungsname.trim().length() == 0) {
  String msg = "Anwendungsname nicht im Anbieter gefunden";
  LogLog.error("Log4JInitializer - " + msg);
  throw new IllegalStateException(msg);
  }
  // Abrufen der URL zur Log4J-Konfiguration aus JNDI
  String jndiName = "url/config/" + applicationName + "/log4j";
  LogLog.debug("Log4JInitializer - Lookup von jndi Name " + jndiName);
  versuchen {
  DefaultServiceLocator locator = new DefaultServiceLocator(); // Hilfsklasse, die den JNDI-Aufruf kapselt
  URL url = locator.getURL(jndiName);
  LogLog.debug("Log4JInitializer - Url gefunden " + url
  + ", Log4j jetzt konfigurieren.");
  DOMConfigurator.configure(url);
  startJMXLog4j(Anwendungsname, url);
  } catch (ServiceLocatorException e) {
  String msg = "Abruf der URL von jndi " + jndiName
  + " schlug mit Fehler fehl: " + e.getLocalizedMessage();
  LogLog.error("Log4JInitializer - " + msg, e);
  throw new IllegalStateException(msg);
  }
  // Die Protokollierung wird initialisiert Registrieren Sie den INITIALIZED KEY bei Log4j
  existingLog = Logger.getLogger(LOGGING_INITIALIZED_KEY);
  existingLog.info("Die Protokollierung ist initialisiert");
  LogLog.debug("Log4JInitializer - Log4J wird jetzt initialisiert");
  }
 
/**
  * Starten Sie eine Log4J mBean für die aktuelle Anwendung.
  *
  * @param applicationName
  * @param URL configurationURL
  */
  private void startJMXLog4j(String applicationName, URL configurationURL) {
  // Initialisieren Sie die mBean
  MBeanFactory factory = AdminServiceFactory.getMBeanFactory();
  LoggingCollaborator collab = new LoggingCollaborator(LogManager
  .getRootLogger(), configurationURL);
  String loggingMBeanName = applicationName + "LoggingMBean";
  Logger logger = Logger.getLogger(Log4JInitializer.class);
  logger.info("Aktiviere MBean mit Namen [" + loggingMBeanName
  + "] in Klasse handle [" + getClass().hashCode()
  + "] für Version "
  + LogManager.class.getPackage().getImplementationVersion());
  versuchen {
  ObjectName foundName = factory.findMBean(loggingMBeanName);
  logger.info("Name " + loggingMBeanName
  + " bereits existiert, deaktivieren Sie es jetzt ....");
  factory.deactivateMBean(foundName);
  if (logger.isDebugEnabled())
  logger.debug("Deaktivierte MBean mit Name " + AnwendungsName
  + ".");
  } catch (InstanceNotFoundException e1) {
  logger.debug("Keine Instanz gefunden für Name " + Anwendungsname);
  } catch (AdminException e) {
  logger.error(
  "Fehler beim Deaktivieren der Bean, wird versuchen, eine neue mit dem Namen " hinzuzufügen
  + applicationName, e);
  }
  versuchen {
  ObjectName objName = factory.activateMBean(LOGGING_TYPE, collab,
  loggingMBeanName, LOGGING_XML_CONFIG);
  logger.info("Die mbean wurde dem Server hinzugefügt, objectName=[" + objName
  + "]");
  } catch (AdminException e) {
  if (e.getCause() instanceof InstanceAlreadyExistsException) {
  logger.error("Instanz existiert bereits für " + loggingMBeanName
  + ", muss die Entfernung fehlgeschlagen sein.");
  }
  logger.error("Exception activating MBean for " + loggingMBeanName,
  e);
  e.printStackTrace();
  throw new IllegalStateException(e.toString());
  }
  }
 
/**
  * Entfernen Sie die mBean und beenden Sie Log4j, wenn die Anwendung entladen wird.
  *
  * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
  */
  public void contextDestroyed(ServletContextEvent event) {
  Logger logger = Logger.getLogger(Log4JInitializer.class);
  String loggingMBeanName = applicationName + "LoggingMBean";
  logger.info("Deaktiviere MBean mit Namen [" + loggingMBeanName
  + "] in der Klasse handle [" + getClass().hashCode()
  + "] für Version "
  + LogManager.class.getPackage().getImplementationVersion());
  MBeanFactory factory = AdminServiceFactory.getMBeanFactory();
  versuchen {
  ObjectName foundName = factory.findMBean(loggingMBeanName);
  logger.info("Name " + loggingMBeanName
  + " existiert, deaktivieren Sie es jetzt ....");
  factory.deactivateMBean(foundName);
  if (logger.isDebugEnabled())
  logger.debug("Deaktivierte MBean mit Namen " + loggingMBeanName
  + ".");
  } catch (InstanceNotFoundException e1) {
  logger.debug("Keine Instanz für den Namen " + loggingMBeanName) gefunden;
  } catch (AdminException e) {
  logger.error("Fehler beim Deaktivieren der Bohne, ignoriert...", e);
  }
  // Sicheres Herunterfahren von Log4J
  logger.info("Log4J wird heruntergefahren...");
  LogManager.shutdown();
  }
}

Verfasst von

Meindert Deen

Contact

Let’s discuss how we can support your journey.