From 6c692bd5843eb2d5f873b7ae5bbf7aa76b5e8f35 Mon Sep 17 00:00:00 2001 From: Dancovich Date: Wed, 22 May 2013 15:00:12 -0300 Subject: [PATCH] -Reparado problema onde o módulo de gerenciamento não conseguia injetar classes ManagementController que fossem anotadas com qualifiers. -Ajuste nos testes do demoiselle-jmx -Alteração de mensagens de erro --- impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/bootstrap/ManagementBootstrap.java | 11 +++++++++++ impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/ManagedType.java | 59 +++++++++++++++++++++++++++++++++++++++++++++-------------- impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/Management.java | 7 ++++--- impl/core/src/main/java/br/gov/frameworkdemoiselle/stereotype/ManagementController.java | 4 +++- impl/core/src/main/resources/demoiselle-core-bundle.properties | 5 +++-- impl/extension/jmx/src/test/java/management/tests/internal/DynamicMBeanProxyTestCase.java | 20 +++++++++++++++----- impl/extension/jmx/src/test/java/management/tests/internal/NotificationBroadcasterTestCase.java | 5 +++-- impl/extension/jmx/src/test/java/management/tests/internal/RemoteManagementTestCase.java | 90 ------------------------------------------------------------------------------------------ impl/extension/jmx/src/test/resources/META-INF/beans.xml | 6 +++++- impl/extension/jmx/src/test/resources/META-INF/persistence.xml | 22 ---------------------- 10 files changed, 89 insertions(+), 140 deletions(-) delete mode 100644 impl/extension/jmx/src/test/java/management/tests/internal/RemoteManagementTestCase.java delete mode 100644 impl/extension/jmx/src/test/resources/META-INF/persistence.xml diff --git a/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/bootstrap/ManagementBootstrap.java b/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/bootstrap/ManagementBootstrap.java index f9f81bd..3bcea0a 100644 --- a/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/bootstrap/ManagementBootstrap.java +++ b/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/bootstrap/ManagementBootstrap.java @@ -1,8 +1,10 @@ package br.gov.frameworkdemoiselle.internal.bootstrap; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Set; import javax.enterprise.event.Observes; @@ -15,13 +17,16 @@ import javax.enterprise.inject.spi.BeforeShutdown; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.ProcessAnnotatedType; +import br.gov.frameworkdemoiselle.DemoiselleException; import br.gov.frameworkdemoiselle.internal.context.ContextManager; import br.gov.frameworkdemoiselle.internal.context.ManagedContext; import br.gov.frameworkdemoiselle.internal.management.ManagedType; import br.gov.frameworkdemoiselle.internal.management.Management; +import br.gov.frameworkdemoiselle.internal.producer.ResourceBundleProducer; import br.gov.frameworkdemoiselle.lifecycle.ManagementExtension; import br.gov.frameworkdemoiselle.stereotype.ManagementController; import br.gov.frameworkdemoiselle.util.Beans; +import br.gov.frameworkdemoiselle.util.ResourceBundle; public class ManagementBootstrap implements Extension { @@ -43,8 +48,14 @@ public class ManagementBootstrap implements Extension { @SuppressWarnings("unchecked") public void registerAvailableManagedTypes(@Observes final AfterDeploymentValidation event,BeanManager beanManager) { + ResourceBundle bundle = ResourceBundleProducer.create("demoiselle-core-bundle", Locale.getDefault()); + Management monitoringManager = Beans.getReference(Management.class); for (AnnotatedType type : types) { + if (type.getJavaClass().isInterface() || Modifier.isAbstract(type.getJavaClass().getModifiers()) ){ + throw new DemoiselleException(bundle.getString("management-abstract-class-defined" , type.getJavaClass().getCanonicalName())); + } + ManagedType managedType = new ManagedType(type.getJavaClass()); monitoringManager.addManagedType(managedType); } diff --git a/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/ManagedType.java b/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/ManagedType.java index 57b1051..2f38593 100644 --- a/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/ManagedType.java +++ b/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/ManagedType.java @@ -39,8 +39,11 @@ package br.gov.frameworkdemoiselle.internal.management; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.TreeMap; +import javax.inject.Qualifier; + import br.gov.frameworkdemoiselle.DemoiselleException; import br.gov.frameworkdemoiselle.annotation.ManagedOperation; import br.gov.frameworkdemoiselle.annotation.ManagedProperty; @@ -60,6 +63,8 @@ import br.gov.frameworkdemoiselle.util.ResourceBundle; public class ManagedType { private Class type; + + private Annotation[] qualifiers; private TreeMap fields; @@ -83,6 +88,7 @@ public class ManagedType { fields = new TreeMap(); operationMethods = new TreeMap(); this.description = type.getAnnotation(ManagementController.class).description(); + this.qualifiers = getQualifierAnnotations(type); initialize(); } @@ -102,6 +108,18 @@ public class ManagedType { public TreeMap getOperationMethods() { return operationMethods; } + + /** + *

Return a (possibly empty) list of all qualifiers this type have. Qualifiers + * are any annotations marked as {@link Qualifier}.

+ * + *

This method returns the true list of qualifiers. If implementators change this list, it will + * affect future calls of this method. This is so that resources can be spared by not creating many instances of this list.

+ * + */ + public Annotation[] getQualifiers(){ + return this.qualifiers; + } private void initialize() { // Para cada atributo verifica se ele está anotado com ManagedProperty e extrai as informações dele (método get, set e @@ -224,6 +242,33 @@ public class ManagedType { return setterMethod; } + + /** + * Indicates another {@link ManagedType} represents the same {@link Class} as this one. This method also supports a + * {@link Class} as a parameter, in this case it will return true if the passed class is exactly the + * same Java class represented by this {@link ManagedType}. + */ + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } + + return ((ManagedType) other).getType().getCanonicalName().equals(this.getType().getCanonicalName()); + } + + private synchronized Annotation[] getQualifierAnnotations(Class beanClass){ + Annotation[] annotations = beanClass.getAnnotations(); + ArrayList qualifiers = new ArrayList(annotations.length); + + for (int i=0; itrue if the passed class is exactly the - * same Java class represented by this {@link ManagedType}. - */ - @Override - public boolean equals(Object other) { - if (other == null) { - return false; - } - - return ((ManagedType) other).getType().getCanonicalName().equals(this.getType().getCanonicalName()); - } } diff --git a/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/Management.java b/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/Management.java index 4d06295..d3158aa 100644 --- a/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/Management.java +++ b/impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/Management.java @@ -129,7 +129,7 @@ public class Management { activateContexts(managedType.getType()); try { - Object delegate = Beans.getReference(managedType.getType()); + Object delegate = Beans.getReference(managedType.getType() , managedType.getQualifiers()); MethodDetail method = managedType.getOperationMethods().get(actionName); if (method != null) { @@ -179,7 +179,7 @@ public class Management { activateContexts(managedType.getType()); try { - Object delegate = Beans.getReference(managedType.getType()); + Object delegate = Beans.getReference(managedType.getType() , managedType.getQualifiers()); return getterMethod.invoke(delegate, (Object[]) null); } catch (Exception e) { @@ -227,7 +227,7 @@ public class Management { // Obtém uma instância da classe gerenciada, lembrando que // classes // anotadas com @ManagementController são sempre singletons. - Object delegate = Beans.getReference(managedType.getType()); + Object delegate = Beans.getReference(managedType.getType() , managedType.getQualifiers() ); // Se houver um validador anexado à propriedade alterada, executa o validador sobre // o novo valor. @@ -343,5 +343,6 @@ public class Management { return this.validator; } + } diff --git a/impl/core/src/main/java/br/gov/frameworkdemoiselle/stereotype/ManagementController.java b/impl/core/src/main/java/br/gov/frameworkdemoiselle/stereotype/ManagementController.java index 9f2e7d6..89ff9b8 100644 --- a/impl/core/src/main/java/br/gov/frameworkdemoiselle/stereotype/ManagementController.java +++ b/impl/core/src/main/java/br/gov/frameworkdemoiselle/stereotype/ManagementController.java @@ -49,12 +49,14 @@ import javax.enterprise.inject.Stereotype; import javax.enterprise.util.Nonbinding; /** - *

Identifies a management controller class. What it means is that an external client can manage the application + *

Identifies a management controller bean. What it means is that an external client can manage the application * this class is in by reading or writing it's attributes and calling it's operations.

*

* Only fields annotated with {@link br.gov.frameworkdemoiselle.annotation.ManagedProperty} or * methods annotated with {@link br.gov.frameworkdemoiselle.annotation.ManagedOperation} will be exposed * to clients.

+ *

Only bean implementations (concrete classes) can be management controllers. It's a runtime error to mark an interface + * or abstract class with this annotation.

*

This stereotype only defines a class as managed, you need to choose an extension that will expose this managed class * to external clients using any technology available. One example is the Demoiselle JMX extension, that will expose * managed classes as MBeans.

diff --git a/impl/core/src/main/resources/demoiselle-core-bundle.properties b/impl/core/src/main/resources/demoiselle-core-bundle.properties index 6984a5f..0197197 100644 --- a/impl/core/src/main/resources/demoiselle-core-bundle.properties +++ b/impl/core/src/main/resources/demoiselle-core-bundle.properties @@ -102,8 +102,9 @@ user-has-role=Usu\u00E1rio {0} possui a(s) role(s)\: {1} authenticator-not-defined=Nenhum mecanismo de autentica\u00E7\u00E3o foi definido. Para utilizar {0} \u00E9 preciso definir a propriedade frameworkdemoiselle.security.authenticator.class como mecanismo de autentica\u00E7\u00E3o desejado no arquivo demoiselle.properties. management-notification-attribute-changed=O atributo [{0}] da classe gerenciada [{1}] foi alterado -management-null-class-defined=A classe gerenciada informada n\u00E3o pode ser nula -management-no-annotation-found=Classe {0} precisa ser anotada com @Managed +management-null-class-defined=O controlador de gerenciamento informado n\u00E3o pode ser [null] +management-abstract-class-defined=O controlador de gerenciamento [{0}] precisa ser uma classe concreta +management-no-annotation-found=Classe {0} precisa ser anotada com @ManagementController management-invalid-property-no-getter-setter=Falha ao inicializar classe gerenciada {0}, n\u00E3o foi encontrado um m\u00E9todo get ou m\u00E9todo set para a propriedade {1} management-invalid-property-as-operation=Falha ao inicializar classe gerenciada {0}, n\u00E3o \u00E9 poss\u00EDvel declarar uma propriedade cujo m\u00E9todo get ou set \u00E9 uma opera\u00E7\u00E3o management-introspection-error=Erro ao ler atributos da classe gerenciada {0} diff --git a/impl/extension/jmx/src/test/java/management/tests/internal/DynamicMBeanProxyTestCase.java b/impl/extension/jmx/src/test/java/management/tests/internal/DynamicMBeanProxyTestCase.java index 2291308..20f5f31 100644 --- a/impl/extension/jmx/src/test/java/management/tests/internal/DynamicMBeanProxyTestCase.java +++ b/impl/extension/jmx/src/test/java/management/tests/internal/DynamicMBeanProxyTestCase.java @@ -52,6 +52,7 @@ import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.FileAsset; +import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.junit.Test; import org.junit.runner.RunWith; @@ -68,13 +69,16 @@ public class DynamicMBeanProxyTestCase { mainDeployment .addPackages(true, "br") .addAsResource(new FileAsset(new File("src/test/resources/test/beans.xml")), "beans.xml") - .addAsResource(new FileAsset(new File("src/test/resources/configuration/demoiselle.properties")), - "demoiselle.properties").addPackages(false, DynamicMBeanProxyTestCase.class.getPackage()) + .addAsResource(new FileAsset(new File("src/test/resources/configuration/demoiselle.properties")),"demoiselle.properties") + .addPackages(false, DynamicMBeanProxyTestCase.class.getPackage()) .addClasses(LocaleProducer.class, ManagedTestClass.class); - + + mainDeployment.as(ZipExporter.class).exportTo( + new File("/home/81986912515/myPackage.jar"), true); + return mainDeployment; } - + /** * Testa se o bootstrap está corretamente carregando e registrando classes anotadas com {@link Managed} como MBeans. */ @@ -89,10 +93,12 @@ public class DynamicMBeanProxyTestCase { // o NotificationBroadcaster. Qualquer classe gerenciada criada pelo usuário // será adicionada a ela, então esperamos 2 MBeans aqui. Assert.assertEquals(2, manager.listRegisteredMBeans().size()); + } @Test public void testAttributeWrite() { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); ObjectName name = null; @@ -107,10 +113,12 @@ public class DynamicMBeanProxyTestCase { } catch (Exception e) { Assert.fail(e.getMessage()); } + } @Test public void testAttributeRead() { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); ObjectName name = null; @@ -129,6 +137,7 @@ public class DynamicMBeanProxyTestCase { } catch (Exception e) { Assert.fail(); } + } @Test @@ -156,6 +165,7 @@ public class DynamicMBeanProxyTestCase { @Test public void testTryWriteOverReadOnly() { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); ObjectName name = null; @@ -170,6 +180,6 @@ public class DynamicMBeanProxyTestCase { } catch (Exception e) { Assert.fail(e.getMessage()); } + } - } diff --git a/impl/extension/jmx/src/test/java/management/tests/internal/NotificationBroadcasterTestCase.java b/impl/extension/jmx/src/test/java/management/tests/internal/NotificationBroadcasterTestCase.java index 14a9e0b..edc4117 100644 --- a/impl/extension/jmx/src/test/java/management/tests/internal/NotificationBroadcasterTestCase.java +++ b/impl/extension/jmx/src/test/java/management/tests/internal/NotificationBroadcasterTestCase.java @@ -88,11 +88,12 @@ public class NotificationBroadcasterTestCase { public void sendMessageTest(){ JMXConfig config = Beans.getReference(JMXConfig.class); + //Este será o lado cliente. Este manager é usado para enviar notificações a partir do código da aplicação + NotificationManager notificationManager = Beans.getReference(NotificationManager.class); + //Obtém o servidor MBean onde anexaremos um listener para a notificação MBeanServer server = ManagementFactory.getPlatformMBeanServer(); - NotificationManager notificationManager = Beans.getReference(NotificationManager.class); - //Aqui obtemos o MBean de notificações já registrado pelo bootstrap StringBuffer notificationMBeanName = new StringBuffer() .append( config.getNotificationDomain()!=null ? config.getNotificationDomain() : "br.gov.frameworkdemoiselle.jmx" ) diff --git a/impl/extension/jmx/src/test/java/management/tests/internal/RemoteManagementTestCase.java b/impl/extension/jmx/src/test/java/management/tests/internal/RemoteManagementTestCase.java deleted file mode 100644 index 3e4321e..0000000 --- a/impl/extension/jmx/src/test/java/management/tests/internal/RemoteManagementTestCase.java +++ /dev/null @@ -1,90 +0,0 @@ -package management.tests.internal; - -import java.io.File; - -import javax.management.Attribute; -import javax.management.MBeanServerConnection; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXServiceURL; - -import management.LocaleProducer; -import management.domain.ManagedTestClass; - -import org.jboss.arquillian.container.test.api.Deployment; -import org.jboss.arquillian.container.test.api.RunAsClient; -import org.jboss.arquillian.junit.Arquillian; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.asset.FileAsset; -import org.jboss.shrinkwrap.api.spec.JavaArchive; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * - * Tests remote management using JMX. - * - *

- * TODO Currently you need to configure Eclipse Run configuration to pass - * system properties enabling remote management to the Java VM. Arquillian's - * current version doesn't support this. - *

- * - *

- * On a SUN virtual machine these properties need to be set to enable remote management: - *

    - *
  • com.sun.management.jmxremote.port=9999
  • - *
  • com.sun.management.jmxremote.authenticate=false
  • - *
  • com.sun.management.jmxremote.ssl=false
  • - *
- *

- * - * @author serpro - * - */ -@RunWith(Arquillian.class) -@Ignore -public class RemoteManagementTestCase { - - @Deployment(testable=false) - public static JavaArchive createDeployment() { - JavaArchive mainDeployment = ShrinkWrap.create(JavaArchive.class); - mainDeployment - .addPackages(true, "br") - .addAsResource(new FileAsset(new File("src/test/resources/test/beans.xml")), "beans.xml") - .addAsResource(new FileAsset(new File("src/test/resources/configuration/demoiselle.properties")), - "demoiselle.properties").addPackages(false, DynamicMBeanProxyTestCase.class.getPackage()) - .addClasses(LocaleProducer.class, ManagedTestClass.class); - - return mainDeployment; - } - - @Test - @RunAsClient - public void testRemotePropertyReading() { - try { - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi"); - JMXConnector jmxc = JMXConnectorFactory.connect(url, null); - MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); - - ObjectName name = null; - try { - name = new ObjectName("br.gov.frameworkdemoiselle.jmx.domain:name=ManagedTest"); - } catch (MalformedObjectNameException e) { - Assert.fail(); - } - - mbsc.setAttribute(name, new Attribute("attribute", "New Value")); - Object info = mbsc.getAttribute(name, "attribute"); - - Assert.assertEquals("New Value", info); - } catch (Exception e) { - Assert.fail(e.getMessage()); - } - } - -} diff --git a/impl/extension/jmx/src/test/resources/META-INF/beans.xml b/impl/extension/jmx/src/test/resources/META-INF/beans.xml index bb028b1..d85497f 100644 --- a/impl/extension/jmx/src/test/resources/META-INF/beans.xml +++ b/impl/extension/jmx/src/test/resources/META-INF/beans.xml @@ -1,7 +1,11 @@ - + br.gov.frameworkdemoiselle.transaction.TransactionalInterceptor + br.gov.frameworkdemoiselle.security.RequiredPermissionInterceptor + br.gov.frameworkdemoiselle.security.RequiredRoleInterceptor + br.gov.frameworkdemoiselle.exception.ExceptionHandlerInterceptor + diff --git a/impl/extension/jmx/src/test/resources/META-INF/persistence.xml b/impl/extension/jmx/src/test/resources/META-INF/persistence.xml deleted file mode 100644 index 0486d41..0000000 --- a/impl/extension/jmx/src/test/resources/META-INF/persistence.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - br.gov.frameworkdemoiselle.jmx.domain.PersistedTestClass - - - - - - - - - - - - - - - \ No newline at end of file -- libgit2 0.21.2