SeamFramework.orgCommunity Documentation
The service handler facility allow you to declare interfaces and abstract classes as automatically implemented beans. Any call to an abstract method on the interface or abstract class will be forwarded to the invocation handler for processing.
If you wish to convert some non-type-safe lookup to a type-safe lookup, then service handlers may be useful for you, as they allow the end user to map a lookup to a method using domain specific annotations.
We will work through using this facility, taking the example of a service which can execute JPA queries upon abstract method calls. First we define the annotation used to mark interfaces as automatically implemented beans. We meta-annotate it, defining the invocation handler to use:
@ServiceHandlerType(QueryHandler.class)
@Retention(RUNTIME)
@Target({TYPE})
@interface QueryService {}
We now define an annotation which provides the query to execute:
@Retention(RUNTIME)
@Target({METHOD})
@interface Query {
String value();
}
And finally, the invocation handler, which simply takes the query, and executes it using JPA, returning the result:
class QueryHandler {
@Inject EntityManager em;
@AroundInvoke
Object handle(InvocationContext ctx) {
return em.createQuery(ctx.getMethod().getAnnotation(Query.class).value()).getResultList();
}
}
The invocation handler is similar to an interceptor. It must have an @AroundInvoke
method that
returns an object and takes an InvocationContext
as an argument.
Do not call InvocationContext.proceed()
as there is no method to proceed to.
Injection is available into the handler class, however the handler is not a bean definition, so observer methods, producer fields and producer methods defined on the handler will not be registered.
Finally, we can define (any number of) interfaces which define our queries:
@QueryService
interface UserQuery {
@Query("select u from User u")
public List<User> getAllUsers();
}
Finally, we can inject the query interface, and call methods, automatically executing the JPA query.
class UserListManager {
@Inject
UserQuery userQuery;
List<User> users;
@PostConstruct
void create() {
users=userQuery.getAllUsers();
}
}