org.apache.wicket.jmx.Initializer Maven / Gradle / Ivy
Show all versions of wicket-jmx Show documentation
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.wicket.jmx;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.StandardMBean;
import org.apache.wicket.IInitializer;
import org.apache.wicket.ThreadContext;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.jmx.wrapper.Application;
import org.apache.wicket.jmx.wrapper.ApplicationSettings;
import org.apache.wicket.jmx.wrapper.DebugSettings;
import org.apache.wicket.jmx.wrapper.MarkupSettings;
import org.apache.wicket.jmx.wrapper.PageSettings;
import org.apache.wicket.jmx.wrapper.RequestCycleSettings;
import org.apache.wicket.jmx.wrapper.RequestLogger;
import org.apache.wicket.jmx.wrapper.ResourceSettings;
import org.apache.wicket.jmx.wrapper.SecuritySettings;
import org.apache.wicket.jmx.wrapper.SessionSettings;
import org.apache.wicket.jmx.wrapper.StoreSettings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Registers Wicket's MBeans.
*
* Users can specify the MBeanServer implementation in which to register the MBeans by setting the
* org.apache.wicket.mbean.server.agentid
property to the agent id of the MBeanServer
* implementation they want, or by setting org.apache.wicket.mbean.server.class
to the
* mbean server class they want (if both are provided, and the agent id returns a server, that one
* is used). This initializer will log an error when no mbean server with the provided agent id can
* be found, and will then fall back to use the platform mbean server. When no agent id is provided,
* the platform mbean server will be used.
*
* @author eelcohillenius
* @author David Hosier
*/
public class Initializer implements IInitializer
{
private static final Logger log = LoggerFactory.getLogger(Initializer.class);
// It's best to store a reference to the MBeanServer rather than getting it
// over and over
private MBeanServer mbeanServer = null;
/**
* List of registered names
*/
private final List registered = new ArrayList<>();
@Override
public void destroy(final org.apache.wicket.Application application)
{
for (ObjectName objectName : registered)
{
try
{
mbeanServer.unregisterMBean(objectName);
}
catch (InstanceNotFoundException | MBeanRegistrationException e)
{
log.error(e.getMessage(), e);
}
}
}
@Override
public void init(final org.apache.wicket.Application application)
{
try
{
String name = application.getName();
String agentId = null;
try
{
agentId = System.getProperty("wicket.mbean.server.agentid");
}
catch (SecurityException e)
{
// Ignore - we're not allowed to read this property.
log.warn("not allowed to read property wicket.mbean.server.agentid due to security settings; ignoring");
}
if (agentId != null)
{
ArrayList mbeanServers = MBeanServerFactory.findMBeanServer(agentId);
if (!mbeanServers.isEmpty())
{
mbeanServer = mbeanServers.get(0); // get first
}
else
{
log.error("unable to find mbean server with agent id {}", agentId);
}
}
if (mbeanServer == null)
{
String impl = null;
try
{
impl = System.getProperty("wicket.mbean.server.class");
}
catch (SecurityException e)
{
// Ignore - we're not allowed to read this property.
log.warn("Not allowed to read property wicket.mbean.server.class due to security settings: {}. Ignoring",
e.getMessage());
}
if (impl != null)
{
ArrayList mbeanServers = MBeanServerFactory.findMBeanServer(null);
if (!mbeanServers.isEmpty())
{
for (MBeanServer mbs : mbeanServers)
{
if (mbs.getClass().getName().equals(impl))
{
mbeanServer = mbs;
break;
}
}
}
if (mbeanServer == null)
{
log.error("unable to find mbean server of type '{}'", impl);
}
}
}
if (mbeanServer == null)
{
mbeanServer = ManagementFactory.getPlatformMBeanServer();
// never null
}
log.info("registering Wicket mbeans with server '{}'", mbeanServer);
// register top level application object, but first check whether
// multiple instances of the same application (name) are running and
// if so adjust the name
String domain = "org.apache.wicket.app." + name;
ObjectName appBeanName = new ObjectName(domain + ":type=Application");
String tempDomain = domain;
int i = 0;
while (mbeanServer.isRegistered(appBeanName))
{
tempDomain = name + "-" + i++;
appBeanName = new ObjectName(tempDomain + ":type=Application");
}
domain = tempDomain;
Application appBean = new Application(application);
register(application, appBean, appBeanName);
register(application, new ApplicationSettings(application), new ObjectName(domain
+ ":type=Application,name=ApplicationSettings"));
register(application, new DebugSettings(application), new ObjectName(domain
+ ":type=Application,name=DebugSettings"));
register(application, new MarkupSettings(application), new ObjectName(domain
+ ":type=Application,name=MarkupSettings"));
register(application, new ResourceSettings(application), new ObjectName(domain
+ ":type=Application,name=ResourceSettings"));
register(application, new PageSettings(application), new ObjectName(domain
+ ":type=Application,name=PageSettings"));
register(application, new RequestCycleSettings(application), new ObjectName(domain
+ ":type=Application,name=RequestCycleSettings"));
register(application, new SecuritySettings(application), new ObjectName(domain
+ ":type=Application,name=SecuritySettings"));
register(application, new SessionSettings(application), new ObjectName(domain
+ ":type=Application,name=SessionSettings"));
register(application, new StoreSettings(application), new ObjectName(domain
+ ":type=Application,name=StoreSettings"));
RequestLogger sessionsBean = new RequestLogger(application);
ObjectName sessionsBeanName = new ObjectName(domain + ":type=RequestLogger");
register(application, sessionsBean, sessionsBeanName);
}
catch (MalformedObjectNameException | InstanceAlreadyExistsException |
MBeanRegistrationException | NotCompliantMBeanException e)
{
throw new WicketRuntimeException(e);
}
}
@Override
public String toString()
{
return "Wicket JMX initializer";
}
/**
* Register MBean.
*
* @param o
* MBean
* @param objectName
* Object name
*
* @throws NotCompliantMBeanException
* @throws MBeanRegistrationException
* @throws InstanceAlreadyExistsException
*/
private void register(final org.apache.wicket.Application application, final T o,
final ObjectName objectName) throws InstanceAlreadyExistsException,
MBeanRegistrationException, NotCompliantMBeanException
{
StandardMBean bean = new StandardMBean(o, (Class)o.getClass().getInterfaces()[0]) {
@Override
public Object getAttribute(String attribute)
{
return withApplication(() -> super.getAttribute(attribute));
}
@Override
public void setAttribute(Attribute attribute)
{
withApplication(() -> {
super.setAttribute(attribute);
return null;
});
}
@Override
public AttributeList setAttributes(AttributeList attributes)
{
return withApplication(() -> super.setAttributes(attributes));
}
@Override
public Object invoke(String actionName, Object[] params, String[] signature)
{
return withApplication(() -> super.invoke(actionName, params, signature));
}
private R withApplication(Callable callable)
{
boolean existed = ThreadContext.exists();
if (existed == false)
{
ThreadContext.setApplication(application);
}
try
{
return callable.call();
}
catch (Exception ex)
{
throw new WicketRuntimeException(ex);
}
finally
{
if (existed == false)
{
ThreadContext.detach();
}
}
}
};
mbeanServer.registerMBean(bean, objectName);
registered.add(objectName);
}
}