Skip to content

Commit

Permalink
Merge pull request wildfly#17949 from bstansberry/WFLY-19218
Browse files Browse the repository at this point in the history
[WFLY-19218] Ensure that service mbeans are registered with the mbean…
  • Loading branch information
bstansberry authored Jun 10, 2024
2 parents 8c85ad9 + 370cab1 commit 5e16342
Show file tree
Hide file tree
Showing 10 changed files with 476 additions and 164 deletions.
2 changes: 1 addition & 1 deletion sar/src/main/java/org/jboss/as/service/MBeanServices.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void addDependency(final String dependencyMBeanName) {
final ServiceName injectedMBeanStartStopServiceName = ServiceNameFactory.newStartStop(dependencyMBeanName);
startStopServiceBuilder.requires(injectedMBeanStartStopServiceName);
final ServiceName injectedMBeanRegisterUnregisterServiceName = ServiceNameFactory.newRegisterUnregister(dependencyMBeanName);
registerUnregisterServiceBuilder.requires(injectedMBeanRegisterUnregisterServiceName);
createDestroyServiceBuilder.requires(injectedMBeanRegisterUnregisterServiceName);
}

void addAttribute(final String attributeMBeanName, final Method setter, final DelegatingSupplier propertySupplier) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/

package org.jboss.as.test.integration.sar.order;

import static org.jboss.as.test.integration.sar.order.LifecycleEmitterMBean.invokeListener;
import static org.jboss.as.test.integration.sar.order.LifecycleEmitterMBean.safeInvokeListener;

import java.util.ArrayList;
import java.util.List;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.ObjectName;

import org.jboss.system.Service;

public class CustomLifecycleEmitter implements CustomLifecycleEmitterMBean, Service, MBeanRegistration {

private volatile String id;
private volatile ObjectName listener;
private volatile ObjectName dependency;
private volatile MBeanServer server;
private final List<String> unrecordedEvents = new ArrayList<>();


@Override
public String getId() {
return id;
}

@Override
public void setId(String id) {
this.id = id;
}

@Override
public ObjectName getDependency() {
return dependency;
}

@Override
public void setDependency(ObjectName dependency) {
this.dependency = dependency;
}

@Override
public ObjectName getLifecycleListener() {
return listener;
}

@Override
public void setLifecycleListener(ObjectName lifecycleListener) {
this.listener = lifecycleListener;
}

@Override
public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
this.server = server;
for (String unrecordedEvent : unrecordedEvents) {
invokeListener(id, unrecordedEvent, server);
}
invokeListener(id, MBEAN_PRE_REGISTERED, server);
return name;
}

@Override
public void postRegister(Boolean registrationDone) {
safeInvokeListener(id, MBEAN_POST_REGISTERED, server);
}

@Override
public void preDeregister() throws Exception {
invokeListener(id, MBEAN_PRE_DEREGISTERED, server);
}

@Override
public void postDeregister() {
safeInvokeListener(id, MBEAN_POST_DEREGISTERED, server);
}

@Override
public void create() throws Exception {
if (server != null) {
invokeListener(id, MBEAN_CREATED, server);
} else {
unrecordedEvents.add(MBEAN_CREATED);
}
}

@Override
public void start() throws Exception {
if (server != null) {
invokeListener(id, MBEAN_STARTED, server);
} else {
unrecordedEvents.add(MBEAN_STARTED);
}
}

@Override
public void stop() {
safeInvokeListener(id, MBEAN_STOPPED, server);
}

@Override
public void destroy() {
safeInvokeListener(id, MBEAN_DESTROYED, server);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/

package org.jboss.as.test.integration.sar.order;

public interface CustomLifecycleEmitterMBean extends LifecycleEmitterMBean {
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
Expand All @@ -15,11 +16,12 @@

public class LifecycleEmitter extends ServiceMBeanSupport implements LifecycleEmitterMBean {

private static final String[] LISTENER_SIG = { "java.lang.String" };
private static final String[] LISTENER_SIG = { "java.lang.String", "java.lang.String" };
private static volatile ObjectName LISTENER;

private volatile String id;
private volatile ObjectName listener;
private volatile ObjectName dependency;

@Override
public String getId() {
Expand All @@ -31,6 +33,16 @@ public void setId(String id) {
this.id = id;
}

@Override
public ObjectName getDependency() {
return dependency;
}

@Override
public void setDependency(ObjectName dependency) {
this.dependency = dependency;
}

@Override
public ObjectName getLifecycleListener() {
return listener;
Expand All @@ -43,34 +55,68 @@ public void setLifecycleListener(ObjectName listener) {

@Override
protected void createService() throws Exception {
invokeListener("mbeanCreated");
invokeListener(MBEAN_CREATED);
}

@Override
protected void startService() throws Exception {
invokeListener("mbeanStarted");
invokeListener(MBEAN_STARTED);
}

@Override
public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
ObjectName result = super.preRegister(server, name);
invokeListener(MBEAN_PRE_REGISTERED);
return result;
}

@Override
public void postRegister(Boolean registrationDone) {
super.postRegister(registrationDone);
safeInvokeListener(MBEAN_POST_REGISTERED);
}

@Override
public void preDeregister() throws Exception {
super.preDeregister();
invokeListener(MBEAN_PRE_DEREGISTERED);
}

@Override
public void postDeregister() {
super.postDeregister();
safeInvokeListener(MBEAN_POST_DEREGISTERED);
}

@Override
protected void stopService() throws Exception {
invokeListener("mbeanStopped");
invokeListener(MBEAN_STOPPED);
}

@Override
protected void destroyService() throws Exception {
invokeListener("mbeanDestroyed");
invokeListener(MBEAN_DESTROYED);
}

private void invokeListener(String methodName) throws MalformedObjectNameException, ReflectionException, InstanceNotFoundException, MBeanException {
private void safeInvokeListener(String methodName) {
try {
invokeListener(methodName);
} catch (MalformedObjectNameException | ReflectionException | InstanceNotFoundException | MBeanException e) {
throw new RuntimeException(e);
}
}

private void invokeListener(String eventName) throws MalformedObjectNameException, ReflectionException, InstanceNotFoundException, MBeanException {
if ("A".equals(id)) {
// Add a delay to give the other mbeans a chance to (incorrectly) move ahead
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
if (!MBEAN_PRE_DEREGISTERED.equals(eventName) && !MBEAN_POST_DEREGISTERED.equals(eventName)) {
// Add a delay to give the other mbeans a chance to (incorrectly) move ahead
sleep(100);
}
} else if (MBEAN_STOPPED.equals(eventName) || MBEAN_DESTROYED.equals(eventName)) {
// Add a delay to give A chance to (incorrectly) deregister
sleep(50);
}
getServer().invoke(getListenerObjectName(), methodName, new Object[]{ id }, LISTENER_SIG);
getServer().invoke(getListenerObjectName(), "mbeanEvent", new Object[]{ id, eventName }, LISTENER_SIG);
}

private static ObjectName getListenerObjectName() throws MalformedObjectNameException {
Expand All @@ -79,4 +125,12 @@ private static ObjectName getListenerObjectName() throws MalformedObjectNameExce
}
return LISTENER;
}

private static void sleep(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,56 @@

package org.jboss.as.test.integration.sar.order;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

public interface LifecycleEmitterMBean {

String MBEAN_CREATED = "mbeanCreated";
String MBEAN_STARTED = "mbeanStarted";
String MBEAN_STOPPED = "mbeanStopped";
String MBEAN_DESTROYED = "mbeanDestroyed";
String MBEAN_PRE_REGISTERED = "mbeanPreRegistered";
String MBEAN_POST_REGISTERED = "mbeanPostRegistered";
String MBEAN_PRE_DEREGISTERED = "mbeanPreDeregistered";
String MBEAN_POST_DEREGISTERED = "mbeanPostDeregistered";

String[] LISTENER_SIG = { "java.lang.String", "java.lang.String" };


String getId();

void setId(String id);

ObjectName getDependency();

void setDependency(ObjectName dependency);

ObjectName getLifecycleListener();

void setLifecycleListener(ObjectName lifecycleListener);

static void safeInvokeListener(String id, String methodName, MBeanServer mBeanServer) {
try {
invokeListener(id, methodName, mBeanServer);
} catch (MalformedObjectNameException | ReflectionException | InstanceNotFoundException | MBeanException e) {
throw new RuntimeException(e);
}
}

static void invokeListener(String id, String eventName, MBeanServer mBeanServer) throws MalformedObjectNameException, ReflectionException, InstanceNotFoundException, MBeanException {
if ("A".equals(id)) {
// Add a delay to give the other mbeans a chance to (incorrectly) move ahead
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
mBeanServer.invoke(ObjectName.getInstance("jboss:name=OrderListener"), "mbeanEvent", new Object[]{ id, eventName }, LISTENER_SIG);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,18 @@

public class LifecycleListener extends ServiceMBeanSupport implements LifecycleListenerMBean {

private final List<String> creates = Collections.synchronizedList(new ArrayList<>());
private final List<String> starts = Collections.synchronizedList(new ArrayList<>());
private final List<String> stops = Collections.synchronizedList(new ArrayList<>());
private final List<String> destroys = Collections.synchronizedList(new ArrayList<>());
private final List<Tuple> allEvents = Collections.synchronizedList(new ArrayList<>());

@Override
public void mbeanCreated(String id) {
creates.add(id);
}

@Override
public synchronized void mbeanStarted(String id) {
starts.add(id);
}

@Override
public synchronized void mbeanStopped(String id) {
stops.add(id);
public void mbeanEvent(String id, String event) {
allEvents.add(new Tuple(id, event));
}

@Override
public void mbeanDestroyed(String id) {
destroys.add(id);
}

@Override
public List<String> getCreates() {
return creates;
public List<Tuple> getAllEvents() {
return allEvents;
}

@Override
public List<String> getStarts() {
return starts;
}

@Override
public List<String> getStops() {
return stops;
}

@Override
public List<String> getDestroys() {
return destroys;
}
}
Loading

0 comments on commit 5e16342

Please sign in to comment.