Skip to: Site menu | Main content

Groovy 

      Download | Documentation | Developers | Community

An agile dynamic language for the Java Platform

GroovyWS Add comment to Wiki View in Wiki Edit Wiki page Printable Version

Module Overview

GroovyWS is taking over GroovySOAP as CXF replaces XFire. The major difference here is that GroovyWS is using Java5 so if you need to stick to 1.4 please continue to use GroovySOAP.

Warning: Most of the documentation is adapted from the former GroovySOAP documentation and will improve in the future. I tried to make it as accurate as possible but feel free to report any error.

Warning: GroovyWS is Java5 dependent (due to CXF) and has been tested using groovy-1.5.

Warning: In order to use GroovyWS, you must ensure that GroovySOAP is not in your classpath (~/.groovy/lib) 

Download

Distributions

GroovyWS is available in two packages:

  • as a full jar containing all CXF JARs and dependencies. It is located here
  • as a jar containing all except the jetty server and servlet files. It aimed at being deployed into third party containers. It is located here

Installing

You just need to place the above mentioned JAR file in your ${user.home}/.groovy/lib directory.

Pre-requisites

As the pre-requisites are quite tricky to handle, an all-in-one JAR file is distributed  

Documentation

Getting Started

The Server

You can develop your web service using a groovy script and/or a groovy class. The following two groovy files are valid for building a web-service.

  1. MathService.groovy
    public class MathService {
        double add(double arg0, double arg1) {
          return (arg0 + arg1)
        }
        double square(double arg0) {
          return (arg0 * arg0)
        }
    }
  2. Then the easy part ... no need for comments

    import groovyx.net.ws.WSServer
    
    def server = new WSServer()
    
    server.setNode("MathService", "http://localhost:6980/MathService")


    That's all !

The Client

  1. Oh ... you want to test it ... two more lines.
    import groovyx.net.ws.WSClient
    
    def proxy = new WSClient("http://localhost:6980/MathService?wsdl", this.class.classLoader)
    
    def result = proxy.add(1.0 as double, 2.0 as double)
    assert (result == 3.0)
    
    result = proxy.square(3.0 as double)
    assert (result == 9.0)
  2. You're done!

Complex types

The Server

Let say we have a server that manage a library in which you can add a book, find a book and get all the books. The server code will probably look like this

  1. BookService.groovy

    class BookService {
    
      private List allBooks = new ArrayList()
    
      Book findBook(String isbn) {
        for (book in allBooks) {
          if (book.isbn == isbn) return book
        }
        return null
      }
    
      void addBook(Book book) {
        allBooks.add(book)
      }
    
      Book[] getBooks() {
        return (Book[])allBooks.toArray(new Book[allBooks.size()])
      }
    
    }


  2. with the class Book being something like that.

    Book.groovy
    class Book {
      String author
      String title
      String isbn
    }


    To ignore the metaClass property a custom type mapping must be defined (for details refer to Aegis Binding).

    Book.aegis.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <mappings xmlns:sample="http://DefaultNamespace">
      <mapping name="sample:Book">
        <property name="metaClass" ignore="true"/>
      </mapping>
    </mappings>


    However, if you compile custom data types from Java the bytecode won't contain a metaClass property and, hence, there is no need to define a custom mapping.

The Client

The good think here is that the client does not have to know about the Book class. It is automatically generated during the proxy creation time and can be used by your client. Here it is located in the defaultnamespace package since no package was used on the server side.

Here is how the client looks like now:



import groovyx.net.ws.WSClient

def proxy = new WSClient("http://localhost:6981/BookService?wsdl", this.class.classLoader)

def books =  proxy.getBooks()

for (book in books) println book

def book = proxy.create("defaultnamespace.Book")

book.title = "Groovy in Action"
book.author = "Dierk"
book.isbn = "123"

proxy.addBook(book)

def bks =  proxy.getBooks()

println bks.books[0].isbn

Iterating over the books is slightly more complicated since SOAP wrap the arrays in an element (in our case ArrayOfBook). Therefore you have to extract a field from that element. In our case:



def aob =  proxy.getBooks()

for (book in aob.books) println book.name

More Information

Using proxies

If you are using a proxy for accessing internet, you can use the following environment variables to get rid of it:

  • proxyHost
  • proxyPort
  • proxy.user
  • proxy.password

Using basic authentication

If your server use basic authentication, you need to set up the following properties:

  • http.user
  • http.password

TODO

 If you have ideas how the API should look, do not hesitate to post on the user list ;-

Known problems (and work around)

You will not be able to create a proxy directly for a service that requires a username and password to fetch the WSDL. One alternate way is to download the WSDL (using wget or curl with the username and password set) and to create the proxy using the local file.

Demos with public web services

Currency rate calculator

There exist a lot of web-services available for testing. One which is pretty easy to evaluate is the currency rate calculator from webservicex.net.

Here is a small swing sample that demonstrate the use of the service. Enjoy !

import groovy.swing.SwingBuilder
import groovyx.net.ws.WSClient

proxy = new WSClient("http://www.webservicex.net/CurrencyConvertor.asmx?WSDL", this.class.classLoader)

def currency = ['USD', 'EUR', 'CAD', 'GBP', 'AUD', 'SGD']
def rate = 0.0

swing = new SwingBuilder()

refresh = swing.action(
  name:'Refresh',
  closure:this.&refreshText,
  mnemonic:'R'
)

frame = swing.frame(title:'Currency Demo') {
  panel {
    label 'Currency rate from '
    comboBox(id:'from', items:currency)
    label ' to '
    comboBox(id:'to', items:currency)
    label ' is '
    textField(id:'currency', columns:10, rate.toString())
    button(text:'Go !', action:refresh)
  }
}
frame.pack()
frame.show()

def refreshText(event) {
  rate = proxy.ConversionRate(swing.from.getSelectedItem(), swing.to.getSelectedItem())
  swing.currency.text = rate
}

TerraServer-USA by Microsoft



TerraServer supports a Tiling Web Service that enables you to build applications that integrate with USGS imagery found on their site. Here is a sample of what you can achieve.

import groovyx.net.ws.WSClient;
def proxy = new WSClient("http://terraservice.net/TerraService.asmx?WSDL", this.class.classLoader)

// Create the Place object
def place = proxy.create("com.terraserver_usa.terraserver.Place")

// Initialize the Place object
place.city = "mountain view"
place.state = "ca"
place.country = "us"

// Geocode the place
def result = proxy.ConvertPlaceToLonLatPt(place)

println "Longitude: ${result.lon}"
println "Latitude: ${result.lat}"

will give:

Longitude: -122.08000183105469
Latitude: 37.400001525878906

Developers

Guillaume Alleon

Building

Contributing

Community

Mailing List(s)

use user@groovy.codehaus.org

Issue tracker

There is a GroovyWS category in JIRA

Articles

A nice article from Geertjan's blog with several examples: http://blogs.sun.com/geertjan/entry/groovy_web_service