spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.13k stars 40.68k forks source link

Autoconfiguration HandlerInterceptor Unable to be seen in Demo Project #29324

Closed orubel closed 2 years ago

orubel commented 2 years ago

Project : https://github.com/orubel/spring-boot-starter-beapi

Have been trying to config a handlerInterceptor in an autoconfiguration for a while now to now avail.

Everytime I make the call, I always see the same thing in the demo project:

12:31:35.712 [http-nio-8080-exec-1] DEBUG i.b.a.f.RequestInitializationFilter - doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) : {}
12:31:35.762 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - GET "/v0.4-1/user/show/5", parameters={}
12:31:35.768 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped to demo.application.controller.UserController#show(HttpServletRequest, HttpServletResponse)
12:31:35.784 [http-nio-8080-exec-1] DEBUG org.hibernate.SQL - 
 ...
12:31:35.803 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
12:31:35.804 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Writing [{user=demo.application.domain.User@76aca0ae}]
12:31:35.861 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Completed 200 OK

Call works fine but I need the handlerInterceptor for processing of FORWARD that way once it has been preprocessed, handlerInterceptor can handle all routing with preHandle/postHandle

In reading this article (https://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/handler-interceptors-registration.html), it looked as though I needed to set a HandlerMapping but when following it example from previous example, I still get nothing...

Is this a bug?

orubel commented 2 years ago

Oh this is the code I am currently using that I haven't committed :


    @Bean
    public ApiInterceptor apiInterceptor() {
        return new ApiInterceptor(principle(), apiCacheService(), apiProperties);
    }

    //@Bean
    //public BatchInterceptor batchInterceptor() {
    //  return new BatchInterceptor(principle(), apiCacheService(), apiProperties);
    //}

    //@Bean
    //public ChainInterceptor chainInterceptor() {
    //  return new ChainInterceptor(principle(), apiCacheService(), apiProperties);
    //}

    @Configuration
    public class BeapiWebAutoConfiguration implements WebMvcConfigurer {

/*
        @Bean
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
            RequestMappingHandlerAdapter requestMappingHandlerAdapter = super.requestMappingHandlerAdapter();

            //List<RequestBodyAdvice> requestBodyAdvices = new ArrayList<>();
            //requestBodyAdvices.add(new BeapiRequestBodyAdvice(principle(),apiCacheService()))
            //requestMappingHandlerAdapter.setRequestBodyAdvice(requestBodyAdvices);

            List<ResponseBodyAdvice<?>> responseBodyAdvices = new ArrayList<>();
            responseBodyAdvices.add(new BeapiResponseBodyAdvice(principle(),apiCacheService()))
            requestMappingHandlerAdapter.setResponseBodyAdvice(responseBodyAdvices);

            return requestMappingHandlerAdapter;
        }
*/

        @Bean
        public SimpleUrlHandlerMapping simpleUrlHandlerMapping () {
            SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
            Map<String, Object> map = new HashMap<>();
            map.put("/app", httpRequestHandler());
            mapping.setUrlMap(map);
            mapping.setInterceptor(apiInterceptor()).addPathPatterns("/**");
            //mapping.setInterceptors(new Object[]{new MyInterceptor()});
            return mapping;
        }

        @Bean
        BeapiHttpRequestHandler httpRequestHandler() {
            return new BeapiHttpRequestHandler();
        }

    }
wilkinsona commented 2 years ago

You don't seem to have added any interceptors to your custom RequestMappingHandlerAdapter and your custom SimpleUrlHandlerMapping wasn't used for the request in the logs.

If I've missed something and you think there's a bug here, please provide a complete yet minimal sample that reproduces it and we can take another look.

orubel commented 2 years ago

Oh. Am I supposed to do it in the 'requestMappingHandlerAdapter' ?? I'll give that a shot.

The example I gave stated to use a simpleUrlAdapter

Was using the requestMappingHandlerAdapter for the Advice (which I commented out for the time being.

orubel commented 2 years ago

nope. same thing.

14:37:59.047 [http-nio-8080-exec-1] DEBUG i.b.a.f.RequestInitializationFilter - doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) : {}
14:37:59.091 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - GET "/v0.4-1/user/show/5", parameters={}
14:37:59.097 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped to demo.application.controller.UserController#show(HttpServletRequest, HttpServletResponse)
14:37:59.112 [http-nio-8080-exec-1] DEBUG org.hibernate.SQL - 
 ...
14:37:59.128 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
14:37:59.138 [http-nio-8080-exec-1] DEBUG i.b.api.interceptor.ApiInterceptor - (BeapiResponseBodyAdvice) beforeBodyWrite(Object, MethodParameter, MediaType, Class, ServletHttpRequest, ServletHttpResponse) - parses RESPONSE output against expect output for ROLE for endpoint (see https://apisecurity.io/encyclopedia/content/owasp/api3-excessive-data-exposure.htm)
14:37:59.186 [http-nio-8080-exec-1] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Writing [{id=5, username=admin, accountExpired=null, version=0, enabled=true, email=orubel@gmail.com}]
14:37:59.222 [http-nio-8080-exec-1] DEBUG o.s.web.servlet.DispatcherServlet - Completed 200 OK

Heres the new function...

        @Bean
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
            RequestMappingHandlerAdapter requestMappingHandlerAdapter = super.requestMappingHandlerAdapter();

            requestMappingHandlerAdapter.setInterceptor(apiInterceptor()).addPathPatterns("/**");

            //List<RequestBodyAdvice> requestBodyAdvices = new ArrayList<>();
            //requestBodyAdvices.add(new BeapiRequestBodyAdvice(principle(),apiCacheService()))
            //requestMappingHandlerAdapter.setRequestBodyAdvice(requestBodyAdvices);

            List<ResponseBodyAdvice<?>> responseBodyAdvices = new ArrayList<>();
            responseBodyAdvices.add(new BeapiResponseBodyAdvice(principle(),apiCacheService()))
            requestMappingHandlerAdapter.setResponseBodyAdvice(responseBodyAdvices);

            return requestMappingHandlerAdapter;
        }

/*
        @Bean
        public SimpleUrlHandlerMapping simpleUrlHandlerMapping () {
            SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
            Map<String, Object> map = new HashMap<>();
            map.put("/app", httpRequestHandler());
            mapping.setUrlMap(map);
            mapping.setInterceptor(apiInterceptor()).addPathPatterns("/**");
            //mapping.setInterceptors(new Object[]{new MyInterceptor()});
            return mapping;
        }

        @Bean
        BeapiHttpRequestHandler httpRequestHandler() {
            return new BeapiHttpRequestHandler();
        }
*/
orubel commented 2 years ago

for the record, there is a DEBUG statement at preHandle/postHandle so I need to see those to know the Interceptor is working.

I see the advice (and I know it is handling the body) so I know the advice is working properly but the Interceptor never gets called

wilkinsona commented 2 years ago

Thanks. Unfortunately that's not really what I'm looking for. I'm afraid I don't have time to piece things together from snippets of code pasted here and a link to your starter. If you would like us to spend some more time investigating, please spend some time providing a complete yet minimal sample. That sample should be self-contained and make it as easy as possible for us to run it and reproduce the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it up and attaching it to this issue.

orubel commented 2 years ago

will do. I'll strip out the unnecessary and create a simple example. Might even fix my problem. Heh

Will have that to you this afternoon. :)

orubel commented 2 years ago

My underlying issue seems to be that FILTER and INTERCEPTOR and ADVICE SHOULD be able to work together and THEY DO in a project... but when trying to push these from an autoconfiguration to a demo project, they work selectively or have integration issues. So I'm going to have to provide you with an autoconfiguration and demo project no matter what... but I can remove some kruft.

I think right now this issue may be SPECIFIC to 'autoconfiguration' so whatever I build out IS going to have to have an autoconfiguration and a demo project to show this.

wilkinsona commented 2 years ago

That's absolutely fine. Ideally the sample should be as simple as possible to reproduce the problem but no simpler.

orubel commented 2 years ago

Okee dokee. I just did a bunch of stripping away of cruft and unused files and functions so you only need to focus on what is going on.

Hasven't tested the bootstrapped user but I checked it in the DB and it's there so it should be fine.

Will test more tomorrow morning just to be sure but some basic tests show it working fine.

https://github.com/orubel/beapi-spring-boot-test/

Have some basic instructions for build/config... let me know if you have ANY problem and I am there in a flash.

wilkinsona commented 2 years ago

Thanks but I'm afraid that's still not what I'm looking for as it doesn't look to be minimal. For example, a database shouldn't be required to reproduce a web-related problem. I would also be surprised if any of the JWT-related code is necessary.

Regardless, I have spent some time trying to run it with MySQL 5.7.36 and Java 1.8 and it was unable to connect due to a failed SSL handshake. At that point, I noticed that you're using Spring Boot 2.2 which has been out of OSS support since 16 October 2020. I also noticed that you're configuring your demo application to component scan classes in your auto-configuration. This will result in them being treated as part of the application's configuration rather than auto-configuration.

If you'd like us to spend any more time on this please provide a truly minimal sample that reproduces the problem. It may be easier to start from scratch and build up until the problem occurs rather than stripping what you already have back down again. Furthermore, unless the problem is specific to Groovy, ideally the sample should be written in Java as it eliminates one possible cause.

orubel commented 2 years ago

So problem is not specific to Groovy (knew that would come up) as this has been used in local Springboot project as well as in Grails plugins with Springboot. Interceptor works fine in local project

But upgrading may definitely help :)

I can try again without JWT or DB and upgrade project.

Will also test better before handoff. My apologies.

orubel commented 2 years ago

Y'know. I highly suspect you nailed it with 'ComponentScan'; I had completely forgotten that was there and didn't know it ignored autoconfig when doing that.

Going to run a bunch more tests (and build more tests) and do alot more configuring but I think you nailed it.

Please close as I dont want to waste any more of anyones time and I'll just edit here with a note if that solved it :)

Thanks again.

orubel commented 2 years ago

Ok, so the ComponentScan was correct as Filter/Interceptor/Advice needs to be in project because request/response flows through project (not the autoconfig); so that effectively was bringing them in ... but not the right way. So you definitely pointed me in a better direction

Thanks again. :)