Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding interceptors docs (EN) #647

Merged
merged 8 commits into from
Jun 30, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 169 additions & 0 deletions vraptor-site/content/en/docs/interceptors.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,172 @@
---
title: Interceptors
---

#When intercept?

Interceptors are used to perform some task before or after a business logic like data validation,
connection control, database transaction, logs and data encryption/compression.

##How to intercept?

VRaptor uses an approach where the interceptor defines who will be intercepted, more closer to the
interception approaches used by <strong>AOP</ strong> (Aspect Oriented Programming).

Therefore, to intercept a request, you need just to annotate the class with the `@Intercepts`. Like any
other component, you can use scoped annotation to define the interceptor life cicle. The default scope
for an interceptor is `RequestScoped`.

##A simple example

The class below shows an example how to intercept all requests in a request scoped and simply show
the console output that is being invoked. Remember that the interceptor is a component like any
other and can receive any dependencies using Dependency Injection.

~~~
#!java
@Intercepts
@RequestScoped
public class Log {

@Inject
private final HttpServletRequest request;

@AroundCall
public void intercept(SimpleInterceptorStack stack) {
System.out.println("Intercepting " + request.getRequestURI());
// code to be executed before the stack

stack.next(); // execute the stack
}
}
~~~

To execute the code just before or after the controller execution, we can use annotations
`@BeforeCall` and `@AfterCall`:

~~~
#!java
@Intercepts
@RequestScoped
public class Log {
@BeforeCall
public void before() {
// code executed before
}

@AfterCall
public void after() {
// code executed after
}
}
~~~

##Defining when intercepting

In the example above, all requests are intercepted. But we can define, as example, only methods
annotated with `@Audit` annotation. You just to implement a method that returns a `boolean` with
the necessary condition and annotate it with `@Accepts`.

~~~
#!java
@Accepts
public boolean accepts(ControllerMethod method) {
return method.containsAnnotation(Audit.class);
}
~~~

Or we can use the more simple way. The example above is a very common case and thus often repeat
this code. For this situation we can use the annotation `@AcceptsWithAnnotations` as described below:

~~~
#!java
@AcceptsWithAnnotations(Audit.class)
public class AuditInterceptor {

@AroundCall
public void around(SimpleInterceptorStack stack) {
stack.next();
}
}
~~~

##Customizing your Accepts

In the example above we used a customized accepts with annotation `AcceptsWithAnnotations`. And if you
need, you can create your custom annotation to define when intercepts. Before you need to create your
annotation like this example below.

~~~
#!java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@AcceptsConstraint(WithAnnotationAcceptor.class)
@Inherited
public @interface AcceptsWithAnnotations {
public Class<? extends Annotation>[] value();
}
~~~

As you can see, we use the Annotation `@AcceptsConstraint` to define the class that have our logic.
Now we need to implement this class.

~~~
#!java
public class WithAnnotationAcceptor implements AcceptsValidator<AcceptsWithAnnotations> {

@Override
public boolean validate(ControllerMethod controllerMethod, ControllerInstance instance) {
//your code here
return true;
}

@Override
public void initialize(AcceptsWithAnnotations annotation) {
//your code here
this.allowedTypes = Arrays.asList(annotation.value());
}
}
~~~

This class needs only to implements `AcceptsValidator<T>` interface, where generic `T` is the type
of your custom annotation.

##How to guarantee the order: after and before

If you need to guarantee the execution order for your interceptors, you can use the `after` and
`before` attributes from the `@Intercepts` annotation. Like the example below, if you have an
interceptor named `FirstInterceptor` that needs to be executed before `SecondInterceptor`, you
can declare like this:

~~~
#!java
@Intercepts(before=SecondInterceptor.class)
public class FirstInterceptor {
...
}
~~~

and:

~~~
#!java
@Intercepts(after=FirstInterceptor.class)
public class SecondInterceptor {
...
}
~~~

You can define one more Interceptor:

~~~
#!java
@Intercepts(after={FirstInterceptor.class, SecondInterceptor.class},
before={FourthInterceptor.class, FifthInterceptor.class})
public class ThirdInterceptor {
...
}
~~~

Note: VRaptor throws an exception if there is a cycle in the interceptors order. So be
careful when you define interceptors order to avoid cicles.

51 changes: 38 additions & 13 deletions vraptor-site/content/pt/docs/interceptadores.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,27 @@

#Quando interceptar?

O uso de interceptadores é feito para executar alguma tarefa antes e/ou depois de uma lógica de negócios, sendo os usos mais comuns a validação de dados, controle de conexão e transação do banco, log e criptografia/compactação de dados.
O uso de interceptadores é feito para executar alguma tarefa antes e/ou depois de uma lógica de
negócios, sendo os usos mais comuns a validação de dados, controle de conexão e transação do
banco, log e criptografia/compactação de dados.

##Como interceptar?

No VRaptor utilizamos uma abordagem onde o interceptador define quem será interceptado, muito mais próxima a abordagens de interceptação que aparecem em sistemas baseados em <strong>AOP</strong> (Programação Orientada a Aspectos).
No VRaptor utilizamos uma abordagem onde o interceptador define quem será interceptado, muito
mais próxima da abordagens de interceptação que aparecem em sistemas baseados
em <strong>AOP</strong> (Programação Orientada a Aspectos). O escopo padrão de um interceptor
é `RequestScoped`.

Portanto, para interceptar uma requisição, basta anotar a classe com a anotação `@Intercepts`. Assim como qualquer outro componente, com o uso das anotações de escopo você pode dizer em que escopo o interceptador será armazenado.
Portanto, para interceptar uma requisição, basta anotar a classe com a anotação `@Intercepts`.
Assim como qualquer outro componente, com o uso das anotações de escopo você pode dizer em que
escopo o interceptador será armazenado.

##Exemplo simples

A classe a seguir mostra um exemplo de como interceptar todas as requisições em um escopo de requisição e simplesmente mostrar na saída do console o que está sendo invocado. Lembre-se de que o interceptador é um componente como qualquer outro e pode receber quaisquer dependências por meio de Injeção de Dependências.
A classe a seguir mostra um exemplo de como interceptar todas as requisições em um escopo de
requisição e simplesmente mostrar na saída do console o que está sendo invocado. Lembre-se
de que o interceptador é um componente como qualquer outro e pode receber quaisquer
dependências por meio de Injeção de Dependências.

~~~
#!java
Expand All @@ -35,7 +45,8 @@
}
~~~

Para executar um código apenas antes ou depois da execução do controller, podemos usar as anotações `@BeforeCall` e `@AfterCall`:
Para executar um código apenas antes ou depois da execução do controller, podemos usar as
anotações `@BeforeCall` e `@AfterCall`:

~~~
#!java
Expand All @@ -53,11 +64,14 @@
}
~~~

Repare que não é mais obrigatório implementar a interface `Interceptor`, basta criar a classe e usar as anotações acima.
Repare que não é mais obrigatório implementar a interface `Interceptor`, basta criar a
classe e usar as anotações acima.

##Definindo quando interceptar

No exemplo acima todas as requisições são interceptadas. Podemos então definir que iremos interceptar apenas os métodos que possuem uma anotação chamada `@Audit`. Para isso basta implementar um método que retorne um `boolean`com a condição necessária e anotá-lo com `@Accepts`.
No exemplo acima todas as requisições são interceptadas. Podemos então definir que iremos
interceptar apenas os métodos que possuem uma anotação chamada `@Audit`. Para isso basta
implementar um método que retorne um `boolean`com a condição necessária e anotá-lo com `@Accepts`.

~~~
#!java
Expand All @@ -67,7 +81,9 @@
}
~~~

No VRaptor4 também temos outra maneira de definir a condição de aceitação. O exemplo acima é um caso bem comum e acabamos tendo de repetir esse código muitas vezes. Para essas situações você pode usar a annotation `@AcceptsWithAnnotations`.
No VRaptor4 também temos outra maneira de definir a condição de aceitação. O exemplo acima é
um caso bem comum e acabamos tendo de repetir esse código muitas vezes. Para essas situações
você pode usar a annotation `@AcceptsWithAnnotations`.

~~~
#!java
Expand All @@ -83,7 +99,9 @@

##Criando o seu Accepts customizado

Logo acima usamos o exemplo do Accepts customizado. Este é um que já vem pronto VRaptor. Mas nada impede de você criar o seu para as suas necessidades. O fluxo é bem parecido com o de criação de uma validação customizada para a BeanValidation. Primeiro você deve criar sua Annotation.
Logo acima usamos o exemplo do Accepts customizado. Este é um que já vem pronto VRaptor. Mas
nada impede de você criar o seu para as suas necessidades. O fluxo é bem parecido com o de
criação de uma validação customizada para a BeanValidation. Primeiro você deve criar sua Annotation.


~~~
Expand All @@ -97,7 +115,8 @@
}
~~~

Perceba que usamos a Annotation `@AcceptsConstraint` para indicar qual a classe responsável por fazer a verificação. Agora precisamos implementar essa classe.
Perceba que usamos a Annotation `@AcceptsConstraint` para indicar qual a classe responsável
por fazer a verificação. Agora precisamos implementar essa classe.

~~~
#!java
Expand All @@ -117,12 +136,17 @@
}
~~~

Esta classe só precisa implemetar a interface `AcceptsValidator<T>` onde T é o tipo da sua Annotation customizada. Dessa maneira você pode criar as suas condições customizadas e disponibilizá-las para todos os projetos que você precisa.
Esta classe só precisa implemetar a interface `AcceptsValidator<T>` onde T é o tipo da sua
Annotation customizada. Dessa maneira você pode criar as suas condições customizadas e
disponibilizá-las para todos os projetos que você precisa.


##Como garantir ordem: after e before

Se é preciso garantir a ordem de execução de um conjunto de interceptors, você pode usar os atributos `after` e `before` da anotação `@Intercepts`. Suponha que o `PrimeiroInterceptor` tenha que rodar antes do `SegundoInterceptor`, então você pode configurar isso tanto com:
Se é preciso garantir a ordem de execução de um conjunto de interceptors, você pode
usar os atributos `after` e `before` da anotação `@Intercepts`. Suponha que o
`PrimeiroInterceptor` tenha que rodar antes do `SegundoInterceptor`, então você pode
configurar isso tanto com:

~~~
#!java
Expand Down Expand Up @@ -153,5 +177,6 @@
}
~~~

O VRaptor lançará uma exception se existir um ciclo na ordem dos interceptors, então tenha cuidado.
O VRaptor lançará uma exception se existir um ciclo na ordem dos interceptors, então
tenha cuidado.