There is an xsd schema. It is necessary to generate Kotlin-classes according to the xsd description. How can I do this? Using the code below, I can get java classes. But I need kotlin classes
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.21'
// Apply the application plugin to add support for building a CLI application.
id 'application'
/* Generate Java code from XSD */
id 'org.unbroken-dome.xjc' version '1.4.3'
}
group 'org.example'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
xjc {
includeInMainCompilation = false
}
xjcGenerate {
source = fileTree('src/main/schema') { include '*.xsd' }
bindingFiles = fileTree('src/main/jaxb') { include '*.xjb' }
catalogs = fileTree('src/main/catalog') { include '*.cat' }
}
sourceSets {
main { java { srcDir xjcGenerate.outputDirectory } }
}
compileKotlin {
dependsOn xjcGenerate
}
/* END: Make xjcGenerate work with Kotlin */
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
mavenCentral()
google()
}
dependencies {
/* Add JAXB dependencies for Java 11 */
implementation 'javax.xml.bind:jaxb-api:2.3.1'
// Use the Kotlin JDK 8 standard library.
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
// Use the Kotlin test library.
testImplementation 'org.jetbrains.kotlin:kotlin-test'
// Use the Kotlin JUnit integration.
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit'
}
// Define the main class for the application.
mainClassName = 'ru.goryacms.AppKt'
I've tried https://github.com/reaster/schema-gen. It generates Kotlin data classes with annotations, but it has bugs so that the generated code does not compile, however this is easy to fix. In my case I also had to fix many annotations and some property names. Still much better than manually writing code.
You can try https://github.com/SixRQ/KAXB - Kotlin based class generator to generate native Kotlin classes from an XML Schema:
This project is used to generate native Kotlin classes from an xsd schema, similar to the JAXB tool for Java. The project will include a plugin for gradle and Intellij IDEA. ...
Once the archive has been extracted run the
bin/kaxb --P <destination package> --S <schema file> --T <target directory>
Related
I have a simple spring boot project using the kotlin gradle dsl. I want to generate an OpenApi client using the openapi client generator gradle Plugin. I have successfully done so, using this configuration. Until now, this was a single project build. But when i try to include it, i get an error message "Could not find method wrapper()".
This is how i generated the client and added it's file into my source sets:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "3.0.2"
id("io.spring.dependency-management") version "1.1.0"
kotlin("jvm") version "1.7.22"
kotlin("plugin.spring") version "1.7.22"
id("org.openapi.generator") version "6.3.0"
}
// other dependencies
openApiGenerate {
generatorName.set("kotlin")
inputSpec.set("src/main/openapi/my-api.yml")
outputDir.set("$buildDir/generated/my-api")
packageName.set("com.myapi")
}
kotlin.sourceSets["main"].kotlin.srcDir("$buildDir/generated/my-api/src/main/kotlin")
Now i want to use this generated client in my project. It comes with it's own build.gradle (in groovy) which loads the necessary dependencies etc.
I have modified my settings.gradle.kts file accordingly:
rootProject.name = "myapp"
include("build:generated:my-api")
When i reload gradle, i get the follwing error:
> Could not find method wrapper() for arguments [build_gdswinwcvulw9afq79kj4v6h$_run_closure1#582f32f7] on project ':build:generated:my-api' of type org.gradle.api.Project.
This is due to the build.gradle file generated by the generator looking like this:
group 'org.openapitools'
version '1.0.0'
wrapper {
gradleVersion = '7.5'
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}
buildscript {
ext.kotlin_version = '1.7.21'
repositories {
maven { url "https://repo1.maven.org/maven2" }
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'maven-publish'
repositories {
maven { url "https://repo1.maven.org/maven2" }
}
test {
useJUnitPlatform()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation "com.squareup.moshi:moshi-kotlin:1.13.0"
implementation "com.squareup.moshi:moshi-adapters:1.13.0"
implementation "com.squareup.okhttp3:okhttp:4.10.0"
testImplementation "io.kotlintest:kotlintest-runner-junit5:3.4.2"
}
I am using Gradle 7.6 and i am a bit out of ideas here since i am pretty new to Gradle.
I have a gradle kotlin project, and I'm generating a kotlin file from a Rust project, so it ends up in a totally different place with no gradle project structure, etc.
How do I import this file into my gradle project?
It has its own package but it's a completely standalone file. This is my gradle file:
rootProject.name = "my_project"
include("app")
It's a desktop project, NOT android.
My build.gradle.kts:
plugins {
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
id("org.jetbrains.kotlin.jvm") version "1.5.31"
// Apply the application plugin to add support for building a CLI application in Java.
application
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
// Align versions of all Kotlin components
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
// Use the Kotlin JDK 8 standard library.
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
// This dependency is used by the application.
implementation("com.google.guava:guava:30.1.1-jre")
// Use the Kotlin test library.
testImplementation("org.jetbrains.kotlin:kotlin-test")
// Use the Kotlin JUnit integration.
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}
application {
// Define the main class for the application.
mainClass.set("my_project.ffi.AppKt")
}
Adding the following code to your build.gradle.kts should do the trick (tested with Gradle 7.3.2):
// TODO: replace this dummy task with the task from your Rust project which
// generates the Kotlin source directory. Make sure that the generated
// directory (with the Kotlin file(s)) is the task output directory.
val rustTask by tasks.registering(Copy::class) {
// To test this, I had simply put a Kotlin file into this "somewhere"
// directory.
from("somewhere")
into(temporaryDir)
}
sourceSets {
main {
java {
srcDir(rustTask)
}
}
}
tasks {
compileKotlin {
dependsOn(rustTask)
}
}
So, we’re simply adding the generated sources as an additional source directory to the default SourceSet which is consumed by the compileKotlin task. In addition, we make sure that the sources are generated before compileKotlin runs.
I recently switched from old 1.2 multiplatform into 1.3. Difference is, there's one one build.gradle file per multiplatform module (I got 5 of them) so a lot less configuration.
However I can't seem to be able to configure creating runnable fat jar with all dependencies from jvm platform.
I used to use standard "application" plugin in my jvm project and jar task, but that does not work anymore. I found there's "jvmJar" task and I modified it (set Main-class), but created jar doesn't contain dependencies and crashes on ClassNotFoundException. How do I do it?
This is what I have now:
jvm() {
jvmJar {
manifest {
attributes 'Main-Class': 'eu.xx.Runner'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
}
I did hit that bump and used this work around.
1. Restructure your project
Lets call your project Project.
create another submodule say subA, which will have the gradle notation Project:subA
now, subA has your multiplatform code in it (It is the gradle project with apply :kotlin-multiplafrom) in its build.gradle
2. Add Another submodule
create another submodule which targets only jvm say subB, which will have the gradle notation Project:subB
So, subB will have plugins: 'application' and 'org.jetbrains.kotlin.jvm'
3. Add your module as a gradle dependency (see my build.gradle)
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.31'
id "application"
}
apply plugin: "kotlinx-serialization"
group 'tz.or.self'
version '0.0.0'
mainClassName = "com.example.MainKt"
sourceCompatibility = 1.8
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
dependencies {
implementation project(':subA')
}
you can proceed and build subB as you would a regular java project or even use the existing plugins, it will work
Got it working with the multiplatform plugin in kotlin 1.3.61:
The following works for a main file in src/jvmMain/kotlin/com/example/Hello.kt
Hello.kt must also specify its package as package com.example
I configured my jvm target in this way:
kotlin {
targets {
jvm()
configure([jvm]) {
withJava()
jvmJar {
manifest {
attributes 'Main-Class': 'com.example.HelloKt'
}
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}
}
}
}
Got it to work with a slightly modified version of what luca992 did:
kotlin {
jvm() {
withJava()
jvmJar {
manifest {
attributes 'Main-Class': 'sample.MainKt'
}
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}
}
...
}
The only way to get gradle/multiplatform working appears to be endless trial and error; It's a nightmare, it's not being built as a "build" system so much as a "build system"; to put it another way, these two tools (together or in isolation) are a means of implementing only a single software development life cycle that the plugin maker intended, however, if you've engineered a desired software lifecycle and CI/CD system and now your trying to implement that engineering, it will be MUCH harder to do it with these tools than it would be to do it with scripts, code or maven. There are a number of reasons for this:
Massive changing in coding convention due to the plugin makers only exposing bar minimum configurability, probably only giving access to the things they need for their own personal project.
Very poor documentation updates; Kotlin, gradle and plugins are changing so rapidly I have begun to seriously question the usefulness of these tools.
Thus, at the time of writing this seems to be the correct syntax to use when using kotlin 1.3.72, multiplatform 1.3.72, ktor 1.3.2 and gradle 6.2.2 (using the kts format).
Note the fatJar seems to assemble correctly but won't run, it can't find the class, so I included the second runLocally task I've been using in the mean time.
This isn't a complete solution so I hate posting it on here, but from what I can tell... it is the most complete and up to date solution I can find documented anywhere.
//Import variables from gradle.properties
val environment: String by project
val kotlinVersion: String by project
val ktorVersion: String by project
val kotlinExposedVersion: String by project
val mySqlConnectorVersion: String by project
val logbackVersion: String by project
val romeToolsVersion: String by project
val klaxonVersion: String by project
val kotlinLoggingVersion: String by project
val skrapeItVersion: String by project
val jsoupVersion: String by project
val devWebApiServer: String by project
val devWebApiServerVersion: String by project
//Build File Configuration
plugins {
java
kotlin("multiplatform") version "1.3.72"
}
group = "com.app"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
jcenter()
jcenter {
url = uri("https://kotlin.bintray.com/kotlin-js-wrappers")
}
maven {
url = uri("https://jitpack.io")
}
}
//Multiplatform Configuration
kotlin {
jvm {
compilations {
val main = getByName("main")
tasks {
register<Jar>("buildFatJar") {
group = "application"
manifest {
attributes["Implementation-Title"] = "Gradle Jar File Example"
attributes["Implementation-Version"] = archiveVersion
attributes["Main-Class"] = "com.app.BackendAppKt"
}
archiveBaseName.set("${project.name}-fat")
from(main.output.classesDirs, main.compileDependencyFiles)
with(jar.get() as CopySpec)
}
register<JavaExec>("runLocally") {
group = "application"
setMain("com.app.BackendAppKt")
classpath = main.output.classesDirs
classpath += main.compileDependencyFiles
}
}
}
}
js {
browser { EXCLUDED FOR LENGTH }
}
sourceSets { EXCLUDED FOR LENGTH }
}
I'm trying to make swagger codegen work in a project built with gradle (kotlin).
My reference is this example here : https://github.com/int128/gradle-swagger-generator-plugin which is made in Gradle groovy version.
Now the build.gradle.kts is the following:
repositories {
jcenter()
}
plugins {
java
id("org.springframework.boot") version "2.1.2.RELEASE"
id("io.spring.dependency-management") version "1.0.6.RELEASE"
id("org.hidetake.swagger.generator") version "2.16.0"
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation ("io.swagger:swagger-annotations:1.5.21")
swaggerCodeGen("io.swagger:swagger-codegen-cli:2.3.1")
// Use JUnit test framework
testImplementation ("junit:junit:4.12")
}
swaggerSources {
petstore {
inputFile = file('petstore.yaml')
code {
language = 'spring'
}
}
}
But IntelliJ does not like lines talking about swagger:
I am a newbie in gradle so I don't understand what I am supposed to do. Is swaggerCodeGen supposed to be a function? Where does this function supposed to be imported? Where swaggerSources supposed to imported?
import org.hidetake.gradle.swagger.generator.GenerateSwaggerCode
// plugins, repositories are same, but note import above ^^^
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation ("io.swagger:swagger-annotations:1.5.21")
"swaggerCodegen"("io.swagger:swagger-codegen-cli:2.3.1") // 1
// Use JUnit test framework
testImplementation ("junit:junit:4.12")
}
swaggerSources {
create("petstore").apply { // 2
setInputFile(file("petstore.yaml")) // 3
code(closureOf<GenerateSwaggerCode> { // 4
language = "spring"
})
}
}
1 - dynamically resolved configuration in Kotlin looks like this (dynamically from Groovy, so there is problematically to use it on compile time, extension invoke operator on String is our saviour);
2 - swaggerSources returns you NamedDomainObjectContainer<SwaggerSource>, so to add new container we invoke create with it's name as parameter;
3 - Kotlin does not as flexible as Groovy, so calling setter instead of setting field;
4 - Groovy's closure is far from functional interface, so we specify generic type as in plugin's sources Closure is not parametrised.
You can use this openapi-generator plugin task to generate the swagger code as well.
It does the same thing as the swagger codegen plugin. Use it in your build.gradle.kts like:
plugins {
id("org.openapi.generator") version "5.1.1"
}
openApiGenerate {
generatorName.set("spring")
inputSpec.set("$rootDir/src/main/resources/petstore.yaml")
outputDir.set("$buildDir/generated/")
}
dependencies {
//Spring boot dependency
implementation("org.springframework.boot:spring-boot-starter-web")
// For swagger generated code and annotations
implementation("io.springfox:springfox-boot-starter:3.0.0")
implementation("javax.validation:validation-api:2.0.0.Final")
}
This could be used with a kotlin or java project, then you need to add the generated classes to your sourceSet by doing:
configure<SourceSetContainer> {
named("main") {
java.srcDir("$buildDir/generated/src/main/java")
}
}
The last step is make sure you generate the swagger files before compiling, for Kotlin, add this in your compile task:
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
dependsOn("openApiGenerate")
kotlinOptions.jvmTarget = "11"
}
You can check the generator's properties to adjust the configuration of the generated files.
considering Kotlin 1.2 introduced kotlin-platform-common I'm trying to build my first common .class file, so I did the below:
main.kt:
package hello
fun main() {
println("kotlin!")
}
gradle.build:
group 'h'
version 'prn'
buildscript {
ext.kotlin_version = '1.2.0'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin-platform-common'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
}
sourceSets {
main.kotlin.srcDirs += 'src/kotlin'
main.resources.srcDirs += 'src/resources'
}
jar {
manifest {
attributes 'Main-Class': 'hello.MainKt'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
Then I run gradle build
Q1- I coud not find any .class file generated? how to get it generated and where should I find it?
Q2- I got a .jar file generated, but once I tried to run it, I got an error:
Error: Could not find or load main class hello.MainKt
I tried to run it using the below 2 option, but got the same error for bot:
Option 1:
kotlin -cp <filename>.jar hello.MainKt
Option 2:
java -jar <filename>.jar
Project structure, and errors are as in this pic below:
With Kotlin 1.2, common modules don't generate binaries (like .class files), only metadata files. This is true even if you don't use the expect keyword anywhere.
So you have to create another module which includes something like this:
apply plugin: 'kotlin-platform-jvm'
The JVM modules will also need an expectedBy entry in dependencies for your common module. Plus you'll probably want a corresponding JS module of course.
It's probably best to let IntelliJ create the whole multiplatform project for you and then edit the Gradle files to suit, but this page lists the manual steps: https://kotlinlang.org/docs/reference/multiplatform.html#setting-up-a-multiplatform-project