Commit dbc9dcc2ced859a6efd7474125db081759718a37

Authored by Dancovich
1 parent 0d9f1260
Exists in master

-Alterada mensagem de erro ao ler propriedade inexistente em classe

gerenciada
-Adicionado recurso para marcar propriedade com apenas leitura ou
escrita ignorando presença ou ausência de métodos set e get
-Iniciada escrita de documentação
documentation/reference/pt-BR/gerenciamento.xml 0 → 100644
@@ -0,0 +1,62 @@ @@ -0,0 +1,62 @@
  1 +<?xml version='1.0' encoding="utf-8"?>
  2 +<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
  3 + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" []>
  4 +<chapter id="mensagem">
  5 +
  6 + <title>Monitoração e Gerenciamento de Recursos</title>
  7 +
  8 + <section>
  9 + <title>Por que monitorar e gerenciar aplicações</title>
  10 +
  11 + <para>Ao implantar um sistema para produção, muitas vezes é necessário monitorar aspectos sobre o funcionamento desse sistema. Quanta memória
  12 + ele está utilizando? Qual o pico de MIPS utilizados? Quantas sessões estão autenticadas no momento?</para>
  13 +
  14 + <para>Além de monitorar um sistema, as vezes é necessário gerencia-lo alterando aspectos de seu comportamento. Se o sistema está implantado em um
  15 + servidor alugado, talvez seja necessário ajustar o uso de MIPS para reduzir custos ou talvez deseje-se solicitar que o sistema limpe dados de sessão
  16 + de autenticação abandonados por usuários que desligaram suas estações sem efetuar "logoff".</para>
  17 +
  18 + <para>Para esse fim existem diversas tecnologias que permitem ao desenvolvedor expor aspectos monitoráveis e gerenciáves de seu sistema
  19 + para clientes de gerenciamento. Exemplos dessas tecnologias incluem o <emphasis>Simple Network Management Protocol</emphasis> (SNMP) e o
  20 + <emphasis>Java Management Extension</emphasis> (JMX).</para>
  21 +
  22 + <para>O <emphasis>Demoiselle Framework</emphasis> dispõe de uma série de ferramentas para nivelar
  23 + o conhecimento do desenvolvedor e facilitar o uso e integraçao de várias tecnologias de gerenciamento e monitoração. Através de seu
  24 + uso o desenvolvedor pode se despreocupar com detalhes de implementação de cada tecnologia individual e facilmente integrar tais tecnologias.</para>
  25 + </section>
  26 +
  27 + <section>
  28 + <title>Introdução ao mecanismo</title>
  29 +
  30 + <para>Para expor aspectos monitoráveis da sua aplicação, o primeiro passo é criar uma interface contendo os atributos monitoráveis e as operações
  31 + de gerenciamento que serão expostas para clientes de gerenciamento. Isso é feito através de uma simples classe Java (<emphasis>ou POJO</emphasis>)
  32 + anotada com o estereótipo <code>@ManagementController</code>.</para>
  33 +
  34 + <programlisting role="JAVA"><![CDATA[
  35 + @ManagementController
  36 + public class GerenciadorUsuarios]]></programlisting>
  37 +
  38 + <para>Essa anotação é suficiente para o mecanismo de gerenciamento descobrir sua classe e disponibiliza-la para ser monitorada e gerenciada.</para>
  39 +
  40 + <para>Contudo, a simples anotação acima não informa ao mecanismo quais aspectos da classe serão expostos. Por padrão, um <emphasis>Management Controller</emphasis>
  41 + não expõe nenhum aspecto seu. Para selecionais quais aspectos serão expostos usamos as anotações <code>@ManagedProperty</code> e <code>@ManagedOperation</code>.</para>
  42 +
  43 + <table>
  44 + <tbody>
  45 + <row>
  46 + <entry>
  47 + <emphasis role="BOLD">@ManagedProperty</emphasis>
  48 + </entry>
  49 + </row>
  50 +
  51 + <row>
  52 + <entry>
  53 + <para>Marca um atributo na classe como uma propriedade gerenciada, significando que clientes externos podem ler e/ou escrever valores nesses atributos.</para>
  54 + <para>Um</para>
  55 + </entry>
  56 + </row>
  57 + </tbody>
  58 + </table>
  59 +
  60 + </section>
  61 +
  62 +</chapter>
0 \ No newline at end of file 63 \ No newline at end of file
impl/core/src/main/java/br/gov/frameworkdemoiselle/annotation/ManagedProperty.java
@@ -47,7 +47,8 @@ import javax.enterprise.util.Nonbinding; @@ -47,7 +47,8 @@ import javax.enterprise.util.Nonbinding;
47 /** 47 /**
48 * <p>Indicates that a field must be exposed as a property to management clients.</p> 48 * <p>Indicates that a field must be exposed as a property to management clients.</p>
49 * <p>The property will be writable if there's a public setter method 49 * <p>The property will be writable if there's a public setter method
50 - * declared for the field and readable if there's a getter method.</p> 50 + * declared for the field and readable if there's a getter method. You can override this behaviour by passing a value
  51 + * to the {@link #accessLevel()} property.</p>
51 * <p>It's a runtime error to annotate a field with no getter and no setter method.</p> 52 * <p>It's a runtime error to annotate a field with no getter and no setter method.</p>
52 * <p>It's also a runtime error to declare a field as a property and one or both of it's getter and setter 53 * <p>It's also a runtime error to declare a field as a property and one or both of it's getter and setter
53 * methods as an operation using the {@link ManagedOperation} annotation.</p> 54 * methods as an operation using the {@link ManagedOperation} annotation.</p>
@@ -65,5 +66,36 @@ public @interface ManagedProperty { @@ -65,5 +66,36 @@ public @interface ManagedProperty {
65 */ 66 */
66 @Nonbinding 67 @Nonbinding
67 String description() default ""; 68 String description() default "";
  69 +
  70 + @Nonbinding
  71 + ManagedPropertyAccess accessLevel() default ManagedPropertyAccess.DEFAULT;
  72 +
  73 + /**
  74 + * <p>Access level of a managed property.</p>
  75 + *
  76 + * <p>These values only affect access via external management clients, the application is still able to inject and use the normal visibility of the property
  77 + * by Java standards.</p>
  78 + *
  79 + * @author serpro
  80 + *
  81 + */
  82 + enum ManagedPropertyAccess{
  83 +
  84 + /**
  85 + * Restricts a property to be only readable even if a setter method exists.
  86 + */
  87 + READ_ONLY
  88 +
  89 + /**
  90 + * Restricts a property to be only writeable even if a getter method exists.
  91 + */
  92 + ,WRITE_ONLY
  93 +
  94 + /**
  95 + * Says that the read or write access will
  96 + * be determined by the presence of a getter method <code>(getProperty())</code> or setter method <code>(setProperty(propertyValue))</code> for a property.
  97 + */
  98 + ,DEFAULT;
  99 + }
68 100
69 } 101 }
impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/ManagedType.java
@@ -47,6 +47,7 @@ import javax.inject.Qualifier; @@ -47,6 +47,7 @@ import javax.inject.Qualifier;
47 import br.gov.frameworkdemoiselle.DemoiselleException; 47 import br.gov.frameworkdemoiselle.DemoiselleException;
48 import br.gov.frameworkdemoiselle.annotation.ManagedOperation; 48 import br.gov.frameworkdemoiselle.annotation.ManagedOperation;
49 import br.gov.frameworkdemoiselle.annotation.ManagedProperty; 49 import br.gov.frameworkdemoiselle.annotation.ManagedProperty;
  50 +import br.gov.frameworkdemoiselle.annotation.ManagedProperty.ManagedPropertyAccess;
50 import br.gov.frameworkdemoiselle.annotation.OperationParameter; 51 import br.gov.frameworkdemoiselle.annotation.OperationParameter;
51 import br.gov.frameworkdemoiselle.internal.producer.ResourceBundleProducer; 52 import br.gov.frameworkdemoiselle.internal.producer.ResourceBundleProducer;
52 import br.gov.frameworkdemoiselle.stereotype.ManagementController; 53 import br.gov.frameworkdemoiselle.stereotype.ManagementController;
@@ -195,6 +196,12 @@ public class ManagedType { @@ -195,6 +196,12 @@ public class ManagedType {
195 .append("get") 196 .append("get")
196 .append(field.getName().substring(0, 1).toUpperCase()) 197 .append(field.getName().substring(0, 1).toUpperCase())
197 .append(field.getName().substring(1)); 198 .append(field.getName().substring(1));
  199 +
  200 + //Se propriedade está anotada como WRITE-ONLY, ignora essa etapa.
  201 + ManagedProperty annotation = field.getAnnotation(ManagedProperty.class);
  202 + if (annotation.accessLevel() == ManagedPropertyAccess.WRITE_ONLY){
  203 + return null;
  204 + }
198 205
199 Method getterMethod; 206 Method getterMethod;
200 207
@@ -227,6 +234,13 @@ public class ManagedType { @@ -227,6 +234,13 @@ public class ManagedType {
227 * Returns the public setter method for a given field, or <code>null</code> if no setter method can be found. 234 * Returns the public setter method for a given field, or <code>null</code> if no setter method can be found.
228 */ 235 */
229 private Method getSetterMethod(Field field) { 236 private Method getSetterMethod(Field field) {
  237 +
  238 + //Se propriedade está anotada como READ-ONLY, ignora essa etapa.
  239 + ManagedProperty annotation = field.getAnnotation(ManagedProperty.class);
  240 + if (annotation.accessLevel() == ManagedPropertyAccess.READ_ONLY){
  241 + return null;
  242 + }
  243 +
230 StringBuffer setterMethodName = new StringBuffer() 244 StringBuffer setterMethodName = new StringBuffer()
231 .append("set") 245 .append("set")
232 .append(field.getName().substring(0, 1).toUpperCase()) 246 .append(field.getName().substring(0, 1).toUpperCase())
impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/management/Management.java
@@ -189,7 +189,7 @@ public class Management { @@ -189,7 +189,7 @@ public class Management {
189 deactivateContexts(managedType.getType()); 189 deactivateContexts(managedType.getType());
190 } 190 }
191 } else { 191 } else {
192 - throw new DemoiselleException(bundle.getString("management-invoke-error", propertyName)); 192 + throw new DemoiselleException(bundle.getString("management-read-value-error", propertyName));
193 } 193 }
194 } else { 194 } else {
195 throw new DemoiselleException(bundle.getString("management-type-not-found")); 195 throw new DemoiselleException(bundle.getString("management-type-not-found"));
@@ -282,7 +282,7 @@ public class Management { @@ -282,7 +282,7 @@ public class Management {
282 } 282 }
283 283
284 } else { 284 } else {
285 - throw new DemoiselleException(bundle.getString("management-invoke-error", propertyName)); 285 + throw new DemoiselleException(bundle.getString("management-write-value-error", propertyName));
286 } 286 }
287 } else { 287 } else {
288 throw new DemoiselleException(bundle.getString("management-type-not-found")); 288 throw new DemoiselleException(bundle.getString("management-type-not-found"));
impl/core/src/main/resources/demoiselle-core-bundle.properties
@@ -110,6 +110,8 @@ management-invalid-property-as-operation=Falha ao inicializar classe gerenciada @@ -110,6 +110,8 @@ management-invalid-property-as-operation=Falha ao inicializar classe gerenciada
110 management-introspection-error=Erro ao ler atributos da classe gerenciada {0} 110 management-introspection-error=Erro ao ler atributos da classe gerenciada {0}
111 management-type-not-found=A classe gerenciada informada n\u00E3o existe\: {0} 111 management-type-not-found=A classe gerenciada informada n\u00E3o existe\: {0}
112 management-invoke-error=Erro ao tentar invocar a opera\u00E7\u00E3o "{0}" da classe gerenciada, a opera\u00E7\u00E3o n\u00E3o foi encontrada 112 management-invoke-error=Erro ao tentar invocar a opera\u00E7\u00E3o "{0}" da classe gerenciada, a opera\u00E7\u00E3o n\u00E3o foi encontrada
  113 +management-write-value-error=N\u00E3o foi poss\u00EDvel definir um valor para a propriedade {0}
  114 +management-read-value-error=N\u00E3o foi poss\u00EDvel ler o valor da propriedade {0}
113 management-debug-acessing-property=Acessando propriedade {0} da classe gerenciada {1} 115 management-debug-acessing-property=Acessando propriedade {0} da classe gerenciada {1}
114 management-debug-setting-property=Definindo novo valor para propriedade {0} da classe gerenciada {1} 116 management-debug-setting-property=Definindo novo valor para propriedade {0} da classe gerenciada {1}
115 management-debug-invoking-operation=Invocando opera\u00E7\u00E3o {0} da classe gerenciada {1} 117 management-debug-invoking-operation=Invocando opera\u00E7\u00E3o {0} da classe gerenciada {1}
impl/core/src/test/java/management/ManagementTestCase.java
@@ -169,6 +169,21 @@ public class ManagementTestCase { @@ -169,6 +169,21 @@ public class ManagementTestCase {
169 } 169 }
170 170
171 @Test 171 @Test
  172 + public void testAccessLevelControl(){
  173 + //tentamos escrever em uma propriedade que, apesar de ter método setter, está marcada como read-only.
  174 + ManagedClassStore store = Beans.getReference(ManagedClassStore.class);
  175 +
  176 + try{
  177 + store.setProperty(DummyManagedClass.class, "readOnlyPropertyWithSetMethod","A Value");
  178 + Assert.fail();
  179 + }
  180 + catch(DemoiselleException de){
  181 + System.out.println(de.getMessage());
  182 + //success
  183 + }
  184 + }
  185 +
  186 + @Test
172 public void testRequestScopedOperation() { 187 public void testRequestScopedOperation() {
173 ManagedClassStore store = Beans.getReference(ManagedClassStore.class); 188 ManagedClassStore store = Beans.getReference(ManagedClassStore.class);
174 189
impl/core/src/test/java/management/testclasses/DummyManagedClass.java
@@ -42,6 +42,7 @@ import javax.validation.constraints.NotNull; @@ -42,6 +42,7 @@ import javax.validation.constraints.NotNull;
42 42
43 import br.gov.frameworkdemoiselle.annotation.ManagedOperation; 43 import br.gov.frameworkdemoiselle.annotation.ManagedOperation;
44 import br.gov.frameworkdemoiselle.annotation.ManagedProperty; 44 import br.gov.frameworkdemoiselle.annotation.ManagedProperty;
  45 +import br.gov.frameworkdemoiselle.annotation.ManagedProperty.ManagedPropertyAccess;
45 import br.gov.frameworkdemoiselle.stereotype.ManagementController; 46 import br.gov.frameworkdemoiselle.stereotype.ManagementController;
46 import br.gov.frameworkdemoiselle.util.Beans; 47 import br.gov.frameworkdemoiselle.util.Beans;
47 48
@@ -71,6 +72,12 @@ public class DummyManagedClass { @@ -71,6 +72,12 @@ public class DummyManagedClass {
71 @ManagedProperty 72 @ManagedProperty
72 private String readOnlyProperty = "Default Value"; 73 private String readOnlyProperty = "Default Value";
73 74
  75 + @ManagedProperty(accessLevel=ManagedPropertyAccess.READ_ONLY)
  76 + private String readOnlyPropertyWithSetMethod = "Default Value";
  77 +
  78 + @ManagedProperty(accessLevel=ManagedPropertyAccess.WRITE_ONLY)
  79 + private String writeOnlyPropertyWithGetMethod;
  80 +
74 /** 81 /**
75 * Propriedade para testar detecção de métodos GET e SET quando propriedade tem apenas uma letra. 82 * Propriedade para testar detecção de métodos GET e SET quando propriedade tem apenas uma letra.
76 */ 83 */
@@ -192,11 +199,26 @@ public class DummyManagedClass { @@ -192,11 +199,26 @@ public class DummyManagedClass {
192 return gender; 199 return gender;
193 } 200 }
194 201
195 -  
196 public void setGender(String gender) { 202 public void setGender(String gender) {
197 this.gender = gender; 203 this.gender = gender;
198 } 204 }
199 205
  206 + public String getReadOnlyPropertyWithSetMethod() {
  207 + return readOnlyPropertyWithSetMethod;
  208 + }
  209 +
  210 + public void setReadOnlyPropertyWithSetMethod(String readOnlyPropertyWithSetMethod) {
  211 + this.readOnlyPropertyWithSetMethod = readOnlyPropertyWithSetMethod;
  212 + }
  213 +
  214 + public String getWriteOnlyPropertyWithGetMethod() {
  215 + return writeOnlyPropertyWithGetMethod;
  216 + }
  217 +
  218 + public void setWriteOnlyPropertyWithGetMethod(String writeOnlyPropertyWithGetMethod) {
  219 + this.writeOnlyPropertyWithGetMethod = writeOnlyPropertyWithGetMethod;
  220 + }
  221 +
200 @ManagedOperation 222 @ManagedOperation
201 public String requestScopedOperation(){ 223 public String requestScopedOperation(){
202 RequestScopeBeanClient client = Beans.getReference(RequestScopeBeanClient.class); 224 RequestScopeBeanClient client = Beans.getReference(RequestScopeBeanClient.class);