Commit dbc9dcc2ced859a6efd7474125db081759718a37
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
Showing
7 changed files
with
151 additions
and
4 deletions
Show diff stats
@@ -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); |