Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schemata integration example #44

Merged
merged 4 commits into from
Dec 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions vlingo-schemata-integration/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
= Integration w/ vlingo/schemata

ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]

`vlingo/schemata` allows for managing schemata for events and commands that
to be consumed by other bounded contexts, thus implementing the published language pattern.

`vlingo/schemata` can be run as standalone service and comes with a user interface
and an HTTP API that lets you manage master data and schemata. Using `vlingo-build-plugins`,
you can also interact with schemata as part of your build process.

In projects, you'll typically consume and/or publish schemata to be able to integrate
with other bounded contexts in a type safe and versioned manner.

In this example, you'll see how to ...

* ... build an run `vlingo/schemata`
* ... manage schemata and schemata meta data using the UI and the HTTP API.
* ... push schemata to the registry from maven builds and
* ... consume schemata stored in the registry as part of the build.


NOTE: This is the first iteration of the example. We're already working on updates showing
version validation and the schemata lifecycle.

== Prerequisites

To be able to follow along, you'll need:

* JDK 8
* Maven 3.3.x
* A running instance of `vlingo/schemata` (see <<Set up vlingo/schemata>>)
* Some master data (see <<Provision schemata master data>>)

=== Set up vlingo/schemata

* Clone https://github.com/vlingo/vlingo-schemata
* Make sure your JDK is set to a 1.8 version in the shell you're building in footnote:[If you're juggling JDKs, https://sdkman.io/ might help you.]
* Run `mvn package -Pfrontend` in the project root
* Run `java -jar target/vlingo-schemata-<version>-jar-with-dependencies.jar dev`. This starts a schemata instance listening on port 9019 running on an embedded in memory database.
* Open http://localhost:9019/. If you see something with `vlingo/schemata` in the the title bar, you're good to go.

NOTE: To run against a persistent database, please have a look at https://github.com/vlingo/vlingo-schemata/

TIP: We'll provide a working docker image soon, please bear with us and build schemata yourself in the meantime.

=== Provision schemata master data

To be able to integrate your projects with the schema registry, you need to
make your organization structure and available published languages known first.
You can do this either via the HTTP API or the UI.

Schemata are structured in a hierarchical manner:
`Organisation -> Units -> Contexts -> Schemas -> Schema Versions`.
We'll push new schema versions using the maven plugin.
Before running the build, you need to have at least one of each other entity prepared.

==== Using the UI

From the navigation drawer to the left, open the editor for each of these entities and create one.
The build assumes the following structure:

* Organisation: `Vlingo`
** Unit: `examples`
***** Context Namepace: `io.vlingo.examples.schemata`
****** Schema: `SchemaDefined`
****** Schema: `SchemaPublished`

.Create context using the UI
image::doc/ui-context.png[]

.The result should look like this
image::doc/ui-browse.png[]

==== Using the API

In case you are using IntelliJ, you can just run the requests in `masterdata.http` directly;
`masterdata.sh` is a bash script doing the same footnote:[Requires `curl` and `jq`].
Otherwise, deriving the `wget` footnote:[`PostMan`, `HTTPie`, `Insomnia`, `Invoke-WebRequest` pick your flavor.]
calls from the snippets should be a simple exercise.

== Run

Now that we have the master data in place, we can publish some schemata from
`vlingo-schemata-producer`. The schema sources live in `src/main/vlingo/schemata`
in that project. To publish them, simply run `mvn install` in the project root.
The build output should contain <<output-producer>>, the <<ui-schema-version>> should look like
the screenshot below. You can also have a look at the generated code (`Specification -> Source`) and description using the
and the generated description (`Description -> Preview`)


Next, hop over to `vlingo-schemata-consumer` and open `SchemataUsageTest` in your IDE.
You'll notice that it does not compile, as the schema class is missing.
Now run `mvn generate-sources` and verify that the code generated from schemata is
pulled and written to `target/generated-sources/vlingo` as shown in <<output-consumer>>.
The test relying on schemata sources will now compile and execute as expected.

NOTE: This is just for illustration purposes. Typically, you'll rely on maven's default lifecycle binding
and not call `generate-sources` explicitly. Simply running `mvn install` will determine
that `vlingo-build-plugin` is bound to `generate-sources` and run it before.


[[output-producer]]
.producer build output
[source]
---
[INFO] --- vlingo-build-plugins:0.9.3-RC4:push-schemata (default) @ vlingo-schemata-producer ---
[INFO] vlingo/maven: Pushing project schemata to vlingo-schemata registry.
[INFO] Pushing Vlingo:examples:io.vlingo.examples.schemata:SchemaDefined:0.0.1 to http://localhost:9019/versions/Vlingo:examples:io.vlingo.examples.schemata:SchemaDefined:0.0.1.
[INFO] Successfully pushed http://localhost:9019/versions/Vlingo:examples:io.vlingo.examples.schemata:SchemaDefined:0.0.1
[INFO] Setting source to SchemaPublished.vss for Vlingo:examples:io.vlingo.examples.schemata:SchemaPublished:0.0.1
[INFO] Pushing Vlingo:examples:io.vlingo.examples.schemata:SchemaPublished:0.0.1 to http://localhost:9019/versions/Vlingo:examples:io.vlingo.examples.schemata:SchemaPublished:0.0.1.
[INFO] Successfully pushed http://localhost:9019/versions/Vlingo:examples:io.vlingo.examples.schemata:SchemaPublished:0.0.1
---

[[ui-schema-version]]
.schema version in the UI
image::doc/ui-schema-version.png[]

[[output-consumer]]
.consumer build output
[source]
---
[INFO] --- vlingo-build-plugins:0.9.3-RC4:pull-schemata (pullSchemata) @ vlingo-schemata-consumer ---
[INFO] vlingo/maven: Pulling code generated from vlingo/schemata registry.
[INFO] SchemataService{url=http://localhost:9019, clientOrganization='Vlingo', clientUnit='examples'}
[INFO] Pulling Vlingo:examples:io.vlingo.examples.schemata:SchemaDefined:0.0.1 from http://localhost:9019/code/Vlingo:examples:io.vlingo.examples.schemata:SchemaDefined:0.0.1/java
[INFO] Pulled Vlingo:examples:io.vlingo.examples.schemata:SchemaDefined:0.0.1
[INFO] Writing Vlingo:examples:io.vlingo.examples.schemata:SchemaDefined:0.0.1 to /Users/wwerner/Projects/vlingo/vlingo-examples/vlingo-schemata-integration/vlingo-schemata-consumer/target/classes/generated-sources/vlingo/io/vlingo/examples/schemata/event/SchemaDefined.java
[INFO] Wrote /Users/wwerner/Projects/vlingo/vlingo-examples/vlingo-schemata-integration/vlingo-schemata-consumer/target/classes/generated-sources/vlingo/io/vlingo/examples/schemata/event/SchemaDefined.java
[INFO] Pulling Vlingo:examples:io.vlingo.examples.schemata:SchemaPublished:0.0.1 from http://localhost:9019/code/Vlingo:examples:io.vlingo.examples.schemata:SchemaPublished:0.0.1/java
[INFO] Pulled Vlingo:examples:io.vlingo.examples.schemata:SchemaPublished:0.0.1
[INFO] Writing Vlingo:examples:io.vlingo.examples.schemata:SchemaPublished:0.0.1 to /Users/wwerner/Projects/vlingo/vlingo-examples/vlingo-schemata-integration/vlingo-schemata-consumer/target/classes/generated-sources/vlingo/io/vlingo/examples/schemata/event/SchemaPublished.java
[INFO] Wrote /Users/wwerner/Projects/vlingo/vlingo-examples/vlingo-schemata-integration/vlingo-schemata-consumer/target/classes/generated-sources/vlingo/io/vlingo/examples/schemata/event/SchemaPublished.java
---
Binary file added vlingo-schemata-integration/doc/ui-browse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added vlingo-schemata-integration/doc/ui-context.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 75 additions & 0 deletions vlingo-schemata-integration/masterdata.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
### Create Organization
POST http://localhost:9019/organizations
Content-Type: application/json

{
"organizationId": "",
"name": "Vlingo",
"description": "Vlingo Organization"
}

> {% client.global.set('orgId', response.body.organizationId) %}


### Create Unit
POST http://localhost:9019/organizations/{{orgId}}/units
Content-Type: application/json

{
"organizationId": "{{orgId}}",
"unitId": "",
"name": "examples",
"description": "Examples for vlingo/schemata"
}

> {% client.global.set('unitId', response.body.unitId) %}

### Create Context
POST http://localhost:9019/organizations/{{orgId}}/units/{{unitId}}/contexts
Content-Type: application/json

{
"organizationId": "{{orgId}}",
"unitId": "{{unitId}}",
"contextId": "",
"namespace": "io.vlingo.examples.schemata",
"description": "Bounded context for vlingo/schemata examples"
}

> {% client.global.set('contextId', response.body.contextId) %}

### Create SchemaDefined schema
POST http://localhost:9019/organizations/{{orgId}}/units/{{unitId}}/contexts/{{contextId}}/schemas
Content-Type: application/json

{
"organizationId": "{{orgId}}",
"unitId": "{{unitId}}",
"contextId": "{{contextId}}",
"schemaId": "",
"category": "Event",
"name": "SchemaDefined",
"scope": "Public",
"description": "Fired whenever a new schema is defined."
}

> {% client.global.set('schemaId', response.body.schemaId) %}

### Create SchematPublished schema
POST http://localhost:9019/organizations/{{orgId}}/units/{{unitId}}/contexts/{{contextId}}/schemas
Content-Type: application/json

{
"organizationId": "{{orgId}}",
"unitId": "{{unitId}}",
"contextId": "{{contextId}}",
"schemaId": "",
"category": "Event",
"name": "SchemaPublished",
"scope": "Public",
"description": "Fired whenever a schema version is published."
}

> {% client.global.set('schemaId', response.body.schemaId) %}

###
11 changes: 11 additions & 0 deletions vlingo-schemata-integration/masterdata.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# Small utility script to add master data required for the example to a schemata instance
# Requires curl and jq to be on the path.
# Set the port to the port the schemata server is listening on

PORT=9039
ORG_ID=$(curl -s -d '{ "organizationId": "", "name": "Vlingo", "description": "Vlingo Organization" }' -H 'Content-Type: application/json' -X POST http://localhost:${PORT}/organizations | jq -r '.organizationId')
UNIT_ID=$(curl -s -d '{ "organizationId": "'${ORG_ID}'", "unitId": "", "name": "examples", "description": "Examples for vlingo/schemata" }' -X POST -H 'Content-Type: application/json' http://localhost:${PORT}/organizations/${ORG_ID}/units | jq -r '.unitId')
CONTEXT_ID=$(curl -s -X POST -H 'Content-Type: application/json' -d '{ "organizationId": "'${ORG_ID}'", "unitId": "'${UNIT_ID}'", "contextId": "", "namespace": "io.vlingo.examples.schemata", "description": "Bounded context for vlingo/schemata examples" }' http://localhost:${PORT}/organizations/${ORG_ID}/units/${UNIT_ID}/contexts | jq -r '.contextId')
curl -s -X POST -H 'Content-Type: application/json' -d '{ "organizationId": "'${ORG_ID}'", "unitId": "'${UNIT_ID}'", "contextId": "'${CONTEXT_ID}'", "schemaId": "", "category": "Event", "name": "SchemaDefined", "scope": "Public", "description": "Fired whenever a new schema is defined." }' http://localhost:${PORT}/organizations/${ORG_ID}/units/${UNIT_ID}/contexts/${CONTEXT_ID}/schemas
curl -s -X POST -H 'Content-Type: application/json' -d '{ "organizationId": "'${ORG_ID}'", "unitId": "'${UNIT_ID}'", "contextId": "'${CONTEXT_ID}'", "schemaId": "", "category": "Event", "name": "SchemaPublished", "scope": "Public", "description": "Fired whenever a schema version is published." }' http://localhost:${PORT}/organizations/${ORG_ID}/units/${UNIT_ID}/contexts/${CONTEXT_ID}/schemas
68 changes: 68 additions & 0 deletions vlingo-schemata-integration/vlingo-schemata-consumer/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>io.vlingo</groupId>
<artifactId>vlingo-schemata-consumer</artifactId>
<version>0.9.3-RC4</version>
<name>vlingo-schemata-consumer</name>
<description>Example of a project consuming schemas from vlingo/schemata.</description>
<url>https://github.com/vlingo/vlingo-examples</url>
<licenses>
<license>
<name>Mozilla Public License 2.0</name>
<url>https://mozilla.org/MPL/2.0/</url>
</license>
</licenses>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<vlingo.build.plugins.version>${project.version}</vlingo.build.plugins.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>io.vlingo</groupId>
<artifactId>vlingo-build-plugins</artifactId>
<version>${vlingo.build.plugins.version}</version>
<executions>
<execution>
<id>pullSchemata</id>
<goals>
<goal>pull-schemata</goal>
</goals>
<configuration>
<schemataService>
<url>http://localhost:9019</url>
<clientOrganization>Vlingo</clientOrganization>
<clientUnit>examples</clientUnit>
</schemataService>
<outputDirectory>${project.build.directory}/generated-sources/vlingo</outputDirectory>
<schemata>
<schema>
<ref>Vlingo:examples:io.vlingo.examples.schemata:SchemaDefined:0.0.1</ref>
</schema>
<schema>
<ref>Vlingo:examples:io.vlingo.examples.schemata:SchemaPublished:0.0.1</ref>
</schema>
</schemata>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- required to have access to schemata base classes -->
<dependency>
<groupId>io.vlingo</groupId>
<artifactId>vlingo-lattice</artifactId>
<version>0.9.3-RC4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright © 2012-2018 Vaughn Vernon. All rights reserved.
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL
// was not distributed with this file, You can obtain
// one at https://mozilla.org/MPL/2.0/.

import io.vlingo.examples.schemata.event.SchemaDefined;
import io.vlingo.examples.schemata.event.SchemaPublished;
import org.junit.Test;

public class SchemataUsageTest {

@Test
public void testThatSchemaIsPulledAndCompiledTest() {
new SchemaDefined();
new SchemaPublished();
}
}
57 changes: 57 additions & 0 deletions vlingo-schemata-integration/vlingo-schemata-producer/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>io.vlingo</groupId>
<artifactId>vlingo-schemata-producer</artifactId>
<version>0.9.3-RC4</version>
<name>vlingo-schemata-producer</name>
<description>Example of a project pushing schemas to vlingo/schemata.</description>
<url>https://github.com/vlingo/vlingo-examples</url>
<licenses>
<license>
<name>Mozilla Public License 2.0</name>
<url>https://mozilla.org/MPL/2.0/</url>
</license>
</licenses>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<vlingo.build.plugins.version>${project.version}</vlingo.build.plugins.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>io.vlingo</groupId>
<artifactId>vlingo-build-plugins</artifactId>
<version>${vlingo.build.plugins.version}</version>
<executions>
<execution>
<goals>
<goal>push-schemata</goal>
</goals>
<configuration>
<srcDirectory>${basedir}/src/main/vlingo/schemata</srcDirectory>
<schemataService>
<url>http://localhost:9019</url>
<clientOrganization>Vlingo</clientOrganization>
<clientUnit>examples</clientUnit>
</schemataService>
<schemata>
<schema>
<ref>Vlingo:examples:io.vlingo.examples.schemata:SchemaDefined:0.0.1</ref>
<src>SchemaDefined.vss</src>
<previousVersion>0.0.0</previousVersion>
</schema>
<schema>
<ref>Vlingo:examples:io.vlingo.examples.schemata:SchemaPublished:0.0.1</ref>
<!-- src defaults to the name part of the reference -->
<!-- previousVersion defaults to 0.0.0 -->
</schema>
</schemata>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
event SchemaDefined {
type eventType
timestamp occurredOn
version eventVersion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
event SchemaPublished {
timestamp publishedOn
version publishedVersion
}