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

    Additive interceptors

    adamw

      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
          mbogoevici
          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
            adamw

            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.j.allen

              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
                adamw

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


                Adam

                • 5. Re: Additive interceptors
                  dan.j.allen

                  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
                    nickarls

                    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
                      swd847

                      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
                        nickarls

                        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.j.allen

                          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
                            adamw

                            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
                              adamw

                              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