3

I uploaded Spring boot jar file (it has lambda request stream handler) into AWS Lambda as zip file. Since the zip is big, I uploaded in S3 and given that link while creating this Lambda function in AWS Console. As I read everywhere that that's all the spring boot service deployment in lambda with the simple method. My spring boot service has 2 GET end points in it. Please find entire Spring boot service code and Lambda screenshots below.

Error: (It gave timeout error, so increased to 15 mins in Lambda test and the result is below, which seems to be not working still)

Executing function: succeeded (logs )
    {
  "statusCode": 502,
  "multiValueHeaders": {
    "Content-Type": [
      "application/json"
    ]
  },
  "body": "{\"message\":\"Gateway timeout\"}",
  "isBase64Encoded": false
}

Spring boot Request Stream Handler for Lambda: (Asynchronous, as i felt Lambda takes much time to start initially)

    public class StreamLambdaHandler implements RequestStreamHandler {
    private SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
    
    public StreamLambdaHandler() throws ContainerInitializationException {
        handler = new SpringBootProxyHandlerBuilder()
                .defaultProxy()
                .asyncInit()
                .springBootApplication(SlowApplication.class)
                .buildAndInitialize();
    }

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context)
            throws IOException {
        handler.proxyStream(inputStream, outputStream, context);
    }
}

build.gradle ( I added "task buildZip" here to get build->"distributions" jar in zip file)

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.0'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-test'
    implementation 'mysql:mysql-connector-java:8.0.32'
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    implementation 'com.amazonaws:aws-lambda-java-core:1.2.2'
    implementation 'com.amazonaws:aws-lambda-java-events:3.11.1'
    implementation 'com.amazonaws.serverless:aws-serverless-java-container-spring:1.5.2'
}
task buildZip(type: Zip) {
    into('lib') {
        from(jar)
        from(configurations.runtimeClasspath)
    }
}
tasks.named('test') {
    useJUnitPlatform()
}
jar {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    manifest {
        attributes "Main-Class": "com.example.awstest"
    }

    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

Spring Boot Application Class:

package com.example.awstest.client;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@ComponentScan ("com.example.awstest")
public class AWSTestApplication  extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(AWSTestApplication.class, args);
    }
}

Spring Boot Controller:

package com.example.awstest.controller;

@RestController

public class AWSTestController {

        @Autowired
            private AWSTestServiceDAO awstestServiceDAO;
    
            @CrossOrigin(origins = "*")
            @GetMapping("/searchAllData")
            public List<TESTData> searchAllData() {
    
                List<TESTData> dataList = awstestServiceDAO.getAllData();
                return dataList;
             }
    
            @CrossOrigin(origins = "*")
            @GetMapping("/searchDataByUser/{userno}")
            public List<TESTData> searchDataByUser(@PathVariable Integer userno) {
    
                List<TESTData> dataList = awstestServiceDAO.findDataByMemberNo(userno);
                return dataList;
            }
    
    }

Lambda Console:

Added handler as: com.example.awstest.handler.AWSLambdaHandler::handleRequest

Test Function: apigateway-awsproxy

{
  "body": "eyJ0ZXN0IjoiYm9keSJ9",
  "resource": "/{proxy+}",
  "path": "/searchAllData",
  "httpMethod": "GET",
  "isBase64Encoded": true,
  "pathParameters": {
    "proxy": "/searchAllData"
  },
  "stageVariables": {
    "baz": "qux"
  },
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, sdch",
    "Accept-Language": "en-US,en;q=0.8",
    "Cache-Control": "max-age=0",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Desktop-Viewer": "true",
    "CloudFront-Is-Mobile-Viewer": "false",
    "CloudFront-Is-SmartTV-Viewer": "false",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Viewer-Country": "US",
    "Host": "1234567890.execute-api.us-east-1.amazonaws.com",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Custom User Agent String",
    "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
    "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
    "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
    "X-Forwarded-Port": "443",
    "X-Forwarded-Proto": "https"
  },
  "multiValueHeaders": {
    "Accept": [
      "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
    ],
    "Accept-Encoding": [
      "gzip, deflate, sdch"
    ],
    "Accept-Language": [
      "en-US,en;q=0.8"
    ],
    "Cache-Control": [
      "max-age=0"
    ],
    "CloudFront-Forwarded-Proto": [
      "https"
    ],
    "CloudFront-Is-Desktop-Viewer": [
      "true"
    ],
    "CloudFront-Is-Mobile-Viewer": [
      "false"
    ],
    "CloudFront-Is-SmartTV-Viewer": [
      "false"
    ],
    "CloudFront-Is-Tablet-Viewer": [
      "false"
    ],
    "CloudFront-Viewer-Country": [
      "US"
    ],
    "Host": [
      "0123456789.execute-api.us-east-1.amazonaws.com"
    ],
    "Upgrade-Insecure-Requests": [
      "1"
    ],
    "User-Agent": [
      "Custom User Agent String"
    ],
    "Via": [
      "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)"
    ],
    "X-Amz-Cf-Id": [
      "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA=="
    ],
    "X-Forwarded-For": [
      "127.0.0.1, 127.0.0.2"
    ],
    "X-Forwarded-Port": [
      "443"
    ],
    "X-Forwarded-Proto": [
      "https"
    ]
  },
  "requestContext": {
    "accountId": "123456789012",
    "resourceId": "123456",
    "stage": "prod",
    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "requestTime": "09/Apr/2015:12:34:56 +0000",
    "requestTimeEpoch": 1428582896000,
    "identity": {
      "cognitoIdentityPoolId": null,
      "accountId": null,
      "cognitoIdentityId": null,
      "caller": null,
      "accessKey": null,
      "sourceIp": "127.0.0.1",
      "cognitoAuthenticationType": null,
      "cognitoAuthenticationProvider": null,
      "userArn": null,
      "userAgent": "Custom User Agent String",
      "user": null
    },
    "path": "/prod/searchAllData",
    "resourcePath": "/{proxy+}",
    "httpMethod": "GET",
    "apiId": "1234567890",
    "protocol": "HTTP/1.1"
  }
}

Error:

s.exceptions.ContainerInitializationException: Could not initialize framework within the 20000ms timeout
    at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:207)
    at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:254)
    at com.example.awstest.handler.AWSLambdaHandler.handleRequest(AWSLambdaHandler.java:36)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:379)
    at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:903)
    at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:238)
    at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190)
    at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:185)
    04:36:48.470 [main] ERROR com.amazonaws.serverless.proxy.AwsProxyExceptionHandler -- Called exception handler for:
    com.amazonaws.serverless.exceptions.ContainerInitializationException: Could not initialize framework within the 20000ms timeout
    at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:207)
    at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:254)
    at com.example.awstest.handler.AWSLambdaHandler.handleRequest(AWSLambdaHandler.java:36)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:379)
    at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:903)
    at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:238)
    at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190)
    at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:185)
    com.amazonaws.serverless.exceptions.ContainerInitializationException: Could not initialize framework within the 20000ms timeout
    at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxy(LambdaContainerHandler.java:207)
    at com.amazonaws.serverless.proxy.internal.LambdaContainerHandler.proxyStream(LambdaContainerHandler.java:254)
    at com.example.awstest.handler.AWSLambdaHandler.handleRequest(AWSLambdaHandler.java:36)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:379)
    at com.amazonaws.services.lambda.runtime.api.client.EventHandlerLoader$2.call(EventHandlerLoader.java:903)
    at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:238)
    at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.startRuntime(AWSLambda.java:190)
    at com.amazonaws.services.lambda.runtime.api.client.AWSLambda.main(AWSLambda.java:185)
    END RequestId: 21464e19-8dee-47e0-9acd-5ae04d24431a
    REPORT RequestId: 21464e19-8dee-47e0-9acd-5ae04d24431a  Duration: 20003.03 ms   Billed Duration: 20004 ms   Memory Size: 512 MB Max Memory Used: 137 MB
5
  • When you test your function from the console you need to provide an event that looks like an API Gateway (or function URL) event (Create new event -> Template apigateway-aws-proxy), but you also need to point to a path that your application recognizes! (so if you test through the console, replace all the /path/to/resource in that default event with your path, like /searchAllData) The same thing happens if you use the fURL link, you need to pass a location that your app knows about, so you need to add /searchAllData too. Commented Jun 29, 2023 at 20:54
  • Hi @Renato I have a doubt. Is this not due to some kind of startup method not initialized in code or something? Is this not due to my spring boot application takes more time to start in lambda in the startup? I just tried testing event with apigateway-aws-proxy, changed to GET and /searchAllData instead /path/to/resource, but i got the same error (NoSuchMethod) i mentioned in my query above. Commented Jun 29, 2023 at 21:20
  • It could be because of another reason, I just wanted to mention how you need to test it. The error seems like it's missing a Spring dependency somehow, so I don't know if there's an issue in your build process. I'm not really familiar with Gradle, so I wouldn't be able to tell if the problem's there. And on another note and maybe not related, but did you try increasing the function's timeout? That causes issues sometimes. Commented Jun 29, 2023 at 23:22
  • Okay, thanks! I increased max 15 mins but still i get this error in around 8 secs. Commented Jun 29, 2023 at 23:31
  • I have updated my actual question above. I fixed version issue. But, I get some other error when testing in Lambda console. I updated my question. Commented Jun 30, 2023 at 2:07

1 Answer 1

4
+50

Looking at your Gradle file you are using a very old outdated AWS Serverless Java Container version that is not compatible with Spring Boot 3.x.

Remove com.amazonaws.serverless:aws-serverless-java-container-spring:1.5.2 and replace it with com.amazonaws.serverless:aws-serverless-java-container-springboot3:2.0.0-M1. You'll also find a fully working sample in https://github.com/awslabs/aws-serverless-java-container/tree/main/samples/springboot3/pet-store for comparison.

If you come across similar timeout challenges in the future, you can also enable AWS X-Ray or OpenTelemetry to gather tracing data and see where time is lost.

Sign up to request clarification or add additional context in comments.

14 Comments

Yes, thank you. That was the issue. After i changed to com.amazonaws.serverless:aws-serverless-java-container-springboot3:2.0.0-M1 and tested it is giving me 200 response with the response data. Though the error code earlier was showing 'gateway timeout', internally it was logging with 'classnotfound exception', but now it's working well. Could you pls tell me, how to make it as end point to include in my friend end ReactJS app? This is just for testing, so looking for not a big method to do, just simple to test as end point.
For testing a Lambda function URL is probably the easiest way: docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html The pet-store sample template contains an Amazon API-Gateway configuration which is also a very common way to provide an HTTPS endpoint.
Hello Sir, I created a function url. When I use it in browser like this, it throws “internal server error” in the browser.<function url>/searchAllData
Can you please check the logs for a more specific error message? It may be related to the payload version (you need to use the corresponding handler implementation for 1.0/ 2.0).
What i did was, 1.) Clicked on "Create Function URL", 2.) Chose "Auth Type - None", 3.) In "Addtional Settings -> "Buffered (default)" enabled, checked "configure CORS , 4.) Save. That's all I did. It created a Function URL. When I clicked on that URL, launched browser and thrown "Internal Server Error", log shows "failed to load resource: status of 502"
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.