<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <!-- This module was also published with a richer model, Gradle metadata,  -->
  <!-- which should be used instead. Do not delete the following line which  -->
  <!-- is to indicate to Gradle or any Gradle module metadata file consumer  -->
  <!-- that they should prefer consuming it instead. -->
  <!-- do_not_remove: published-with-gradle-metadata -->
  <modelVersion>4.0.0</modelVersion>
  <groupId>au.com.dius.pact</groupId>
  <artifactId>pact-jvm-server</artifactId>
  <version>4.1.31</version>
  <name>pact-jvm-server</name>
  <description>
Pact server
===========

The pact server is a stand-alone interactions recorder and verifier, aimed at clients that are non-JVM or non-Ruby based.

The pact client for that platform will need to be implemented, but it only be responsible for generating the `JSON`
interactions, running the tests and communicating with the server.

The server implements a `JSON` `REST` Admin API with the following endpoints.

    /         -&amp;gt; For diagnostics, currently returns a list of ports of the running mock servers.
    /create   -&amp;gt; For initialising a test server and submitting the JSON interactions. It returns a port
    /complete -&amp;gt; For finalising and verifying the interactions with the server.  It writes the `JSON` pact file to disk.
    /publish  -&amp;gt; For publishing contracts. It takes a contract from disk and publishes it to the configured broker

## Running the server

Pact server takes the following parameters:

```
Usage: pact-jvm-server [options] [port]

  port
        port to run on (defaults to 29999)
  --help
        prints this usage text
  -h &amp;lt;value&amp;gt; | --host &amp;lt;value&amp;gt;
        host to bind to (defaults to localhost)
  -l &amp;lt;value&amp;gt; | --mock-port-lower &amp;lt;value&amp;gt;
        lower bound to allocate mock ports (defaults to 20000)
  -u &amp;lt;value&amp;gt; | --mock-port-upper &amp;lt;value&amp;gt;
        upper bound to allocate mock ports (defaults to 40000)
  -d | --daemon
        run as a daemon process
  -v &amp;lt;value&amp;gt; | --pact-version &amp;lt;value&amp;gt;
        pact version to generate for (2 or 3)
  -k &amp;lt;value&amp;gt; | --keystore-path &amp;lt;value&amp;gt;
        Path to keystore
  -p &amp;lt;value&amp;gt; | --keystore-password &amp;lt;value&amp;gt;
        Keystore password
  -s &amp;lt;value&amp;gt; | --ssl-port &amp;lt;value&amp;gt;   
        Ssl port the mock server should run on. lower and upper bounds are ignored
  -b &amp;lt;value&amp;gt; | --broker &amp;lt;value&amp;gt;
        The baseUrl of the broker to publish contracts to (for example https://organization.broker.com
  -t &amp;lt;value | --token &amp;lt;value&amp;gt;
        API token for authentication to the pact broker 
  --debug
        run with debug logging
```

### Using trust store
Trust store can be used. However, it is limited to a single port for the time being.

### Using a distribution archive

You can download a [distribution from maven central](http://search.maven.org/remotecontent?filepath=au/com/dius/pact/pact-jvm-server/4.1.0/).
There is both a ZIP and TAR archive. Unpack it to a directory of choice and then run the script in the bin directory.

### Building a distribution bundle

You can build an application bundle with gradle by running:

    $ ./gradlew :pact-jvm-server:installdist

This will create an app bundle in `build/install/pact-jvm-server`. You can then execute it with:

    $ java -jar pact-jvm-server/build/install/pact-jvm-server/lib/pact-jvm-server-4.0.1.jar

or with the generated bundle script file:

    $ pact-jvm-server/build/install/pact-jvm-server/bin/pact-jvm-server

By default will run on port `29999` but a port number can be optionally supplied.

### Running it with docker

You can use a docker image to execute the mock server as a docker container.

    $ docker run -d -p 8080:8080 -p 20000-20010:20000-20010 uglyog/pact-jvm-server

This will run the main server on port 8080, and each created mock server on ports 20000-20010. You can map the ports to
any you require.

## Life cycle

The following actions are expected to occur

 * The client calls `/create` to initialise a server with the expected `JSON` interactions and state
 * The admin server will start a mock server on a random port and return the port number in the response
 * The client will execute its interaction tests against the mock server with the supplied port
 * Once finished, the client will call `/complete&amp;apos; on the Admin API, posting the port number
 * The pact server will verify the interactions and write the `JSON` `pact` file to disk under `/target`
 * The mock server running on the supplied port will be shutdown.
 * The client will call `/publish` to publish the created contract to the configured pact broker

## Endpoints

### /create

The client will need `POST` to `/create` the generated `JSON` interactions, also providing a state as a query parameter
and a path.

For example:

    POST http://localhost:29999/create?state=NoUsers&amp;amp;path=/sub/ref/path &amp;apos;{ &amp;quot;provider&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Animal_Service&amp;quot;}, ... }&amp;apos;

This will create a new running mock service provider on a randomly generated port.  The port will be returned in the
`201` response:

    { &amp;quot;port&amp;quot; : 34423 }

But you can also reference the path from `/sub/ref/path` using the server port.  The service will not strip
the prefix path, but instead will use it as a differentiator.  If your services do not have differences
in the prefix of their path, then you will have to use the port method.

### /complete

Once the client has finished running its tests against the mock server on the supplied port (in this example port
`34423`) the client will need to `POST` to `/complete` the port number of the mock server that was used.

For example:

    POST http://localhost:29999/complete &amp;apos;{ &amp;quot;port&amp;quot; : 34423 }&amp;apos;

This will cause the Pact server to verify the interactions, shutdown the mock server running on that port and writing
the pact `JSON` file to disk under the `target` directory.

### /publish

Once all interactions have been tested the `/publish` endpoint can be called to publish the created pact to the pact broker
For this it is required to run the pact-jvm-server with the -b parameter to configure the pact broker to publish the pacts to.
Optionaly an authentication token can be used for authentication against the broker.

For example:

    POST http://localhost:29999/publish &amp;apos;{ &amp;quot;consumer&amp;quot;: &amp;quot;Zoo&amp;quot;, &amp;quot;consumerVersion&amp;quot;: &amp;quot;0.0.1&amp;quot;, &amp;quot;provider&amp;quot;: &amp;quot;Animal_Service&amp;quot; }&amp;apos;

This will cause the Pact server to check for the pact `Zoo-Animal_Service.json` on disk under `target` and publish it to
the configured pact broker. After a successful publish the pact will be removed from disk.

### /

The `/` endpoint is for diagnostics and to check that the pact server is running.  It will return all the currently
running mock servers port numbers.

For example:

    GET http://localhost:29999/

        &amp;apos;{ &amp;quot;ports&amp;quot;: [23443,43232] }&amp;apos;
</description>
  <url>https://github.com/DiUS/pact-jvm</url>
  <licenses>
    <license>
      <name>Apache 2</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
      <distribution>repo</distribution>
    </license>
  </licenses>
  <developers>
    <developer>
      <id>thetrav</id>
      <name>Travis Dixon</name>
      <email>the.trav@gmail.com</email>
    </developer>
    <developer>
      <id>rholshausen</id>
      <name>Ronald Holshausen</name>
      <email>rholshausen@dius.com.au</email>
    </developer>
  </developers>
  <scm>
    <connection>https://github.com/DiUS/pact-jvm.git</connection>
    <url>https://github.com/DiUS/pact-jvm</url>
  </scm>
  <dependencies>
    <dependency>
      <groupId>au.com.dius.pact</groupId>
      <artifactId>consumer</artifactId>
      <version>4.1.31</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.2.3</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>com.github.scopt</groupId>
      <artifactId>scopt_2.12</artifactId>
      <version>3.5.0</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>com.typesafe.scala-logging</groupId>
      <artifactId>scala-logging_2.12</artifactId>
      <version>3.7.2</version>
      <scope>runtime</scope>
      <exclusions>
        <exclusion>
          <artifactId>*</artifactId>
          <groupId>org.scala-lang</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>ws.unfiltered</groupId>
      <artifactId>unfiltered-netty-server_2.12</artifactId>
      <version>0.9.1</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.10.0</version>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
</project>
