java - 使用 swagger codegen for openapi 3.0 生成代码时出现 NullPointer 异常

标签 java gradle swagger swagger-codegen

通过 swagger codegen 生成代码时面临 NullPointer 问题。 我是 gradle 新手,并且已更新 build.gradle 以反射(reflect)为给定 API 规范生成代码所需的最新更改。

请提供您宝贵的意见。

我的build.gradle如下所示:

import io.swagger.codegen.v3.CodegenConfigLoader
import io.swagger.codegen.v3.DefaultGenerator
import io.swagger.codegen.v3.ClientOptInput
import io.swagger.codegen.v3.ClientOpts
import io.swagger.v3.parser.OpenAPIV3Parser

buildscript {
    ext {
        springBootVersion = '2.0.5.RELEASE'
        jacocoWorkspaceDirectory = "/jacoco/"
    }
    repositories {
        mavenLocal()
        maven { url "http://repo.maven.apache.org/maven2" }
    }
    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
        classpath group: "io.spring.gradle", name: "dependency-management-plugin", version: "1.0.6.RELEASE"
        classpath 'co.bambo.sonar:bambo-sonar-gradle-plugin:2.7.1.RELEASE'
        classpath group: "org.unbroken-dome.gradle-plugins", name: "gradle-testsets-plugin", version: "1.4.2"
        classpath('io.swagger.codegen.v3:swagger-codegen-maven-plugin:3.0.16')
        classpath("io.swagger.core.v3:swagger-core:2.1.1")
    }
}

apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'maven-publish'
apply plugin: "io.spring.dependency-management"
apply plugin: "org.springframework.boot"
apply plugin: 'bambo-sonar'
apply plugin: "jacoco"
apply plugin: "findbugs"
apply plugin: "checkstyle"
apply plugin: "pmd"
apply plugin: 'org.unbroken-dome.test-sets'


project.buildDir = 'target'

ext {
    appName = 'school-management'
    apiPackage = 'co.bambo.school.management.generated.api'
    modelPackage = 'co.bambo.school.management.generated.model'
    swaggerFile = "${rootDir}/src/main/resources/schoolmanagement.v1.yaml"
    swaggerBuildDir = "${project.buildDir}/" + appName
}


// NOTE :-> Following are to be included as and when required.
// These variables are defined for the purpose of exclusion from the sonar scan. Packages mentioned will be exluded
// from Sonar Scans.
def excludeschoolmanagementConstants = "src/main/java/co/bambo/school/management/constants/schoolmanagementConstants.java"
def excludeCaasConstants = "src/main/java/co/bambo/school/management/pcf/constants/CaasConstants.java"

sourceCompatibility = 1.8
targetCompatibility = 1.8

group = 'co.bambo.schoolmanagement'
version = '1.0.0-SNAPSHOT'

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

repositories {
    mavenLocal()
    maven { url "http://repo.maven.apache.org/maven2" }
}

configurations {
    testUtilCompile.extendsFrom testImplementation
    testUtilRuntime.extendsFrom testRuntime
}

sourceSets {
    testUtil {
        java {
            srcDir 'src/test-util/java'
        }
    }
}

testSets {
    funcTest { dirName = "func-test" }
}


// PLUGIN CONFIGs
springBoot {
    mainClassName = 'co.bambo.school.management.schoolmanagementApplication'
    buildInfo()
}

bootJar {
    baseName = 'school-management'
    destinationDir = project.buildDir
    archiveName = 'school-management.jar'
}

// FIXME - IN FUTURE WE NEED TO MAKE THIS to Zero.
checkstyle {
    maxErrors = 70
    maxWarnings = 70
    toolVersion = 8.17
}

[checkstyleMain, checkstyleTest].each { task ->
    task.logging.setLevel(LogLevel.LIFECYCLE)
    // FIXME -  This is to be updated with False.
    task.ignoreFailures = true
}

findbugs {
    toolVersion = "3.0.1"
    sourceSets = [sourceSets.main]
    // FIXME - Make this false.
    ignoreFailures = true
    effort = "max"
    reportLevel = "medium"
    excludeFilter = file("$rootDir/config/findbugs/exclude.xml")
}

pmd {
    toolVersion = "5.6.1"
    ignoreFailures = true
    sourceSets = [sourceSets.main]
    reportsDir = file("${project.buildDir}/reports/pmdTest")
    ruleSets = [
            'java-basic'
    ]
}

tasks.withType(FindBugs) {
    reports {
        xml.enabled = false
        html.enabled = true
    }
}

tasks.withType(Pmd) {
    reports {
        xml.enabled = false
        html.enabled = true
    }
}


sonarqube {
    properties {
        property "sonar.projectName", "school-management"
        property "sonar.projectKey", "school-management"
        property "sonar.jacoco.reportPath", "build/jacoco/test.exec"
        property "sonar.junit.reportPaths", "build/test-results/test"
        property "sonar.host.url", "https://fusion.bambo.int/sonar"
        property "sonar.gateId", "307"
        property "sonar.projectDescription", "school management microservice."
        property "sonar.skip.qualityGate", "false"
        property "sonar.exclusions", [excludeschoolmanagementConstants, excludeCaasConstants]
    }
}

// Actual task for generating the server
task generateServer {
    doLast {
        def openAPI = new OpenAPIV3Parser().read(rootProject.swaggerFile.toString(), null, null)
        def clientOptInput = new ClientOptInput().openAPI(openAPI)
        def codeGenConfig = CodegenConfigLoader.forName('spring')
        codeGenConfig.setApiPackage(rootProject.ext.apiPackage)            // Package to be used for the API interfaces
        codeGenConfig.setModelPackage(rootProject.ext.modelPackage)        // Package to be used for the API models
        codeGenConfig.setInputSpec(rootProject.ext.swaggerFile.toString()) // The swagger API file
        codeGenConfig.setOutputDir(rootProject.ext.swaggerBuildDir)
        // The output directory, user-service-contract/build/user-service-server/
//        codegenConfig.addSystemProperty("models", "");
//        codegenConfig.addSystemProperty("apis", "");

        def clientOps = new ClientOpts()
        clientOps.setProperties([
                'dateLibrary'  : 'java8', // Date library to use
                'useTags'      : 'true',  // Use tags for the naming
                'interfaceOnly': 'false'// Generating the Controller API interface and the models only
        ])
        clientOptInput.setOpts(clientOps)
        def generator = new DefaultGenerator().opts(clientOptInput)
        generator.generate() // Executing the generation
    }
}

compileJava {
    dependsOn generateServer
}

build {
    dependsOn generateServer
}

// ---- PLUGIN CONFIG ENDs


dependencyManagement {
    imports {
        mavenBom "org.springframework.boot:spring-boot-dependencies:$springBootVersion"
    }
}

funcTest {
    doFirst {
        jacoco {
            destinationFile = file("${buildDir}" + jacocoWorkspaceDirectory + "test.exec")
        }
    }

    dependsOn cleanTest
    dependsOn compileTestUtilJava
    dependsOn cleanJacocoTestReport
    dependsOn cleanJacocoTestCoverageVerification
    finalizedBy jacocoTestReport
    finalizedBy jacocoTestCoverageVerification
    environment SPRING_PROFILES_ACTIVE: environment.SPRING_PROFILES_ACTIVE ?: "local"
}

dependencies {
    // Spring specific dependencies
    implementation('org.springframework:spring-tx')
    implementation('org.springframework:spring-core')
    implementation('org.springframework:spring-context')
    implementation('org.springframework:spring-beans')
    implementation('org.springframework:spring-expression')
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-aop'
    implementation group: 'org.springframework.retry', name: 'spring-retry'

    implementation group: 'org.springframework.boot', name: "spring-boot-starter-data-jpa"

    // Spring cloud
    // Upgraded springcloud-starter-vault from 2.0.0.RC1 to 2.0.1.RELEASE.
    implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-vault-config', version: '2.0.1.RELEASE'
    implementation group: 'io.pivotal.spring.cloud', name: 'spring-cloud-services-starter-config-client', version: '2.0.1.RELEASE'
    // Upgraded "spring-cloud-starter-bus-amqp" following from 2.0.0.RC1 to 2.0.1.RELEASE
    implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-bus-amqp', version: '2.0.1.RELEASE'

    // SWagger dependencies
    implementation group: 'io.swagger', name: 'swagger-parser', version: '1.0.23'
    implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
    implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
    implementation group: 'com.atlassian.oai', name: 'swagger-request-validator-core', version: '1.3.9'

    // Apache - Commons
    implementation group: 'commons-io', name: 'commons-io', version: '2.6'

    // Oracle dependencies
    implementation group: 'com.oracle', name: 'ojdbc7', version: '12.1.0'

    //2nd level cache dependency
    implementation group: 'org.hibernate', name: 'hibernate-ehcache'

    // Logback
    implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'
    implementation group: 'ch.qos.logback', name: 'logback-core', version: '1.2.3'

    implementation group: 'org.apache.camel', name: 'camel-jsonpath', version: '2.22.0'
    implementation group: 'com.google.gdata', name: 'core', version: '1.47.1'
    implementation group: 'com.google.guava', name: 'guava', version: '20.0'

    // FIXME - Eventually phase - out this Mapper
    implementation group: 'ma.glasnost.orika', name: 'orika-core', version: '1.5.4'

    // JSON
    implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.8.10'
    implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1'

    // Mapstruct
    implementation 'org.mapstruct:mapstruct:1.3.0.Final'
    implementation 'org.mapstruct:mapstruct-processor:1.3.0.Final'

    implementation group: 'ch.qos.logback.contrib', name: 'logback-json-classic', version: '0.1.5'
    implementation group: 'ch.qos.logback.contrib', name: 'logback-jackson', version: '0.1.5'

    testImplementation "junit:junit:4.12"
    testImplementation group: "org.springframework.boot", name: "spring-boot-starter-test"
    testImplementation group: 'com.github.tomakehurst', name: 'wiremock', version: '2.21.0'

    testUtilCompile sourceSets.main.output
    funcTestCompile sourceSets.testUtil.output
}

我在这一行遇到 NullPointer 问题 def Generator = new DefaultGenerator().opts(clientOptInput)

更新1 我知道这个问题对于java中的NullPointer异常来说似乎相当简单。但相信我,我无法在 build.gradle 中找出它失败的原因,因为它甚至没有显示缺少内容的正确错误消息。下面显示的消息是我收到的所有消息。即使 groovy 脚本的调试也没有帮助我。

Execution failed for task ':generateServer'.
> java.lang.NullPointerException (no error message)

更新2 我刚刚在 DefaultGenerator.java 的第 77 行上看到了这一行。 这是我收到 NullPointerException this.config.additionalProperties().putAll(opts.getOpts().getProperties());

的地方

我不确定参数中缺少什么。我正在传递 opts ,并且 getOpts() 也在填充属性文件。

使用 gradle 版本 4.9。

最佳答案

好吧,我明白了,这在理解和代码中都是一个愚蠢的错误。

我在调试和浏览 swagger-codegen 代码后就发现了这个错误。我意识到生成代码需要配置,根据指定的配置它正在生成代码。我正在生成基于 spring 的 CodeGenConfiguration,但我没有将其传递到 clientOptInput 中。我的理解是错误的,我认为它将加载 CodeGenConfig 的类(它确实加载),仅此而已。但是您还需要将其传递给 clientOptInput 变量。

def codeGenConfig = CodegenConfigLoader.forName('spring')
clientOptInput.setConfig(codeGenConfig)

由于 DefaultGenerator.java 的代码如下:

    @Override
    public Generator opts(ClientOptInput opts) {
        this.opts = opts;
        this.openAPI = opts.getOpenAPI();
        this.config = opts.getConfig();

我需要将其设置为 ClientOptInput 实例。这就是原因。为像我这样犯错误的人发帖:) :)

关于java - 使用 swagger codegen for openapi 3.0 生成代码时出现 NullPointer 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59966745/

相关文章:

swift - Swagger-codegen 创建了一个模型,其中参数已被对另一个模型的引用覆盖

go - Swagger 在每个 db 调用上初始化 db(gorm) 连接

java - 同步相同的字符串值

java - 如何从 Java 小程序创建文件?

android - 在 Android Studio 中更改 xml 布局文件后需要重建

java - 如何使用gradle API检查工件的存在?

jenkins - 如何将用户名密码传递给Gradle以便从Jenkins管道将工件上传到Nexus

java - OpenGL 深度缓冲区未应用

java - MimeMessage 更改现有邮件上的 sendData

java - 带有 spring mvc 的 swagger ui 空白页面