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 @@ |
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 | 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 | 47 | /** |
48 | 48 | * <p>Indicates that a field must be exposed as a property to management clients.</p> |
49 | 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 | 52 | * <p>It's a runtime error to annotate a field with no getter and no setter method.</p> |
52 | 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 | 54 | * methods as an operation using the {@link ManagedOperation} annotation.</p> |
... | ... | @@ -65,5 +66,36 @@ public @interface ManagedProperty { |
65 | 66 | */ |
66 | 67 | @Nonbinding |
67 | 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 | 47 | import br.gov.frameworkdemoiselle.DemoiselleException; |
48 | 48 | import br.gov.frameworkdemoiselle.annotation.ManagedOperation; |
49 | 49 | import br.gov.frameworkdemoiselle.annotation.ManagedProperty; |
50 | +import br.gov.frameworkdemoiselle.annotation.ManagedProperty.ManagedPropertyAccess; | |
50 | 51 | import br.gov.frameworkdemoiselle.annotation.OperationParameter; |
51 | 52 | import br.gov.frameworkdemoiselle.internal.producer.ResourceBundleProducer; |
52 | 53 | import br.gov.frameworkdemoiselle.stereotype.ManagementController; |
... | ... | @@ -195,6 +196,12 @@ public class ManagedType { |
195 | 196 | .append("get") |
196 | 197 | .append(field.getName().substring(0, 1).toUpperCase()) |
197 | 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 | 206 | Method getterMethod; |
200 | 207 | |
... | ... | @@ -227,6 +234,13 @@ public class ManagedType { |
227 | 234 | * Returns the public setter method for a given field, or <code>null</code> if no setter method can be found. |
228 | 235 | */ |
229 | 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 | 244 | StringBuffer setterMethodName = new StringBuffer() |
231 | 245 | .append("set") |
232 | 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 | 189 | deactivateContexts(managedType.getType()); |
190 | 190 | } |
191 | 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 | 194 | } else { |
195 | 195 | throw new DemoiselleException(bundle.getString("management-type-not-found")); |
... | ... | @@ -282,7 +282,7 @@ public class Management { |
282 | 282 | } |
283 | 283 | |
284 | 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 | 287 | } else { |
288 | 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 | 110 | management-introspection-error=Erro ao ler atributos da classe gerenciada {0} |
111 | 111 | management-type-not-found=A classe gerenciada informada n\u00E3o existe\: {0} |
112 | 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 | 115 | management-debug-acessing-property=Acessando propriedade {0} da classe gerenciada {1} |
114 | 116 | management-debug-setting-property=Definindo novo valor para propriedade {0} da classe gerenciada {1} |
115 | 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 | 169 | } |
170 | 170 | |
171 | 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 | 187 | public void testRequestScopedOperation() { |
173 | 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 | 42 | |
43 | 43 | import br.gov.frameworkdemoiselle.annotation.ManagedOperation; |
44 | 44 | import br.gov.frameworkdemoiselle.annotation.ManagedProperty; |
45 | +import br.gov.frameworkdemoiselle.annotation.ManagedProperty.ManagedPropertyAccess; | |
45 | 46 | import br.gov.frameworkdemoiselle.stereotype.ManagementController; |
46 | 47 | import br.gov.frameworkdemoiselle.util.Beans; |
47 | 48 | |
... | ... | @@ -71,6 +72,12 @@ public class DummyManagedClass { |
71 | 72 | @ManagedProperty |
72 | 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 | 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 | 199 | return gender; |
193 | 200 | } |
194 | 201 | |
195 | - | |
196 | 202 | public void setGender(String gender) { |
197 | 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 | 222 | @ManagedOperation |
201 | 223 | public String requestScopedOperation(){ |
202 | 224 | RequestScopeBeanClient client = Beans.getReference(RequestScopeBeanClient.class); | ... | ... |