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

Allow for retrieving Java code for schemas via the http API #60

Merged
merged 5 commits into from
Oct 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
3 changes: 2 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ services:
ports:
- '5432:5432'
environment:
POSTGRES_USER: vlingo_schemata
POSTGRES_DB: vlingo_schemata
POSTGRES_USER: vlingo_test
POSTGRES_PASSWORD: vlingo123

volumes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,17 @@ protected void createOrganizationStateTable() {
"name VARCHAR(128) NOT NULL, " +
"description VARCHAR(8000) " +

"UNIQUE (name) " +
")");

jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS ORG_ALL_INDEX ON TBL_ORGANIZATIONS (organizationId)");

/*
Dropping the constraint and recreating it afterwards is not an optimal solution once we have actual data.

TODO: Refactor to find out if constraint already exists or switch to a schema migration tool like flyway or liquibase
*/
jdbi.handle().execute("ALTER TABLE TBL_ORGANIZATIONS DROP CONSTRAINT IF EXISTS ORGANIZATION_UNIQUE");
jdbi.handle().execute("ALTER TABLE TBL_ORGANIZATIONS ADD CONSTRAINT ORGANIZATION_UNIQUE UNIQUE (name)");
}

@Override
Expand All @@ -36,11 +43,13 @@ protected void createUnitStateTable() {
"name VARCHAR(128) NOT NULL, " +
"description VARCHAR(8000) " +

"UNIQUE (organizationId, name) " +
")");

jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS UNIT_PARENT_INDEX ON TBL_UNITS (organizationId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS UNIT_ALL_INDEX ON TBL_UNITS (organizationId, unitId)");

jdbi.handle().execute("ALTER TABLE TBL_UNITS DROP CONSTRAINT IF EXISTS UNIT_ALL_UNIQUE");
jdbi.handle().execute("ALTER TABLE TBL_UNITS ADD CONSTRAINT UNIT_ALL_UNIQUE UNIQUE (organizationId, name)");
}

@Override
Expand All @@ -54,11 +63,13 @@ protected void createContextStateTable() {
"namespace VARCHAR(256) NOT NULL, " +
"description VARCHAR(8000) " +

"UNIQUE (unitId, namespace) " +
")");

jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS CONTEXT_PARENT_INDEX ON TBL_CONTEXTS (organizationId, unitId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS CONTEXT_ALL_INDEX ON TBL_CONTEXTS (organizationId, unitId, contextId)");

jdbi.handle().execute("ALTER TABLE TBL_CONTEXTS DROP CONSTRAINT IF EXISTS CONTEXT_ALL_UNIQUE");
jdbi.handle().execute("ALTER TABLE TBL_CONTEXTS ADD CONSTRAINT CONTEXT_ALL_UNIQUE UNIQUE (organizationId, unitId, namespace)");
}

@Override
Expand All @@ -75,11 +86,14 @@ protected void createSchemaStateTable() {
"name VARCHAR(128) NOT NULL, " +
"description VARCHAR(8000) " +

"UNIQUE (contextId, category, name) " +
")");

jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMA_PARENT_INDEX ON TBL_SCHEMAS (organizationId, unitId, contextId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMA_ALL_INDEX ON TBL_SCHEMAS (organizationId, unitId, contextId, schemaId)");

jdbi.handle().execute("ALTER TABLE TBL_SCHEMAS DROP CONSTRAINT IF EXISTS SCHEMA_ALL_UNIQUE");
jdbi.handle().execute("ALTER TABLE TBL_SCHEMAS ADD CONSTRAINT SCHEMA_ALL_UNIQUE UNIQUE (organizationId, unitId, contextId, name)");

}

@Override
Expand Down Expand Up @@ -112,11 +126,13 @@ protected void createSchemaVersionStateTable() {
"previousVersion VARCHAR(20) NOT NULL, " +
"currentVersion VARCHAR(20) NOT NULL " +

"UNIQUE (schemaId, currentVersion) " +
")");

jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMAVERSION_PARENT_INDEX ON TBL_SCHEMAVERSIONS (organizationId, unitId, contextId, schemaId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMAVERSION_ALL_INDEX ON TBL_SCHEMAVERSIONS (organizationId, unitId, contextId, schemaId, schemaVersionId)");

jdbi.handle().execute("ALTER TABLE TBL_SCHEMAVERSIONS DROP CONSTRAINT IF EXISTS SCHEMAVERSIION_ALL_UNIQUE");
jdbi.handle().execute("ALTER TABLE TBL_SCHEMAVERSIONS ADD CONSTRAINT SCHEMAVERSIION_ALL_UNIQUE UNIQUE (organizationId, unitId, contextId, schemaId, currentVersion)");
}

@Override
Expand Down
70 changes: 42 additions & 28 deletions src/main/java/io/vlingo/schemata/resource/CodeResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,6 @@

package io.vlingo.schemata.resource;

import static io.vlingo.http.RequestHeader.Authorization;
import static io.vlingo.http.Response.Status.BadRequest;
import static io.vlingo.http.Response.Status.InternalServerError;
import static io.vlingo.http.Response.Status.Ok;
import static io.vlingo.http.resource.ResourceBuilder.get;
import static io.vlingo.http.resource.ResourceBuilder.resource;
import static io.vlingo.schemata.Schemata.StageName;
import static io.vlingo.schemata.codegen.TypeDefinitionCompiler.compilerFor;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import io.vlingo.actors.Logger;
import io.vlingo.actors.Stage;
import io.vlingo.actors.World;
Expand All @@ -28,15 +16,20 @@
import io.vlingo.http.Response;
import io.vlingo.http.resource.Resource;
import io.vlingo.http.resource.ResourceHandler;
import io.vlingo.schemata.Schemata;
import io.vlingo.schemata.query.Queries;
import io.vlingo.schemata.query.QueryResultsCollector;
import io.vlingo.schemata.resource.data.AuthorizationData;
import io.vlingo.schemata.resource.data.ContextData;
import io.vlingo.schemata.resource.data.OrganizationData;
import io.vlingo.schemata.resource.data.PathData;
import io.vlingo.schemata.resource.data.SchemaData;
import io.vlingo.schemata.resource.data.SchemaVersionData;
import io.vlingo.schemata.resource.data.UnitData;
import io.vlingo.schemata.resource.data.*;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import static io.vlingo.http.RequestHeader.Authorization;
import static io.vlingo.http.Response.Status.*;
import static io.vlingo.http.resource.ResourceBuilder.get;
import static io.vlingo.http.resource.ResourceBuilder.resource;
import static io.vlingo.schemata.Schemata.StageName;
import static io.vlingo.schemata.codegen.TypeDefinitionCompiler.compilerFor;

//
// like this:
Expand All @@ -58,7 +51,9 @@ public CodeResource(final World world) {
}

public Completes<Response> queryCodeForLanguage(final String reference, final String language) {
final Collector collector = given(context().request, reference);
// FIXME: temporary workaround for missing context in handler, see #55
final Request request = context() == null ? null : context().request;
final Collector collector = given(request, reference);

return Queries.forCode()
.schemaVersionFor(collector.authorization, collector.path, collector)
Expand All @@ -74,11 +69,11 @@ public Completes<Response> queryCodeForLanguage(final String reference, final St
logger.debug("COMPILING: " + collector.schemaVersion().specification);
return compile(collector.path.reference, collector.schemaVersion(), language);
})
.andThenTo(code -> {
.andThenTo(code -> {
logger.debug("CODE: \n" + code);
return recordDependency(code, collector);
})
.andThenTo(code -> {
.andThenTo(code -> {
logger.debug("SUCCESS: \n" + code);
return Completes.withSuccess(Response.of(Ok, code));
})
Expand All @@ -95,10 +90,10 @@ public Completes<Response> queryCodeForLanguage(final String reference, final St
@Override
public Resource<?> routes() {
return resource("Code Resource", 1,
get("/code/{reference}/{language}")
.param(String.class)
.param(String.class)
.handle(this::queryCodeForLanguage));
get("/code/{reference}/{language}")
.param(String.class)
.param(String.class)
.handle(this::queryCodeForLanguage));
}

//////////////////////////////////
Expand All @@ -113,12 +108,15 @@ private Completes<String> compile(final String reference, final SchemaVersionDat
private Collector given(final Request request, final String reference) {
AuthorizationData auth = null;
PathData path = null;
final String header = request.headerValueOr(Authorization, "");

// FIXME: temporary workaround for missing context in handler, see #55
String mockAuth = mockAuth(reference);
final String header = request == null ? mockAuth : request.headerValueOr(Authorization, mockAuth);

try {
auth = AuthorizationData.with(header);
path = PathData.withVersion(reference);
final Tuple3<String,String,String> ids = auth.dependentAsIds();
final Tuple3<String, String, String> ids = auth.dependentAsIds();
return Collector.startingWith(auth, path, ContextData.identity(ids._1, ids._2, ids._3));
} catch (Exception e) {
if (auth == null) {
Expand All @@ -128,6 +126,22 @@ private Collector given(final Request request, final String reference) {
}
}

// FIXME: temporary workaround for missing context in handler, see #55
private String mockAuth(String reference) {
final String[] parts = reference.split(Schemata.ReferenceSeparator);

OrganizationData organization = Queries.forOrganizations().organizationNamed(parts[0]).await();
UnitData unit = Queries.forUnits().unitNamed(organization.organizationId, parts[1]).await();
ContextData context = Queries.forContexts().contextOfNamespace(organization.organizationId, unit.unitId, parts[2]).await();

return AuthorizationData.AuthorizationType +
" source = " + organization.organizationId +
" dependent = " +
organization.organizationId + Schemata.ReferenceSeparator +
unit.unitId + Schemata.ReferenceSeparator +
context.contextId;
}

private Completes<ContextData> queryContextWith(final ContextData contextIds, final Collector collector) {
final Completes<ContextData> context =
Queries.forContexts().context(
Expand Down
83 changes: 83 additions & 0 deletions src/test/resources/rest-api-calls.http
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,87 @@ Accept: application/json
GET http://localhost:9019/schema/categories
Accept: application/json

###


// Reproduce https://github.com/vlingo/vlingo-schemata/issues/55
POST http://localhost:9019/organizations
Content-Type: application/json

{
"organizationId": "",
"name": "org",
"description": "My 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": "unit",
"description": "My unit."
}

> {% 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": "context",
"description": "Schemata Context."
}

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

### Create 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": "schema",
"scope": "Private",
"description": "Schemata was defined event."
}

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


### Create Schema Version
POST http://localhost:9019/organizations/{{orgId}}/units/{{unitId}}/contexts/{{contextId}}/schemas/{{schemaId}}/versions
Content-Type: application/json

{
"organizationId": "{{orgId}}",
"unitId": "{{unitId}}",
"contextId": "{{contextId}}",
"schemaId": "{{schemaId}}",
"schemaVersionId": "",
"description": "Initial revision.",
"specification": "event SchemaDefined { type eventType }",
"status": "Published",
"previousVersion": "0.0.0",
"currentVersion": "1.0.0"
}
> {% client.global.set('schemaVersionId', response.body.schemaVersionId) %}


### this crashes the compiler
GET http://localhost:9019/code/org:unit:context:schema:1.0.0/java
Accept: application/json

###