IntelliJ 运行 vs 运行ning 一个 jar,带有 Springboot Kotlin,带有 Social Oauth2 的多模块 Gradle 项目

IntelliJ run vs running a jar, with a Springboot Kotlin, Multi module Gradle project with Social Oauth2

TL;DR:为什么在通过 IntelliJ 启动时一切 运行 都正常,而在调用 java -jar app.jar 时为什么会损坏。我该如何解决这个问题?


好的,我在尝试 dockerize 时遇到了一些后端问题。我在 Spring Oauth (2.0.12.RELEASE) guide on their page 之后使用 Spring Boot (1.4.2.RELEASE) 创建了一个应用程序。我遵循 Gradle 版本,因为我更喜欢 Gradle 而不是 Maven。此外,我正在使用 Kotlin 而不是 Java。一切都很好,我通过 IntelliJ 启动我的后端和静态前端,我可以通过 Facebook 登录(以及 Google 和 Github),我收到了一个很好的 Principal 持有所有我需要的信息,我可以修改 Spring 安全性以授权和允许端点。到目前为止一切顺利。

现在对于不好的部分,当我 运行 ./gradlew clean build app:bootrun./gradlew clean build app:jar 和 运行 通过 java -jar 的罐子时(就像我将在我的 Docker 容器),我的后端出现了。我的静态前端弹出。现在我想通过 Facebook 登录,我最终进入了 Facebook 登录页面,我输入了我的凭据,然后... 什么都没有
我最终回到了我的主页,没有登录,没有对我有意义的日志消息,只是沉默。我在日志中看到的最后一件事是:
Getting user info from: https://graph.facebook.com/me

这个 Url 会在我的浏览器中给我:

{
   "error": {
      "message": "An active access token must be used to query information about the current user.",
      "type": "OAuthException",
      "code": 2500,
      "fbtrace_id": "GV/58H5f4fJ"
   }
}

当通过 IntelliJ 启动进入这个 URL 时,它会给我凭证详细信息。显然出了点问题,但我不知道是什么。特别是因为来自 IntelliJ 的 运行 工作正常。 jar 的启动方式与 IntelliJ 的 运行 配置的工作方式之间存在一些差异,但我不知道在哪里搜索什么。我可以 post 跟踪日志记录,或者我所有的 Gradle 文件,但可能信息太多,无法放入 1 个问题中。如果有人需要更多详细信息,我会明确更新这个问题 :)

本项目结构大纲如下:

root:
  - api: is going to be opensourced later, contains rest definitions and DTOs.
  - core: contains the meat. Also here is included in the gradle file
             spring-boot-starter, -web, -security, spring-security-oauth2, and some jackson stuff.
  - rest: contains versioned rest service implementations.
  - app: contains angular webjars amongst others, the front end, and 
             my `@SpringBootApplication`, `@EnableOAuth2Client` 
             and the impl of `WebSecurityConfigurerAdapter`.

为什么在通过 IntelliJ 启动时 运行 一切正常,为什么使用 bootRun 或 jar 工件时它会损坏。我该如何解决这个问题?

我找到了,问题不在于多模块 Graldle、Spring 引导或 Oauth2 相关。事实上,这是由于 Gradle 的 src set 配置,其中 Java 应该在 Java src set 文件夹中,而 Kotlin 在 Java src set 文件夹中:

sourceSets {
    main.java.srcDirs += 'src/main/java'
    main.kotlin.srcDirs += 'src/main/kotlin'
}

正如 Will Humphreys 在他上面的评论中所述,IntelliJ 获取所有源集并运行该应用程序。但是,当通过 Gradle 构建 jar 时,这些源集更加严格。我的 Kotlin src 集中有一个 Java 文件,这对 IntelliJ 来说没有问题。但是 Gradle 创建的 jar 考虑了 build.gralde 文件中定义的源集,这些源集更严格。

我用下面的代码发现了我丢失的 bean 问题:

@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
    return args -> {
        System.out.println("Let's inspect the beans provided by Spring Boot:");

        String[] beanNames = ctx.getBeanDefinitionNames();
        Arrays.sort(beanNames);
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }

    };
}

我错过的那个 Bean 叫做 AuthenticationController,它是一个 @RestController,对我的身份验证代码很重要。