Commit 2db71850f5b8f63fab14991f823f679572589f74

Authored by Emerson Oliveira
1 parent 7c6c4e7f
Exists in master

Atualização da documentação de referência do Configuration.

Showing 1 changed file with 522 additions and 178 deletions   Show diff stats
documentation/reference/pt-BR/configuracao.xml
... ... @@ -8,38 +8,50 @@
8 8 <section>
9 9 <title>Configurações em uma aplicação</title>
10 10 <para>
11   - Muitas vezes é necessário parametrizar a aplicação à partir de arquivos de configuração ou variáveis de
12   - ambiente. O <emphasis>Demoiselle Framework</emphasis> traz algumas facilidades para você utilizar este
13   - recurso na sua aplicação para os casos mais comuns:
  11 + Muitas vezes, por motivos diversos, é necessário parametrizar a aplicação à partir de algum mecanismo de
  12 + configuração. E em java é comum se utilizar as seguintes abordagens para armazenas as configurações:
14 13 <itemizedlist>
15 14 <listitem>
16   - <emphasis>arquivo de propriedades</emphasis>: tratam-se de simples arquivos de texto nomeados com a extensão
17   - <filename>.properties</filename> e que internamente são escritos com a sintaxe <literal>chave=valor</literal>,
18   - armazenando uma única chave por linha;
  15 + <para>
  16 + <emphasis>arquivo de propriedades</emphasis>: tratam-se de simples arquivos de texto nomeados com a
  17 + extensão <filename>.properties</filename>, os quais são escritos com a sintaxe <literal>chave=valor
  18 + </literal>, armazenando uma única chave por linha;
  19 + </para>
19 20 </listitem>
20 21 <listitem>
21   - <emphasis>arquivo XML</emphasis>: são arquivos de texto altamente estruturados com a sintaxe de tags e que
22   - permitem uma maior validação dos seus valores, sendo geralmente nomeados com a extensão <filename>.xml</filename>;
  22 + <para>
  23 + <emphasis>arquivo XML</emphasis>: são arquivos de texto altamente estruturados com a sintaxe de tags e
  24 + que permitem uma maior validação dos seus valores, sendo geralmente nomeados com a extensão
  25 + <filename>.xml</filename>;
  26 + </para>
23 27 </listitem>
24 28 <listitem>
25   - <emphasis>variáveis de ambiente</emphasis>: valores definidos no sistema operacional, independente de
26   - plataforma (Windows, Linux, etc) e que podem ser recuperados durante a execução da aplicação.
  29 + <para>
  30 + <emphasis>variáveis de ambiente</emphasis>: valores definidos no sistema operacional, independente de
  31 + plataforma (Windows, Linux, Mac OS, etc) e que podem ser recuperados durante a execução da aplicação.
  32 + </para>
27 33 </listitem>
28 34 </itemizedlist>
29 35 </para>
  36 + <para>
  37 + Esse capítulo mostra de que maneira o <emphasis>Demoiselle Framework</emphasis> pode facilitar a utilização dessas
  38 + formas de configuração, oferencendo vários recursos interessantes e poderosos para a sua aplicação.
  39 + </para>
  40 +
30 41 </section>
31 42 <section>
32 43 <title>As classes de configuração</title>
33 44 <para>
34   - A primeira etapa para a utilização do mecanismo de configuração em uma aplicação consiste em criar uma classe específica
35   - para armazenar os parâmetros desejados e anotá-la com <literal>@Configuration</literal>. Eis um exemplo:
  45 + O primeiro passo para a utilização do mecanismo de configuração em uma aplicação consiste em criar uma classe
  46 + específica para armazenar os parâmetros desejados e anotá-la com <literal>@Configuration</literal>. O código
  47 + abaixo mostra um exemplo de classe de configuração:
36 48 </para>
37   - <programlisting role="JAVA"><![CDATA[@Configuration(resource = "bookmark")
  49 + <programlisting role="JAVA"><![CDATA[@Configuration
38 50 public class BookmarkConfig {
39 51  
40 52 private String applicationTitle;
41 53  
42   - private boolean loadInitialData = true;
  54 + private boolean loadInitialData;
43 55  
44 56 public String getApplicationTitle() {
45 57 return applicationTitle;
... ... @@ -49,10 +61,6 @@ public class BookmarkConfig {
49 61 return loadInitialData;
50 62 }
51 63 }]]></programlisting>
52   - <para>
53   - Sugere-se criar apenas os acessores para leitura (<emphasis>getters</emphasis>). Para definir valores padrão,
54   - especifique-os na própria declaração do atributo (ex: <literal>boolean loadInitialData=true</literal>).
55   - </para>
56 64 <note>
57 65 <para>
58 66 As classes anotadas com <literal>@Configuration</literal> são instanciadas uma única vez (seguindo o padrão
... ... @@ -61,73 +69,65 @@ public class BookmarkConfig {
61 69 primeiro acesso à respectiva classe de configuração, quando os seus atributos são preenchidos automaticamente.
62 70 </para>
63 71 </note>
64   - <para>
65   - No exemplo a seguir será buscado um arquivo de propriedades com o nome <filename>bookmark.properties</filename>
66   - contendo as seguintes chaves:
67   - </para>
68   - <programlisting><![CDATA[application.title=Título da Aplicação
69   -load.initial.data=false
70   -]]></programlisting>
71 72 <note>
72 73 <para>
73   - Recomenda-se usar o sufixo <quote>Config</quote> nas classes de configuração.
  74 + Recomenda-se usar o sufixo <quote>Config</quote> nas classes de configuração, e que sejam criados
  75 + apenas os acessores para leitura (<emphasis>getters</emphasis>).
74 76 </para>
75 77 </note>
76   - <para>
77   - O nome do recurso (<literal>resource</literal>) e o tipo de configuração (<literal>type</literal>) são argumentos
78   - opcionais na anotação <literal>@Configuration</literal>. Caso não sejam especificados, será considerado o arquivo
79   - de propriedades padrão do <emphasis>Demoiselle Framework</emphasis>, o <filename>demoiselle.properties</filename>.
80   - </para>
81   - </section>
  78 +
82 79  
83   - <section>
84   - <title>Especificando os parâmetros</title>
85 80 <para>
86   - Por padrão todos os atributos existentes em uma classe anotada com <literal>@Configuration</literal> são tratados
87   - como parâmetros de configuração e serão automaticamente preenchidos durante a leitura do recurso.
  81 + Esse é um exemplo bastante simples, no qual não são especificados nem nome nem tipo do arquivo de configuração. Nessa
  82 + situação os parâmetros de nome <emphasis>applicationTitle</emphasis> e <emphasis>loadInitialData</emphasis> serão
  83 + procurados em um arquivo de propriedades de nome <emphasis>demoiselle.properties</emphasis>. Ou seja, quando não
  84 + especificados nome e tipo do arquivo, assume-se que o arquivo é do tipo <emphasis>propriedades</emphasis>
  85 + e seu nome é <emphasis>demoiselle</emphasis>. Mas como fazer para não utilizar o valor padrão e definir
  86 + nome e tipo do arquivo? Bastante simples. Basta adicionar esses parâmetros à anotação @Configuration, como mostra o
  87 + exemplo a seguir:
88 88 </para>
89   - <tip>
90   - <para>
91   - Para ignorar um determinado atributo no processo automático de carregamento, anote-o com <literal>@Ignore</literal>.
92   - Para torná-lo obrigatório, anote-o com <literal>@NotNull</literal>.
93   - </para>
94   - </tip>
95   - <para>
96   - No arquivo de recursos será buscada a chave correspondente ao nome do atributo da classe.
97   - Por exemplo, para atributo <literal>loadInitialData</literal> será buscada a chave <literal>loadInitialData</literal>
98   - no recurso de configuração.
99   - </para>
100   - <tip>
101   - <para>
102   - Para redefinir os nomes das chaves, utilize a anotação <literal>@Name</literal> no atributo.
103   - </para>
104   - </tip>
  89 + <programlisting role="JAVA"><![CDATA[@Configuration(resource="my-property-file", type=ConfigType.XML)
  90 +public class BookmarkConfig {
  91 +
  92 + private String applicationTitle;
  93 +
  94 + private boolean loadInitialData;
  95 +
  96 + public String getApplicationTitle() {
  97 + return applicationTitle;
  98 + }
  99 +
  100 + public boolean isLoadInitialData() {
  101 + return loadInitialData;
  102 + }
  103 +}]]></programlisting>
  104 +
105 105 <para>
106   - Em determinadas situações é utilizado um prefixo comum a todos as chaves de configuração.
107   - Nestes casos, especifique atributo <literal>prefix</literal> da anotação <literal>@Configuration</literal>.
  106 + Devemos atribuir o nome do arquivo de configuração ao parâmetro <emphasis>resource</emphasis>, sem a extensão.
  107 + Ao parâmetro <emphasis>type</emphasis> pode ser atribuída uma das três possibilidades:
  108 + <emphasis>ConfigType.PROPERTIES</emphasis>, que é o valor padrão e indica que as configurações daquela classe
  109 + estão em um arquivo do tipo <emphasis>properties</emphasis>; <emphasis>ConfigType.XML</emphasis>, que indica que
  110 + as configurações daquela classe estão em um arquivo do tipo <emphasis>xml</emphasis>; e <emphasis>
  111 + ConfigType.SYSTEM</emphasis>, que indica que as configurações daquela classe são valores definidos pelo Sistema
  112 + Operacional. Nesse exemplo, ao definir <emphasis>resource</emphasis> e <emphasis>type</emphasis> os parâmetros de
  113 + nome <emphasis>applicationTitle</emphasis> e <emphasis>loadInitialData</emphasis> serão procurados em um arquivo
  114 + xml de nome <emphasis>my-property-file</emphasis> (my-property-file.xml).
108 115 </para>
109 116 <para>
110   - Veja na listagem abaixo um código fonte que ilustra a utilização das anotações descritas nesta seção:
  117 + Outro parâmetro que você pode ajustar nessa anotação é o prefixo. Ao definir um valor de prefixo você informa que
  118 + o nome das propriedades definidas naquela classe devem ser concatenados com o prefixo, de forma que o nome dos
  119 + atributos procurados no arquivo seja <emphasis>prefixo.nomeatributo</emphasis>. O exemplo abaixo mostra a
  120 + utilização desse parâmetro. Nesse caso, os parâmetros de nome <emphasis>info.applicationTitle</emphasis> e
  121 + <emphasis>info.loadInitialData</emphasis> serão procurados em um arquivo de propriedade de nome
  122 + <emphasis>my-property-file</emphasis> (<emphasis>my-property-file.properties</emphasis>).
111 123 </para>
112   - <programlistingco>
113   - <areaspec>
114   - <area id="resource-prefix" coords="1"/>
115   - <area id="param-name" coords="4"/>
116   - <area id="param-notnull" coords="7"/>
117   - <area id="param-ignore" coords="10"/>
118   - </areaspec>
119   - <programlisting role="JAVA"><![CDATA[@Configuration(resource = "bookmark", prefix = "general.")
  124 + <programlisting role="JAVA"><![CDATA[@Configuration(prefix="info", resource="my-property-file")
120 125 public class BookmarkConfig {
121 126  
122   - @Name("app.title")
123 127 private String applicationTitle;
124 128  
125   - @NotNull
126 129 private boolean loadInitialData;
127 130  
128   - @Ignore
129   - private int dummy;
130   -
131 131 public String getApplicationTitle() {
132 132 return applicationTitle;
133 133 }
... ... @@ -136,141 +136,485 @@ public class BookmarkConfig {
136 136 return loadInitialData;
137 137 }
138 138 }]]></programlisting>
139   - <calloutlist>
140   - <callout arearefs="resource-prefix">
141   - <para>
142   - Na anotação <literal>@Configuration</literal> foram especificados o arquivo de recursos
143   - <filename>bookmark.properties</filename> e o prefixo <literal>general.</literal> para as
144   - chaves de configuração.
145   - </para>
146   - </callout>
147   - <callout arearefs="param-name">
148   - <para>
149   - Ao invés de adotar o padrão convencionado, a anotação <literal>@Name</literal> definirá a chave
150   - <literal>app.title</literal> após o prefixo.
151   - </para>
152   - </callout>
153   - <callout arearefs="param-notnull">
154   - <para>
155   - Como o atributo é anotado com <literal>@NotNull</literal>, presume-se que ele sempre
156   - estará presente no recurso. Caso contrário, uma exceção ocorrerá.
157   - </para>
158   - </callout>
159   - <callout arearefs="param-ignore">
160   - <para>
161   - Este atributo, por estar anotado com <literal>@Ignore</literal>, não será considerado
162   - no carregamento automático das configurações.
163   - </para>
164   - </callout>
165   - </calloutlist>
166   - </programlistingco>
167   - <para>
168   - Neste caso, será buscado um arquivo de propriedades com o nome <filename>bookmark.properties</filename>
169   - contendo as seguintes chaves:
170   - </para>
171   - <programlisting><![CDATA[general.app.title=Título da Aplicação
172   -general.loadInitialData=true
173   -]]></programlisting>
  139 + <note>
  140 + <para>
  141 + O <emphasis>Demoiselle Framework</emphasis> adiciona automaticamente o ponto entre o prefixo e o nome do
  142 + atributo, você não precisa se preocupar com isso.
  143 + </para>
  144 + </note>
174 145 <tip>
175 146 <para>
176   - Além de <literal>String</literal> e <literal>boolean</literal>, existe a possibilidade de se recuperar valores de qualquer
177   - tipo primitivo do Java (i.e., <literal>int, byte, short, char, long, float, double</literal> e <literal>boolean</literal>)
178   - e também arrays desses tipos e de alguns tipos complexos (i.e., <literal>Integer, BigDecimal, BigInteger, Calendar, Date,
179   - Color, Locale, URL</literal> e <literal>String</literal>).
  147 + No arquivo xml o prefixo corresponde a uma <emphasis>tag</emphasis> acima das tag que correspondem aos
  148 + atributos. O exemplo acima ficaria da seguinte forma em um arquivo xml:
180 149 </para>
  150 + <programlisting role="XML"><![CDATA[
  151 +<info>
  152 + <applicationTitle>Demoiselle Application<\applicationTitle>
  153 + <loadInitialData>true<\loadInitialData>
  154 +</info>
  155 +
  156 +]]></programlisting>
  157 +
181 158 </tip>
182 159 </section>
183   -
  160 +
184 161 <section>
185   - <title>Usando a configuração na aplicação</title>
  162 + <title>Especificando os parâmetros</title>
186 163 <para>
187   - A fim de utilizar o objeto de configuração previamente instanciado e preenchido pelo contêiner, basta criar uma variável numa
188   - classe qualquer da aplicação e anotá-la com <literal>@Inject</literal>. Tal variável será injetada automaticamente e pode ser
189   - usada dentro de um método. Veja na listagem a seguir um exemplo de injeção e uso de uma classe de configuração:
  164 + Atualmente são suportados nativamente pelo <emphasis>Demoiselle Framework</emphasis> parâmetros de cinco tipos
  165 + diferentes, são eles: <emphasis>primitivo</emphasis>, <emphasis>wrapped</emphasis>, <emphasis>String</emphasis>,
  166 + <emphasis>class</emphasis>, <emphasis>map</emphasis> e <emphasis>array</emphasis>, sendo que os três últimos
  167 + são suportados a partir da versão 2.4.0. A seguir vamos explicar e exemplificar como utilizar cada um desses
  168 + tipos, e alertar para as possíveis exceções que poderão ser lançadas para sua aplicação.
190 169 </para>
191   -<programlisting role="JAVA"><![CDATA[public class BookmarkBC {
  170 + <caution>
  171 + <para>
  172 + A partir da versão 2.4.0 não são mais reconhecidas as convenções. Os parâmetros serão procurados exatamente
  173 + como foram definidos na classe de configuração.
  174 + </para>
  175 + </caution>
  176 + <informaltable>
  177 + <tgroup cols="1">
  178 + <colspec colwidth="100*" />
  179 + <tbody>
  180 + <row>
  181 + <entry>
  182 + <emphasis role="bold">Primitivos</emphasis>
  183 + </entry>
  184 + </row>
  185 + <row>
  186 + <entry>
  187 + <para>
  188 + A utilização dos tipos primitivos é bastante simples. Veja no exemplo abaixo uma classe de configuração um arquivo
  189 + de configurações, que ilustram como é o procedimento para adicionar parâmetros do tipo primitivo.
  190 + </para>
  191 + <programlisting role="JAVA"><![CDATA[@Configuration
  192 + public class BookmarkConfig {
192 193  
193   - @Inject
194   - private BookmarkConfig config;
  194 + private int pageSize;
195 195  
196   - public void startup() {
197   - if (config.isLoadInitialData()) {
198   - ...
199   - }
  196 + public String getPageSize() {
  197 + return pageSize;
200 198 }
201 199 }]]></programlisting>
202   - <note>
203   - <para>
204   - O <emphasis>Demoiselle Framework</emphasis> utiliza internamente o mecanismo de configurações na leitura do arquivo
205   - <filename>demoiselle.properties</filename> para outras funcionalidades, tais como transação, segurança, persistência e paginação.
206   - </para>
207   - </note>
208   - </section>
209 200  
210   - <section>
211   - <title>Lendo arquivos XML</title>
212   - <para>
213   - Agora veja como ficaria a abordagem de configuração usando arquivos XML. Eis um arquivo de exemplo, o
214   - <filename>escola.xml</filename>, possuindo um valor numérico e um conjunto de strings:
215   - </para>
216   - <programlisting role="XML"><![CDATA[<configuration>
217   - <qtdeInicial>125</qtdeInicial>
218   - <papeis>
219   - <papel>Aluno</papel>
220   - <papel>Professor</papel>
221   - <papel>Administrador</papel>
222   - </papeis>
223   -</configuration>]]></programlisting>
224   - <para>
225   - Neste caso, na classe de configuração <literal>EscolaConfig</literal> a anotação <literal>@Configuration</literal>
226   - precisa apontar para o tipo de recursos XML e usar o respectivo arquivo <filename>escola.xml</filename>. Eis a
227   - implementação necessária para que o referido arquivo XML seja lido e os seus valores carregados automaticamente:
228   - </para>
229   - <programlisting role="JAVA"><![CDATA[@Configuration(resource = "escola", type = ConfigType.XML)
230   -public class EscolaConfig {
  201 + <para>
  202 + Para essa classe, o arquivo de propriedade correspondente (<emphasis>demoiselle.properties</emphasis>) deveria
  203 + apresentar o seguinte conteúdo:
  204 + </para>
  205 + <programlisting role="JAVA"><![CDATA[
  206 +pageSize=10
  207 +]]></programlisting>
  208 + <para>
  209 + Bastante simples, não? Mesmo assim, é bom ficarmos atentos, pois alguns cenários diferentes podem
  210 + acontecer. Vamos supor por exemplo que, por um motivo qualquer, a classe de configuração não esteja associada a um arquivo que contenha a chave de um de
  211 + seus parâmetros. Nesse caso será atribuido o valor padrão da linguagem ao atributo, que para os tipos primitivos
  212 + é 0, exceto para os tipos <emphasis>boolean</emphasis>, cujo valor padrão é <emphasis>false</emphasis>, e
  213 + <emphasis>char</emphasis>, cujo valor padrão é o caracter nulo (<emphasis>'\u0000'</emphasis>).
  214 + Outro cenário possível é a existência da chave, mas sem valor atribuído (<emphasis>pageSize=</emphasis>). Nesse
  215 + caso o valor encontrado no arquivo é equivalente a uma <emphasis>String</emphasis> vazia, e a exceção
  216 + <emphasis>ConfigurationException</emphasis>, cuja causa foi uma <emphasis>ConversionException</emphasis>, será
  217 + lançada.
  218 + </para>
  219 + </entry>
  220 + </row>
  221 + </tbody>
  222 + </tgroup>
  223 + </informaltable>
  224 +
  225 + <informaltable>
  226 + <tgroup cols="1">
  227 + <colspec colwidth="100*" />
  228 + <tbody>
  229 + <row>
  230 + <entry>
  231 + <emphasis role="bold">Wrappers</emphasis>
  232 + </entry>
  233 + </row>
  234 + <row>
  235 + <entry>
  236 + <para>
  237 + Os atributos do tipo <emphasis>wrapper</emphasis> devem ser utilizados da mesma forma que os atributos do tipo
  238 + primitivo. A única diferença entre eles é que o valor padrão atribuído a um parâmetro, no caso da classe de
  239 + configuração não estar associada a um arquivo que contenha sua chave, é nulo.
  240 + </para>
  241 + </entry>
  242 + </row>
  243 + </tbody>
  244 + </tgroup>
  245 + </informaltable>
  246 +
  247 + <informaltable>
  248 + <tgroup cols="1">
  249 + <colspec colwidth="100*" />
  250 + <tbody>
  251 + <row>
  252 + <entry>
  253 + <emphasis role="bold">Strings</emphasis>
  254 + </entry>
  255 + </row>
  256 + <row>
  257 + <entry>
  258 + <para>
  259 + Por sua vez, as configurações do tipo <emphasis>String</emphasis> tem funcionalidade bastante similar às
  260 + configurações do tipo Wrapper. A diferença fica por conta de que, ao deixar a chave sem valor atribuído, para
  261 + atributo desse tipo, não será lançada exceção, pois que não haverá o problema de conversão, e à configuração
  262 + será atribuido o valor de uma <emphasis>String</emphasis> vazia.
  263 + </para>
  264 + </entry>
  265 + </row>
  266 + </tbody>
  267 + </tgroup>
  268 + </informaltable>
  269 +
  270 + <informaltable>
  271 + <tgroup cols="1">
  272 + <colspec colwidth="100*" />
  273 + <tbody>
  274 + <row>
  275 + <entry>
  276 + <emphasis role="bold">Class</emphasis>
  277 + </entry>
  278 + </row>
  279 + <row>
  280 + <entry>
  281 + <para>
  282 + A partir da versão 2.4.0 é possível ter atributos do tipo <emphasis>Class</emphasis> como parâmetro. O atributo
  283 + pode ou não ser tipado, e no arquivo o valor atribuído à chave deve corresponder ao nome (<emphasis>
  284 + Canonical Name</emphasis>) de uma classe existente. Abaixo temos um exemplo de uma classe de configuração com
  285 + dois atributos do tipo <emphasis>Class</emphasis>, um tipado e outro não tipado:
  286 + </para>
  287 + <programlisting role="JAVA"><![CDATA[
  288 +@Configuration
  289 +public class BookmarkConfig {
231 290  
232   - private Integer qtdeInicial = 50;
  291 + private Class<MyClass> typedClass;
233 292  
234   - @Name("papeis.papel")
235   - private List<String> papeis;
  293 + private Class<?> untypedClass;
236 294  
237   - private Integer getQtdeInicial() {
238   - return qtdeInicial;
  295 + public Class<MyClass> getTypedClass() {
  296 + return typedClass;
239 297 }
240 298  
241   - public List<String> getPapeis() {
242   - return papeis;
  299 + public Class<?> getUntypedClass() {
  300 + return untypedClass;
243 301 }
244   -}]]></programlisting>
245   - </section>
  302 +}
  303 + ]]></programlisting>
  304 + <para>O arquivo de propriedades teria o seguinte conteúdo:</para>
  305 + <programlisting role="JAVA"><![CDATA[
  306 +typedClass=package.MyClass
  307 +untypedClass=package.MyOtherClass
  308 + ]]></programlisting>
  309 + <para>
  310 + Caso uma chave de uma configuração do tipo <emphasis>Class</emphasis> não tenha valor atribuído ou seja
  311 + atribuído um nome de classe que não existe (ou não possa ser encontrada pela aplicação), no momento do
  312 + seu carregamento sera lançada uma exceção do tipo <emphasis>ConfigurationException</emphasis>, cuja causa é uma
  313 + <emphasis>ClassNotFoundException</emphasis>. Caso a classe de configuração não esteja associada a um
  314 + arquivo que contenha a chave de um de seus parâmetros do tipo <emphasis>Class</emphasis>, este será carregado
  315 + com valor nulo.
  316 + </para>
  317 + </entry>
  318 + </row>
  319 + </tbody>
  320 + </tgroup>
  321 + </informaltable>
  322 +
  323 + <informaltable>
  324 + <tgroup cols="1">
  325 + <colspec colwidth="100*" />
  326 + <tbody>
  327 + <row>
  328 + <entry>
  329 + <emphasis role="bold">Map</emphasis>
  330 + </entry>
  331 + </row>
  332 + <row>
  333 + <entry>
  334 + <para>
  335 + Para utilizar parâmetros do tipo <emphasis>Map</emphasis>, o arquivo de configurações deve usar a seguinte
  336 + estrutura na formação da chave: <emphasis>prefixo+chavedomap+nomedoatributo</emphasis>. Vejamos um exemplo.
  337 + Se temos em nossa aplicação uma classe de configuração como a mostrada abaixo:
  338 + </para>
  339 + <programlisting role="JAVA"><![CDATA[
  340 +@Configuration
  341 +public class BookmarkConfig {
246 342  
  343 + private Map<String, String> url;
  344 +
  345 + private Map<String, String> driverClass;
  346 +
  347 + public Map<String, String> getUrl() {
  348 + return url;
  349 + }
  350 +
  351 + public Map<String, String> DriverClass() {
  352 + return driverClass;
  353 + }
  354 +}
  355 + ]]></programlisting>
  356 + <para>
  357 + O arquivo de configuração deverá ser preenchido no formato seguinte (se for do tipo <emphasis>properties</emphasis>):
  358 + </para>
  359 + <programlisting role="PROPERTIES"><![CDATA[
  360 +mapkey1.url=jdbc:postgresql://localhost:5432/app
  361 +mapkey2.url=jdbc:mysql://localhost:3306/app
  362 +mapkey1.driverClass=org.postgresql.Driver
  363 +mapkey2.driverClass=com.mysql.Driver
  364 + ]]></programlisting>
  365 + <para>
  366 + Dessa forma, ao fazer a chamada <emphasis>url.get("mapkey2");</emphasis>por exemplo, o valor retornado será
  367 + <emphasis>jdbc:mysql://localhost:3306/app</emphasis>.
  368 + </para>
  369 + <note>
  370 + <para>
  371 + O ponto entre a chave do <emphasis>Map</emphasis> e o nome do parâmetro é adicionado automaticamente pelo
  372 + framework.
  373 + </para>
  374 + </note>
  375 + <tip>
  376 + <para>
  377 + Você pode utilizar a chave do Map com nome "default" para indicar que, no arquivo de configuração, a chave é formada
  378 + apenas pela junção do prefixo com o atributo, sem utilizar a própria chave do Map. Por exemplo, se na sua classe
  379 + existir um comando como este:
  380 + </para>
  381 + <programlisting role="JAVA"><![CDATA[
  382 + myMap.get("default");
  383 + ]]></programlisting>
  384 + <para>o framework irá procurar no arquivo de configuração uma linha como esta:</para>
  385 + <programlisting role="JAVA"><![CDATA[
  386 + prefix.myMap=Default Value
  387 + ]]></programlisting>
  388 + </tip>
  389 + <para>
  390 + Caso a classe de configuração não esteja associada a um arquivo que contenha a chave de um de seus parâmetros
  391 + do tipo <emphasis>Map</emphasis>, este será carregado com valor nulo, e estará sujeito às exceções
  392 + informadas anteriormente, conforme o tipo de variáveis que ele contenha.
  393 + </para>
  394 + </entry>
  395 + </row>
  396 + </tbody>
  397 + </tgroup>
  398 + </informaltable>
  399 +
  400 + <informaltable>
  401 + <tgroup cols="1">
  402 + <colspec colwidth="100*" />
  403 + <tbody>
  404 + <row>
  405 + <entry>
  406 + <emphasis role="bold">Array</emphasis>
  407 + </entry>
  408 + </row>
  409 + <row>
  410 + <entry>
  411 + <para>
  412 + No caso do <emphasis>Array</emphasis>, a principal diferença em relação às demais formas de declarar
  413 + configurações é a maneira de atribuir valores aos seus respectivos elementos no arquivo de configuração.
  414 + Por exemplo, para que um <emphasis>Array</emphasis> de inteiros, de nome <emphasis>integerArray</emphasis>
  415 + tenha o conteúdo <emphasis>{-1, 0, 1}</emphasis>, você deve criar um arquivo de propriedades que contenha
  416 + as seguintes linhas:
  417 + </para>
  418 + <programlisting role="JAVA"><![CDATA[
  419 +integerArray=-1
  420 +integerArray=0
  421 +integerArray=1
  422 + ]]></programlisting>
  423 + <para>
  424 + Exceto a forma de atribuir os valores às configurações, se comporta de acordo com o tipo de variável que ele
  425 + contém, conforme o espeficifcado para cada um.
  426 + </para>
  427 + </entry>
  428 + </row>
  429 + </tbody>
  430 + </tgroup>
  431 + </informaltable>
  432 +
  433 + </section>
  434 +
247 435 <section>
248   - <title>Lendo variáveis de ambiente</title>
249   - <para>
250   - A terceira abordagem na configuração consiste em utilizar as variáveis de ambiente do sistema operacional.
251   - Estas variáveis geralmente são carregadas na inicialização do sistema ou após a criação da sessão do usuário
252   - (i.e., após o login), mas também podem ser modificadas manualmente através de comandos como <literal>set</literal>
253   - ou <literal>export</literal>.
254   - </para>
255   - <para>
256   - O mecanismo de configurações no <emphasis>Demoiselle Framework</emphasis> faz uso da classe
257   - <ulink url="http://download.oracle.com/javase/6/docs/api/java/lang/System.html">
258   - <literal>java.lang.System</literal></ulink> fornecida pela API do Java para carregar os valores nas
259   - propriedades a partir de variáveis de ambiente independente do sistema operacional.
260   - </para>
  436 + <title>Mais Recursos</title>
261 437 <para>
262   - Veja na listagem abaixo o código necessário para a leitura de uma variável de ambiente:
  438 + Além das possibilidades relacionadas acima, existem ainda algumas anotações e recursos extras que o
  439 + <emphasis>Demoiselle Framework</emphasis> oferece para o desenvolvedor na utilização das configurações. A seguir
  440 + listamos e explicamos como utilizar esses recursos em sua aplicação.
263 441 </para>
264   - <programlisting role="JAVA"><![CDATA[@Configuration(type = ConfigType.SYSTEM)
265   -public class EscolaConfig {
  442 +
  443 + <informaltable>
  444 + <tgroup cols="1">
  445 + <colspec colwidth="100*" />
  446 + <tbody>
  447 + <row>
  448 + <entry>
  449 + <emphasis role="bold">Ignore</emphasis>
  450 + </entry>
  451 + </row>
  452 + <row>
  453 + <entry>
  454 + <para>
  455 + Por padrão, todos os atributos existentes em uma classe anotada com <literal>@Configuration</literal> são tratados
  456 + como parâmetros de configuração e serão automaticamente preenchidos durante a leitura do recurso. Porém, caso você
  457 + não queira que determinado atributo seja tratado como parâmetro dentro desse tipo de classe, basta anotá-lo com
  458 + a anotação <literal>@Ignore</literal>, que o atributo será ignorado (como indica a própria anotação) pelo carregador
  459 + de configurações.
  460 + </para>
  461 + </entry>
  462 + </row>
  463 + </tbody>
  464 + </tgroup>
  465 + </informaltable>
  466 +
  467 + <informaltable>
  468 + <tgroup cols="1">
  469 + <colspec colwidth="100*" />
  470 + <tbody>
  471 + <row>
  472 + <entry>
  473 + <emphasis role="bold">Valor Padrão</emphasis>
  474 + </entry>
  475 + </row>
  476 + <row>
  477 + <entry>
  478 + <para>
  479 + Muitas vezes é interessante que especifiquemos um valor padrão para o parâmetro, para o caso dele não estar
  480 + presente no arquivo de configuração. Para isso, basta atribuir o valor desejado no momento da declaração do
  481 + atributo, como exemplificado abaixo:
  482 + </para>
  483 + <programlisting role="JAVA"><![CDATA[@Configuration
  484 +public class BookmarkConfig {
266 485  
267   - @Name("java.home")
268   - private String javaDirectory;
  486 + private String applicationTitle = "My App";
269 487  
270   - public String getJavaDirectory() {
271   - return javaDirectory;
  488 + public String getApplicationTitle() {
  489 + return applicationTitle;
272 490 }
273   -}]]></programlisting>
274   - </section>
  491 +} ]]></programlisting>
  492 + <para>
  493 + Com essa atribuição, se no arquivo de propriedades não existir uma chave com valor <literal>applicationTitle</literal>
  494 + esse parametro será carregado com o valor <literal>My App</literal>.
  495 + </para>
  496 + </entry>
  497 + </row>
  498 + </tbody>
  499 + </tgroup>
  500 + </informaltable>
  501 +
  502 + <informaltable>
  503 + <tgroup cols="1">
  504 + <colspec colwidth="100*" />
  505 + <tbody>
  506 + <row>
  507 + <entry>
  508 + <emphasis role="bold">Bean Validation</emphasis>
  509 + </entry>
  510 + </row>
  511 + <row>
  512 + <entry>
  513 + <para>
  514 + Fazer validação mantém a integridade dos dados e pode ser fator importante na lógica da aplicação. A partir da
  515 + versão 2.4.0 o <emphasis>Demoiselle</emphasis> permite que os atributos das classes de configuração sejam
  516 + anotados com todas as anotações definidas pela JSR 303 (Bean Validation). Com esse recurso você pode exigir que
  517 + determinado parâmetro não seja nulo (<emphasis>@NotNull</emphasis>), limitar um valor máximo ou mínimo para ele
  518 + (<emphasis>@Max</emphasis> e <emphasis>@Min</emphasis>, respectivamente), dentre outras restrições (que podem
  519 + ser feitas simultâneamente). A lista completa das restrições que podem ser aplicadas nos atributos das classes
  520 + de configuração pode ser conferida aqui:
  521 + <ulink url="http://docs.oracle.com/javaee/6/tutorial/doc/gircz.html">
  522 + <literal>http://docs.oracle.com/javaee/6/tutorial/doc/gircz.html</literal></ulink>.
  523 + </para>
  524 + <para>
  525 + Para utilizar esse recurso você deve ter como dependência de seu projeto alguma implementação da especificação
  526 + Bean Validation. A implementação de referência é o
  527 + <ulink url="http://www.hibernate.org/subprojects/validator"><emphasis>Hibernate Validator</emphasis></ulink>.
  528 + </para>
  529 + </entry>
  530 + </row>
  531 + </tbody>
  532 + </tgroup>
  533 + </informaltable>
  534 +
  535 + <informaltable>
  536 + <tgroup cols="1">
  537 + <colspec colwidth="100*" />
  538 + <tbody>
  539 + <row>
  540 + <entry>
  541 + <emphasis role="bold">Name</emphasis>
  542 + </entry>
  543 + </row>
  544 + <row>
  545 + <entry>
  546 + <para>
  547 + Em alguns casos você pode querer que um determinado parâmetro tenha nomes diferentes na classe de configuração e
  548 + no arquivo de propriedades. Para isso você pode utilizar a anotação <emphasis>@Name</emphasis>. Basta anotar
  549 + o atributo passando como parâmetro o nome pelo qual você deseja que ele seja procurado no arquivo de propriedades,
  550 + como mostra o exemplo abaixo:
  551 + </para>
  552 + <programlisting role="JAVA"><![CDATA[@Configuration(resource = "bookmark", prefix = "general.")
  553 +public class BookmarkConfig {
275 554  
  555 + @Name("app.title")
  556 + private String applicationTitle;
  557 +
  558 + public String getApplicationTitle() {
  559 + return applicationTitle;
  560 + }
  561 +} ]]></programlisting>
  562 + <para>
  563 + Com essa anotação, ao invés de procurar pela chave <emphasis>applicationTitle</emphasis>, o
  564 + <emphasis>Demoiselle</emphasis> irá buscar pela chave <emphasis>app.title</emphasis>.
  565 + </para>
  566 + </entry>
  567 + </row>
  568 + </tbody>
  569 + </tgroup>
  570 + </informaltable>
  571 +
  572 + <informaltable>
  573 + <tgroup cols="1">
  574 + <colspec colwidth="100*" />
  575 + <tbody>
  576 + <row>
  577 + <entry>
  578 + <emphasis role="bold">Escopo</emphasis>
  579 + </entry>
  580 + </row>
  581 + <row>
  582 + <entry>
  583 + <para>
  584 + A partir da versão 2.3.3 do <emphasis>Demoiselle Framework</emphasis> as classes anotadas com
  585 + <emphasis>@Configuration</emphasis> estarão por padrão no escopo estático (<emphasis>@StaticScoped</emphasis>).
  586 + </para>
  587 + </entry>
  588 + </row>
  589 + </tbody>
  590 + </tgroup>
  591 + </informaltable>
  592 +
  593 + <informaltable>
  594 + <tgroup cols="1">
  595 + <colspec colwidth="100*" />
  596 + <tbody>
  597 + <row>
  598 + <entry>
  599 + <emphasis role="bold">Extratores</emphasis>
  600 + </entry>
  601 + </row>
  602 + <row>
  603 + <entry>
  604 + <para>
  605 + Você precisa de parâmetros de um tipo que ainda não é suportado pelo <emphasis>Demoiselle</emphasis>? Você
  606 + pode implementar sua própria classe extratora. A partir da versão 2.4.0 as aplicações
  607 + podem implementar a interface <emphasis>ConfigurationValueExtractor</emphasis>, e ter um
  608 + extrator de configurações para atributos de qualquer tipo. Essa interface obriga a classe
  609 + a implementar os métodos: <emphasis>boolean isSupported(Field field)</emphasis>, que retorna <literal>true</literal>
  610 + caso a classe seja extratora daquele tipo de campo, e
  611 + <emphasis>Object getValue(String prefix, String key, Field field, Configuration configuration)
  612 + throws Exception</emphasis> que deve extrair o valor do campo da forma correta.
  613 + </para>
  614 + </entry>
  615 + </row>
  616 + </tbody>
  617 + </tgroup>
  618 + </informaltable>
  619 + </section>
276 620 </chapter>
... ...