/* * Copyright (C) 2015 SoftIndex LLC. * * Licensed 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 io.datakernel.jmx; import io.datakernel.eventloop.Eventloop; import io.datakernel.jmx.helper.JmxStatsStub; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import static io.datakernel.eventloop.FatalErrorHandlers.rethrowOnAnyError; import static io.datakernel.jmx.MBeanSettings.defaultSettings; import static java.util.Arrays.asList; public class JmxMBeansAttributeExceptionsTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void concurrentJmxMBeansAreNotAllowedToBeInPool_OnlyEventloopJmxMBeansAreAllowedToBeInPool() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("ConcurrentJmxMBeans cannot be used in pool. " + "Only EventloopJmxMBeans can be used in pool"); JmxMBeans.factory().createFor( asList(new ConcurrentJmxMBeanWithSingleIntAttr(), new ConcurrentJmxMBeanWithSingleIntAttr()), defaultSettings(), false); } // test JmxRefreshableStats as @JmxAttribute, all returned stats should be concrete classes with public no-arg constructor @Test public void jmxStatsAttributeCannotBeInterface() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Return type of JmxRefreshableStats attribute must be concrete class " + "that implements JmxRefreshableStats interface " + "and contains static factory \"createAccumulator()\" method " + "or static factory \"create()\" method " + "or public no-arg constructor"); JmxMBeans.factory().createFor(asList(new MBeanWithInterfaceAsJmxStatsAttributes()), defaultSettings(), false); } @Test public void jmxStatsAttributeCannotBeAbstractClass() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Return type of JmxRefreshableStats attribute must be concrete class " + "that implements JmxRefreshableStats interface " + "and contains static factory \"createAccumulator()\" method " + "or static factory \"create()\" method " + "or public no-arg constructor"); JmxMBeans.factory().createFor(asList(new MBeanWithAbstractClassAsJmxStatsAttributes()), defaultSettings(), false); } @Test public void jmxStatsAttributesClassMustHavePublicNoArgConstructor() { expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Return type of JmxRefreshableStats attribute must be concrete class " + "that implements JmxRefreshableStats interface " + "and contains static factory \"createAccumulator()\" method " + "or static factory \"create()\" method " + "or public no-arg constructor"); JmxMBeans.factory().createFor(asList(new MBeanWithJmxStatsClassWhichDoesntHavePublicNoArgConstructor()), defaultSettings(), false); } public static final class ConcurrentJmxMBeanWithJmxStats implements ConcurrentJmxMBean { @JmxAttribute public JmxStatsStub getStats() { return new JmxStatsStub(); } } public static final class ConcurrentJmxMBeanWithSingleIntAttr implements ConcurrentJmxMBean { @JmxAttribute public int getCount() { return 0; } } public static final class MBeanWithInterfaceAsJmxStatsAttributes implements EventloopJmxMBean { @JmxAttribute public JmxStatsAdditionalInterface getStats() { return null; } @Override public Eventloop getEventloop() { return Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); } } public interface JmxStatsAdditionalInterface extends JmxRefreshableStats<JmxStatsAdditionalInterface> { } public static final class MBeanWithAbstractClassAsJmxStatsAttributes implements EventloopJmxMBean { @JmxAttribute public JmxStatsAbstractClass getStats() { return null; } @Override public Eventloop getEventloop() { return Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); } } public static abstract class JmxStatsAbstractClass implements JmxRefreshableStats<JmxStatsAbstractClass> { } public static final class MBeanWithJmxStatsClassWhichDoesntHavePublicNoArgConstructor implements EventloopJmxMBean { @JmxAttribute public JmxStatsWithNoPublicNoArgConstructor getStats() { return null; } @Override public Eventloop getEventloop() { return Eventloop.create().withFatalErrorHandler(rethrowOnAnyError()); } } public static final class JmxStatsWithNoPublicNoArgConstructor implements JmxRefreshableStats<JmxStatsWithNoPublicNoArgConstructor> { private final int count; public JmxStatsWithNoPublicNoArgConstructor(int count) { this.count = count; } @JmxAttribute public int getAttr() { return 0; } @Override public void add(JmxStatsWithNoPublicNoArgConstructor another) { } @Override public void refresh(long timestamp) { } } }