CDI call interceptor annotated method within same instance
Asked Answered
S

3

3

here is my DAO implementation, i will load the whole table and cached in memory for a certain period of time

@ApplicationScoped
public class DataAccessFacade {

   @Inject
   private EntityManager em;

   @CacheOutput
   public Map<String, String> loadAllTranslation() {
      List<Translation> list = em.createQuery("select t from Translation t").getResultList();    
      Map<String, String> result = new HashMap<String, String>();
      // do more processing here, omitted for clarity     
      return result;
   }

   public String getTranslation(String key) {
      return loadAllTranslation().get(key);
   }

}

here is my jersey client

@Inject
DataAccessFacade dataAccessFacade;

@Path("/5")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String t5(@QueryParam("id") String key) {
  // load the data from dataAccessFacade
  String text = dataAccessFacade.getTranslation(key); 
  String text2 = dataAccessFacade.loadAllTranslation().get(key); 
}

in the client if i call the dataAccessFacade.loadAllTranslation(), i will see the interceptor logic been executed

if i call the dataAccessFacade.getTranslation() which internally call the loadAllTranslation(), then i didn't see the interceptor been executed

what is the problem here?

how to solve it?

Siloam answered 1/10, 2010 at 7:3 Comment(0)
M
2

This is the correct behavior as in the CDI spec. Only methods called by "client" classes are considered "business methods" and, thus, are intercepted.

Mcginn answered 16/9, 2011 at 9:55 Comment(0)
M
1

just do the following in your DataAccessFacade:

@Inject
private Provider<DataAccessFacade> self;

public String getTranslation(String key) {
  return self.get().loadAllTranslation().get(key);
}
Mulvihill answered 19/6, 2014 at 6:49 Comment(1)
What if we don't know how the object was injected? It may be a subclass, and/or it may have qualifiers at the injection point. Is there a way to get the same object the client sees?Phrenic
T
-1

An interceptor bound to a class will intercept all methods. It looks like you have chosen to bind your interceptor (@CacheOutput?) to specific methods rather than at the class level.

I imagine that if you explicitly bound your interceptor to the getTranslation method in addition to loadAllTranslation then you would see the interceptor working in both situations.

I have not found any explanation in the specification to explain the current behaviour. My guess is that it could be thought of as a kind of encapsulation (information hiding). Externally, there is no reason to expect that a call to getTranslation would result in a call to loadAllTranslation. If the interceptor was to be invoked as the result of a call to getTranslation (without an explicit annotation) it could be seen as leaking the details of the class' internal workings.

Tarpan answered 5/10, 2010 at 22:9 Comment(2)
i have tried to move the annotation to the class level, same result.Siloam
Not really sure. Could you try this very simple business interceptor and see what you get: easybeans.org/doc/userguide/en/chunk-integrated/ch04s04.htmlTarpan

© 2022 - 2024 — McMap. All rights reserved.