aws / serverless-java-container

A Java wrapper to run Spring, Spring Boot, Jersey, and other apps inside AWS Lambda.
https://aws.amazon.com/serverless/
Apache License 2.0
1.49k stars 551 forks source link

Whenever spring-boot-starter-data-jpa is included, java.lang.NumberFormatException: For input string: "-2147483648,-2147483648" #332

Open yubinchen18 opened 4 years ago

yubinchen18 commented 4 years ago

Springboot 2.1.3 Runs fine locally, even using AWS Toolkit with SAM, it runs fine locally in docker. But the moment I push to AWS Lambda, i get this! Help!!!

Now I'm not 100% sure if this the aws-serverless-java-container is the cause of this, but it seems to me that this is the only factor that can explain the difference in results between running locally and on aws lambda.

Error loading class com.api.locations.Handler: java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
Caused by: java.lang.NumberFormatException: For input string: "-2147483648,-2147483648"
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:580)
    at java.lang.Integer.valueOf(Integer.java:766)
    at org.springframework.boot.autoconfigure.AutoConfigurationMetadataLoader$PropertiesAutoConfigurationMetadata.getInteger(AutoConfigurationMetadataLoader.java:92)
    at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.getOrder(AutoConfigurationSorter.java:211)
    at org.springframework.boot.autoconfigure.AutoConfigurationSorter$AutoConfigurationClass.access$000(AutoConfigurationSorter.java:155)
    at org.springframework.boot.autoconfigure.AutoConfigurationSorter.lambda$getInPriorityOrder$0(AutoConfigurationSorter.java:62)
    at java.util.TimSort.countRunAndMakeAscending(TimSort.java:360)
    at java.util.TimSort.sort(TimSort.java:234)
    at java.util.Arrays.sort(Arrays.java:1512)
    at java.util.ArrayList.sort(ArrayList.java:1462)
    at org.springframework.boot.autoconfigure.AutoConfigurationSorter.getInPriorityOrder(AutoConfigurationSorter.java:61)
    at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.sortAutoConfigurations(AutoConfigurationImportSelector.java:461)
    at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.selectImports(AutoConfigurationImportSelector.java:442)
    at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:881)
    at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:804)
    at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:774)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:185)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:315)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
    at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.initialize(SpringBootLambdaContainerHandler.java:160)
    at com.amazonaws.serverless.proxy.InitializationWrapper.start(InitializationWrapper.java:23)
    at com.amazonaws.serverless.proxy.spring.SpringBootProxyHandlerBuilder.buildAndInitialize(SpringBootProxyHandlerBuilder.java:59)
    at com.amazonaws.serverless.proxy.spring.SpringBootLambdaContainerHandler.getAwsProxyHandler(SpringBootLambdaContainerHandler.java:79)
    at com.api.locations.Handler.<clinit>(Handler.kt:187)
    ... 2 more
sapessi commented 4 years ago

@yubinchen18 any chance you can share some code we can use to try and replicate?

yubinchen18 commented 4 years ago

This is part of the build.gradle. Basically the moment I uncomment the last line

compile ("org.springframework.boot:spring-boot-starter-data-jpa") , everything would still work locally. but the moment we push to Aws Lambda we get the above mentioned error. The most basic things such as datasource is set. Maybe for you guys to reproduce just start with new spring boot project and include spring-boot-starter-data-jpa and see if it works?

Actually the same happens when I include

// Batch with csv compile 'org.springframework.boot:spring-boot-starter-batch'

I'm honestly not sure if this is because these packages have conflict with our chosen custom dependencies, but why would it work locally and not on AWS?

apply plugin: 'org.sonarqube'
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'kotlin'
apply plugin: 'jacoco'
apply plugin: 'org.springframework.boot'

buildscript {
    ext {
        kotlinVersion = '1.3.50'
        springBootVersion = '2.1.3.RELEASE'
        shadowVersion = '2.0.4' // Keep it to version 2.0.4 as this works on CI, lower/ higher (thus) other versions don't
        springCloudStarterVersion = '2.0.1.RELEASE'
        jacksonVersion = '2.9.5'
        gradleCheckVersion = "3.2.1"
        sonarscannerVersion = '2.6.2'
        okHttpVersion = '3.14.0'
        sentryVersion = '1.7.22'
        lamdaLoggingVersion = '1.0.3'
        lambaSpringContainerVersion = '1.4'
        jUnitVersion = '4.12'
        kotlinTestVersion = '1.3.5'
        springDependencyManagementVersion = '1.0.3.RELEASE'
        retrofitVersion = '2.4.0'
        retrofitInterceptorVersion = '3.14.1'
        thymeleafVersion = '3.0.11.RELEASE'
        thymeleafDialectVersion = '2.4.1'
        springContextSupportVersion = '5.1.7.RELEASE'
        springBootMailerVersion = '2.1.5.RELEASE'
        sesSdkVersion = '1.11.568'
        mailApiVersion = '1.6.2'
        thymeleafJodaDialectVersion = '2.0.0'
        stripeVersion = '12.0.0'
        hibernateVersion = '5.4.0.Final'
        hibernateValidatorVersion = '6.0.16.Final'
        mySqlJdbcVersion = '8.0.15'
        c3p0Version = '0.9.5.4'
    }

    repositories {
        jcenter()
        mavenCentral()
        mavenLocal()
        maven { setUrl("https://plugins.gradle.org/m2/") }
    }

    dependencies {
        /**
         * Kotlin library
         *
         * @link https://kotlinlang.org/docs/reference/compiler-plugins.html#all-open-compiler-plugin
         */
        classpath ("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
        classpath ("org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion")
        classpath ("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
        classpath ("org.jetbrains.kotlin:kotlin-noarg:$kotlinVersion")

        // Spring - gradle plugin
        classpath ("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")

        // Spring - dependency management plugin
        classpath ("io.spring.gradle:dependency-management-plugin:$springDependencyManagementVersion")

        // Shaded JAR
        classpath ("com.github.jengelman.gradle.plugins:shadow:${shadowVersion}")

        // Sonar - scanner
        classpath ("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:$sonarscannerVersion")
    }
}

group = 'com'
version = '0.0.1-SNAPSHOT'

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

allprojects {
    apply plugin: 'idea'
    apply plugin: 'kotlin'
    apply plugin: 'kotlin-spring' // instead of "kotlin-allopen"
    apply plugin: 'kotlinx-serialization'
    apply plugin: 'kotlin-noarg'
    apply plugin: "kotlin-jpa"
    apply plugin: 'io.spring.dependency-management'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'com.github.johnrengelman.shadow'
    apply plugin: 'jacoco'

    group = 'com'
    version = '0.0.1-SNAPSHOT'

    tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
    }

    sourceCompatibility = 1.8
    targetCompatibility = 1.8

    repositories {
        jcenter()
        mavenLocal()
        mavenCentral()
        maven { url 'https://dl.bintray.com/konrad-kaminski/maven' }
        maven { setUrl('https://plugins.gradle.org/m2/') }
    }

    dependencyManagement {
        imports {
            mavenBom 'com.amazonaws:aws-java-sdk-bom:1.11.394'
        }
    }
    dependencyManagement {
        imports {
            mavenBom("org.springframework.boot:spring-boot-dependencies:${springBootVersion}")
            mavenBom("com.amazonaws:aws-java-sdk-bom:$sesSdkVersion")
        }
    }

    springBoot { mainClassName = "com.api.${project.name}.Driver" }

    dependencies {
        // Spring Starter - Locally running the functions for local development - excluded from deploy-able jar
        compile ("org.springframework.boot:spring-boot-starter-web") {
            // exclude Tomcat web server, this project will use Jetty web server
            exclude module: "spring-boot-starter-tomcat"
        }

        // Spring - Jetty - Web server, provisions project with Jetty web server instead of (default) Tomcat web server,
        // for local development - excluded from deploy-able jar
        compile ("org.springframework.boot:spring-boot-starter-jetty")

        // Spring boot - dev tools - allows hot swapping - excluded from deploy-able jar
        compile ("org.springframework.boot:spring-boot-devtools")

        // Kotlin - Library
        compile ("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
        compile ("org.jetbrains.kotlin:kotlin-reflect")

        // Jackson - JSON Serialization / Deserialization
        compile ("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion")
        compile ("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion")
        compile ("joda-time:joda-time")
//        compile ("org.jadira.usertype:usertype.core:3.1.0.CR1")
        compile ("com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.2.1")
        compile ("com.fasterxml.jackson.datatype:jackson-datatype-joda")

        // Spring test - test framework
        testCompile ("org.springframework.boot:spring-boot-starter-test")
        testCompile ("junit:junit:$jUnitVersion")
        testCompile ("io.kotlintest:kotlintest:$kotlinTestVersion")

        // AWS - provision the Spring Boot application with the AWS lambda container so it can run as an AWS lambda Function

        // Lambda-logging - AWS logging
        compile ("io.symphonia:lambda-logging:$lamdaLoggingVersion")

        // Lambda - Java container for Spring
        compile ("com.amazonaws.serverless:aws-serverless-java-container-springboot2:$lambaSpringContainerVersion")

        // OkHttp - Http client
        compile ("com.squareup.okhttp3:okhttp:$okHttpVersion")

        // Sentry.io - Error monitoring
        compile ("io.sentry:sentry-spring:$sentryVersion")

        // Retrofit - HTTP client
        compile ("com.squareup.retrofit2:retrofit:${retrofitVersion}")
        compile ("com.squareup.retrofit2:converter-gson:${retrofitVersion}")
        compile ("com.squareup.okhttp3:logging-interceptor:${retrofitInterceptorVersion}")

        // JSlack - Slack Message sender
        compile group: 'com.github.seratch', name: 'jslack', version: '1.5.4'

        // Javax Mail - Mail sender
        compile ("javax.mail:javax.mail-api:$mailApiVersion")
        compile ("com.sun.mail:javax.mail:$mailApiVersion")

        // AWS - SES - SDK Mail service
        compile ("com.amazonaws:aws-java-sdk-ses:$sesSdkVersion")

        // AWS - SDK - For S3
        compile('com.amazonaws:aws-java-sdk-s3')

        // Thymeleaf - HTML templating
        compile ("org.thymeleaf:thymeleaf-spring5:$thymeleafVersion")
        compile ("org.thymeleaf:thymeleaf:$thymeleafVersion")
        compile ("nz.net.ultraq.thymeleaf:thymeleaf-joda-dialect:$thymeleafJodaDialectVersion")

        // Coroutines Retrofit - Concurrent API calls
        compile 'ru.gildor.coroutines:kotlin-coroutines-retrofit:1.1.0'

        // Stripe
        compile ("com.stripe:stripe-java:$stripeVersion")

        // Spring boot starter jpa with hibernate generate entity tables for development
//        compile ("org.springframework.boot:spring-boot-starter-data-jpa")

Here's our handler which is written in Kotlin

@RestController
class Handler : RequestStreamHandler {

    companion object {
        private val logger = LoggerFactory.getLogger(this::class.java1)
        private var handler: SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse>? = null

        init {
            try {
                handler =
                    SpringBootLambdaContainerHandler.getAwsProxyHandler(LocationsDriver::class.java1)
            } catch (e: ContainerInitializationException) {

                e.printStackTrace()
                logger.error(e.message)

                // Re-throw exception to force a cold start
                throw RuntimeException("Could not initialize Spring Boot application", e)
            }
        }
    }

    @Throws(IOException::class)
    override fun handleRequest(inputStream: InputStream, outputStream: OutputStream, context: Context) {

        try {
            handler!!.proxyStream(inputStream, outputStream, context)
        } catch (e: ContainerInitializationException) {
            e.printStackTrace()
            logger.error(e.message)
        } finally {
            outputStream.close()
        }
    }
}
sapessi commented 4 years ago

Looking through the exception, it seems that one of the configuration classes spring is trying to load sets its priority value to that string, which is clearly not a valid number. I'll try to replicate and let you know here.

yubinchen18 commented 4 years ago

Hi, any update on this issue maybe? :) as we really want to use the recommended spring-boot-starter-data-jpa to handle database persistence instead of using customized packages for the production....

because in order to bypass this error, currently we resort to compiling the 'child packages' seperately in order to make it work. and we are facing lot's of database connection and connection pooling problems with this approach due to many configuration problems with the said packages:

        // Spring data jpa with hibernate generate entity tables for development - excluded from deploy-able jar
        compile ("org.springframework.data:spring-data-jpa")
        // Hibernate - ORM
        compile "org.hibernate:hibernate-core:$hibernateVersion"
        compile "org.hibernate:hibernate-entitymanager:$hibernateVersion"
        // Hibernate - ORM test library
        testCompile "org.hibernate:hibernate-testing:$hibernateVersion"
        // Hibernate-c3p0 - Integration of c3p0 in Hibernate
        compile "org.hibernate:hibernate-c3p0:5.4.2.Final"
        // c3p0 - Hibernate connection pool manager
        compile "com.mchange:c3p0:$c3p0Version"
        // MySQL - JDBC Driver
        compile "mysql:mysql-connector-java:$mySqlJdbcVersion"
        // @Entity annotation
        compile group: 'javax.persistence', name: 'javax.persistence-api', version: '2.2'
        // DataSourceBuilder
        compile group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'