Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There is no possibility to disable filtering out configuration-processor jar from spring-boot-maven plugin #27697

Closed
stepanovdg opened this issue Aug 16, 2021 · 16 comments
Labels
status: declined A suggestion or change that we don't feel we should currently apply

Comments

@stepanovdg
Copy link

stepanovdg commented Aug 16, 2021

In our project we are using some annotations tools from configuration processor at runtime.
After recent spring version update (spring-boot-starter-parent 2.3.8 -> 2.5.2) almost everything was fine just at runtime we start getting:

ClassNotFoundException: org.springframework.boot.configurationprocessor.json.JSONException

In our WebSecurityConfigurerAdapter.configure code.

After manually adding spring-boot-configuration-processor-2.5.2.jar into BOOT-INF/lib/ folder of the build jar -> application is working fine (I was sure that previous class not found was due to wrap actual exception - but seems it was original problem).

So right now we are not able to mark this jar not to be deleted from resulted artifact after this change

Is it possible to wrap registering of the

filters.addFilter(new JarTypeFilter()); 

with some flag? by default it would exclude but if it is required for some corner cases like ours we can proceed using it?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 16, 2021
@philwebb
Copy link
Member

Relates to #22036

@philwebb
Copy link
Member

@stepanovdg Using spring-boot-configuration-processor at runtime is quite unusual. Which specific classes do you use from that project and why are they needed at runtime?

@philwebb philwebb added the status: waiting-for-feedback We need additional information before we can continue label Aug 16, 2021
@philwebb
Copy link
Member

If we do want to make things configurable we could either offer a simple on/off switch or change JarTypeFilter and JarTypeFileSpec so that they can accept a list of the types to exclude?

Interestingly the JarTypeFileSpec does not filter annotation processors. I'm assuming because Gradle has a better annotation processor setup and they don't appear in the first place.

@philwebb philwebb added for: team-attention An issue we'd like other members of the team to review and removed for: team-attention An issue we'd like other members of the team to review labels Aug 16, 2021
@stepanovdg
Copy link
Author

stepanovdg commented Aug 16, 2021

@philwebb Not sure that we really used it directly. Maybe some problem with order.
The place where its failing we are actually using org.reflections to scan methods with our own annotations (like frontendapi, internalapi and etc) together with RequestMapping to group up and apply web security settings and in other place to generate proper open api endpoints.

I was thinking just after major update of spring versions something was broken in configuration or third-party dependency versions and this was just masking actual reason.

But putting jar on classpath resolved all problems.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Aug 16, 2021
@philwebb
Copy link
Member

@stepanovdg Do you have a full stack-trace that you can add to this issue? Even better would be a sample application that replicates the problem. I'm curious why org.reflections would be needing to read the org.springframework.boot.configurationprocessor.json.JSONException class at all.

@philwebb philwebb added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Aug 16, 2021
@stepanovdg
Copy link
Author

stepanovdg commented Aug 16, 2021

2021-08-06 01:34:08 ERROR [   main] [o.s.boot.SpringApplication         :843]  Application run failed 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/configurationprocessor/json/JSONException
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:338)
	at c.v.t.TcpBullseyeApplication.main(TcpBullseyeApplication.java:34)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.NoClassDefFoundError: org/springframework/boot/configurationprocessor/json/JSONException
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
	... 27 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/boot/configurationprocessor/json/JSONException
	at c.v.t.config.security.CommonSecurityConfig.configure(CommonSecurityConfig.java:57)
	at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.getHttp(WebSecurityConfigurerAdapter.java:217)
	at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.init(WebSecurityConfigurerAdapter.java:315)
	at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.init(WebSecurityConfigurerAdapter.java:93)
	at c.v.t.config.security.CommonSecurityConfig$$EnhancerBySpringCGLIB$$bd90bedf.init(<generated>)
	at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$$FastClassBySpringCGLIB$$432a6c3b.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
	at c.v.t.config.security.CommonSecurityConfig$$EnhancerBySpringCGLIB$$ce36a12.init(<generated>)
	at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.init(AbstractConfiguredSecurityBuilder.java:338)
	at org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder.doBuild(AbstractConfiguredSecurityBuilder.java:300)
	at org.springframework.security.config.annotation.AbstractSecurityBuilder.build(AbstractSecurityBuilder.java:38)
	at org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration.springSecurityFilterChain(WebSecurityConfiguration.java:127)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
	... 28 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.configurationprocessor.json.JSONException
	at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	... 52 common frames omitted

Actual stacktrace.
Error happening at line:

 .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
          .and()

specifically pointing to this and().

@Override
  @Log(Log.LoggingLevel.INFO)
  protected void configure(HttpSecurity http) {
      HashSet<String> skipUrls =
          new HashSet<>(Arrays.asList("/management/health", "/management/prometheus"));
      HttpSecurity httpSecurity = registerSecuredApi(http);
      httpSecurity
          .csrf()
          .disable()
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
          .and()
          .addFilterBefore(
              new AuthenticationFilter(whitelistedIps, skipUrls),
              UsernamePasswordAuthenticationFilter.class)
          .addFilterBefore(new InitiatedFilter(skipUrls), AuthenticationFilter.class)
          .exceptionHandling()
          .authenticationEntryPoint(exceptionHandler)
          .accessDeniedHandler(exceptionHandler);
  }

  @Log(Log.LoggingLevel.INFO)
  protected HttpSecurity registerSecuredApi(HttpSecurity http) throws Exception {
    ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry
        expressionInterceptUrlRegistry = http.authorizeRequests();
    Map<HttpMethod, List<ApiAnnotationsUtils.MethodPatternPair>> apiAnnotatedWith =
        getApiAnnotatedWith(FrontendApi.class);
    apiAnnotatedWith
        .keySet()
        .forEach(
            method ->
                expressionInterceptUrlRegistry
                    .antMatchers(
                        method,
                        apiAnnotatedWith.get(method).stream()
                            .map(ApiAnnotationsUtils.MethodPatternPair::getPattern)
                            .toArray(String[]::new))
                    .authenticated());
    return expressionInterceptUrlRegistry
        .antMatchers("/actuator/**")
        .permitAll()
        .anyRequest()
        .permitAll()
        .and();
  }

  @Log(Log.LoggingLevel.INFO)
    public static Map<HttpMethod, List<MethodPatternPair>> getApiAnnotatedWith(Class<? extends Annotation> annotation) {
        Map<HttpMethod, List<MethodPatternPair>> collect = getRequestMappingStream(annotation)
                .flatMap(
                        request ->
                                Arrays.stream(request.method())
                                        .map(m -> HttpMethod.resolve(m.toString()))
                                        .flatMap(
                                                m ->
                                                        Arrays.stream(request.path())
                                                                .map(path -> new MethodPatternPair(m, path))))
                .collect(Collectors.groupingBy(MethodPatternPair::getMethod));
        return collect;
    }

    @Log
    public static Stream<RequestMapping> getRequestMappingStream(Class<? extends Annotation> annotation) {
        return new Reflections("c.v.t.web.api.controller", new MethodAnnotationsScanner())
                .getMethodsAnnotatedWith(annotation).stream()
                .map(
                        method ->
                                Objects.requireNonNull(
                                        AnnotationUtils.getAnnotation(method, RequestMapping.class)));
    }

    @Data
    @AllArgsConstructor
    public static class MethodPatternPair {
        HttpMethod method;
        String pattern;
    }

Not sure that will be able to create simple application now.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Aug 16, 2021
@philwebb
Copy link
Member

I'm at a bit of a loss from the code you've attached what could be causing the problem, especially if CommonSecurityConfig.java:57 is on the .sessionCreationPolicy(SessionCreationPolicy.STATELESS) line.

Have you tried searching your codebase to make sure org.springframework.boot.configurationprocessor.json.JSONException hasn't accidentally been imported anywhere?

@philwebb philwebb added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Aug 16, 2021
@snicoll
Copy link
Member

snicoll commented Aug 17, 2021

@stepanovdg the configuration processor shades JSON for internal purpose only. It's not meant to be used anywhere else, especially considering that an annotation processor is meant to be used at compile time only. CommonSecurityConfig should rely on a JSON library directly rather than relying on our shaded, internal version.

You can do so by adding a dependency to com.vaadin.external.google:android-json and fix the import in CommonSecurityConfig.

@snicoll snicoll closed this as completed Aug 17, 2021
@snicoll snicoll added status: invalid An issue that we don't feel is valid and removed status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged labels Aug 17, 2021
@philwebb
Copy link
Member

@snicoll I'm not sure we've determined that CommonSecurityConfig is importing JSONException, it might be the Reflections class that's somehow picking it up from elsewhere.

@stepanovdg If you haven't got any org.springframework.boot.configurationprocessor.json import in your codebase can you please provide a sample that replicates the problem.

@philwebb philwebb added the for: team-meeting An issue we'd like to discuss as a team to make progress label Aug 17, 2021
@stepanovdg
Copy link
Author

@philwebb @snicoll
Thank you very much. Its appeared in side auth filter import was from JsonObject and exception from configuration processor instead of org.json.

Sorry for disturb.

@philwebb philwebb added status: declined A suggestion or change that we don't feel we should currently apply and removed for: team-meeting An issue we'd like to discuss as a team to make progress status: invalid An issue that we don't feel is valid labels Aug 23, 2021
@qyqcswill
Copy link
Contributor

qyqcswill commented Sep 9, 2021

It happens to me. I use another way in my codebase. But I tried spring-boot 2.3.x,it worked. By the way, will you fix this in
next version.

@snicoll
Copy link
Member

snicoll commented Sep 9, 2021

@qyqcswill there's nothing to fix as far as I know. Please review the thread above. If you have imports on org.springframework.boot.configurationprocessor.json, you shouldn't. This is a shaded version that's not meant to be used in user's code. If you don't, please share a small sample that reproduces the problem and we can reopen this issue.

@qyqcswill
Copy link
Contributor

qyqcswill commented Sep 9, 2021

ok, great. I suggested my team upgrading the spring-boot version from spring-boot2.2.x to spring-boot2.4.x.I don't know anyone else who had import on org.springframework.boot.configurationprocessor.json.No matter, everyone review code.

@retamiro
Copy link

Is there any way to wrap the lib spring-boot-configuration-processor-2.x.x.jar.
As stated above, at the time of packaging this lib is not packaged from version 2.4.x, occurring the error at run time: Caused by exception:
java.lang.NoClassDefFoundError
Message:
org.springframework.boot.configurationprocessor.json.JSONException

This is because the code is using the org.springframework.boot.configurationprocessor.json.JSONException class

@wilkinsona
Copy link
Member

@retamiro Please see Stephane's comment above. It sounds like you have some of your own code that's trying to use org.springframework.boot.configurationprocessor.json.JSONException which you should not be using.

@retamiro
Copy link

There are some microservices that have been misused, the goal is to minimize the impact. the problem occurs due to the "Jar Optimizations" implemented in spring 2.4x, so I asked if it has any way, but thanks for the feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

7 participants