JMX: fix and enable tests There was no tests for the JMX library, only a broken runnable sample. This commit fix the sample and add assertions. Introducing JmxFixture in testsupport.
Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/cdfe539e Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/cdfe539e Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/cdfe539e Branch: refs/heads/develop Commit: cdfe539e6e46246ab6944c1de35e817fbde817a5 Parents: 04b74f2 Author: Paul Merlin <[email protected]> Authored: Mon Sep 26 17:56:36 2016 +0200 Committer: Paul Merlin <[email protected]> Committed: Mon Sep 26 18:13:05 2016 +0200 ---------------------------------------------------------------------- .../org/apache/zest/test/util/JmxFixture.java | 120 +++++++++++++++++++ libraries/jmx/src/docs/jmx.txt | 25 +++- .../org/apache/zest/library/jmx/JMXTest.java | 89 +++++++------- 3 files changed, 187 insertions(+), 47 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zest-java/blob/cdfe539e/core/testsupport/src/main/java/org/apache/zest/test/util/JmxFixture.java ---------------------------------------------------------------------- diff --git a/core/testsupport/src/main/java/org/apache/zest/test/util/JmxFixture.java b/core/testsupport/src/main/java/org/apache/zest/test/util/JmxFixture.java new file mode 100644 index 0000000..391ff18 --- /dev/null +++ b/core/testsupport/src/main/java/org/apache/zest/test/util/JmxFixture.java @@ -0,0 +1,120 @@ +/* + * 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.zest.test.util; + +import org.hamcrest.Matcher; +import org.junit.Assert; + +import javax.management.JMException; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.util.List; + +import static java.util.stream.Collectors.toList; + +/** + * JMX Test Fixture. + */ +public class JmxFixture extends Assert { + + private final MBeanServer server; + private final String prefix; + + public JmxFixture() + { + this( ManagementFactory.getPlatformMBeanServer(), "" ); + } + + public JmxFixture( String prefix ) + { + this( ManagementFactory.getPlatformMBeanServer(), prefix ); + } + + public JmxFixture( MBeanServer server ) + { + this( server, "" ); + } + + public JmxFixture( MBeanServer server, String prefix ) + { + this.server = server; + this.prefix = prefix; + } + + public String prefix() { + return prefix; + } + + public boolean objectExists( String objName ) { + try + { + ObjectName objectName = new ObjectName( prefix + objName ); + return server.isRegistered( objectName ); + } + catch( MalformedObjectNameException ex ) + { + throw new IllegalArgumentException( ex.getMessage(), ex ); + } + } + + + public void assertObjectPresent( String objName ) + { + if( !objectExists( objName ) ) + { + fail( objName + " is absent" ); + } + } + + public void assertObjectAbsent( String objName ) + { + if( objectExists( objName ) ) { + fail( objName + " is present" ); + } + } + + public <T> void assertAttributeValue( String objName, String attribute, Class<? extends T> type, Matcher<? super T> matcher ) + { + assertThat( attributeValue( objName, attribute, type ), matcher ); + } + + public <T> T attributeValue( String objName, String attribute, Class<? extends T> type ) + { + try + { + ObjectName objectName = new ObjectName( prefix + objName ); + Object value = server.getAttribute( objectName, attribute ); + return type.cast( value ); + } + catch( MalformedObjectNameException ex ) + { + throw new IllegalArgumentException( ex.getMessage(), ex ); + } + catch( JMException ex ) + { + throw new RuntimeException( ex.getMessage(), ex ); + } + } + + public List<String> allObjectNames() + { + return server.queryNames( null, null ).stream().map( ObjectName::toString ).collect( toList() ); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/zest-java/blob/cdfe539e/libraries/jmx/src/docs/jmx.txt ---------------------------------------------------------------------- diff --git a/libraries/jmx/src/docs/jmx.txt b/libraries/jmx/src/docs/jmx.txt index 5c17265..20e665c 100644 --- a/libraries/jmx/src/docs/jmx.txt +++ b/libraries/jmx/src/docs/jmx.txt @@ -25,13 +25,23 @@ source=libraries/jmx/dev-status.xml -------------- -The JMX library provides a service that exposes a Zest⢠app in -JMX automatically, giving you an opportunity to inspect the app much as +The JMX library provides a service that exposes a Zest⢠application in +http://www.oracle.com/technetwork/articles/java/docs-jsp-135989.html[JMX] +automatically, giving you an opportunity to inspect the application much as you would with the <<tools-envisage>> tool. include::../../build/docs/buildinfo/artifact.txt[] -== Usage == +Services configuration is editable through their corresponding JMX beans. +You can also restart your services so the new configuration is picked up. + +image:library-jmx.png[] + + + +== Assembly == + +JMX Support for Zest⢠applications: [snippet,java] ---- @@ -39,7 +49,10 @@ source=libraries/jmx/src/test/java/org/apache/zest/library/jmx/JMXTest.java tag=assembly ---- -Note that you need to run it with -Dcom.sun.management.jmxremote so that the -JVM starts the MBeanServer. +Managing the MX Beans Server from your Zest⢠application using the `JMXConnectorService`: -image:library-jmx.png[] +[snippet,java] +---- +source=libraries/jmx/src/test/java/org/apache/zest/library/jmx/JMXTest.java +tag=connector +---- http://git-wip-us.apache.org/repos/asf/zest-java/blob/cdfe539e/libraries/jmx/src/test/java/org/apache/zest/library/jmx/JMXTest.java ---------------------------------------------------------------------- diff --git a/libraries/jmx/src/test/java/org/apache/zest/library/jmx/JMXTest.java b/libraries/jmx/src/test/java/org/apache/zest/library/jmx/JMXTest.java index 1c831b4..5d85ea2 100644 --- a/libraries/jmx/src/test/java/org/apache/zest/library/jmx/JMXTest.java +++ b/libraries/jmx/src/test/java/org/apache/zest/library/jmx/JMXTest.java @@ -19,7 +19,6 @@ */ package org.apache.zest.library.jmx; -import org.junit.Test; import org.apache.zest.api.activation.ActivationException; import org.apache.zest.api.activation.ActivatorAdapter; import org.apache.zest.api.activation.Activators; @@ -35,65 +34,73 @@ import org.apache.zest.api.value.ValueComposite; import org.apache.zest.bootstrap.AssemblyException; import org.apache.zest.bootstrap.ModuleAssembly; import org.apache.zest.bootstrap.SingletonAssembler; +import org.apache.zest.bootstrap.unitofwork.DefaultUnitOfWorkAssembler; +import org.apache.zest.test.AbstractZestTest; import org.apache.zest.test.EntityTestAssembler; +import org.apache.zest.test.util.JmxFixture; +import org.junit.Test; /** * Start a simple server so that it can be accessed through JMX remotely. * Run this with -Dcom.sun.management.jmxremote so that the JVM starts the MBeanServer */ -public class JMXTest +public class JMXTest extends AbstractZestTest { - - public static void main( String[] args ) - throws InterruptedException, ActivationException, AssemblyException + @Override + public void assemble(ModuleAssembly module) throws AssemblyException { - /* - Logger logger = Logger.getLogger( "" ); - logger.setLevel( Level.FINE ); - Logger.getLogger("sun.rmi").setLevel( Level.WARNING ); + new EntityTestAssembler().assemble( module ); + new DefaultUnitOfWorkAssembler().assemble( module ); + + module.services( TestService.class, TestService2.class, TestService3.class ).instantiateOnStartup(); + module.entities( TestConfiguration.class ); - ConsoleHandler consoleHandler = new ConsoleHandler(); - consoleHandler.setLevel( Level.FINE ); - logger.addHandler( consoleHandler ); - */ + module.values( TestValue.class ); + module.objects( TestObject.class ); + + // START SNIPPET: assembly + new JMXAssembler().assemble( module ); + // END SNIPPET: assembly + + // START SNIPPET: connector + module.services( JMXConnectorService.class ).instantiateOnStartup(); + module.entities( JMXConnectorConfiguration.class ); + module.forMixin( JMXConnectorConfiguration.class ).declareDefaults().port().set( 1099 ); + // END SNIPPET: connector + } + + public static void main(String[] args ) + throws InterruptedException, ActivationException, AssemblyException + { SingletonAssembler assembler = new SingletonAssembler() { - // START SNIPPET: assembly - + @Override public void assemble( ModuleAssembly module ) throws AssemblyException { - // END SNIPPET: assembly - new EntityTestAssembler().assemble( module ); - - module.services( TestService.class, TestService2.class, TestService3.class ).instantiateOnStartup(); - module.entities( TestConfiguration.class ); - - module.values( TestValue.class ); - - module.objects( TestObject.class ); - - // START SNIPPET: assembly - new JMXAssembler().assemble( module ); - - module.services( JMXConnectorService.class ).instantiateOnStartup(); - module.entities( JMXConnectorConfiguration.class ); - module.forMixin( JMXConnectorConfiguration.class ).declareDefaults().port().set( 1099 ); + new JMXTest().assemble(module); } - // END SNIPPET: assembly }; - // This allows user to connect using VisualVM/JConsole while ( true ) { - Thread.sleep( 10000 ); + Thread.sleep( 10_000 ); } } + + @Test - public void dummy() + public void servicesAndConfiguration() { + JmxFixture jmx = new JmxFixture("Zest:application=Application,layer=Layer 1,module=Module 1,class=Service,"); + jmx.assertObjectPresent("service=TestService"); + jmx.assertObjectPresent("service=TestService,name=Configuration"); + jmx.assertObjectPresent("service=TestService2"); + jmx.assertObjectPresent("service=TestService2,name=Configuration"); + jmx.assertObjectPresent("service=TestService3"); + jmx.assertObjectPresent("service=TestService3,name=Configuration"); } public interface TestActivation @@ -118,7 +125,7 @@ public class JMXTest @Mixins( TestService.Mixin.class ) @Activators( TestActivator.class ) - interface TestService + public interface TestService extends TestActivation, ServiceComposite { @@ -140,7 +147,7 @@ public class JMXTest @Mixins( TestService2.Mixin.class ) @Activators( TestActivator.class ) - interface TestService2 + public interface TestService2 extends TestActivation, ServiceComposite { @@ -162,7 +169,7 @@ public class JMXTest @Mixins( TestService3.Mixin.class ) @Activators( TestActivator.class ) - interface TestService3 + public interface TestService3 extends TestActivation, ServiceComposite { @@ -182,7 +189,7 @@ public class JMXTest } - interface TestConfiguration + public interface TestConfiguration extends ConfigurationComposite { @@ -194,14 +201,14 @@ public class JMXTest } - enum TestEnum + public enum TestEnum { Value1, Value2, Value3 } - interface TestValue + public interface TestValue extends ValueComposite { }
