11 Replies Latest reply on Apr 6, 2010 10:48 AM by Adam Warski

    Additive interceptors

    Adam Warski Master

      Hello,


      I was thinking about implementing a security annotation and interceptor, a bit similar to what can be found in Seam2 security, so the annotation would be: @Security("#{some condition}").


      Now, it makes sense to put this annotation both on a class and on methods. If it's on a class, then it applies to all methods. But what if it's present both on a method and on a class? E.g.:


      @Security("#{condition1}")
      public class Test {
         // ...
      
         @Security("#{condition2}")
         public void doWork() { ... }
      }



      For me it would be logical that then both conditions should apply, so that the class-level annotation specifies a general security condition, and the method-level annotation refines the condition with additional security checks for the method.


      However my attempts to implement this failed so far. Even if I make the annotation element binding, I can't put the annotations as in the example, as I get a Duplicate interceptor binding type error (although the element values are different).


      Not mentioning that I don't know how to write an interceptor that would  intercept all annotations, with any element value? (one way is to specify the parameter as nonbinding, but then I wouldn't expect the interceptor to be called twice).


      Is implementing something like this at all possible, or would this be a portable extension?


      Adam

        • 1. Re: Additive interceptors
          Marius Bogoevici Newbie
          Hi Adam,

          I don't see how this would be possible:

          The spec says this (Section 9.5.2):
          "
          If the set of interceptor bindings of a bean or interceptor, including bindings inherited from stereotypes and other intercept-
          or bindings, has two instances of a certain interceptor binding type and the instances have different values of some annota-
          tion member, the container automatically detects the problem and treats it as a definition error.
          "

          Cheers,
          Marius
          • 2. Re: Additive interceptors
            Adam Warski Master

            Hmm, so the specs doesn't allow this. But I still think it could be useful, but would probably form an extension. Guess you can add interceptors there, so implementing such additive interceptors should be possible.


            Adam

            • 3. Re: Additive interceptors
              Dan Allen Master

              Adam Warski wrote on Mar 26, 2010 16:06:


              I was thinking about implementing a security annotation and interceptor, a bit similar to what can be found in Seam2 security, so the annotation would be: @Security("#{some condition}").


              Would you be willing to join the Seam 3 security module as a contributor? If so, please get in touch with Shane. We'd love to align our efforts!

              • 4. Re: Additive interceptors
                Adam Warski Master

                If anybody's interested, here's how to implement a simple security interceptor (non-additive).


                Adam

                • 5. Re: Additive interceptors
                  Dan Allen Master

                  Another approach to additive interceptors is to have a different annotation for a class (@SecureType) and a method (@SecureMethod). Then you'd bind them to two different interceptors, but could avoid duplicate code by extending from the same abstract security interceptor.

                  • 6. Re: Additive interceptors
                    Nicklas Karlsson Master

                    Did Gavins re-annotate stuff get included in the extensions already? That could perhaps also be used for streamlining some stuff down the same pipe

                    • 7. Re: Additive interceptors
                      Stuart Douglas Master

                      The reannotated stuff is in there, but as much as possible you should use NewAnnotatedTypeBuilder, I want to remove the ReAnnotated* stuff at some point so we don't have to maintain two impls of AnnotatedType.


                      To change an annotation on a method as it is loaded the code should look something like:



                         public void processAnnotatedType(@Observes ProcessAnnotatedType<?> event)
                         {
                            NewAnnotatedTypeBuilder builder = new NewAnnotatedTypeBuilder(event.getAnnotatedType());
                            for(AnnotatedMethod<?> m : event.getAnnotatedType().getMethods())
                            {
                               if(m.isAnnotationPresent(Security.class))
                               {
                                  final String value = m.getAnnotation(Security.class).value();
                                  builder.removeFromMethod(m.getJavaMember(), Security.class);
                                  builder.addToMethod(m.getJavaMember(), new AnnotationLiteral<SecurityMethod> implements SecurityMethod {
                                     
                                     public String value()
                                     {
                                        return value;
                                     }
                                  });
                               }
                            }
                            
                            event.setAnnotatedType(builder.create());
                         }
                      



                      this would allow you to use @Security on a method, but change it to @SecurtyMethod behind the scenes. NewAnnotatedTypeBuilder is part of weld-extendsions.

                      • 8. Re: Additive interceptors
                        Nicklas Karlsson Master

                        Perhaps Pete has some ideas since in https://jira.jboss.org/jira/browse/WELD-53 he mentions


                        "need a full review of how we deal with Annotated*"

                        • 9. Re: Additive interceptors
                          Dan Allen Master

                          Ah, that's right! Of course. For those of you following along, remember that the annotations on a class can be treated as merely hints for the bean processor (i.e., startup). You can swap out, add or remove annotations from a class by wrapping the bean metadata. Great suggestion Stuart!

                          • 10. Re: Additive interceptors
                            Adam Warski Master

                            Dan Allen wrote on Apr 05, 2010 06:27:


                            Another approach to additive interceptors is to have a different annotation for a class (@SecureType) and a method (@SecureMethod). Then you'd bind them to two different interceptors, but could avoid duplicate code by extending from the same abstract security interceptor.


                            Sure, but it's not as elegant as having one annotation :)


                            Adam

                            • 11. Re: Additive interceptors
                              Adam Warski Master

                              Stuart Douglas wrote on Apr 05, 2010 11:30:


                              The reannotated stuff is in there, but as much as possible you should use NewAnnotatedTypeBuilder, I want to remove the ReAnnotated* stuff at some point so we don't have to maintain two impls of AnnotatedType.

                              To change an annotation on a method as it is loaded the code should look something like:



                              That should work perfect, I'll try, thanks a lot for the pointer! :)


                              Adam