add more boilerplates for serverless triggers (#748)

#431
This commit is contained in:
Tomasz Skowroński 2019-08-23 07:32:22 +02:00 committed by Shahidh K Muhammed
parent 8ac78fdaec
commit 669bb40e72
8 changed files with 315 additions and 0 deletions

View File

@ -0,0 +1,30 @@
# Setup tables
1. Create table:
```
notes:
id: int
note: text
```
# Setup AWS Lambda
Create a lambda function in AWS. This will be our webhook.
1. Create a function.
2. Select Java 8 as the runtime.
3. Select "start from scratch".
4. Add API gateway as a trigger.
5. Add an API to API gateway.
6. Edit the code in the `handleRequest` method in `/src/main/java/example/Hello.java`.
# Deploy AWS Lambda
1. In terminal go into project: `cd community/boilerplates/serverless-triggers/aws-lambda/java/echo`
2. Build deployment package: `mvn package`
2. Upload `target/java-lambda-1.0-SNAPSHOT.jar` using AWS console.
# Add the trigger in Hasura GraphQL
1. In events tab, add a trigger
2. Select all insert, update, delete operations for the trigger.
3. Paste the API endpoint of your AWS lambda as the webhook.

View File

@ -0,0 +1,65 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.hasura.serverless</groupId>
<artifactId>java-lambda</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Java Lambda</name>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,48 @@
package example;
import java.util.HashMap;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
public class Hello implements RequestHandler<Map<String, Object>, Map<String, Object>> {
private static final int INTERNAL_SERVER_ERROR = 500;
private final Notebook notebook;
public Hello() {
this.notebook = new Notebook();
}
@Override
public Map<String, Object> handleRequest(Map<String, Object> request, Context context) {
context.getLogger().log(request.toString());
Map<String, Object> response = new HashMap<>();
response.put("isBase64Encoded", false);
try {
String requestBody = (String) request.get("body");
response.put("body", handleRequestBody(requestBody));
response.put("statusCode", 200);
} catch (Exception e) {
response.put("body", e.toString());
response.put("statusCode", INTERNAL_SERVER_ERROR);
}
return response;
}
private String handleRequestBody(String requestBody) {
DocumentContext body = JsonPath.parse(requestBody);
String table = body.read("$.table.name");
if (table != null && table.equals("notes")) {
Notebook.Operation operation = Notebook.Operation.valueOf(body.read("$.event.op"));
Note newNote = body.read("$.event.data.new", Note.class);
Note oldNote = body.read("$.event.data.old", Note.class);
return notebook.handleOperation(operation, newNote, oldNote);
} else {
throw new UnsupportedOperationException("table: " + table);
}
}
}

View File

@ -0,0 +1,23 @@
package example;
class Note {
private Integer id;
private String note;
Integer getId() {
return id;
}
void setId(Integer id) {
this.id = id;
}
String getNote() {
return note;
}
void setNote(String note) {
this.note = note;
}
}

View File

@ -0,0 +1,22 @@
package example;
class Notebook {
enum Operation {
INSERT, UPDATE, DELETE;
}
String handleOperation(Operation operation, Note newNote, Note oldNote) {
switch (operation) {
case INSERT:
return "New note " + newNote.getId() + " inserted, with data: " + newNote.getNote();
case UPDATE:
return "Note " + newNote.getId() + " updated, with data: " + newNote.getNote();
case DELETE:
return "Note " + oldNote.getId() + " deleted, with data: " + oldNote.getNote();
default:
throw new UnsupportedOperationException("operation: " + operation);
}
}
}

View File

@ -0,0 +1,74 @@
package example;
import com.amazonaws.services.lambda.runtime.ClientContext;
import com.amazonaws.services.lambda.runtime.CognitoIdentity;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
public class ContextStub implements Context {
@Override
public LambdaLogger getLogger() {
return new LambdaLogger() {
@Override
public void log(String s) {
System.out.println(s);
}
@Override
public void log(byte[] bytes) {
log(new String(bytes));
}
};
}
@Override
public String getAwsRequestId() {
return null;
}
@Override
public String getLogGroupName() {
return null;
}
@Override
public String getLogStreamName() {
return null;
}
@Override
public String getFunctionName() {
return null;
}
@Override
public String getFunctionVersion() {
return null;
}
@Override
public String getInvokedFunctionArn() {
return null;
}
@Override
public CognitoIdentity getIdentity() {
return null;
}
@Override
public ClientContext getClientContext() {
return null;
}
@Override
public int getRemainingTimeInMillis() {
return -1;
}
@Override
public int getMemoryLimitInMB() {
return -1;
}
}

View File

@ -0,0 +1,35 @@
package example;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class HelloTest {
@Test
void handleRequestDelete() throws IOException {
Map<String, Object> request = new HashMap<>();
request.put("body", loadResource("delete.json"));
Map<String, Object> response = new Hello().handleRequest(request, new ContextStub());
assertEquals(200, response.get("statusCode"));
assertEquals("Note 1 deleted, with data: a", response.get("body"));
}
private String loadResource(String name) {
return new BufferedReader(new InputStreamReader(
ClassLoader.getSystemResourceAsStream(name)
))
.lines()
.collect(Collectors.joining("\n"));
}
}

View File

@ -0,0 +1,18 @@
{
"table": {
"name": "notes"
},
"event": {
"op": "DELETE",
"data": {
"new": {
"id": 2,
"note": "b"
},
"old": {
"id": 1,
"note": "a"
}
}
}
}