Skip to content

Commit

Permalink
Merge pull request #6 from bjornvester/next
Browse files Browse the repository at this point in the history
Version 1.0
  • Loading branch information
nc-bmv committed May 16, 2021
2 parents a192781 + 7195b3d commit 16e73e2
Show file tree
Hide file tree
Showing 46 changed files with 1,273 additions and 278 deletions.
4 changes: 2 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
gradlew text eol=lf
gradlew.bat text eol=crlf
text eol=lf
*.bat eol=crlf
27 changes: 27 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: CI

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1
- uses: actions/setup-java@v1
with:
java-version: 11
- uses: actions/cache@v1
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Set encoding and print version information
run: |
export LANG=C.UTF-8
locale
./gradlew --version
- name: Build plugin
run: ./gradlew check
168 changes: 154 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,193 @@
# wsdl2java-gradle-plugin
A Gradle plugin for generating Java classes from WSDL files through CXF.

## Requirements and limitations
The plugin currently requires Gradle 5.4 or later.
I hope to make it work with earlier versions as well at some point.

It has been tested with Java 8 and Java 11.

It is currently not possible to customize the CXF code generation tool.
This will be implemented later.
## Requirements, features and limitations
* The plugin requires Gradle 6.0 or later. (Tested with Gradle 6.0 and 7.0.)
* It has been tested with Java 8, 11 and 16. It does not (yet) support running it with a custom toolchain.
* It supports the Gradle build cache (enabled by setting "org.gradle.caching=true" in your gradle.properties file).
* It supports project relocation for the build cache (e.g. you move your project to a new path, or make a new copy/clone of it).
This is especially useful in a CI context, where you might clone PRs and/or branches for a repository in their own locations.
* It supports parallel execution (enabled with "org.gradle.parallel=true" in your gradle.properties file).

## Configuration
Apply the plugin ID "com.github.bjornvester.wsdl2java" as specific in the [Gradle Plugin portal page](https://plugins.gradle.org/plugin/com.github.bjornvester.wsdl2java), e.g. like this:

```kotlin
plugins {
id("com.github.bjornvester.wsdl2java") version "0.4"
id("com.github.bjornvester.wsdl2java") version "1.0"
}
```

Put your WSDL and referenced XSD files somewhere in your src/main/resource directory.
By default, the plugin will create Java classes for all the WSDL files in the resource directory.

The generated code will by default end up in the directory build/generated/wsdl2java folder.
The generated code will by default end up in the directory build/generated/sources/wsdl2java folder.

You can configure the plugin using the "wsdl2java" extension like this:

```kotlin
wsdl2java {
// Set properties here...
}
```

Here is a list of all available properties:

| Property | Type | Default | Description |
|-----------------------|-----------------------|--------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|
| wsdlDir | DirectoryProperty | "$projectDir/src<br>/main/resources" | The directory holding the WSDL and referenced XSD files to compile. |
| includes | ListProperty\<String> | \["**/*.wsdl"] | The inclusion filer (Ant style) for which WSDLs to include |
| generatedSourceDir | DirectoryProperty | "$buildDir/generated<br>/sources/wsdl2java/java" | The output directory for the generated Java sources.<br>Note that it will be deleted when running XJC. |
| bindingFile | RegularFileProperty | \[not set\] | A binding file to use in the schema compiler |
| cxfVersion | Provider\<String> | "3.4.3" | The version of CXF to use. |
| verbose | Provider\<Boolean> | true | Enables verbose output from CXF. |
| suppressGeneratedDate | Provider\<Boolean> | true | Suppresses generating dates in CXF. Default is true to support reproducible builds and to work with the build cache. |
| markGenerated | Provider\<Boolean> | "no" | Adds the @Generated annotation to the generated sources. See below for details as there are some gotchas with this. | |
| options | ListProperty\<String> | \[empty\] | Additional options to pass to the tool. See [here](https://cxf.apache.org/docs/wsdl-to-java.html) for details. |


### Configure the CXF version
You can specify the version of CXF used for code generation like this:

```kotlin
wsdl2java {
cxfVersion.set("3.3.2")
cxfVersion.set("3.4.3")
}
```

### Configure directories
You can optionally specify WSDL and generated source directories like this:

```kotlin
wsdl2java {
generatedSourceDir.set(layout.projectDirectory.file("src/generated/wsdl2java"))
wsdlDir.set(layout.projectDirectory.dir("src/main/wsdl"))
}
```

Note that the `generatedSourceDir` will be wiped completely on each run, so don't put other source files in it.

The `wsdlDir` is only used for up-to-date checking. It must contain all resources used by the WSDLs (e.g. included XSDs as well).

By default, the plugin will find all WSDL files in the `wsdlDir` directory.
To specify other files, you can use the `includes` property.
Example:

```kotlin
wsdlDir.set(layout.projectDirectory.file("src/main/wsdl")) // Only if different from the default 'src/main/resources'
wsdlFiles.set(
listOf( // Kotlin method. For the Groovy DSL, use ["one.wsdl", "two.wsdl"] instead
"src/main/wsdls/MyFirstService.wsdl",
"src/main/wsdls/MySecondService.wsdl"
)
)
```

### Configure binding files

A binding file can be added like this:

```kotlin
wsdl2java {
bindingFile.set(layout.projectDirectory.file("src/main/bindings/binding.xjb"))
}
```

If you get a warning on maximum enum member size, you can raise the maximum like this:

```xml
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">

<!-- Raise theEnumMemberSizeCap limit -->
<jxb:bindings>
<jxb:globalBindings typesafeEnumMaxMembers="2000" />
</jxb:bindings>

</jxb:bindings>
```

If you like to use the Java Date/Time API instead of the more clunky GregorianCalendar class, you can use `threeten-jaxb` library with a binding file like this:

```kotlin
dependencies {
implementation("io.github.threeten-jaxb:threeten-jaxb-core:1.2")
}

wsdl2java {
bindingFile.set(layout.projectDirectory.file("src/main/bindings/bindings.xjb"))
}
```

```xml
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
<globalBindings>
<xjc:javaType name="java.time.OffsetDate" xmlType="xs:date"
adapter="io.github.threetenjaxb.core.OffsetTimeXmlAdapter"/>
<xjc:javaType name="java.time.OffsetDateTime" xmlType="xs:dateTime"
adapter="io.github.threetenjaxb.core.OffsetDateTimeXmlAdapter"/>
</globalBindings>
</bindings>
```

### Configure encoding
If your WSDL files include non-ANSI characters, you should set the corresponding file encoding in your gradle.properties file. E.g.:

```properties
org.gradle.jvmargs=-Dfile.encoding=UTF-8
```

Note that the plugin will add the following two dependencies to your "implementation" configuration:
If you are on a POSIX operating system (e.g. Linux), you may in addition to this need to set your operating system locale to one that supports your encoding.
Otherwise, Java (and therefore also Gradle and CXF) may not be able to create files with names outside of what your default locale supports.
Especially some Docker images, like the Java ECR images from AWS, are by default set to a locale supporting ASCII only.
If this is the case for you, and you want to use UTF-8, you could export an environment variable like this:

```shell script
export LANG=C.UTF-8
```

### Enabling the use of the @Generated annotation
CXF (and the underlying XJC tool) can add a `@Generated` annotation to the generated source code.
This is a source annotation useful for marking classes as generated by a tool.
It can also be used by some static code analytic tools to skip these classes.
Note that it is a source code annotation and thus won't work with tools that work with byte code.

While very useful in theory, there are some gotchas with this annotation.
The main one is that here are actually two @Generated annotations.
The first is 'javax.annotation.Generated' and is available in the JDK up til and including Java 8.
The second is 'javax.annotation.processing.Generated' and is available in the JDK from Java 9.
If your project is using Java 8, you will want to use the former.
However, if you are on Java 9 or later, you may still want to use the former if the tools you use only supports that one.
In that case, you can include the annotation class as a dependency.

To support these different use cases, you can chose which annotation to use with the `markGenerated` property.
Supported values are: `no`, `yes-jdk8` and `yes-jdk9`.
Example:

```kotlin
dependencies {
// The dependency below is only needed if using the Java 8 version of @Generated (through "yes-jdk8") on Java 9 or later
// If using "yes-jdk9", it is unnecessary
implementation("javax.annotation:javax.annotation-api:1.3.2")
}

wsdl2java {
markGenerated.set("yes-jdk8")
}
```

## Other
Note that the plugin will add the following two dependencies to your `implementation` configuration:

```
jakarta.xml.ws:jakarta.xml.ws-api:2.3.2
jakarta.xml.ws:jakarta.xml.ws-api:2.3.3
jakarta.jws:jakarta.jws-api:1.1.1
```

These are required to compile the generated code.
However, depending on your runtime platform, you may want to exclude them and instead either put them in the "compileOnly" configuration, or use whatever libraries that are provided by the platform.

There is a full example available in the integration-test directory.
There are full examples available in the integration-test directory.

If you need to compile additional XMl schemas (xsd files) not directly referenced by the wsdl files, you can use the [com.github.bjornvester.xjc](https://plugins.gradle.org/plugin/com.github.bjornvester.xjc) plugin in addition.
116 changes: 71 additions & 45 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,45 +1,71 @@
plugins {
kotlin("jvm") version "1.3.50"
id("java-gradle-plugin")
id("com.gradle.plugin-publish") version "0.10.1"
}

group = "com.github.bjornvester"
version = "0.4"

repositories {
jcenter()
}

dependencies {
implementation(kotlin("stdlib-jdk8"))
}

tasks.withType<Wrapper> {
distributionType = Wrapper.DistributionType.ALL
gradleVersion = "5.6.3"
}

gradlePlugin {
plugins {
create("wsdl2JavaPlugin") {
id = "com.github.bjornvester.wsdl2java"
implementationClass = "com.github.bjornvester.wsdl2java.Wsdl2JavaPlugin"
}
}
}

pluginBundle {
website = "https://github.com/bjornvester/wsdl2java-gradle-plugin"
vcsUrl = "https://github.com/bjornvester/wsdl2java-gradle-plugin"
description = """Adds the CXF wsdl2java tool to your project. Works with Java 8 and 11, and supports the Gradle build cache.
|Please see the Github project page for details.""".trimMargin()
(plugins) {
"wsdl2JavaPlugin" {
displayName = "Gradle Wsdl2Java plugin"
description = "Changes: \n" +
"- Make the extension properties immutable. This gets rid of a deprecation warning in Gradle 6.0."
tags = listOf("wsdl2java", "cxf", "wsimport")
}
}
}
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile

plugins {
`kotlin-dsl`
id("java-gradle-plugin")
id("com.gradle.plugin-publish") version "0.14.0"
}

group = "com.github.bjornvester"
version = "1.0"

repositories {
mavenCentral()
}

tasks.withType<Test>().configureEach {
inputs
.files(layout.projectDirectory.dir("integration-test").asFileTree.matching {
exclude("**/build/**")
exclude("**/gradle/**")
})
.withPathSensitivity(PathSensitivity.RELATIVE)
useJUnitPlatform()
systemProperty("GRADLE_ROOT_FOLDER", projectDir.absolutePath)
systemProperty("GRADLE_PLUGIN_VERSION", version)
}

tasks.withType<Wrapper> {
gradleVersion = "7.0.1"
}

dependencies {
compileOnly("org.apache.cxf:cxf-tools-wsdlto-core:3.4.3")
testImplementation("commons-io:commons-io:2.8.0")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.1")
testImplementation("org.junit.jupiter:junit-jupiter-params")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}

val compiler = javaToolchains.compilerFor {
languageVersion.set(JavaLanguageVersion.of(8))
}

tasks.withType<KotlinJvmCompile>().configureEach {
kotlinOptions.jdkHome = compiler.get().metadata.installationPath.asFile.absolutePath
}

gradlePlugin {
plugins {
create("wsdl2JavaPlugin") {
id = "com.github.bjornvester.wsdl2java"
implementationClass = "com.github.bjornvester.wsdl2java.Wsdl2JavaPlugin"
}
}
}

pluginBundle {
website = "https://github.com/bjornvester/wsdl2java-gradle-plugin"
vcsUrl = "https://github.com/bjornvester/wsdl2java-gradle-plugin"
description = """Adds the CXF wsdl2java tool to your project. Works with Java 8 and 11, and supports the Gradle build cache.
|Please see the Github project page for details.""".trimMargin()
(plugins) {
"wsdl2JavaPlugin" {
displayName = "Gradle Wsdl2Java plugin"
description = "Changes:\n" +
" - New configuration options added, including the ability to specify a binding file\n" +
" - Minimum version is now 6.0 (previously 5.4) due to internal use of new APIs"
tags = listOf("wsdl2java", "cxf", "wsimport")
}
}
}
4 changes: 3 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
org.gradle.jvmargs=-Dfile.encoding=UTF-8
org.gradle.jvmargs=-Dfile.encoding=UTF-8
org.gradle.warning.mode=fail
org.gradle.priority=low
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 16e73e2

Please sign in to comment.