Commit 6c692bd5843eb2d5f873b7ae5bbf7aa76b5e8f35

Authored by Dancovich
1 parent eedd4c0d
Exists in master

-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
1 1 package br.gov.frameworkdemoiselle.internal.bootstrap;
2 2  
  3 +import java.lang.reflect.Modifier;
3 4 import java.util.ArrayList;
4 5 import java.util.Collections;
5 6 import java.util.List;
  7 +import java.util.Locale;
6 8 import java.util.Set;
7 9  
8 10 import javax.enterprise.event.Observes;
... ... @@ -15,13 +17,16 @@ import javax.enterprise.inject.spi.BeforeShutdown;
15 17 import javax.enterprise.inject.spi.Extension;
16 18 import javax.enterprise.inject.spi.ProcessAnnotatedType;
17 19  
  20 +import br.gov.frameworkdemoiselle.DemoiselleException;
18 21 import br.gov.frameworkdemoiselle.internal.context.ContextManager;
19 22 import br.gov.frameworkdemoiselle.internal.context.ManagedContext;
20 23 import br.gov.frameworkdemoiselle.internal.management.ManagedType;
21 24 import br.gov.frameworkdemoiselle.internal.management.Management;
  25 +import br.gov.frameworkdemoiselle.internal.producer.ResourceBundleProducer;
22 26 import br.gov.frameworkdemoiselle.lifecycle.ManagementExtension;
23 27 import br.gov.frameworkdemoiselle.stereotype.ManagementController;
24 28 import br.gov.frameworkdemoiselle.util.Beans;
  29 +import br.gov.frameworkdemoiselle.util.ResourceBundle;
25 30  
26 31 public class ManagementBootstrap implements Extension {
27 32  
... ... @@ -43,8 +48,14 @@ public class ManagementBootstrap implements Extension {
43 48  
44 49 @SuppressWarnings("unchecked")
45 50 public void registerAvailableManagedTypes(@Observes final AfterDeploymentValidation event,BeanManager beanManager) {
  51 + ResourceBundle bundle = ResourceBundleProducer.create("demoiselle-core-bundle", Locale.getDefault());
  52 +
46 53 Management monitoringManager = Beans.getReference(Management.class);
47 54 for (AnnotatedType<?> type : types) {
  55 + if (type.getJavaClass().isInterface() || Modifier.isAbstract(type.getJavaClass().getModifiers()) ){
  56 + throw new DemoiselleException(bundle.getString("management-abstract-class-defined" , type.getJavaClass().getCanonicalName()));
  57 + }
  58 +
48 59 ManagedType managedType = new ManagedType(type.getJavaClass());
49 60 monitoringManager.addManagedType(managedType);
50 61 }
... ...
impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/ManagedType.java
... ... @@ -39,8 +39,11 @@ package br.gov.frameworkdemoiselle.internal.management;
39 39 import java.lang.annotation.Annotation;
40 40 import java.lang.reflect.Field;
41 41 import java.lang.reflect.Method;
  42 +import java.util.ArrayList;
42 43 import java.util.TreeMap;
43 44  
  45 +import javax.inject.Qualifier;
  46 +
44 47 import br.gov.frameworkdemoiselle.DemoiselleException;
45 48 import br.gov.frameworkdemoiselle.annotation.ManagedOperation;
46 49 import br.gov.frameworkdemoiselle.annotation.ManagedProperty;
... ... @@ -60,6 +63,8 @@ import br.gov.frameworkdemoiselle.util.ResourceBundle;
60 63 public class ManagedType {
61 64  
62 65 private Class<?> type;
  66 +
  67 + private Annotation[] qualifiers;
63 68  
64 69 private TreeMap<String, FieldDetail> fields;
65 70  
... ... @@ -83,6 +88,7 @@ public class ManagedType {
83 88 fields = new TreeMap<String, FieldDetail>();
84 89 operationMethods = new TreeMap<String, MethodDetail>();
85 90 this.description = type.getAnnotation(ManagementController.class).description();
  91 + this.qualifiers = getQualifierAnnotations(type);
86 92  
87 93 initialize();
88 94 }
... ... @@ -102,6 +108,18 @@ public class ManagedType {
102 108 public TreeMap<String, MethodDetail> getOperationMethods() {
103 109 return operationMethods;
104 110 }
  111 +
  112 + /**
  113 + * <p>Return a (possibly empty) list of all qualifiers this type have. Qualifiers
  114 + * are any annotations marked as {@link Qualifier}.</p>
  115 + *
  116 + * <p>This method returns the true list of qualifiers. If implementators change this list, it will
  117 + * affect future calls of this method. This is so that resources can be spared by not creating many instances of this list.</p>
  118 + *
  119 + */
  120 + public Annotation[] getQualifiers(){
  121 + return this.qualifiers;
  122 + }
105 123  
106 124 private void initialize() {
107 125 // 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 {
224 242  
225 243 return setterMethod;
226 244 }
  245 +
  246 + /**
  247 + * Indicates another {@link ManagedType} represents the same {@link Class} as this one. This method also supports a
  248 + * {@link Class} as a parameter, in this case it will return <code>true</code> if the passed class is exactly the
  249 + * same Java class represented by this {@link ManagedType}.
  250 + */
  251 + @Override
  252 + public boolean equals(Object other) {
  253 + if (other == null) {
  254 + return false;
  255 + }
  256 +
  257 + return ((ManagedType) other).getType().getCanonicalName().equals(this.getType().getCanonicalName());
  258 + }
  259 +
  260 + private synchronized Annotation[] getQualifierAnnotations(Class<?> beanClass){
  261 + Annotation[] annotations = beanClass.getAnnotations();
  262 + ArrayList<Annotation> qualifiers = new ArrayList<Annotation>(annotations.length);
  263 +
  264 + for (int i=0; i<annotations.length; i++){
  265 + if (annotations[i].annotationType().getAnnotation(Qualifier.class) != null){
  266 + qualifiers.add(annotations[i]);
  267 + }
  268 + }
  269 +
  270 + return qualifiers.toArray(new Annotation[0]);
  271 + }
227 272  
228 273 public final class FieldDetail {
229 274  
... ... @@ -317,18 +362,4 @@ public class ManagedType {
317 362 return parameterDescription;
318 363 }
319 364 }
320   -
321   - /**
322   - * Indicates another {@link ManagedType} represents the same {@link Class} as this one. This method also supports a
323   - * {@link Class} as a parameter, in this case it will return <code>true</code> if the passed class is exactly the
324   - * same Java class represented by this {@link ManagedType}.
325   - */
326   - @Override
327   - public boolean equals(Object other) {
328   - if (other == null) {
329   - return false;
330   - }
331   -
332   - return ((ManagedType) other).getType().getCanonicalName().equals(this.getType().getCanonicalName());
333   - }
334 365 }
... ...
impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/Management.java
... ... @@ -129,7 +129,7 @@ public class Management {
129 129 activateContexts(managedType.getType());
130 130  
131 131 try {
132   - Object delegate = Beans.getReference(managedType.getType());
  132 + Object delegate = Beans.getReference(managedType.getType() , managedType.getQualifiers());
133 133 MethodDetail method = managedType.getOperationMethods().get(actionName);
134 134  
135 135 if (method != null) {
... ... @@ -179,7 +179,7 @@ public class Management {
179 179 activateContexts(managedType.getType());
180 180  
181 181 try {
182   - Object delegate = Beans.getReference(managedType.getType());
  182 + Object delegate = Beans.getReference(managedType.getType() , managedType.getQualifiers());
183 183  
184 184 return getterMethod.invoke(delegate, (Object[]) null);
185 185 } catch (Exception e) {
... ... @@ -227,7 +227,7 @@ public class Management {
227 227 // Obtém uma instância da classe gerenciada, lembrando que
228 228 // classes
229 229 // anotadas com @ManagementController são sempre singletons.
230   - Object delegate = Beans.getReference(managedType.getType());
  230 + Object delegate = Beans.getReference(managedType.getType() , managedType.getQualifiers() );
231 231  
232 232 // Se houver um validador anexado à propriedade alterada, executa o validador sobre
233 233 // o novo valor.
... ... @@ -343,5 +343,6 @@ public class Management {
343 343  
344 344 return this.validator;
345 345 }
  346 +
346 347  
347 348 }
... ...
impl/core/src/main/java/br/gov/frameworkdemoiselle/stereotype/ManagementController.java
... ... @@ -49,12 +49,14 @@ import javax.enterprise.inject.Stereotype;
49 49 import javax.enterprise.util.Nonbinding;
50 50  
51 51 /**
52   - * <p>Identifies a <b>management controller</b> class. What it means is that an external client can manage the application
  52 + * <p>Identifies a <b>management controller</b> bean. What it means is that an external client can manage the application
53 53 * this class is in by reading or writing it's attributes and calling it's operations.</p>
54 54 * <p>
55 55 * Only fields annotated with {@link br.gov.frameworkdemoiselle.annotation.ManagedProperty} or
56 56 * methods annotated with {@link br.gov.frameworkdemoiselle.annotation.ManagedOperation} will be exposed
57 57 * to clients.</p>
  58 + * <p>Only bean implementations (concrete classes) can be management controllers. It's a runtime error to mark an interface
  59 + * or abstract class with this annotation.</p>
58 60 * <p>This stereotype only defines a class as managed, you need to choose an extension that will expose this managed class
59 61 * to external clients using any technology available. One example is the Demoiselle JMX extension, that will expose
60 62 * managed classes as MBeans.</p>
... ...
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}
102 102 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.
103 103  
104 104 management-notification-attribute-changed=O atributo [{0}] da classe gerenciada [{1}] foi alterado
105   -management-null-class-defined=A classe gerenciada informada n\u00E3o pode ser nula
106   -management-no-annotation-found=Classe {0} precisa ser anotada com @Managed
  105 +management-null-class-defined=O controlador de gerenciamento informado n\u00E3o pode ser [null]
  106 +management-abstract-class-defined=O controlador de gerenciamento [{0}] precisa ser uma classe concreta
  107 +management-no-annotation-found=Classe {0} precisa ser anotada com @ManagementController
107 108 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}
108 109 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
109 110 management-introspection-error=Erro ao ler atributos da classe gerenciada {0}
... ...
impl/extension/jmx/src/test/java/management/tests/internal/DynamicMBeanProxyTestCase.java
... ... @@ -52,6 +52,7 @@ import org.jboss.arquillian.container.test.api.Deployment;
52 52 import org.jboss.arquillian.junit.Arquillian;
53 53 import org.jboss.shrinkwrap.api.ShrinkWrap;
54 54 import org.jboss.shrinkwrap.api.asset.FileAsset;
  55 +import org.jboss.shrinkwrap.api.exporter.ZipExporter;
55 56 import org.jboss.shrinkwrap.api.spec.JavaArchive;
56 57 import org.junit.Test;
57 58 import org.junit.runner.RunWith;
... ... @@ -68,13 +69,16 @@ public class DynamicMBeanProxyTestCase {
68 69 mainDeployment
69 70 .addPackages(true, "br")
70 71 .addAsResource(new FileAsset(new File("src/test/resources/test/beans.xml")), "beans.xml")
71   - .addAsResource(new FileAsset(new File("src/test/resources/configuration/demoiselle.properties")),
72   - "demoiselle.properties").addPackages(false, DynamicMBeanProxyTestCase.class.getPackage())
  72 + .addAsResource(new FileAsset(new File("src/test/resources/configuration/demoiselle.properties")),"demoiselle.properties")
  73 + .addPackages(false, DynamicMBeanProxyTestCase.class.getPackage())
73 74 .addClasses(LocaleProducer.class, ManagedTestClass.class);
74   -
  75 +
  76 + mainDeployment.as(ZipExporter.class).exportTo(
  77 + new File("/home/81986912515/myPackage.jar"), true);
  78 +
75 79 return mainDeployment;
76 80 }
77   -
  81 +
78 82 /**
79 83 * Testa se o bootstrap está corretamente carregando e registrando classes anotadas com {@link Managed} como MBeans.
80 84 */
... ... @@ -89,10 +93,12 @@ public class DynamicMBeanProxyTestCase {
89 93 // o NotificationBroadcaster. Qualquer classe gerenciada criada pelo usuário
90 94 // será adicionada a ela, então esperamos 2 MBeans aqui.
91 95 Assert.assertEquals(2, manager.listRegisteredMBeans().size());
  96 +
92 97 }
93 98  
94 99 @Test
95 100 public void testAttributeWrite() {
  101 +
96 102 MBeanServer server = ManagementFactory.getPlatformMBeanServer();
97 103  
98 104 ObjectName name = null;
... ... @@ -107,10 +113,12 @@ public class DynamicMBeanProxyTestCase {
107 113 } catch (Exception e) {
108 114 Assert.fail(e.getMessage());
109 115 }
  116 +
110 117 }
111 118  
112 119 @Test
113 120 public void testAttributeRead() {
  121 +
114 122 MBeanServer server = ManagementFactory.getPlatformMBeanServer();
115 123  
116 124 ObjectName name = null;
... ... @@ -129,6 +137,7 @@ public class DynamicMBeanProxyTestCase {
129 137 } catch (Exception e) {
130 138 Assert.fail();
131 139 }
  140 +
132 141 }
133 142  
134 143 @Test
... ... @@ -156,6 +165,7 @@ public class DynamicMBeanProxyTestCase {
156 165  
157 166 @Test
158 167 public void testTryWriteOverReadOnly() {
  168 +
159 169 MBeanServer server = ManagementFactory.getPlatformMBeanServer();
160 170  
161 171 ObjectName name = null;
... ... @@ -170,6 +180,6 @@ public class DynamicMBeanProxyTestCase {
170 180 } catch (Exception e) {
171 181 Assert.fail(e.getMessage());
172 182 }
  183 +
173 184 }
174   -
175 185 }
... ...
impl/extension/jmx/src/test/java/management/tests/internal/NotificationBroadcasterTestCase.java
... ... @@ -88,11 +88,12 @@ public class NotificationBroadcasterTestCase {
88 88 public void sendMessageTest(){
89 89 JMXConfig config = Beans.getReference(JMXConfig.class);
90 90  
  91 + //Este será o lado cliente. Este manager é usado para enviar notificações a partir do código da aplicação
  92 + NotificationManager notificationManager = Beans.getReference(NotificationManager.class);
  93 +
91 94 //Obtém o servidor MBean onde anexaremos um listener para a notificação
92 95 MBeanServer server = ManagementFactory.getPlatformMBeanServer();
93 96  
94   - NotificationManager notificationManager = Beans.getReference(NotificationManager.class);
95   -
96 97 //Aqui obtemos o MBean de notificações já registrado pelo bootstrap
97 98 StringBuffer notificationMBeanName = new StringBuffer()
98 99 .append( config.getNotificationDomain()!=null ? config.getNotificationDomain() : "br.gov.frameworkdemoiselle.jmx" )
... ...
impl/extension/jmx/src/test/java/management/tests/internal/RemoteManagementTestCase.java
... ... @@ -1,90 +0,0 @@
1   -package management.tests.internal;
2   -
3   -import java.io.File;
4   -
5   -import javax.management.Attribute;
6   -import javax.management.MBeanServerConnection;
7   -import javax.management.MalformedObjectNameException;
8   -import javax.management.ObjectName;
9   -import javax.management.remote.JMXConnector;
10   -import javax.management.remote.JMXConnectorFactory;
11   -import javax.management.remote.JMXServiceURL;
12   -
13   -import management.LocaleProducer;
14   -import management.domain.ManagedTestClass;
15   -
16   -import org.jboss.arquillian.container.test.api.Deployment;
17   -import org.jboss.arquillian.container.test.api.RunAsClient;
18   -import org.jboss.arquillian.junit.Arquillian;
19   -import org.jboss.shrinkwrap.api.ShrinkWrap;
20   -import org.jboss.shrinkwrap.api.asset.FileAsset;
21   -import org.jboss.shrinkwrap.api.spec.JavaArchive;
22   -import org.junit.Assert;
23   -import org.junit.Ignore;
24   -import org.junit.Test;
25   -import org.junit.runner.RunWith;
26   -
27   -/**
28   - *
29   - * Tests remote management using JMX.
30   - *
31   - * <p>
32   - * TODO Currently you need to configure Eclipse Run configuration to pass
33   - * system properties enabling remote management to the Java VM. Arquillian's
34   - * current version doesn't support this.
35   - * </p>
36   - *
37   - * <p>
38   - * On a SUN virtual machine these properties need to be set to enable remote management:
39   - * <ul>
40   - * <li>com.sun.management.jmxremote.port=9999</li>
41   - * <li>com.sun.management.jmxremote.authenticate=false</li>
42   - * <li>com.sun.management.jmxremote.ssl=false</li>
43   - * </ul>
44   - * </p>
45   - *
46   - * @author serpro
47   - *
48   - */
49   -@RunWith(Arquillian.class)
50   -@Ignore
51   -public class RemoteManagementTestCase {
52   -
53   - @Deployment(testable=false)
54   - public static JavaArchive createDeployment() {
55   - JavaArchive mainDeployment = ShrinkWrap.create(JavaArchive.class);
56   - mainDeployment
57   - .addPackages(true, "br")
58   - .addAsResource(new FileAsset(new File("src/test/resources/test/beans.xml")), "beans.xml")
59   - .addAsResource(new FileAsset(new File("src/test/resources/configuration/demoiselle.properties")),
60   - "demoiselle.properties").addPackages(false, DynamicMBeanProxyTestCase.class.getPackage())
61   - .addClasses(LocaleProducer.class, ManagedTestClass.class);
62   -
63   - return mainDeployment;
64   - }
65   -
66   - @Test
67   - @RunAsClient
68   - public void testRemotePropertyReading() {
69   - try {
70   - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");
71   - JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
72   - MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
73   -
74   - ObjectName name = null;
75   - try {
76   - name = new ObjectName("br.gov.frameworkdemoiselle.jmx.domain:name=ManagedTest");
77   - } catch (MalformedObjectNameException e) {
78   - Assert.fail();
79   - }
80   -
81   - mbsc.setAttribute(name, new Attribute("attribute", "New Value"));
82   - Object info = mbsc.getAttribute(name, "attribute");
83   -
84   - Assert.assertEquals("New Value", info);
85   - } catch (Exception e) {
86   - Assert.fail(e.getMessage());
87   - }
88   - }
89   -
90   -}
impl/extension/jmx/src/test/resources/META-INF/beans.xml
1   -<?xml version="1.0" encoding="UTF-8"?>
2 1 <beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 2 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
  3 +
4 4 <interceptors>
5 5 <class>br.gov.frameworkdemoiselle.transaction.TransactionalInterceptor</class>
  6 + <class>br.gov.frameworkdemoiselle.security.RequiredPermissionInterceptor</class>
  7 + <class>br.gov.frameworkdemoiselle.security.RequiredRoleInterceptor</class>
  8 + <class>br.gov.frameworkdemoiselle.exception.ExceptionHandlerInterceptor</class>
6 9 </interceptors>
  10 +
7 11 </beans>
... ...
impl/extension/jmx/src/test/resources/META-INF/persistence.xml
... ... @@ -1,22 +0,0 @@
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3   - xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
4   -
5   - <persistence-unit name="bookmark-ds" transaction-type="RESOURCE_LOCAL">
6   -
7   - <class>br.gov.frameworkdemoiselle.jmx.domain.PersistedTestClass</class>
8   -
9   - <properties>
10   - <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" />
11   - <property name="javax.persistence.jdbc.user" value="sa" />
12   - <property name="javax.persistence.jdbc.password" value="" />
13   - <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:hsql:." />
14   -
15   - <property name="eclipselink.logging.level" value="FINE" />
16   - <property name="eclipselink.ddl-generation" value="create-tables" />
17   - <property name="eclipselink.ddl-generation.output-mode" value="database" />
18   - </properties>
19   - </persistence-unit>
20   -
21   -
22   -</persistence>
23 0 \ No newline at end of file