configuracao.xml
13.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" []>
<chapter id="configuracao">
<title>Configuração</title>
<section>
<title>Configurações em uma aplicação</title>
<para>
Em aplicações no modelo Java EE, as quais são hospedadas em um servidor de aplicações ou contêiner Web,
existem diversos papéis além do desenvolvedor, tais como assembler e deployer. É comum nestas aplicações que informações
de configuração de ambiente, especialmente por questões de segurança, sejam de conhecimento restrito. Por exemplo,
o usuário e senha de um banco de dados ou o nome de uma fila de mensagens são informações que o desenvolvedor não deve
possuir, pelo menos para o ambiente de produção. Além disso, o profissional responsável pelo deploy (i.e., a implantação)
da aplicação geralmente não pode ser encarregado de recompilar os códigos fontes para efetivar a alteração desses dados.
</para>
<para>
Para resolver essas questões, faz-se necessário um <emphasis>mecanismo de configuração</emphasis> para as aplicações.
O desenvolvedor e o assembler constroem inteiramente uma aplicação e entregam o respectivo arquivo para o deployer
colocá-la em produção. Paralelamente a isso, o deployer configura arquivos externos e variáveis de sistema com as
informações sigilosas e protegidas que serão posteriormente lidas pela aplicação. A aplicação não precisará ser
reconstruída caso um dado de configuração precise ser modificado.
</para>
<para>
Frequentemente em Java utilizamos as seguintes abordagens para armazenar as configurações:
<itemizedlist>
<listitem>
<emphasis>arquivo de propriedades</emphasis>: tratam-se de simples arquivos de texto nomeados com a extensão
<filename>.properties</filename> e que internamente são escritos com a sintaxe <literal>chave = valor</literal>,
armazenando uma única chave por linha;
</listitem>
<listitem>
<emphasis>arquivo XML</emphasis>: são arquivos de texto altamente estruturados com a sintaxe de tags e que
permitem uma maior validação de seus valores, sendo geralmente nomeados com a extensão <filename>.xml</filename>;
</listitem>
<listitem>
<emphasis>variáveis de ambiente</emphasis>: valores definidos a nível de sistema operacional, independente de
plataforma (Windows, Linux, etc) e que podem ser recuperados durante a execução da aplicação.
</listitem>
</itemizedlist>
</para>
<para>
Na seção a seguir veremos como o <emphasis>Demoiselle Framework</emphasis> apoia o desenvolvimento de aplicações nas tarefas
de carregamento de configurações. Tal mecanismo é comumente utilizado internamente em diversos componentes do framework.
</para>
</section>
<!--
<section>
<title>Configurando</title>
<para>
Para um correto funcionamento do Demoiselle é necessário inserir o interceptador de configuração no arquivo <filename>src/main/WEB-INF/beans.xml</filename>.
</para>
<programlisting role="XML">
<![CDATA[
<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<interceptors>
<class>br.gov.frameworkdemoiselle.internal.interceptor.ConfigurationInterceptor</class>
</interceptors>
</beans>
]]>
</programlisting>
</section>
-->
<section>
<title>As classes de configuração</title>
<para>
A primeira etapa para a utilização do mecanismo de configuração em uma aplicação consiste em criar uma classe específica
para armazenar os parâmetros desejados e anotá-la com <literal>@Configuration</literal>. Eis um exemplo:
</para>
<programlisting role="JAVA"><![CDATA[@Configuration(resource = "bookmark")
public class BookmarkConfig {
private String applicationTitle;
private boolean loadInitialData;
public String getApplicationTitle() {
return applicationTitle;
}
public boolean isLoadInitialData() {
return loadInitialData;
}
}]]></programlisting>
<para>
Na classe os atributos devem ser tratados como sendo somente de leitura, possuindo apenas seus respectivos métodos
<emphasis>getter</emphasis>. Valores default podem ser especificados com literais na própria declaração do atributo
(ex: <literal>boolean loadInitialData = true</literal>).
</para>
<note>
<para>
As classes anotadas com <literal>@Configuration</literal> são tratadas de forma diferenciada pelo contêiner. Elas
são instanciadas uma única vez (seguindo o padrão de projeto <emphasis>singleton</emphasis>) e podem ser utilizadas
em qualquer ponto da aplicação. Seu ciclo de vida é gerenciado automaticamente pela implementação CDI. O arquivo de
recursos especificado é lido apenas na inicialização da aplicação e os atributos da classe são preenchidos
automaticamente nessa etapa.
</para>
</note>
<para>
No exemplo em questão, será buscado um arquivo de propriedades com o nome <filename>bookmark.properties</filename>
contendo as seguintes chaves:
</para>
<programlisting><![CDATA[application.title = Título da Aplicação
load.initial.data = true
]]></programlisting>
<note>
<para>
Recomenda-se usar o sufixo <quote>Config</quote> em uma classe de configuração para indicá-la como tal.
</para>
</note>
<para>
O nome do recurso (<literal>resource</literal>) e o tipo de configuração (<literal>type</literal>) são argumentos
opcionais na anotação <literal>@Configuration</literal>. Caso não sejam especificados, será considerado o arquivo
de propriedades padrão do <emphasis>Demoiselle Framework</emphasis>, o <filename>demoiselle.properties</filename>.
</para>
</section>
<section>
<title>Especificando os parâmetros</title>
<para>
Por padrão todos os atributos existentes em uma classe anotada com <literal>@Configuration</literal> são tratados
como parâmetros de configuração e serão automaticamente preenchidos durante a leitura do arquivo de recursos.
</para>
<tip>
<para>
Para indicar que um determinado atributo da classe não corresponde a um parâmetro, utilize a anotação
<literal>@Ignore</literal> nele. Desta forma ele será desconsiderado no momento de leitura da configuração.
</para>
</tip>
<tip>
<para>
Para forçar a existência de um parâmetro de configuração, utilize a anotação <literal>@NotNull</literal> no
respectivo atributo. Caso ele não seja encontrado no recurso, uma exceção será lançada na inicialização da
aplicação.
</para>
</tip>
<para>
No arquivo de recursos será buscada a chave correspondente ao atributo seguindo convenções pré-determinadas.
Por exemplo, no caso do atributo <literal>loadInitialData</literal>, serão buscadas as seguintes versões de chaves
no arquivo de recursos:
<itemizedlist>
<listitem><literal>loadInitialData</literal></listitem>
<listitem><literal>load.initial.data</literal></listitem>
<listitem><literal>load_initial_data</literal></listitem>
<listitem><literal>loadinitialdata</literal></listitem>
</itemizedlist>
</para>
<tip>
<para>
A fim de utilizar uma nomenclatura de chave diferente dos formatos convencionados, utilize a anotação
<literal>@Name</literal> no atributo.
</para>
</tip>
<para>
Em determinadas situações é utilizado um prefixo de chave comum a todos os parâmetros de uma classe de
configuração. Neste caso, é possível especificar tal prefixo na anotação <literal>@Configuration</literal>.
Isso permite, por exemplo, que um mesmo arquivo de recursos (ex: <filename>demoiselle.properties</filename>)
seja compartilhado por diversas classes de configuração.
</para>
<para>
Veja na listagem abaixo um código fonte que ilustra a utilização das anotações descritas nesta seção:
</para>
<programlistingco>
<areaspec>
<area id="resource-prefix" coords="1"/>
<area id="param-name" coords="4"/>
<area id="param-notnull" coords="7"/>
<area id="param-ignore" coords="10"/>
</areaspec>
<programlisting role="JAVA"><![CDATA[@Configuration(resource = "bookmark", prefix = "general")
public class BookmarkConfig {
@Name("app.title")
private String applicationTitle;
@NotNull
private boolean loadInitialData;
@Ignore
private int dummy;
public String getApplicationTitle() {
return applicationTitle;
}
public boolean isLoadInitialData() {
return loadInitialData;
}
}]]></programlisting>
<calloutlist>
<callout arearefs="resource-prefix">
<para>
Na anotação <literal>@Configuration</literal> são especificados o arquivo de recursos
<filename>bookmark.properties</filename> e o prefixo <literal>general</literal> a ser
considerado em cada uma das chaves.
</para>
</callout>
<callout arearefs="param-name">
<para>
Ao invés de adotar o padrão convencionado, com a anotação <literal>@Name</literal> será
considerada a chave <literal>app.title</literal> após o prefixo.
</para>
</callout>
<callout arearefs="param-notnull">
<para>
Como o atributo é anotado com <literal>@NotNull</literal>, presume-se que ele sempre
estará presente no arquivo de recursos. Caso contrário, uma exceção ocorrerá na
inicialização da aplicação.
</para>
</callout>
<callout arearefs="param-ignore">
<para>
Este atributo, por estar anotado com <literal>@Ignore</literal>, não será considerado
pelo mecanismo de configurações.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
Neste caso, será buscado um arquivo de propriedades com o nome <filename>bookmark.properties</filename>
contendo as seguintes chaves:
</para>
<programlisting><![CDATA[general.app.title = Título da Aplicação
general.load.initial.data = true
]]></programlisting>
<tip>
<para>
Além de <literal>String</literal> e <literal>boolean</literal>, existe a possibilidade de se recuperar valores de qualquer
tipo primitivo do Java (i.e., <literal>int, byte, short, char, long, float, double</literal> e <literal>boolean</literal>)
e também arrays desses tipos e de alguns tipos complexos (i.e., <literal>Integer, BigDecimal, BigInteger, Calendar, Date,
Color, Locale, URL</literal> e <literal>String</literal>).
</para>
</tip>
</section>
<section>
<title>Usando a configuração na aplicação</title>
<para>
A fim de utilizar o objeto de configuração previamente instanciado e preenchido pelo contêiner, basta criar uma variável numa
classe qualquer da aplicação e anotá-la com <literal>@Inject</literal>. Tal variável será injetada automaticamente e pode ser
usada dentro de um método. Veja na listagem a seguir um exemplo de injeção e uso de uma classe de configuração:
</para>
<programlisting role="JAVA"><![CDATA[public class BookmarkBC {
@Inject
private BookmarkConfig config;
public void startup() {
if (config.isLoadInitialData()) {
...
}
}
}]]></programlisting>
<note>
<para>
O <emphasis>Demoiselle Framework</emphasis> utiliza internamente o mecanismo de configurações na leitura do arquivo
<filename>demoiselle.properties</filename> para outras funcionalidades, tais como transação, persistência e paginação.
</para>
</note>
</section>
<section>
<title>Lendo arquivos XML</title>
<para>
Agora veja como ficaria a abordagem de configuração usando arquivos XML. Eis um arquivo de exemplo, o
<filename>escola.xml</filename>, possuindo um valor numérico e um conjunto de strings:
</para>
<programlisting role="XML"><![CDATA[<configuration>
<qtdeInicial>125</qtdeInicial>
<papeis>
<papel>Aluno</papel>
<papel>Professor</papel>
<papel>Administrador</papel>
</papeis>
</configuration>]]></programlisting>
<para>
Neste caso, na classe de configuração <literal>EscolaConfig</literal> a anotação <literal>@Configuration</literal>
precisa apontar para o tipo de recursos XML e usar o respectivo arquivo <filename>escola.xml</filename>. Eis a
implementação necessária para que o referido arquivo XML seja lido e os seus valores carregados automaticamente:
</para>
<programlisting role="JAVA"><![CDATA[@Configuration(resource = "escola", type = ConfigType.XML)
public class EscolaConfig {
private Integer qtdeInicial = 50;
@Name("papeis.papel")
private List<String> papeis;
private Integer getQtdeInicial() {
return qtdeInicial;
}
public List<String> getPapeis() {
return papeis;
}
}]]></programlisting>
</section>
<section>
<title>Lendo variáveis de ambiente</title>
<para>
A terceira abordagem na configuração consiste em utilizar as variáveis de ambiente do sistema operacional.
Estas variáveis geralmente são carregadas na inicialização do sistema ou após a criação da sessão do usuário
(i.e., após o login), mas também podem ser modificadas manualmente através de comandos como <literal>set</literal>
ou <literal>export</literal>.
</para>
<para>
O mecanismo de configurações no <emphasis>Demoiselle Framework</emphasis> faz uso da classe
<ulink url="http://download.oracle.com/javase/6/docs/api/java/lang/System.html">
<literal>java.lang.System</literal></ulink> fornecida pela API do Java para carregar os valores nas
propriedades a partir de variáveis de ambiente independente do sistema operacional.
</para>
<para>
Veja na listagem abaixo o código necessário para a leitura de uma variável de ambiente:
</para>
<programlisting role="JAVA"><![CDATA[@Configuration(type = ConfigType.SYSTEM)
public class EscolaConfig {
@Name("java.home")
private String javaDirectory;
public String getJavaDirectory() {
return javaDirectory;
}
}]]></programlisting>
</section>
</chapter>