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

Issues with ScheduledEvent in lambdas using java 17 #1033

Closed
wsoderlu opened this issue May 9, 2023 · 11 comments
Closed

Issues with ScheduledEvent in lambdas using java 17 #1033

wsoderlu opened this issue May 9, 2023 · 11 comments
Assignees
Milestone

Comments

@wsoderlu
Copy link

wsoderlu commented May 9, 2023

Describe the bug
Since upgrading org.springframework.cloud:spring-cloud-dependencies from 2021.0.6 -> 2021.0.7 we started facing issues with lambda executions utilizing ScheduledEvent from cloudwatch events.

For now we've fixed this by downgrading to 2021.0.6 version which seems to do the trick.

Error:
java.lang.ClassCastException: class [B cannot be cast to class com.amazonaws.services.lambda.runtime.events.ScheduledEvent ([B is in module java.base of loader 'bootstrap'; com.amazonaws.services.lambda.runtime.events.ScheduledEvent is in unnamed module of loader 'app')

Sample
Create lambda using provided java 17 runtime and trigger it through scheduled cloudwatch events using ScheduledEvent from com.amazonaws.services.lambda.runtime.events.ScheduledEvent.
Manual invocations from lambda console still works.

@olegz olegz added the AWS label May 24, 2023
@maximevdk-tidal
Copy link

I'm experiencing the same issue after upgrading to 2022.0.2 consuming a DynamodbEvent.

java.lang.ClassCastException: class [B cannot be cast to class 
com.amazonaws.services.lambda.runtime.events.DynamodbEvent ([B is in module java.base of loader 'bootstrap'; 
com.amazonaws.services.lambda.runtime.events.DynamodbEvent is in unnamed module of loader 
com.amazonaws.services.lambda.runtime.api.client.CustomerClassLoader @6e8cf4c6)

Downgrading back to version 2021.0.6 solves the issue.

@olegz
Copy link
Contributor

olegz commented May 24, 2023

I can't seem to reproduce it, so need some help.
I'll admit I have never worked with events and while I was able to configure one that invokes function i stil can't seem to figure out how to produce an input., Any help?
Anyway, here is my log



2023-05-24T13:32:17.603+02:00 | 2023-05-24 11:32:17.603 INFO 8 --- [ main] o.s.c.f.adapter.aws.AWSLambdaUtils : Received: {"version":"0","id":"1e15fb3f-2769-6091-b3e5-f99009c94886","detail-type":"Scheduled Event","source":"aws.events","account":"313369169943","time":"2023-05-24T11:31:46Z","region":"eu-west-3","resources":["arn:aws:events:eu-west-3:313369169943:rule/myRule"],"detail":{}}
-- | --
  | 2023-05-24T13:32:17.603+02:00 | 2023-05-24 11:32:17.603 DEBUG 8 --- [ main] c.f.c.c.BeanFactoryAwareFunctionRegistry : Invoking function uppercase<class java.lang.String, class java.lang.String>
  | 2023-05-24T13:32:17.604+02:00 | 2023-05-24 11:32:17.603 DEBUG 8 --- [ main] c.f.c.c.BeanFactoryAwareFunctionRegistry : Converted Message: GenericMessage [payload=byte[267], headers={aws-context=lambdainternal.api.LambdaContext@6f43c82, id=435dd55b-a563-492b-0ff0-43dbdd14cc69, timestamp=1684927937603}] to: class java.lang.String
  | 2023-05-24T13:32:17.604+02:00 | 2023-05-24 11:32:17.604 DEBUG 8 --- [ main] c.f.c.c.BeanFactoryAwareFunctionRegistry : Invoking function: uppercase<class java.lang.String, class java.lang.String>with input type: class java.lang.String
  | 2023-05-24T13:32:17.604+02:00 | 2023-05-24 11:32:17.604 DEBUG 8 --- [ main] o.s.cloud.function.json.JsonMapper : String already represents JSON. Skipping conversion in favor of 'getBytes(StandardCharsets.UTF_8'.
  | 2023-05-24T13:32:17.605+02:00 | END RequestId: 350a7699-023c-47af-8072-a4272c86ece7
  | 2023-05-24T13:32:17.605+02:00 | REPORT RequestId: 350a7699-023c-47af-8072-a4272c86ece7 Duration: 2.49 ms Billed Duration: 3 ms Memory Size: 512 MB Max Memory Used: 136 MB


2023-05-24T13:32:17.603+02:00 | 2023-05-24 11:32:17.603 INFO 8 --- [ main] o.s.c.f.adapter.aws.AWSLambdaUtils : Received: {"version":"0","id":"1e15fb3f-2769-6091-b3e5-f99009c94886","detail-type":"Scheduled Event","source":"aws.events","account":"313369169943","time":"2023-05-24T11:31:46Z","region":"eu-west-3","resources":["arn:aws:events:eu-west-3:313369169943:rule/myRule"],"detail":{}}
-- | --
  | 2023-05-24T13:32:17.603+02:00 | 2023-05-24 11:32:17.603 DEBUG 8 --- [ main] c.f.c.c.BeanFactoryAwareFunctionRegistry : Invoking function uppercase<class java.lang.String, class java.lang.String>
  | 2023-05-24T13:32:17.604+02:00 | 2023-05-24 11:32:17.603 DEBUG 8 --- [ main] c.f.c.c.BeanFactoryAwareFunctionRegistry : Converted Message: GenericMessage [payload=byte[267], headers={aws-context=lambdainternal.api.LambdaContext@6f43c82, id=435dd55b-a563-492b-0ff0-43dbdd14cc69, timestamp=1684927937603}] to: class java.lang.String
  | 2023-05-24T13:32:17.604+02:00 | 2023-05-24 11:32:17.604 DEBUG 8 --- [ main] c.f.c.c.BeanFactoryAwareFunctionRegistry : Invoking function: uppercase<class java.lang.String, class java.lang.String>with input type: class java.lang.String
  | 2023-05-24T13:32:17.604+02:00 | 2023-05-24 11:32:17.604 DEBUG 8 --- [ main] o.s.cloud.function.json.JsonMapper : String already represents JSON. Skipping conversion in favor of 'getBytes(StandardCharsets.UTF_8'.
  | 2023-05-24T13:32:17.605+02:00 | END RequestId: 350a7699-023c-47af-8072-a4272c86ece7
  | 2023-05-24T13:32:17.605+02:00 | REPORT RequestId: 350a7699-023c-47af-8072-a4272c86ece7 Duration: 2.49 ms Billed Duration: 3 ms Memory Size: 512 MB Max Memory Used: 136 MB



2023-05-24T13:32:17.603+02:00 | 2023-05-24 11:32:17.603 INFO 8 --- [ main] o.s.c.f.adapter.aws.AWSLambdaUtils : Received: {"version":"0","id":"1e15fb3f-2769-6091-b3e5-f99009c94886","detail-type":"Scheduled Event","source":"aws.events","account":"313369169943","time":"2023-05-24T11:31:46Z","region":"eu-west-3","resources":["arn:aws:events:eu-west-3:313369169943:rule/myRule"],"detail":{}}
-- | --
  | 2023-05-24T13:32:17.603+02:00 | 2023-05-24 11:32:17.603 DEBUG 8 --- [ main] c.f.c.c.BeanFactoryAwareFunctionRegistry : Invoking function uppercase<class java.lang.String, class java.lang.String>
  | 2023-05-24T13:32:17.604+02:00 | 2023-05-24 11:32:17.603 DEBUG 8 --- [ main] c.f.c.c.BeanFactoryAwareFunctionRegistry : Converted Message: GenericMessage [payload=byte[267], headers={aws-context=lambdainternal.api.LambdaContext@6f43c82, id=435dd55b-a563-492b-0ff0-43dbdd14cc69, timestamp=1684927937603}] to: class java.lang.String
  | 2023-05-24T13:32:17.604+02:00 | 2023-05-24 11:32:17.604 DEBUG 8 --- [ main] c.f.c.c.BeanFactoryAwareFunctionRegistry : Invoking function: uppercase<class java.lang.String, class java.lang.String>with input type: class java.lang.String
  | 2023-05-24T13:32:17.604+02:00 | 2023-05-24 11:32:17.604 DEBUG 8 --- [ main] o.s.cloud.function.json.JsonMapper : String already represents JSON. Skipping conversion in favor of 'getBytes(StandardCharsets.UTF_8'.
  | 2023-05-24T13:32:17.605+02:00 | END RequestId: 350a7699-023c-47af-8072-a4272c86ece7
  | 2023-05-24T13:32:17.605+02:00 | REPORT RequestId: 350a7699-023c-47af-8072-a4272c86ece7 Duration: 2.49 ms Billed Duration: 3 ms Memory Size: 512 MB Max Memory Used: 136 MB


@olegz
Copy link
Contributor

olegz commented May 24, 2023

Also, I am noticing that you are using old version of spring* Since you are using Java 17, you should be 2022.0.2

@olegz
Copy link
Contributor

olegz commented May 24, 2023

In any event i need detailed instructions on how to reproduce otherwise there is nothing to fix

@maximevdk-tidal
Copy link

I'm experiencing it with 2022.0.2.

Sample
pom.xml (partially)

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.0</version> <!-- lookup parent from repository -->
    </parent>

<properties>
        <!-- General properties -->
        <java.version>17</java.version>

        <!-- Spring -->
        <spring-cloud.version>2022.0.2</spring-cloud.version>

        <!-- AWS -->
        <aws-lambda.version>1.2.2</aws-lambda.version>
        <amazon-sdk.version>2.17.272</amazon-sdk.version>
        <spring-cloud-aws.version>3.0.1</spring-cloud-aws.version>
        <aws-lambda-java-events.version>3.11.2</aws-lambda-java-events.version>
</properties>

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-function-adapter-aws</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-function-context</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-function-core</artifactId>
        </dependency>

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-core</artifactId>
            <version>${aws-lambda.version}</version>
        </dependency>

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-events</artifactId>
            <version>${aws-lambda-java-events.version}</version>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

The Event consumer

@SpringBootApplication
public class DynamodbEventConsumer {

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

    @Bean
    public Consumer<DynamodbEvent> consume() {
        return event -> event.getRecords()
                .forEach(this::logRecord);
    }

    private void logRecord(DynamodbEvent.DynamodbStreamRecord record) {
        System.out.println(record);
    }
}

application.yml

spring:
  main:
    banner-mode: off

  profiles:
    include: aws

  cloud:
    function:
      definition: consume

Running the app:

mvn clean package

unzip -o -q -d ./target/docker ./target/lambda.jar

docker run --rm \
-e MAIN_CLASS=com.example.DynamodbEventConsumer \
-v "/${PWD}/target/docker":/var/task \
public.ecr.aws/shogo82148/lambda-java:17 \
org.springframework.cloud.function.adapter.aws.FunctionInvoker \
'... ddb event ...'

results in:

{"errorType":"java.lang.ClassCastException","errorMessage":"class [B cannot be cast to class com.amazonaws.services.lambda.runtime.events.DynamodbEvent ([B is in module java.base of loader 'bootstrap'; com.amazonaws.services.lambda.runtime.events.DynamodbEvent is in unnamed module of loader com.amazonaws.services.lambda.runtime.api.client.CustomerClassLoader @7cc355be)","stackTrace":["org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.invokeConsumer(SimpleFunctionRegistry.java:990)","org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.doApply(SimpleFunctionRegistry.java:701)","org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.apply(SimpleFunctionRegistry.java:550)","org.springframework.cloud.function.adapter.aws.FunctionInvoker.handleRequest(FunctionInvoker.java:85)"]}

It works when downgrading to spring-cloud version 2021.0.6 as @wsoderlu suggests.

@olegz
Copy link
Contributor

olegz commented May 24, 2023

Could you push the whole sample project to the GitHib or attach in the Zip file?

@olegz
Copy link
Contributor

olegz commented May 24, 2023

. . . or at least paste a JSON representing DynamodbEvent

@olegz
Copy link
Contributor

olegz commented May 24, 2023

I used the event from https://github.com/aws/aws-lambda-go/blob/main/events/testdata/dynamodb-event.json and still can't reproduce so, please push a sample project to GitHub

@maximevdk-tidal
Copy link

maximevdk-tidal commented May 24, 2023

This event also works for me. The only difference with the event in your example and mine is the ApproximateCreationDateTime field. I get it in the style of 1.684934517E9.
When you change one of the fields in your example event to 1.684934517E9 it fails.

Defining an ObjectMapper bean with the following module fixes the mapping issue for me:

return new ObjectMapper()
            .registerModule(new SimpleModule().addDeserializer(Date.class, new JsonDeserializer<>() {
                @Override
                public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(jsonParser.getValueAsLong());
                    return calendar.getTime();
                }
            }));

Maybe this module was registered somewhere before when in more recent versions (after 2021.0.6) its not?

@olegz
Copy link
Contributor

olegz commented May 24, 2023

ahha, that helps

@olegz olegz self-assigned this May 24, 2023
@olegz olegz added the bug label May 24, 2023
@olegz olegz added this to the 4.0.3 milestone May 24, 2023
@olegz olegz closed this as completed in 22bc928 May 24, 2023
@olegz
Copy link
Contributor

olegz commented May 24, 2023

Fixed and the best part is that we're in the middle of the release so 4.0.3 will be available today/tomorrow ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants