Skip to content
Open
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
118 changes: 67 additions & 51 deletions src/render/tutorials/configurable-api-gateway/2_0.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Configurable API gateway
author: marcinkp
keywords: tutorial
date: 2019-08-07
date: 2019-10-18
layout: tutorial
knotxVersions:
- 2.0.0
Expand Down Expand Up @@ -205,16 +205,35 @@ Once all data from external services are fetched, action `payments` is executed.
Now, you are ready to implement custom [Action](https://github.com/Knotx/knotx-fragments/tree/master/handler/api#action).
The purpose of Action is to transform collected `json` data from external services into one `json` which will be returned by ours API.

Create the directory for new module `modules/payments`.
Edit the `settings.gradle.kts` and add two lines:
You should create a new Gradle module for our implementation. After creating this tutorial, newly created files structure should look as follows:

```
├── composing-many-apis.yml // Swarm file defining stack on Docker
└── modules
└──payments
├──
├── build.gradle.kts // gradle build script
└── src
└── main
├── java/io/knotx/example/payment
| ├── action
| | └── PaymentsActionFactory.java // the action factory
| └── utils
| └── PaymentProvidersProcessor.java // class that processes all payment providers
└── resources
└── META-INF/services
└── io.knotx.server.api.handler.RoutingHandlerFactory // META-INF file used by Knot.x to find the handler
```

You should start with editing the `settings.gradle.kts` file and adding two lines:

```
include("payments")

project(":payments").projectDir = file("modules/payments")

```
Add the following files:
Then create the following files content:

*build.gradle.kts*
```kotlin
Expand Down Expand Up @@ -248,8 +267,7 @@ io.knotx.example.payment.action.PaymentsActionFactory
```java
package io.knotx.example.payment.action;

import static io.knotx.example.payment.utils.ProvidersProvider.calculateProviders;

import io.knotx.example.payment.utils.PaymentProvidersProcessor;
import org.apache.commons.lang3.StringUtils;

import io.knotx.fragments.handler.api.Action;
Expand All @@ -270,55 +288,56 @@ public class PaymentsActionFactory implements ActionFactory {
@Override
public Action create(String alias, JsonObject config, Vertx vertx, Action doAction) {
return (fragmentContext, resultHandler) ->
Single.just(fragmentContext.getFragment())
.map(fragment -> {
JsonObject payload = fragment.getPayload();
JsonObject user = payload.getJsonObject("user");
JsonObject payments = processProviders(payload);
fragment.clearPayload();
fragment.mergeInPayload(new JsonObject().put(getAlias(alias), payments)
.put("user", user));
return new FragmentResult(fragment, FragmentResult.SUCCESS_TRANSITION);
})
.subscribe(onSuccess -> {
Future<FragmentResult> resultFuture = Future.succeededFuture(onSuccess);
resultFuture.setHandler(resultHandler);
}, onError -> {
Future<FragmentResult> resultFuture = Future.failedFuture(onError);
resultFuture.setHandler(resultHandler);
});
Single.just(fragmentContext.getFragment())
.map(fragment -> {
JsonObject payload = fragment.getPayload();
JsonObject user = payload.getJsonObject("user");
JsonObject payments = processProviders(payload);
fragment.clearPayload();
fragment.mergeInPayload(new JsonObject().put(getAlias(alias), payments)
.put("user", user));
return new FragmentResult(fragment, FragmentResult.SUCCESS_TRANSITION);
})
.subscribe(onSuccess -> {
Future<FragmentResult> resultFuture = Future.succeededFuture(onSuccess);
resultFuture.setHandler(resultHandler);
}, onError -> {
Future<FragmentResult> resultFuture = Future.failedFuture(onError);
resultFuture.setHandler(resultHandler);
});
}

private JsonObject processProviders(JsonObject payload) {
return new JsonObject()
.put("timestamp", System.currentTimeMillis())
.put("providers", calculateProviders(payload));
.put("timestamp", System.currentTimeMillis())
.put("providers", PaymentProvidersProcessor.processProviders(payload));
}

private String getAlias(String alias) {
return StringUtils.defaultString(alias, "payments");
}
}

```

*src/main/java/io/knotx/example/payment/utils/ProvidersProvider.java*
*src/main/java/io/knotx/example/payment/utils/PaymentProvidersProcessor.java*
```java
package io.knotx.example.payment.utils;

import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;

public final class ProvidersProvider {
public final class PaymentProvidersProcessor {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I liked this tricky name ;) Sure, change it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please apply those changes in the example code.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will create dedicated PR for example code and will share PR link shortly.


private ProvidersProvider() {
private PaymentProvidersProcessor() {
//util
}

public static JsonArray calculateProviders(JsonObject creditCard,
JsonObject paypal, JsonObject payU) {
public static JsonArray processProviders(JsonObject creditCard,
JsonObject paypal, JsonObject payU) {
JsonArray providers = new JsonArray();
if (creditCard != null && creditCard.containsKey("allowed") && creditCard
.getBoolean("allowed")) {
.getBoolean("allowed")) {
providers.add(getProviderData(creditCard, "label", "url"));
}
if (paypal != null && paypal.containsKey("verified") && paypal.getBoolean("verified")) {
Expand All @@ -330,34 +349,34 @@ public final class ProvidersProvider {
return providers;
}

public static JsonArray calculateProviders(JsonObject payload) {
return calculateProviders(getResult(payload, "creditCard"), getResult(payload, "paypal"),
getResult(payload, "payU"));
public static JsonArray processProviders(JsonObject payload) {
return processProviders(getResult(payload, "creditCard"), getResult(payload, "paypal"),
getResult(payload, "payU"));
}


private static JsonObject getProviderData(JsonObject data, String label, String paymentUrl) {
return new JsonObject()
.put("label", data.getString(label))
.put("paymentUrl", data.getString(paymentUrl));
.put("label", data.getString(label))
.put("paymentUrl", data.getString(paymentUrl));
}

private static JsonObject getResult(JsonObject payload, String provider) {
if (payload.containsKey(provider)) {
return payload.getJsonObject(provider)
.getJsonObject("_result");
.getJsonObject("_result");
} else {
return null;
}
}

}

```

## External services

We need to define the responses for external services. Our definition calls 4 services. Let's define them.
Create `../common-services` directory. Let's put this directory in the parent directory of our current project, since we will be reusing files created there in different tutorials. Now let's create `../common-services/webapi/__files` and put 4 files there:
We need to define the responses for external services. Our definition calls 4 services. Let's define them.

Create `<KNOTX-STARTERKIT-ROOT>/common-services` directory. Let's put it in the main directory of the project, since we will be reusing files created there in different tutorials. Now create `<KNOTX-STARTERKIT-ROOT>/common-services/webapi/__files` and put 4 files there:

*creditcard.json*
```json
Expand Down Expand Up @@ -418,7 +437,7 @@ Create `../common-services` directory. Let's put this directory in the parent di

We will use [WireMock](http://wiremock.org/) for mock services and we need to define the mappings.

Create the `../common-services/webapi/mappings` directory and put there those four files:
Create the `<KNOTX-STARTERKIT-ROOT>/common-services/webapi/mappings` directory and put there those four files:

*creditcard.json*
```json
Expand Down Expand Up @@ -489,7 +508,7 @@ Create the `../common-services/webapi/mappings` directory and put there those fo
[Knot.x Starter Kit](https://github.com/Knotx/knotx-starter-kit) project builds docker image. Edit `gradle.properties` and change property `docker.image.name`:

```
docker.image.name=knotx-example/api-gateway
docker.image.name=knotx-example/composing-many-apis
```

You will refer to the image name in the swarm file.
Expand All @@ -500,7 +519,7 @@ Let's define the swarm file where we will setup following services:
- `webapi` - external Web APIs for: `user`, `creditcard`, `payu` and `paypal` (which we've just created above)
- `knotx` - Knot.x image with our customization we build during this tutorial

Create the `api-gateway.yml` file:
Create the `composing-many-apis.yml` file:

```yaml
version: '3.7'
Expand All @@ -513,36 +532,33 @@ services:
webapi:
image: rodolpheche/wiremock
volumes:
- "../common-services/webapi:/home/wiremock"
- "../../common-services/webapi:/home/wiremock"
ports:
- "3000:8080"
networks:
- knotnet

knotx:
image: knotx-example/gateway-api:latest
image: knotx-example/composing-many-apis:latest
command: ["knotx", "run-knotx"]
ports:
- "8092:8092"
- "18092:18092"
networks:
- knotnet


```


## Run

Now we are ready to run. First, build your docker image
```
$ gradlew clean build
$ gradlew clean build-docker
```

Run Knot.x instance and example data services (Web API and Content Repository) in a single-node Docker Swarm:
```
$ docker swarm init
$ docker stack deploy -c api-gateway.yml api-gateway
$ docker stack deploy -c composing-many-apis.yml composing-many-apis
```

### Final page
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Configurable API gateway
author: marcinkp
description: "In this tutorial, we will explain how to implement API gateway using Knot.x."
order: 7
date: 2019-08-07
date: 2019-10-18
layout: redirect
target: /tutorials/configurable-api-gateway/2_0/
---
8 changes: 8 additions & 0 deletions src/team/contributors/mateuszgrab-cognifide.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should stay here :)

member: mateuszgrab-cognifide
name: Mateusz Grab
avatar: https://avatars1.githubusercontent.com/u/21056178?s=460&v=4
website:
twitter:
showOnPage: true
---