diff --git a/pom.xml b/pom.xml index 66c5fa850..3d1c5a18f 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,9 @@ 3.3.0 1.7.21 1.1.7 + 1.1.0 + 1.0.0 + 2.8.5 abstract-factory @@ -154,6 +157,7 @@ eip-splitter eip-aggregator retry + serverless diff --git a/serverless/README.md b/serverless/README.md new file mode 100644 index 000000000..75fc40ac0 --- /dev/null +++ b/serverless/README.md @@ -0,0 +1,122 @@ +--- +layout: pattern +title: serverless +folder: serverless +permalink: /patterns/serverless/ +categories: Architectural +tags: + - Java + - Difficulty-Intermittent +--- + +## Serverless + +Serverless eliminates the need to plan for infrastructure and let's you focus on your +application. + +## Intent + +Whether to reduce your infrastructure costs, shrink the time you spend on ops tasks, +simplify your deployment processes, reach infinite scalability, serverless cuts time +to market in half. + +## Explanation + +Serverless computing is a cloud computing execution model in which the cloud provider +dynamically manages the allocation of machine resources. Pricing is based on the +actual amount of resources consumed by an application, rather than on pre-purchased +units of capacity. + +## Serverless framework + +[Serverless](https://serverless.com/) is a toolkit for deploying and operating serverless architectures. + +## (Function as a Service or "FaaS") + +The term ‘Serverless’ is confusing since with such applications there are both server +hardware and server processes running somewhere, but the difference to normal +approaches is that the organization building and supporting a ‘Serverless’ application + is not looking after the hardware or the processes - they are outsourcing this to a vendor. + +Some of the Serverless Cloud Providers are + +![https://serverless.com/framework/docs/providers/aws/](./etc/aws-black.png "aws") +![https://serverless.com/framework/docs/providers/azure/](./etc/azure-black.png "azure") +![https://serverless.com/framework/docs/providers/openwhisk/](./etc/openwhisk-black.png "openwhisk") +![https://serverless.com/framework/docs/providers/google/](./etc/gcf-black.png "google") +![https://serverless.com/framework/docs/providers/kubeless/](./etc/kubeless-logos-black.png "kubeless") +![https://serverless.com/framework/docs/providers/spotinst/](./etc/spotinst-logos-black-small.png "spotinst") +![https://serverless.com/framework/docs/providers/webtasks/](./etc/webtask-small-grayscale.png "webtask") +... + +Anything that triggers an Lambda Function to execute is regarded by the Framework as +an Event. Most of the Serverless Cloud Providers support following Events +- Http +- PubSub Events +- scheduled + +AWS supports processing event generated from AWS Services (S3/Cloudwatch/etc) and +using aws as a compute engine is our first choice. + +## AWS lambda function implementation + +AWS lambda SDK provides pre-defined interface `com.amazonaws.services.lambda.runtime +.RequestHandler` to implement our lambda function. + +```java +public class LambdaInfoApiHandler implements RequestHandler, ApiGatewayResponse> { + + private static final Logger LOG = Logger.getLogger(LambdaInfoApiHandler.class); + private static final Integer SUCCESS_STATUS_CODE = 200; + + + @Override + public ApiGatewayResponse handleRequest(Map input, Context context) { + + } +} +``` +handleRequest method is where the function code is implemented. Context provides +useful information about Lambda execution environment. AWS Lambda function needs a +deployment package. This package is either a .zip or .jar file that contains all the +dependencies of the function. + +`serverless.yml` contains configuration to manage deployments for your functions. + +## Run example in local + +# Pre-requisites +* Node.js v6.5.0 or later. +* Serverless CLI v1.9.0 or later. You can run npm install -g serverless to install it. +* An AWS account. If you don't already have one, you can sign up for a free trial that includes 1 million free Lambda requests per month. +* [Set-up](https://serverless.com/framework/docs/providers/aws/guide/credentials/) your Provider Credentials. Watch the video on setting up credentials + +# build and deploy + +* `cd serverless` +* `mvn clean package` +* `serverless deploy --stage=dev --verbose` + +Based on the configuration in `serverless.yml` serverless framework creates a +cloud formation stack for S3 (ServerlessDeploymentBucket), IAM Role +(IamRoleLambdaExecution), cloud watch (log groups), API Gateway (ApiGatewayRestApi) +and the Lambda function. + +The command will print out Stack Outputs which looks something like this + +```yaml +endpoints: + GET - https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/info +``` + +```yaml +CurrentTimeLambdaFunctionQualifiedArn: arn:aws:lambda:us-east-1:xxxxxxxxxxx:function:lambda-info-http-endpoint-dev-currentTime:4 +ServiceEndpoint: https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev +ServerlessDeploymentBucketName: lambda-info-http-endpoin-serverlessdeploymentbuck-2u8uz2i7cap2 +``` +access the endpoint to invoke the function. + +## Credits + +* [serverless docs](https://serverless.com/framework/docs/) +* [Serverless Architectures](https://martinfowler.com/articles/serverless.html) \ No newline at end of file diff --git a/serverless/etc/aws-black.png b/serverless/etc/aws-black.png new file mode 100644 index 000000000..7b5ba3178 Binary files /dev/null and b/serverless/etc/aws-black.png differ diff --git a/serverless/etc/azure-black.png b/serverless/etc/azure-black.png new file mode 100644 index 000000000..95ceb7e82 Binary files /dev/null and b/serverless/etc/azure-black.png differ diff --git a/serverless/etc/gcf-black.png b/serverless/etc/gcf-black.png new file mode 100644 index 000000000..b4e22982c Binary files /dev/null and b/serverless/etc/gcf-black.png differ diff --git a/serverless/etc/kubeless-logos-black.png b/serverless/etc/kubeless-logos-black.png new file mode 100644 index 000000000..dd6523c51 Binary files /dev/null and b/serverless/etc/kubeless-logos-black.png differ diff --git a/serverless/etc/openwhisk-black.png b/serverless/etc/openwhisk-black.png new file mode 100644 index 000000000..e70139088 Binary files /dev/null and b/serverless/etc/openwhisk-black.png differ diff --git a/serverless/etc/spotinst-logos-black-small.png b/serverless/etc/spotinst-logos-black-small.png new file mode 100644 index 000000000..b748f80c7 Binary files /dev/null and b/serverless/etc/spotinst-logos-black-small.png differ diff --git a/serverless/etc/webtask-small-grayscale.png b/serverless/etc/webtask-small-grayscale.png new file mode 100644 index 000000000..8e2180935 Binary files /dev/null and b/serverless/etc/webtask-small-grayscale.png differ diff --git a/serverless/pom.xml b/serverless/pom.xml new file mode 100644 index 000000000..491946e71 --- /dev/null +++ b/serverless/pom.xml @@ -0,0 +1,113 @@ + + + + 4.0.0 + serverless + + com.iluwatar + java-design-patterns + 1.19.0-SNAPSHOT + + + + + com.amazonaws + aws-lambda-java-core + ${aws-lambda-core.version} + + + com.amazonaws + aws-lambda-java-log4j + ${aws-lambda-log4j.version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.mockito + mockito-core + test + + + junit + junit + test + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + false + + + + package + + shade + + + ${project.artifactId} + + + + + + + + \ No newline at end of file diff --git a/serverless/serverless.yml b/serverless/serverless.yml new file mode 100644 index 000000000..8f2199d26 --- /dev/null +++ b/serverless/serverless.yml @@ -0,0 +1,49 @@ +# +# The MIT License +# Copyright (c) 2014 Ilkka Seppälä +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +service: lambda-info-http-endpoint + +frameworkVersion: ">=1.2.0 <2.0.0" + +provider: + name: aws + runtime: java8 + usagePlan: + quota: + limit: 500 + offset: 2 + period: MONTH + throttle: + burstLimit: 20 + rateLimit: 10 + +package: + artifact: target/serverless.jar + +functions: + currentTime: + handler: com.iluwatar.serverless.api.LambdaInfoApiHandler + events: + - http: + path: info + method: get diff --git a/serverless/src/main/java/com/iluwatar/serverless/ApiGatewayResponse.java b/serverless/src/main/java/com/iluwatar/serverless/ApiGatewayResponse.java new file mode 100644 index 000000000..f20cc13c8 --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/ApiGatewayResponse.java @@ -0,0 +1,166 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.serverless; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.Serializable; +import java.util.Map; + +/** + * Api gateway response + * + * @param serializable object + */ +public class ApiGatewayResponse implements Serializable { + + private static final long serialVersionUID = 1181159426782844892L; + + private final Integer statusCode; + private final String body; + private final Map headers; + private final Boolean isBase64Encoded; + + /** + * api gateway response + * + * @param statusCode - http status code + * @param body - response body + * @param headers - response headers + * @param isBase64Encoded - base64Encoded flag + */ + public ApiGatewayResponse(Integer statusCode, String body, Map headers, + Boolean isBase64Encoded) { + this.statusCode = statusCode; + this.body = body; + this.headers = headers; + this.isBase64Encoded = isBase64Encoded; + } + + /** + * http status code + * + * @return statusCode - http status code + */ + public Integer getStatusCode() { + return statusCode; + } + + /** + * response body + * + * @return string body + */ + public String getBody() { + return body; + } + + /** + * response headers + * + * @return response headers + */ + public Map getHeaders() { + return headers; + } + + /** + * base64Encoded flag, API Gateway expects the property to be called "isBase64Encoded" + * + * @return base64Encoded flag + */ + public Boolean isBase64Encoded() { + return isBase64Encoded; + } + + /** + * ApiGatewayResponse Builder class + * @param Serializable object + */ + public static class ApiGatewayResponseBuilder { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private Integer statusCode; + private T body; + private Map headers; + private Boolean isBase64Encoded; + + /** + * http status code + * @param statusCode - http status code + * @return ApiGatewayResponseBuilder + */ + public ApiGatewayResponseBuilder statusCode(Integer statusCode) { + this.statusCode = statusCode; + return this; + } + + /** + * Serializable body + * @param body - Serializable object + * @return ApiGatewayResponseBuilder + */ + public ApiGatewayResponseBuilder body(T body) { + this.body = body; + return this; + } + + /** + * response headers + * @param headers - response headers + * @return ApiGatewayResponseBuilder + */ + public ApiGatewayResponseBuilder headers(Map headers) { + this.headers = headers; + return this; + } + + /** + * base64Encoded glag + * @param isBase64Encoded - base64Encoded flag + * @return ApiGatewayResponseBuilder + */ + public ApiGatewayResponseBuilder base64Encoded(Boolean isBase64Encoded) { + this.isBase64Encoded = isBase64Encoded; + return this; + } + + /** + * build ApiGatewayResponse + * + * @return ApiGatewayResponse + */ + public ApiGatewayResponse build() { + String strBody = null; + if (this.body != null) { + try { + strBody = OBJECT_MAPPER.writeValueAsString(body); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + return new ApiGatewayResponse(this.statusCode, strBody, this.headers, this.isBase64Encoded); + } + } +} diff --git a/serverless/src/main/java/com/iluwatar/serverless/LambdaInfo.java b/serverless/src/main/java/com/iluwatar/serverless/LambdaInfo.java new file mode 100644 index 000000000..aedb6f72f --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/LambdaInfo.java @@ -0,0 +1,140 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.serverless; + +import java.io.Serializable; + +/** + * Lambda context information + */ +public class LambdaInfo implements Serializable { + + private static final long serialVersionUID = 3936130599040848923L; + + private String awsRequestId; + private String logGroupName; + private String logStreamName; + private String functionName; + private String functionVersion; + private Integer memoryLimitInMb; + + public String getAwsRequestId() { + return awsRequestId; + } + + public void setAwsRequestId(String awsRequestId) { + this.awsRequestId = awsRequestId; + } + + public String getLogGroupName() { + return logGroupName; + } + + public void setLogGroupName(String logGroupName) { + this.logGroupName = logGroupName; + } + + public String getLogStreamName() { + return logStreamName; + } + + public void setLogStreamName(String logStreamName) { + this.logStreamName = logStreamName; + } + + public String getFunctionName() { + return functionName; + } + + public void setFunctionName(String functionName) { + this.functionName = functionName; + } + + public String getFunctionVersion() { + return functionVersion; + } + + public void setFunctionVersion(String functionVersion) { + this.functionVersion = functionVersion; + } + + public Integer getMemoryLimitInMb() { + return memoryLimitInMb; + } + + public void setMemoryLimitInMb(Integer memoryLimitInMb) { + this.memoryLimitInMb = memoryLimitInMb; + } + + @Override + public String toString() { + return "LambdaInfo{" + + "awsRequestId='" + awsRequestId + '\'' + + ", logGroupName='" + logGroupName + '\'' + + ", logStreamName='" + logStreamName + '\'' + + ", functionName='" + functionName + '\'' + + ", functionVersion='" + functionVersion + '\'' + + ", memoryLimitInMb=" + memoryLimitInMb + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + LambdaInfo that = (LambdaInfo) o; + + if (awsRequestId != null ? !awsRequestId.equals(that.awsRequestId) : that.awsRequestId != null) { + return false; + } + if (logGroupName != null ? !logGroupName.equals(that.logGroupName) : that.logGroupName != null) { + return false; + } + if (logStreamName != null ? !logStreamName.equals(that.logStreamName) : that.logStreamName != null) { + return false; + } + if (functionName != null ? !functionName.equals(that.functionName) : that.functionName != null) { + return false; + } + if (functionVersion != null ? !functionVersion.equals(that.functionVersion) : that.functionVersion != null) { + return false; + } + return memoryLimitInMb != null ? memoryLimitInMb.equals(that.memoryLimitInMb) : that.memoryLimitInMb == null; + } + + @Override + public int hashCode() { + int result = awsRequestId != null ? awsRequestId.hashCode() : 0; + result = 31 * result + (logGroupName != null ? logGroupName.hashCode() : 0); + result = 31 * result + (logStreamName != null ? logStreamName.hashCode() : 0); + result = 31 * result + (functionName != null ? functionName.hashCode() : 0); + result = 31 * result + (functionVersion != null ? functionVersion.hashCode() : 0); + result = 31 * result + (memoryLimitInMb != null ? memoryLimitInMb.hashCode() : 0); + return result; + } +} diff --git a/serverless/src/main/java/com/iluwatar/serverless/api/LambdaInfoApiHandler.java b/serverless/src/main/java/com/iluwatar/serverless/api/LambdaInfoApiHandler.java new file mode 100644 index 000000000..669601a23 --- /dev/null +++ b/serverless/src/main/java/com/iluwatar/serverless/api/LambdaInfoApiHandler.java @@ -0,0 +1,83 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.serverless.api; + +import com.iluwatar.serverless.ApiGatewayResponse; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.iluwatar.serverless.LambdaInfo; +import org.apache.log4j.BasicConfigurator; +import org.apache.log4j.Logger; + +import java.util.HashMap; +import java.util.Map; + +/** + * LambdaInfoApiHandler - simple api to get lambda context + * Created by dheeraj.mummar on 2/5/18. + */ +public class LambdaInfoApiHandler implements RequestHandler, ApiGatewayResponse> { + + private static final Logger LOG = Logger.getLogger(LambdaInfoApiHandler.class); + private static final Integer SUCCESS_STATUS_CODE = 200; + + + @Override + public ApiGatewayResponse handleRequest(Map input, Context context) { + BasicConfigurator.configure(); + LOG.info("received: " + input); + + return new ApiGatewayResponse + .ApiGatewayResponseBuilder() + .headers(headers()) + .statusCode(SUCCESS_STATUS_CODE) + .body(lambdaInfo(context)) + .build(); + + } + + /** + * lambdaInfo + * @param context - Lambda context + * @return LambdaInfo + */ + private LambdaInfo lambdaInfo(Context context) { + LambdaInfo lambdaInfo = new LambdaInfo(); + lambdaInfo.setAwsRequestId(context.getAwsRequestId()); + lambdaInfo.setFunctionName(context.getFunctionName()); + lambdaInfo.setFunctionVersion(context.getFunctionVersion()); + lambdaInfo.setLogGroupName(context.getLogGroupName()); + lambdaInfo.setLogStreamName(context.getLogStreamName()); + lambdaInfo.setMemoryLimitInMb(context.getMemoryLimitInMB()); + + return lambdaInfo; + } + + private Map headers() { + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/json"); + + return headers; + } +} diff --git a/serverless/src/main/resources/log4j.properties b/serverless/src/main/resources/log4j.properties new file mode 100644 index 000000000..15a25e61b --- /dev/null +++ b/serverless/src/main/resources/log4j.properties @@ -0,0 +1,29 @@ +# +# The MIT License +# Copyright (c) 2014 Ilkka Seppälä +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +log = . +log4j.rootLogger = DEBUG, LAMBDA + +log4j.appender.LAMBDA=com.amazonaws.services.lambda.runtime.log4j.LambdaAppender +log4j.appender.LAMBDA.layout=org.apache.log4j.PatternLayout +log4j.appender.LAMBDA.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss} <%X{AWSRequestId}> %-5p %c:%L - %m%n diff --git a/serverless/src/test/java/com/iluwatar/serverless/api/LambdaInfoApiHandlerTest.java b/serverless/src/test/java/com/iluwatar/serverless/api/LambdaInfoApiHandlerTest.java new file mode 100644 index 000000000..6c7a03386 --- /dev/null +++ b/serverless/src/test/java/com/iluwatar/serverless/api/LambdaInfoApiHandlerTest.java @@ -0,0 +1,49 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.serverless.api; + +import com.amazonaws.services.lambda.runtime.Context; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * LambdaInfoApiHandlerTest + */ +@RunWith(MockitoJUnitRunner.class) +public class LambdaInfoApiHandlerTest { + + @Test + public void handleRequestWithMockContext() { + LambdaInfoApiHandler lambdaInfoApiHandler = new LambdaInfoApiHandler(); + Context context = mock(Context.class); + when(context.getAwsRequestId()).thenReturn("mock aws request id"); + + assertThat(lambdaInfoApiHandler.handleRequest(null, context), notNullValue()); + } +} \ No newline at end of file