-
Notifications
You must be signed in to change notification settings - Fork 332
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #647 from caelum/ot-docseninterceptors-chpk
Adding interceptors docs (EN)
- Loading branch information
Showing
2 changed files
with
207 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters