= @AccessTimeout a forma Meta-anotação 
:index-group: Meta-Annotations
:jbake-type: page
:jbake-status: status=published
ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:stylesheet: ../github-stylesheet.css
endif::[]

== Indrodução
Qualquer anotação que recebe parâmetros podem se beneficiar das meta-anotações. Aquí observamos como `@AccessTimeout` pode ser mais fácil de entender e administrar mediante meta-anotações.
Usaremos [access-timeout](../access-timeout/README.html) como nosso exemplo de caso de uso.

O valor dos parâmetros do fornecido para o `@AccessTimeout` tem um efeito dramático em que a anotação realmente faz. Além disso, `@ AccessTimeout` tem um desses designs
onde `-1` e `0` tem um significado totalmente diferente. Um quer dizer "espere para sempre", o outro "nunca espere". Só alguns com sorte podem lembrar qual é qual.
Para o resto de nós é uma fonte constante de erros.

TIP: Meta-Anotações. ao resgate!


== *_Criando Meta-Anotações._*

Com respeito as melhores práticas, colocaremos nossas meta-anotações em um pacote chamado `api`, para este exemplo que nós da `org.superbiz.accesstimeout.api`. O pacote `org.superbiz.api` também vai funcionar.


A ideia básica é ter um pacote onde anotações "aprovadas" sejam usadas e proibir uso de versões não-meta-anotações. Toda a configuração
estará centralizada no pacote `api` e alterações nos valores de tempo limite estarão localizadas nesse pacote e refletidas automaticamente em todo o aplicativo.

Um efeito secundário interessante desta abordagem é que se o pacote `api` onde as definições de meta-anotação existem localizados em um jar separado, então efetivamente alguém
pode trocar toda a configuração de uma aplicação simplesmente substituindo o jar `api`.


=== @Metatype [.small]#A Meta-Anotação "root"#

Como todo o uso de meta-anotação, primeiro devemos criar nossa própria meta-anotação "root". Isto é tão facil como criar uma anotação
chamada `Metatype` que esta anotada com esta mesma anotação e tem um `ElementType.ANNOTATION_TYPE` como seu objetivo.


[source,java,numbered]
----
package org.superbiz.accesstimeout.api;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Metatype
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Metatype {
}
----

=== @AwaitNever

Quando a anotação `@AccessTimeout` tem o valor de `0` que tem a implicação que nunca deve esperar para acessar o bean. Se o bean esta ocupado, aquele que o chama imediatamente
receberá uma `ConcurrentAccessException`. Isto é difícil de lembrar e definitivamente não é auto-documentado para aqueles que nunca conheceram os detalhes.

Para criar uma versão de meta-anotação `@AccessTimeout(0)` nós simplesmente devemos pensar um bom nome de anotação, criar essa anotação e anota-la com ambas `@AccessTimeout`
e `@Metatype`


[source,java,numbered]
----
package org.superbiz.accesstimeout.api;

import javax.ejb.AccessTimeout;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Metatype
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)

@AccessTimeout(0)
public @interface AwaitNever {
}
----

=== @AwaitForever

Assim como `0` tem seu significado especial como "nunca esperar" , o valor de `-1` quer dizer "espere para sempre."

Enquanto estamos exigindo, o que podemos fazer com meta-anotações,
tecnicamente "espere para sempre" não é a melhor descrição. Atualmente os métodos de `javax.util.concurrent` APIs usam "await" em vez de "wait". Um (wait) provavelmente implica
um comando de espera, que neste caso não é , o outro (await) em vez disso, significa que esperar é possível, mas não é certo. Então, usaremos "await" no nome de nossas anotações.

Nós fazemos o nosso próprio `@AwaitForever` e a anotamos com `@AccessTimeout(0)` e `@Metatype`

[source,java,numbered]
----
package org.superbiz.accesstimeout.api;

import javax.ejb.AccessTimeout;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Metatype
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)

@AccessTimeout(-1)
public @interface AwaitForever {
}
----

=== @AwaitBriefly

Tanto os valores de `-1` e `0` a `@AccessTimeout` eles não incluem o escopo completo da anotação. Aqui é onde podemos especificar o máximo de minutos , segundos,
milisegundos,etc. onde se pode esperar acessar a instância do bean.

[source,java,numbered]
----
@Metatype
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})

@AccessTimeout(value = 5, unit = TimeUnit.SECONDS)
public @interface AwaitBriefly {
}
----

== Configuração vs Operação

Depois de criar algumas meta-anotações e a diversão se tornar vulgar, você começa a se perguntar qual será a melhor maneira de se beneficiar das meta-anotações.

Você realmente tem que começar a pensar como você quer usar a meta-anotação e colocar o chapéu de designer. O dilema fundamental é
**configuração vs operação** e a resposta é subjetiva; Quanta flexibilidade você deseja projetar em sua aplicação e onde?

## Nomes de configuração [.small]#descrevendo a configuração#

A abordagem mais simples é chamar suas meta-anotações depois da **configuração** que encapsulam. Nós seguimos este formato até agora com `@AwaitNever` e `@AwaitForever`
para que seja claro o conteúdo de cada meta-anotação (`@AccessTimeout(-1)` e `@AccessTimeout(0)` respectivamente).

Os **contras** desta abordagem é que você vai querer alterar as configurações deste aplicativo apenas alterando as meta-anotações -- este é um dos grandes beneficios
das meta-anotações -- mas isto podería trocar o significado da anotação. Certamente , a anotação `@AwaitNever` não pode ter outro valor que '0' se estiver na altura do nome.

## Nomes de operação  [.small]#descrevendo o código#

A abordagem alternativa é chamar as meta-anotações depois de **operações** a que se aplica. Brevemente descrever, descrever o próprio código e não a configuração. Assim que,
nomes como `@OrderCheckTimeout` ou `@TwitterUpdateTimeout`. Estes nomes são provas de troca de configuração. Isso não mudará se a configuração mudar e, de fato, eles podem facilitar o controle de
localizador de grãos sobre a configuração do aplicativo.

Os **contras** desta abordagem é que requer muito mais deliberação e consideração, se, mencionar mais anotações. Suas habilidades como arquiteto, designer e capacidade de pensar como
administrador serão postas a prova. Você tem que ser bom para usar o chapéu dev-ops.


## Pragmatismo  [.small]#o melhor dos dois mundos#

Felizmente, as meta-anotações são recursivas. Você pode fazer um pouco dos dois.

[source,java,numbered]
----
@Metatype
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)

@AwaitBriefly
public @interface TwitterUpdateTimeout {
}
----

Claro ainda temos que ser muito deliberado em como usar as anotações. Quando se usa uma "configuração" chamada meta-anotação no código pode ser usada para dizer a si mesmo
"Você não quer reconfigurá-lo depois". Se isso não parecer certo, faça um esforço extra para criar uma operação chamada anotação e use-a no código.


# Aplicando a Meta-Anotação

Juntando tudo , talvez assim é como deveríamos aplicar nossas meta-anotações para o exemplo  [access-timeout](../access-timeout/README.html).

=== Antes

[source,java,numbered]
----
package org.superbiz.accesstimeout;

import javax.ejb.AccessTimeout;
import javax.ejb.Asynchronous;
import javax.ejb.Lock;
import javax.ejb.Singleton;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import static javax.ejb.LockType.WRITE;

/**
    * @version $Revision$ $Date$
    */
@Singleton
@Lock(WRITE)
public class BusyBee {

    @Asynchronous
    public Future stayBusy(CountDownLatch ready) {
        ready.countDown();

        try {
            new CountDownLatch(1).await();
        } catch (InterruptedException e) {
            Thread.interrupted();
        }

        return null;
    }

    @AccessTimeout(0)
    public void doItNow() {
        // do something
    }

    @AccessTimeout(value = 5, unit = TimeUnit.SECONDS)
    public void doItSoon() {
        // do something
    }

    @AccessTimeout(-1)
    public void justDoIt() {
        // do something
    }

}
----

=== Depois

[source,java,numbered]
----
package org.superbiz.accesstimeout;

import org.superbiz.accesstimeout.api.AwaitBriefly;
import org.superbiz.accesstimeout.api.AwaitForever;
import org.superbiz.accesstimeout.api.AwaitNever;

import javax.ejb.Asynchronous;
import javax.ejb.Lock;
import javax.ejb.Singleton;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;

import static javax.ejb.LockType.WRITE;

/**
    * @version $Revision$ $Date$
    */
@Singleton
@Lock(WRITE)
public class BusyBee {

    @Asynchronous
    public Future stayBusy(CountDownLatch ready) {
        ready.countDown();

        try {
            new CountDownLatch(1).await();
        } catch (InterruptedException e) {
            Thread.interrupted();
        }

        return null;
    }

    @AwaitNever
    public void doItNow() {
        // do something
    }

    @AwaitBriefly
    public void doItSoon() {
        // do something
    }

    @AwaitForever
    public void justDoIt() {
        // do something
    }

}
----
