1. Introduction

This plugin enables the usage of groovy-wslite on a Griffon application.

Griffon version: 2.2.0

2. Usage

The following sections describe how you may use this plugin in an project.

2.1. Configuration

The plugin’s module registers a WsliteHandler helper class that defines the base contract for issuing REST or SOAP calls using an appropriate client class. This helper class has the following methods

griffon.plugins.wslite.WsliteHandler.java
@Nullable
<R> R withRest(@Nonnull Map<String, Object> params, @Nonnull RESTClientCallback<R> callback) throws RESTException;

@Nullable
<R> R withSoap(@Nonnull Map<String, Object> params, @Nonnull SOAPClientCallback<R> callback) throws SOAPException;

void destroyRestClient(@Nonnull String clientId);

void destroySoapClient(@Nonnull String clientId);

The following properties will be set on the implicit HTTPClient when using either withRest or withSoap:

  • connectTimeout

  • readTimeout

  • followRedirects

  • useCaches

  • sslTrustAllCerts

  • sslTrustStoreFile

  • sslTrustStorePassword

  • proxy

  • httpConnectionFactory

  • authorization

These methods will create a new client when invoked unless you define an id: attribute. When this attribute is supplied the client will be stored in a cache managed by their respective storage classes (RESTClientStorage, SOAPClientStorage).

You can inject an instance of WsliteHandler anywhere it’s needed using @Inject. There are two callbacks you may use with these methods: either you work with a wslite.rest.RESTClient instance using RESTClientCallback or with a wslite.soap.SOAPClient instance using SOAPClientCallback. Both options will come in handy with other plugins or APIs that require one instance or the other.

Both callbacks are defined using a functional interface approach, which means you can apply lambda expressions if running with JDK8+ or closures if running Groovy.

griffon.plugins.wslite.WsliteCallback.java
public interface RESTClientCallback<R> {
    @Nullable
    R handle(@Nonnull Map<String, Object> params, @Nonnull RESTClient client) throws RESTException;
}
griffon.plugins.wslite.SOAPClientCallback.java
public interface SOAPClientCallback<R> {
    @Nullable
    R handle(@Nonnull Map<String, Object> params, @Nonnull SOAPClient client) throws SOAPException;
}

2.2. Example

The following is a trivial usage of the WsliteHandler inside a service

CalculatorService.java
import griffon.core.GriffonApplication;
import griffon.core.artifact.GriffonService;
import griffon.metadata.ArtifactProviderFor;
import griffon.plugins.wslite.exceptions.RESTException;
import griffon.util.CollectionUtils;
import org.codehaus.griffon.runtime.core.artifact.AbstractGriffonService;
import wslite.json.JSONException;
import wslite.json.JSONObject;
import wslite.rest.ContentType;
import wslite.rest.RESTClient;
import wslite.rest.Response;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.util.Map;

import static griffon.util.CollectionUtils.newMap;

@ArtifactProviderFor(GriffonService.class)
public class CalculatorService extends AbstractGriffonService {
    @Inject
    private WsliteHandler wsliteHandler;

    @Inject
    public CalculatorService(@Nonnull GriffonApplication application) {
        super(application);
    }

    public Double calculate(final @Nonnull String num1, final @Nonnull String num2) {
        Map<String, Object> params = CollectionUtils.<String, Object>map()
            .e("url", "http://localhost:9988/calculator")
            .e("readTimeout", 1000)
            .e("id", "client");
        return wsliteHandler.withRest(params,
            new RESTClientCallback<Double>() {
                @Nullable
                public Double handle(@Nonnull Map<String, Object> params, @Nonnull RESTClient client) throws RESTException {
                    Response response = client.get(newMap(
                        "path", "/add",
                        "accept", ContentType.JSON,
                        "query", newMap("num1", num1, "num2", num2)));
                    JSONObject json = (JSONObject) response.propertyMissing("json");
                    try {
                        return json.getDouble("result");
                    } catch (JSONException e) {
                        return Double.NaN;
                    }
                }
            });
    }
}

Here’s the Groovy version of the same service

GroovyCalculatorService.groovy
import griffon.core.artifact.GriffonService
import griffon.metadata.ArtifactProviderFor
import wslite.rest.ContentType
import wslite.rest.RESTClient
import wslite.rest.Response

import javax.annotation.Nonnull
import javax.inject.Inject

@ArtifactProviderFor(GriffonService)
class GroovyCalculatorService {
    @Inject
    private WsliteHandler wsliteHandler

    Double calculate(@Nonnull String num1, @Nonnull String num2) {
        Map args = [
            url        : 'http://localhost:9988/calculator',
            readTimeout: 1000,
            id         : 'client'
        ]
        wsliteHandler.withRest(args, { Map<String, Object> params, RESTClient client ->
            Response response = client.get(
                path: '/add',
                accept: ContentType.JSON,
                query: [num1: num1, num2: num2])
            response.json.result
        })
    }
}

2.3. AST Transformation

You can apply the @WsliteAware AST transformation on any class. This injects the behavior of WsliteHandler into said class.

2.4. DSL Descriptors

This plugin provides DSL descriptors for Intellij IDEA and Eclipse (provided you have the Groovy Eclipse plugin installed). These descriptors are found inside the griffon-wslite-groovy-compile-1.1.0.jar, with locations

  • dsdl/griffon_wslite.dsld

  • gdsl/griffon_wslite.gdsl

3. Build Configuration

3.1. Gradle

You have two options for configuring this plugin: automatic and manual.

3.1.1. Automatic

As long as the project has the org.codehaus.griffon.griffon plugin applied to it you may include the following snippet in build.gradle

dependencies {
    griffon 'org.codehaus.griffon.plugins:griffon-wslite-plugin:1.1.0'
}

The griffon plugin will take care of the rest given its configuration.

3.1.2. Manual

You will need to configure any of the following blocks depending on your setup

dependencies {
    compile 'org.codehaus.griffon.plugins:griffon-wslite-core:1.1.0'
}
Compile Only
dependencies {
    compileOnly 'org.codehaus.griffon.plugins:griffon-wslite-groovy-compile:1.1.0'
}

3.2. Maven

First configure the griffon-wslite-plugin BOM in your POM file, by placing the following snippet before the <build> element

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.griffon.plugins</groupId>
            <artifactId>griffon-wslite-plugin</artifactId>
            <version>1.1.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Next configure dependencies as required by your particular setup

<dependency>
    <groupId>org.codehaus.griffon.plugins</groupId>
    <artifactId>griffon-wslite-core</artifactId>
</dependency>
Provided scope
<dependency>
    <groupId>org.codehaus.griffon.plugins</groupId>
    <artifactId>griffon-wslite-groovy-compile</artifactId>
</dependency>

Don’t forget to configure all -compile dependencies with the maven-surefire-plugin, like so

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <classpathDependencyExcludes>
            <classpathDependencyExclude>
                org.codehaus.griffon:griffon-wslite-groovy-compile
            </classpathDependencyExclude>
        </classpathDependencyExcludes>
    </configuration>
</plugin>

4. Modules

The following sections display all bindings per module. Use this information to successfully override a binding on your own modules or to troubleshoot a module binding if the wrong type has been applied by the Griffon runtime.

4.1. Wslite

Module name: wslite

bind(RESTClientStorage.class)
    .to(DefaultRESTClientStorage.class)
    .asSingleton();

bind(RESTClientFactory.class)
    .to(DefaultRESTClientFactory.class)
    .asSingleton();

bind(SOAPClientStorage.class)
    .to(DefaultSOAPClientStorage.class)
    .asSingleton();

bind(SOAPClientFactory.class)
    .to(DefaultSOAPClientFactory.class)
    .asSingleton();

bind(WsliteHandler.class)
    .to(DefaultWsliteHandler.class)
    .asSingleton();

bind(GriffonAddon.class)
    .to(WsliteAddon.class)
    .asSingleton();