7 Replies Latest reply on Jan 13, 2011 5:12 AM by Serkan Eskici

    Interceptor & RESTEasy provider, in which order are they called ?

    Serkan Eskici Novice

      Hi everyone,


      I'm building an app with Seam and RESTEasy and I've the following question.


      I'm using a RESTEasy provider for marshalling and unmarshalling of the content and I'm also using a Seam interceptor on the same method to validate the incoming request.


      So here is my resource class:


      @POST
      @Consumes("text/xml")
      @Produces("text/xml")
      @ValidateRequest // this is  my own interceptor which validates MyEntity and throws WebApplicationException if validation errors occurs.
      public Response insert(MyEntity entity)  {
          ...
      }
      



      And I also have a provider:


      @Provider
      @Consumes({ "application/*+xml", "text/*+xml" })
      public class JiBXProvider implements MessageBodyReader<MyEntity> {
         ...
      }
      




      Now the question is when you arrive in the interceptor... is MyEntity already unmarshalled or not ?
      Does the provider get invoked before the interceptor ? -And if not, what is the best way to do this ?


      Thx in advance !

        • 1. Re: Interceptor & RESTEasy provider, in which order are they called ?
          Jozef Hartinger Master

          No, the interceptor gets called first. Then, the returned value is passed to the provider. It seems that you need the opposite execution order (to manipulate the XML?). What exactly do you want to do?

          • 2. Re: Interceptor & RESTEasy provider, in which order are they called ?
            Serkan Eskici Novice

            Hi Jozef,


            Thx for the reply.


            I want to validate the incoming XML first before it enters the method.


            But my requirement is that I want to validate it using OO and not XML techniques (I'm already validating it against a XSD, but that's not enough for my use case).


            I'm using Drools for conditional checks and JPA to compare some values against old values in the DB.


            Thus summarized, I want to do the following:


            Incoming XML request --> gets validated against a XSD --> Unmarshall to entity --> do complex validating stuff with Drools and JPA --> if validation is OK --> do business logic stuff with entity --> send XML back to client via REST.

            • 3. Re: Interceptor & RESTEasy provider, in which order are they called ?
              Serkan Eskici Novice

              Btw, the interceptor I'm using is a default Seam (EJB3/Pojo) interceptor, not the ones coming with RESTEasy.

              • 4. Re: Interceptor & RESTEasy provider, in which order are they called ?
                Jozef Hartinger Master

                You can do this easily with a Seam interceptor. Simply run your drools-based validation logic in the interceptor method before invoking the web service method (calling ctx.proceed()). You'll have the unmarshalled incomming entity available in the method parameters already.

                • 5. Re: Interceptor & RESTEasy provider, in which order are they called ?
                  Serkan Eskici Novice

                  OK thx for the info.


                  I thought that you stated the opposit in your previous message e.g. that it was not possible to get the unmarshalled object in the interceptor because it gets called earlier than the Jaxb provider.


                  So if this is my interceptor than the code should work, right ?


                  public class ValidationInterceptor {
                  
                      @Logger
                      private Log log;
                  
                      @In
                      private EntityManager em;
                  
                      @In
                      private WorkingMemory validationWM;
                  
                      // TODO: use @WrappedMap for marshalling maps.
                      private Map<String, String> errorMessages;
                  
                  
                      @AroundInvoke
                      public Object validate(InvocationContext ctx) throws Exception {
                          Notification not = (Notification) ctx.getParameters()[0]; //this is the unmarshalled Entity (unmarshalled by the provider first)
                          if (not != null) {
                              log.debug("in validation...");
                              validate(not);
                          }
                  
                          log.debug("going out of validation...");
                          if (errorMessages == null) {
                              // TODO: set status to VALID or whatever
                              log.debug("Notification was succesfully validated.");
                              return ctx.proceed();
                          }
                          else {            
                              Events.instance().raiseAsynchronousEvent("notification.invalid", not);
                              throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(errorMessages).build());
                          }
                      }
                  
                      private void validate(Notification not) {
                          validateUniqueness(not);
                  
                          if (errorMessages == null)
                              validateCompleteness(not);
                          if (errorMessages == null)
                              validateSequence(not);
                          if (errorMessages == null)
                              validateBusinessRules(not);
                      }
                     
                      ...
                    
                      private void validateBusinessRules(Notification not) {
                          this.validationWM.setGlobal("errorMessages", errorMessages);
                          this.validationWM.insert(not);
                          this.validationWM.fireAllRules();
                      }
                  }
                  


                  • 6. Re: Interceptor & RESTEasy provider, in which order are they called ?
                    Jozef Hartinger Master

                    Serkan, sorry for confusion. It gets called after JAX-RS unmarshalling of the incomming entity and before JAX-RS marshalling of the response. Imagine the interceptor as an inner wrapper of the method call while the JAX-RS providers represent and outer wrapper. So the execution flow looks like this:


                    Incoming request --> JAX-RS reader (unmarshalling) --> Seam interceptor (the code before ctx.proceed()) --> resource method invocation --> Seam interceptor (the code after ctx.proceed()) --> JAX-RS writer (marshalling)