【问题标题】:Spring Boot Integration fails to start due to TestRestTemplate and apache SSL由于 TestRestTemplate 和 apache SSL,Spring Boot 集成无法启动
【发布时间】:2017-01-21 04:17:51
【问题描述】:

我正在使用 Spring Boot 1.4、Spock 和 spring-boot-starter-security。这是我相关的 gradle 文件:

springBootVersion = '1.4.0.BUILD-SNAPSHOT'
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-devtools')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.jasypt:jasypt-spring31:1.9.2')
compile('org.apache.httpcomponents:httpclient:4.5.2')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.spockframework:spock-core:1.1-groovy-2.4-rc-2')
testCompile('org.spockframework:spock-spring:1.1-groovy-2.4-rc-2')

我也已将此添加到我的 application-test.properties 文件中:

server.ssl.enabled=false
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver

我能够创建一个经过身份验证的端点,该端点创建一个 JWT(使用 jasypt-spring31:1.9.2)并在 Authorization 标头中返回它。这在通过浏览器或 Postman 访问时非常有用。但是,我无法在我的 Spring Boot 集成测试中完成这项工作。

因为我的密码是加密的,所以我确实有 DB Configuration 类:

@Configuration
public class DBConfig {

    @Autowired
    private Environment env;

    @Value("${spring.datasource.driverClassName}")
    private String databaseDriverClassName;

    @Value("${spring.datasource.url}")
    private String datasourceUrl;

    @Value("${spring.datasource.username}")
    private String databaseUsername;

    @Value("${jasypt.key}")
    private String jasyptKey;

    @Bean
    public DataSource datasource() throws IOException {

        return DataSourceBuilder
                        .create()
                        .username(databaseUsername)
                        .password(getSecurePassword())
                        .url(datasourceUrl)
                        .driverClassName(databaseDriverClassName)
                        .build();
    }

    private String getSecurePassword() throws IOException {
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword(jasyptKey);
        Properties props = new EncryptableProperties(encryptor);
        props.load(this.getClass().getClassLoader().getResourceAsStream("application-" + env.getActiveProfiles()[0] + ".properties"));
        return props.getProperty("spring.datasource.password");
    }
}

我的基础测试类将启动一个嵌入式 Tomcat 实例并使所有端点可用,并且有一个获取 JWT 的方法:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource("classpath:application-test.properties")
class BaseSpecification extends Specification {

    @Autowired
    def TestRestTemplate restTemplate

    String loginAndGetJWT() {

        def model = new ModelMap();
        model.addAttribute("username", "ausername")
        model.addAttribute("password", "apassword");

        ResponseEntity<JwtAuthenticationResponse> response = restTemplate.getForEntity("/auth", String.class, model);
        def jwt = response.getBody().token

        return jwt;
    }
}

当我尝试运行我的示例测试时:

class ApplicationSpecWithoutAnnotation extends BaseSpecification {

    @Autowired
    WebApplicationContext context

    def "should boot up without errors"() {

        expect: "web application context exists"
        context != null
    }
}

我得到以下信息:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testRestTemplate': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.apache.http.conn.ssl.SSLConnectionSocketFactory
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]

根据this:现在只要使用@SpringBootTest,TestRestTemplate 就可以作为bean 使用。

如果我删除 compile('org.apache.httpcomponents:httpclient:4.5.2') 则错误变为:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testRestTemplate': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/apache/http/impl/client/HttpClients

因此,似乎存在对 Spring web 和 apache 的依赖,这似乎并不正确。

【问题讨论】:

  • 我认为您不需要 httpclient 作为显式依赖项,您的错误表明初始化类时出现问题(请参阅此 link 以了解 NoClassDefFoundError 的解释)。您使用的是哪个 JDK 版本?您也可以尝试将server.ssl.enabled=false 设置为true 或直接省略配置键。
  • 我实际上有 server.ssl.enabled=false 并且正在使用 JDK1.8。当我从 build.gradle 中删除“compile('org.apache.httpcomponents:httpclient:4.5.2')”行时,我仍然收到错误: Caused by: java.lang.NoClassDefFoundError: org/apache/http/impl /客户端/HttpClients。我想知道这是否是一个 gradle 问题,因为我基于此的所有 spring 示例都在 maven 中?
  • 我认为这不是 Gradle 问题。您能否在 Github 上发布一个小示例项目来展示您的问题?
  • 抱歉,Kevin,不知道如何在不违反我的保密协议的情况下解决这个问题。

标签: spring-mvc testing gradle spring-security spring-boot


【解决方案1】:

原来我包含的 QBO 库有违规的 http 库。我删除了对该 2.5 库的所有引用,并且我的构建已修复。不知道为什么它没有出现在我的 gradle 依赖树中,但是当我查看导入的 jar 时我发现了它。

【讨论】:

  • 我也有同样的问题,你怎么看导入的jar?我正在使用 Maven 顺便说一句。
猜你喜欢
  • 2014-08-12
  • 1970-01-01
  • 2021-10-19
  • 2017-01-05
  • 1970-01-01
  • 1970-01-01
  • 2019-08-07
  • 2017-08-16
  • 1970-01-01
相关资源
最近更新 更多