ejb-spec
  1. ejb-spec
  2. EJB_SPEC-100

Provide @Idempotent functionallity to the EJB Container

    Details

    • Type: Improvement Improvement
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 3.2
    • Fix Version/s: Future version
    • Labels:
      None

      Description

      My proposal is to add functionality in the EJB-Container to support @Idempotent for Stateless EJB methods.

      A method is idempotent, when a call to this method does not have any side-effects. This means, that multiple calls to such a method always give the same result.

      So a container could provide this functionality for methods of a Stateless Session Bean, marked with @Idempotent to cache the result of the method for further calls.

      An example:

      @Stateless
      public class MyService {
      
          @Idempotent
          public Long add(Long a1, Long a2) {
              return a1 + a2;
          }
      }
      

      With this, a container is told to handle each call with the same arguments idempotent and return exactly the same value. So a call:

      @Stateless
      public class AnotherService {
      
          @EJB
          MyService myService;
      
          public void someMethod() {
              // assuming, this is the first call ever to this service's method...
              // the container calls the method directly and caches the result.
              System.out.println(myService.add(1024, 42));
      
              // the container will return always the same value, read from a cache, without explicitly call the method.
              for(int i = 0; i<10; i++) {
                  System.out.println(myService.add(1024, 42));
              }
          }
      }
      

      A container is responsible for caching the result of the method as well as how long or under which circumstances the result is cached (e.g. WeakReference).

      Another responsibility for the container is the error handling and transaction rollback for idempotent methods, especially in cluster environments. (see the similar functionality with weblogic.javaee.Idempotent, but my proposal goes a bit further).

      This would be a performance gain, but also a potential risk for developers, that do not know, what they exactly do.

      I think, there is a general need for this functionality, even in REST-Resources or in Cluster-Environment to simplify things and to standardize the behavior of containers in this way.

      Comments are requested

        Activity

        Hide
        arjan tijms added a comment -

        I like the proposal, but want to add that the JCache annotations with respect to the caching aspect do something similar. See e.g. javax.cache: The new Java Caching Standard

        Most JCache annotation examples work with the concept of a getter and setter method though (I don't know if @CacheResult and @CachePut can be applied to the same method), but it would probably be useful to coordinate with JCache for this aspect.

        Show
        arjan tijms added a comment - I like the proposal, but want to add that the JCache annotations with respect to the caching aspect do something similar. See e.g. javax.cache: The new Java Caching Standard Most JCache annotation examples work with the concept of a getter and setter method though (I don't know if @CacheResult and @CachePut can be applied to the same method), but it would probably be useful to coordinate with JCache for this aspect.
        Hide
        rherschke added a comment -

        Hi Arjan,

        yes, I appreciate to see JSR-107 in next Java EE spec.

        Although you could build an @Idempotent method with javax.cache Annotations (or (I already do this) by an proprietary interceptor), there is one little exception:

        If the container should handle the "tracking of idempotent method results", he could even decide if - or if not - it has to construct the bean instance itself.

        Look at the second example above. The container already injects just a proxy at @EJB MyService myService. The bean at this state in some container implementations isn't instantiated itself nor is it caught from the bean instance pool. The method myService.add() is proxied with the logic to decide whether to return the cached value or to get an instance from the pool (or instantiate one) and invoke the method.

        The javax.cache Annotations acts like an interceptor with an "AroundInvoke" method, that does the caching logic. But to have the interceptor's "AroundInvoke" executed, the bean (which is returned from InvocationContext#getTarget()) is completely instantiated before the execution. This isn't necessary in the case, the container is responsible.

        Next, the @Idempotent handling by the container is not only responsible for caching the result but also for doing a retry of a method in a cluster environment on another cluster-node instance for example in case the current cluster-node result in an error (which is not an @ApplicationException). This is true, because of the convention behind @Idempotent which means, ALL invocations of this method - even on another cluster-node instance WILL return the SAME value under the same invocation conditions (parameter values...).

        So JCache is really fine, but I compare it a bit with @Asynchronous, that is completely the responsibility of the container too.

        Many thanks for your comment and for your vote

        Show
        rherschke added a comment - Hi Arjan, yes, I appreciate to see JSR-107 in next Java EE spec. Although you could build an @Idempotent method with javax.cache Annotations (or (I already do this) by an proprietary interceptor), there is one little exception: If the container should handle the "tracking of idempotent method results", he could even decide if - or if not - it has to construct the bean instance itself. Look at the second example above. The container already injects just a proxy at @EJB MyService myService . The bean at this state in some container implementations isn't instantiated itself nor is it caught from the bean instance pool. The method myService.add() is proxied with the logic to decide whether to return the cached value or to get an instance from the pool (or instantiate one) and invoke the method. The javax.cache Annotations acts like an interceptor with an "AroundInvoke" method, that does the caching logic. But to have the interceptor's "AroundInvoke" executed, the bean (which is returned from InvocationContext#getTarget() ) is completely instantiated before the execution. This isn't necessary in the case, the container is responsible. Next, the @Idempotent handling by the container is not only responsible for caching the result but also for doing a retry of a method in a cluster environment on another cluster-node instance for example in case the current cluster-node result in an error (which is not an @ApplicationException ). This is true, because of the convention behind @Idempotent which means, ALL invocations of this method - even on another cluster-node instance WILL return the SAME value under the same invocation conditions (parameter values...). So JCache is really fine, but I compare it a bit with @Asynchronous , that is completely the responsibility of the container too. Many thanks for your comment and for your vote

          People

          • Assignee:
            marina vatkina
            Reporter:
            rherschke
          • Votes:
            5 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: