SeamFramework.orgCommunity Documentation

Chapter 14. Service Handler

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:

@ServiceHandler(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();
   }
}

Note

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();
   }
}