Another Way for Spring Request interceptors or writing an middle-ware: SpringSandwich

Another Way for Spring Request interceptors or writing an middle-ware: SpringSandwich

We usually try to Intercept HTTP requests for logging purpose or Authorisation or create an trigger for certain activity based action, typical usage is always Logging or Authorisation.While i was try to implement request logging i found a beautiful plugin called SpringSandwich. As website states its an Annoted, type-safe interceptors for Spring web controllers and it had simple beautiful example to implement. so in couple of on going projects i have implemented Logging, Authorisation for my micro services. so we shall go in brief to implement the simple logging for rest APIs

So now lets include  SpringSandwich as dependency for Spring boot web application

 <dependencies>
        <dependency>
            <groupId>com.kastkode</groupId>
            <artifactId>springsandwich</artifactId>
            <version>[1.0.2,)</version>
        </dependency>
    </dependencies>

Now we instruct Spring boot app to scan for packages using ComponentScan annotation in our main Application class

@ComponentScan(basePackages = {"com.kastkode.springsandwich.filter", "com.your-app-here.*"})
    public class Main { ... } 

As this plugin has to override spring boot default application scan to intersept we have include main package of of our spring boot application as mention int above example.

Now we shall implement Simple request logger logic which writes the information.

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import com.kastkode.springsandwich.filter.api.BeforeHandler;
import com.kastkode.springsandwich.filter.api.Flow;

@Component
public class ConsoleLogger implements BeforeHandler {

    Logger logger = LoggerFactory.getLogger(ConsoleLogger.class);

    @Override
    public Flow handle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler, String[] flags) throws Exception {
        logger.debug(request.getMethod() + "request is executing on" + request.getURI());
        return Flow.CONTINUE;
    }
}

the above example will log the http method and the uri which is intersepted. for debugging this can also be used for authorization just by implementing the required logic.

Now We shall Instruct our Controller to use the  Handler for logging the information.

There are two ways to implement either we as entire class to log all the request or for the pirticular controller.

  1. Implemting for the entire class.
@RestController
@Before( @BeforeElement(ConsoleLogger.class)) 
Class Controlle {...}
  1. For the required Method we Annotate the method insted of entire class.
...
Class Controller {
...
@GetMapping(path="/test")
@Before( @BeforeElement(ConsoleLogger.class))
public String test() {
    ...
}
...
}

Also we can Add multiple Handlers just by passing the class as list as mentioned int he example.

@Before({
    @BeforeElement(IPWhiteListCheck.class),
    @BeforeElement(LoginWall.class),
    @BeforeElement(value = RestrictByRole.class, flags = {"admin", "manager"})
}) 

And also we can use after annotation to perform action after executing the method by using @After( @AfterElement(DoThisAfter.class) )

After going through the example when we compare to Spring's APO aspects this is very simple and we get far more control over our handler and clearer code which  can be refactored when necessary. we your not aware of spring APO basic Authorisation example is implemented in this link : https://blogs.ashrithgn.com/2018/07/19/custom-authorization-annotation/.