How to solve 'IllegalStateException: This object has not been built' when using token endpoint in Spring Boot 2.1.5.RELEASE?

Fen*_*cer 5 java spring-security gradle oauth-2.0 spring-boot

I recently upgraded one of my services to Spring Boot 2.1.5.RELEASE FROM 2.0.9.RELEASE. And I can't really go back, because I need some of the new features. The Spring Security Version pulled by Spring Boot is 5.1.5.RELEASE. Furthermore I'm using spring-security-jwt, version 1.0.10.RELEASE, and spring-security-oauth2', version 2.3.6.RELEASE.'

All unit and integration tests are fine and I was just about to release it when the "real world" test that uses the jar-file built by gradle blew up. When trying to obtain a token from '/oauth/token' I get the exception shown below.

The frustrating thing now is that the endpoint will work perfectly if I run it using gradle bootrun. But If I build the jar with gradle bootjar and then run it with java -jar service.jar the exception will show up.

Maybe someone already had this experience and knows what to do. I'm not sure which part of my code I could post to help investigating the issue and I'm not allowed to make the project public on GitHub.

ERROR  org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.handleException:169
Handling error: IllegalStateException, This object has not been built
java.lang.IllegalStateException: This object has not been built
    at org.springframework.security.config.annotation.AbstractSecurityBuilder.getObject(AbstractSecurityBuilder.java:55) ~[spring-security-config-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:508) ~[spring-security-config-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
    at org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter.getOAuth2Authentication(ResourceOwnerPasswordTokenGranter.java:71) ~[spring-security-oauth2-2.3.6.RELEASE.jar!/:?]
    at org.springframework.security.oauth2.provider.token.AbstractTokenGranter.getAccessToken(AbstractTokenGranter.java:72) ~[spring-security-oauth2-2.3.6.RELEASE.jar!/:?]
    at org.springframework.security.oauth2.provider.token.AbstractTokenGranter.grant(AbstractTokenGranter.java:67) ~[spring-security-oauth2-2.3.6.RELEASE.jar!/:?]
    at org.springframework.security.oauth2.provider.CompositeTokenGranter.grant(CompositeTokenGranter.java:38) ~[spring-security-oauth2-2.3.6.RELEASE.jar!/:?]
    at org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer$4.grant(AuthorizationServerEndpointsConfigurer.java:583) ~[spring-security-oauth2-2.3.6.RELEASE.jar!/:?]
    at org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(TokenEndpoint.java:132) ~[spring-security-oauth2-2.3.6.RELEASE.jar!/:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_211]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_211]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0_211]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0_211]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.1.7.RELEASE.jar!/:5.1.7.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.7.RELEASE.jar!/:5.1.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-5.1.7.RELEASE.jar!/:5.1.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892) ~[spring-webmvc-5.1.7.RELEASE.jar!/:5.1.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-5.1.7.RELEASE.jar!/:5.1.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.7.RELEASE.jar!/:5.1.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) [spring-webmvc-5.1.7.RELEASE.jar!/:5.1.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) [spring-webmvc-5.1.7.RELEASE.jar!/:5.1.7.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) [spring-webmvc-5.1.7.RELEASE.jar!/:5.1.7.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908) [spring-webmvc-5.1.7.RELEASE.jar!/:5.1.7.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:665) [javax.servlet-api-4.0.1.jar!/:4.0.1]
    ...
    ...
    ...
Run Code Online (Sandbox Code Playgroud)

UPDATE: I digged a little deeper. The "problematic" code resides in WebSecurityConfigurerAdapter. In the bootRun-case delegateBuilderin line 508 is a org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$DefaultPasswordEncoderAuthenticationManagerBuilder which has already been built and therefore getObjectsucceeds and delegate is not null anymore for future calls. In the bootJar-case the delegateBuilder is of the same class, but the internal building-flag is false. And that's why the exception is thrown.

500:    public Authentication authenticate(Authentication authentication)
501:            throws AuthenticationException {
502:        if (delegate != null) {
503:            return delegate.authenticate(authentication);
504:        }
505:
506:        synchronized (delegateMonitor) {
507:            if (delegate == null) {
508:                delegate = this.delegateBuilder.getObject();
509:                this.delegateBuilder = null;
510:            }
511:        }
512:
513:        return delegate.authenticate(authentication);
514:    }
Run Code Online (Sandbox Code Playgroud)

更新:构建文件:

buildscript {
    ext {
        springBootVersion = '2.1.5.RELEASE'
    }

    repositories {
        jcenter()
        maven { url "http://repo.spring.io/snapshot" }
        maven { url "http://repo.spring.io/milestone" }
    }

    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
    }
}

apply plugin: "java"
apply plugin: "eclipse"
apply plugin: "org.springframework.boot"
apply plugin: "io.spring.dependency-management"

//Java version
sourceCompatibility = 1.8
targetCompatibility = 1.8 


defaultTasks "bootRun"


/* Configuration of the application package */

jar {
    baseName = "service"
    version =  "1.0.0"
}

bootJar {
    manifest {
        attributes("Manifest-Version": "1.0",
            "Specification-Title": "Example Service",
            "Specification-Version": "1.0",
            "Specification-Vendor": "Company",
            "Implementation-Title": "com.company.service",
            "Implementation-Version": "1.0.0",
            "Implementation-Vendor": "Company Inc.")
    }
}

repositories {
    jcenter()
    mavenCentral()
    maven { url "https://repo.spring.io/libs-release" }
    maven { url "http://repo.spring.io/snapshot" }
    maven { url "http://repo.spring.io/milestone" }
}

dependencies {
    implementation group:"org.springframework.boot", name:"spring-boot-starter-jersey"
    implementation group:"org.springframework.boot", name:"spring-boot-starter-tomcat"
    implementation group:"org.springframework.boot", name:"spring-boot-starter-log4j2"

    implementation group:"org.springframework.boot", name:"spring-boot-starter-actuator"

    implementation group:"org.springframework.boot", name:"spring-boot-devtools"

    implementation group:"org.apache.logging.log4j", name:"log4j-jul"

    implementation group:"javax.servlet", name:"javax.servlet-api"
    implementation group:"org.glassfish.jersey.containers", name:"jersey-container-servlet"
    implementation group:"org.glassfish.jersey.inject", name:"jersey-hk2"
    implementation group:"org.glassfish.jersey.ext", name:"jersey-spring4"

    implementation group:"org.springframework", name:"spring-context"
    implementation group:"org.springframework", name:"spring-web"
    implementation group:"org.springframework", name:"spring-aspects"

    implementation group:"org.springframework.security", name:"spring-security-core"
    implementation group:"org.springframework.security", name:"spring-security-web"
    implementation group:"org.springframework.security", name:"spring-security-config"
    implementation group:"org.springframework.security", name:"spring-security-jwt", version:"1.0.10.RELEASE"
    implementation group:"org.springframework.security.oauth", name:"spring-security-oauth2", version:"2.3.6.RELEASE"
    implementation group:"org.jasypt", name:"jasypt", version:"1.9.3"

    implementation group:"org.thymeleaf", name:"thymeleaf-spring5"

    implementation group:"org.springframework.data", name:"spring-data-jpa"
    implementation group:"org.hibernate", name:"hibernate-core"
    implementation group:"org.apache.tomcat", name:"tomcat-jdbc", version:"9.0.1"
    implementation group: "org.postgresql", name:"postgresql", version:"42.2.5"

    implementation group:"org.apache.commons", name:"commons-text", version:"1.6"
    implementation group:"commons-validator", name:"commons-validator", version:"1.6"

    testImplementation group:"org.springframework.boot", name:"spring-boot-starter-test"
    testImplementation group:"org.apache.httpcomponents", name:"httpclient"
}

configurations.all {
   exclude group:"org.springframework.boot", module: "spring-boot-starter-logging"
   exclude group:"ch.qos.logback", module:"logback-core"
   exclude group:"commons-logging", module:"commons-logging"
}
Run Code Online (Sandbox Code Playgroud)

更新:

是一个存储库,可让您重现该问题。如果我EncryptionConverter从项目中删除或仅删除@Autowired加密器,问题将消失。当然,这不是解决方案,因为实际上将某些东西自动接线到a Converter是首先升级Spring Boot的主要原因之一。很有意思的是,如果我删除PasswordResetManagerImpl易于定义的类,问题也将消失,因为无论如何在示例项目中都不会使用它。确切地说,足以删除PersistenceContext该类中的注入。我想那些上课的人有些矛盾。但是同样,这只是启动jar文件时的问题。只运行项目bootRun?仍然可以很好地工作。