How to include the client from openapi-generator in a gradle java application?
Asked Answered
B

2

9

I want to create a gradle java application that generates a client from an openAPI specification file and uses that client. So I created a java application with gradle init (type:application, language:Java, DSL:groovy, test-framework:Junit Jupiter, project-name:simple-java-app, package-structure:a.aa).

Small example of what works:

I can create a new source folder second/loc/src/main/java with a package b.bb and a class Foo. And with the following build.gradle

plugins {
    id 'java'
    id 'application'
}

repositories {
    jcenter()
}

sourceSets {
    second {
        java {
            srcDir 'second/loc/src/main/java'
        }
    }
}

compileJava {
    source += sourceSets.second.java
}

dependencies {
    implementation 'com.google.guava:guava:29.0-jre'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
}

application {
    mainClassName = 'a.aa.App'
}

test {
    useJUnitPlatform()
}

The main class can access Foo:

package a.aa;

import b.bb.Foo;

public class App {

    public static void main(String[] args) {
        System.out.println(new Foo().sayFoo());
    }
}

What doesn't work

Now I try the same for generated code by openapi-generator:

Under plugins I add id "org.openapi.generator" version "4.3.1"

And I add a new task:

openApiGenerate {
    generatorName = "java"
    inputSpec = "$rootDir/specs/petstore.yaml".toString()
    outputDir = "$buildDir/generated".toString()
    apiPackage = "org.openapi.example.api"
    invokerPackage = "org.openapi.example.invoker"
    modelPackage = "org.openapi.example.model"
     configOptions = [
        dateLibrary: "java8"
    ]
}

Then I execute the task openApiGenerate and confirm in the file system that the sources have been generated(eclipse won't show the build folder). Now I use the same method as above resulting in below build.gradle

plugins {
    id 'java'
    id 'application'
    id "org.openapi.generator" version "4.3.1"
}

repositories {
    jcenter()
}

openApiGenerate {
    generatorName = "java"
    inputSpec = "$rootDir/specs/petstore.yaml".toString()
    outputDir = "$buildDir/generated".toString()
    apiPackage = "org.openapi.example.api"
    invokerPackage = "org.openapi.example.invoker"
    modelPackage = "org.openapi.example.model"
    configOptions = [
        dateLibrary: "java8"
    ]
}

sourceSets {
    client {
        java {
            srcDir '$buildDir/generated/src/main/java'
        }
    }
}

compileJava {
    source += sourceSets.client.java
}

dependencies {
    implementation 'com.google.guava:guava:29.0-jre'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
}

application {
    mainClassName = 'a.aa.App'
}

test {
    useJUnitPlatform()
}

But when I try to use the classes now:

package a.aa;

import org.openapi.example.model.Pet;

public class App {

    public static void main(String[] args) {
        Pet p = new Pet(0L);
        System.out.println(p.getId());
    }
}

neither import nor Pet can be resolved.

> Task :compileJava FAILED
C:\...\simple-java-app\src\main\java\a\aa\App.java:6: error: package org.openapi.example.model does not exist
import org.openapi.example.model.Pet;
                                ^
C:\...\simple-java-app\src\main\java\a\aa\App.java:14: error: cannot find symbol
        Pet p = new Pet(0);
        ^
  symbol:   class Pet
  location: class App
C:\...\simple-java-app\src\main\java\a\aa\App.java:14: error: cannot find symbol
        Pet p = new Pet(0);
                    ^
  symbol:   class Pet
  location: class App
3 errors

FAILURE: Build failed with an exception.

I don't know how to debug this, frankly I'm unsure if source sets are even the right way. All openapi-generator tutorials seem to use them, I haven't tried subprojects yet, the openApiGenerate task seems to create a complete project with build.gradle and everything.

Baroda answered 23/7, 2020 at 12:42 Comment(2)
the generated classes, are inside the classpath ? or inside '$buildDir/generated' ? ? if they are not in the classpath, then the builder correctly throws the cannot find symbol. You will either make an external-reference/dependency or directly export them in a client package inside your projectAzores
The generated sources are in '$buildDir/generated'. I thought adding to source was enough. Can you tell me how to add them to the classpath? I've tried sourceSets.main { compileClasspath += x } with x = sourceSets.client.java (same error) | srcDir '$buildDir/generated' (Could not find method srcDir() for arguments) | '$buildDir/generated' (Cannot cast [...] ArrayList to [...] FileCollection )Baroda
D
10

You need to add the sources from the generated code to your project. One example from one of my projects:

sourceSets.main.java.srcDir "${buildDir}/generated/src/main/java"

After generation make sure you refresh gradle and project.

Devonna answered 23/7, 2020 at 13:23 Comment(5)
That works! (For future visitors: I still had to copy the dependencies from the generated build.gradle to the main build.gradle.)Baroda
I'm coming from Maven and was wondering if gradle plugins are able to add folders to to source theirself? Good Maven plugins did that on their own.Zeph
I feel this approach is flawed, doesn't it ignore the dependencies listed in the generated projects build.gradle files? If it works its because you have those same dependencies in your project already (potentially at different versions to those of the client).Coulter
My code generates correctly the java classes but I can't import the generated classes. I added sourceSets directory to my app/build.gradle but still not working. ¿Any help pls?Panaggio
Additionally to this, you may need to make the compilation depend on source-generation: tasks.compileJava.dependsOn('openApiGenerate')Underhanded
S
3

With build.gradle.kts and gradle 7+ I used in Kotlin DSL:

configure<SourceSetContainer> {
    named("main") {
        java.srcDir("$buildDir/generated/src/main/java")
    }
}

To add the java generated sources to the project's source.

Saltern answered 28/6, 2021 at 18:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.