scubacabra / gradle-wsdl-plugin

Gradle plugin that helps with using WSDL files and generating their WARs
GNU General Public License v2.0
12 stars 7 forks source link

gradle-wsdl-plugin

[Build Status] (https://drone.io/github.com/djmijares/gradle-wsdl-plugin/latest)

Download

:boom: :collision:

:exclamation:IMPORTANT PLUGIN ID CHANGES:exclamation:

In compliance with the gradle plugin submission guidelines, this plugin's id is now fully qualified.

It changed from wsdl to com.github.jacobono.wsdl. This affects how you apply the plugin (apply plugin: 'com.github.jacobono.wsdl)

:boom: :collision:

Gradle plugin that defines some conventions for web service Projects. Eases the manual configuration of web service project by:

Using The Plugin

:boom: :collision:

Now in the gradle plugins repo :exclamation:

:boom: :collision:

Using Gradle 2.1 plugins script block

plugins {
    id 'com.github.jacobono.wsdl' version '1.7.8'
}

Using Straight-Up JCenter

buildscript {
  repositories { 
    jcenter()
    mavenCentral()
  }

  dependencies {
    classpath 'com.github.jacobono:gradle-wsdl-plugin:1.7.8'
  }
}

apply plugin: 'com.github.jacobono.wsdl'

Setting Up The jaxws Configurations

You need the jaxws configuration to run the wsimport task, but that is the only task that has an external dependency. Any version of jaxws that you care to use will work. I try to stay with the latest releases.

    dependencies { 
      jaxws 'com.sun.xml.ws:jaxws-tools:2.2.8-promoted-b131'
      jaxws 'com.sun.xml.ws:jaxws-rt:2.2.8-promoted-b131'
    }

Plugin Tasks

Artifact Output

The war would look like this (see the hello-world-episode-binding-ws project in the examples folder)

  drwxr-xr-x         0  20-Jan-2013  21:19:26  META-INF/
  -rw-r--r--        25  20-Jan-2013  21:19:26  META-INF/MANIFEST.MF
  drwxr-xr-x         0  20-Jan-2013  21:19:26  WEB-INF/
  drwxr-xr-x         0  20-Jan-2013  21:19:26  WEB-INF/classes/
  drwxr-xr-x         0  19-Jan-2013  21:00:16  WEB-INF/classes/helloworld/
  drwxr-xr-x         0  19-Jan-2013  21:00:16  WEB-INF/classes/helloworld/sample/
  drwxr-xr-x         0  19-Jan-2013  21:00:16  WEB-INF/classes/helloworld/sample/ibm/
  drwxr-xr-x         0  19-Jan-2013  21:00:16  WEB-INF/classes/helloworld/sample/ibm/com/
  -rw-r--r--       993  19-Jan-2013  21:00:16  WEB-INF/classes/helloworld/sample/ibm/com/HelloWorld.class
  -rw-r--r--      2194  19-Jan-2013  21:00:16  WEB-INF/classes/helloworld/sample/ibm/com/HelloWorldService.class
  -rw-r--r--      1837  19-Jan-2013  21:00:16  WEB-INF/classes/helloworld/sample/ibm/com/ObjectFactory.class
  drwxr-xr-x         0  20-Jan-2013  21:19:26  WEB-INF/lib/
  -rw-r--r--      2674  19-Jan-2013  21:00:14  WEB-INF/lib/hello-world-schema-0.1.jar
  drwxr-xr-x         0  20-Jan-2013  21:19:26  WEB-INF/wsdl/
  -rw-r--r--      2049  19-Jan-2013  20:56:44  WEB-INF/wsdl/HelloWorldEpisodeBindingService.wsdl
  drwxr-xr-x         0  20-Jan-2013  21:19:26  WEB-INF/schema/
  drwxr-xr-x         0  20-Jan-2013  21:19:26  WEB-INF/schema/HelloWorld/
  -rw-r--r--       581  19-Jan-2013  20:56:44  WEB-INF/schema/HelloWorld/HelloWorld.xsd
  - ----------  --------  -----------  --------  -----------------------------------------------------------------

wsdl and schema folders are auto populated on the fly :)

Schema Organization

The Problem of Schema Document Duplication

This is probably the biggest reason for this plugin and what it attempts to do -- have some sort of standard for xsd and wsdl projects that use schema to source generation and episode binding, eliminating document and generated code duplication.

I have seen a few ways of managing schema documents in projects. Some duplicated xsds in the xsd project AND in the wsdl project, so that the WSDL file could see those xsds. Hard. To. Manage.

I have found that the easiest way to keep things DRY is to have two folders at the root of the repository. Which is great, but the same code ended up being replicated for differnet projects, hence the plugin to stop the copypasta.

Conventions I Like To Use

These are defaulted into the plugin, but you can change the naming convention, the location convention (under a project, not under the root), or change both.

With this folder layout, any subproject can know where the documents are with project.rootDir, and the wsdl and xsd imports/includes can be written and won't ever have to change.

Schema Projects

With this convention, you can have any number of schema projects and generate code through jaxb. I wrote a plugin gradle-jaxb-plugin that handles all of the steps listed below.

This minimizes the duplicate code regeneration like crazy

Look at the examples folder for some examples using the jaxb plugin.

Plugin Conventions

WSDL Location Convention

For a WSDL project, there must be at least one WSDL that the project depends on. This file needs to be directly under the wsdl folder. Abstract WSDLs can be saved in subfolder, but the main WSDL for the project requires this location convention.

WSDL Naming Conventions

These conventions are not definable -- the WSDL file MUST:

i.e. ChuckNorrisRoundhouseKickToTheFaceService.wsdl

Project Naming Conventions

The project name MUST also follow these conventions to find the WSDL file correctly:

i.e. chuck-norris-roundhouse-kick-to-the-face-ws

What This Convention Really Helps With

Applying this plugin to all projects with the -ws suffix.

subprojects { project ->
  if(project.name.endsWith("-ws")) { 
    apply plugin: 'com.github.jacobono.wsdl'

    dependencies { 
      jaxws 'com.sun.xml.ws:jaxws-tools:2.2.8-promoted-b131'
      jaxws 'com.sun.xml.ws:jaxws-rt:2.2.8-promoted-b131'
    }
  }
}

Plugin Conventions

Listed in the following sections are the default conventions that are possible to override if desired.

There is a nested configuration, with the wsdl extension being the parent to the wsimport extension. You can change these defaults with a closure in your build script.

    wsdl {
      ...
      wsimport {
        ...
      }
    }

WSDL Plugin Conventions

There are 4 overridable defaults that declare the location defaults above. These defaults are changed via the wsdl closure.

ws-import Conventions

These defaults are changed via the nested wsimport closure. Several boolean sensible defaults are defined to be passed into the wsimport task:

And a few other String defaults

sourceDestionationDirectory is relative to project.projectDir. It defaults to src/main/java, but can be set to anywhere in the project.projectDir.

Optional Parameters

For more information on the jaxws wsimport ant task options, visit here

Default Conventions

These are the current default conventions:

wsdl {
  wsdlFolder    = "wsdl"
  schemaFolder  = "schema"
  episodeFolder = "schema/episodes"
  nameRules     = [:]
  episodes      = []
  wsimport {
    sourceDestinationDirectory = "src/main/java"
    verbose     = true
    keep        = true  
    xnocompile  = true
    fork        = false
    xadditionalHeaders  = false
    xdebug      = false
    target      = "2.1"
    wsdlLocation = "FILL_IN_BY_SERVER"
  }
}

Other Features

Got a really REALLY long WSDL name??

I have seen WSDL names that can be really long, like REALLY long. This becomes a problem with the project name and wsdl naming conventions. Before you know it, you could have a WSDL file

ProjectNameIsSoLongDataManagementService.wsdl

With a corresponding project name of

project-name-is-so-long-data-management-ws

This is just too long of a project name for me (the WSDL can be that long if that is how it is named, but not the project name)!

A tidy feature I added is something called a "nameRule". This allows you to specify a map of strings to transform in your project name to get the correct wsdl name.

Basically, you can configure the extension closure with something like:

wsdl {
     nameRules = ["-dm" : "DataManagement", "-isl" : "IsSoLong"]
}

Now, your project name becomes

project-name-isl-dm-ws

Which is pretty cryptic, yes, but it really reduces the length of your project name. And usually, a project will dictate a Service naming convention like "DataManagement" or "TransactionProcessing" that you can put into a name rule.

I happen to quite like this.

Binding Previously Genrated Episode Files in JAX-WS

A user can define the episodes wished to be bound (to prevent re-generated duplicates that have already been generated by the jaxb task). This is the episodes property, which is just a list of defined episodes, with their extension.

Configure the wsimport task to bind with episode files located under episodeDirectory with

wsdl {
  episodes = ["name-of-episode-file.episode"]
}

or if there are many episode files,

wsdl {
  episodes = ["file1", "file2", "file3"].collect { it + ".episode" }
}

Examples

You can find some examples in the examples folder

Improvements

If you think this plugin could be better, please fork it! If you have an idea that would make something a little easier, I'd love to hear about it.

In my head, I see a few possible improvements