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

InternalConfig throws exception in runtime with native application #3035

Closed
fethiyildiz opened this issue Oct 15, 2023 · 2 comments
Closed
Labels
bug This issue is a bug. needs-triage This issue or PR still needs to be triaged.

Comments

@fethiyildiz
Copy link

fethiyildiz commented Oct 15, 2023

Describe the bug

Hello,

I use Spring Native for my application. I use AWS S3 Sdk for my S3 related operations.

I can build and run my application with normal maven build.

When it comes to native application, i can build my application successfully but when i run my application aws-java-sdk-core throws exception because it cannot load awssdk_config_default.json file.

image

I don't know why this is happening with native application.

Thank you 🧡

Expected Behavior

I expect to not throwing any exception when i run my application with native build.

Just like old fashion java jar application.

Current Behavior

Currently, InternalConfig throws exception during run time.

You can see stack trace of exception that throw during runtime (last part is the most important);

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testController': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 's3Client': Instantiation of supplied bean failed
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:317) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArguments(BeanInstanceSupplier.java:260) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:200) ~[na:na]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:947) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1214) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1158) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973) ~[awsnativedemo:6.0.12]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:942) ~[awsnativedemo:6.0.12]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) ~[awsnativedemo:6.0.12]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[awsnativedemo:3.1.4]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) ~[awsnativedemo:3.1.4]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[awsnativedemo:3.1.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[awsnativedemo:3.1.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) ~[awsnativedemo:3.1.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) ~[awsnativedemo:3.1.4]
        at com.example.awsnativedemo.AwsNativeDemoApplicationKt.main(AwsNativeDemoApplication.kt:15) ~[awsnativedemo:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 's3Client': Instantiation of supplied bean failed
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1220) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1158) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:560) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1417) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:910) ~[na:na]
        at org.springframework.beans.factory.support.RegisteredBean.resolveAutowiredArgument(RegisteredBean.java:229) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:314) ~[na:na]
        ... 21 common frames omitted
Caused by: java.lang.ExceptionInInitializerError: null
        at com.amazonaws.util.VersionInfoUtils.userAgent(VersionInfoUtils.java:142) ~[na:na]
        at com.amazonaws.util.VersionInfoUtils.initializeUserAgent(VersionInfoUtils.java:137) ~[na:na]
        at com.amazonaws.util.VersionInfoUtils.getUserAgent(VersionInfoUtils.java:100) ~[na:na]
        at com.amazonaws.internal.EC2ResourceFetcher.<clinit>(EC2ResourceFetcher.java:44) ~[awsnativedemo:na]
        at java.base@20.0.2/java.lang.Class.ensureInitialized(DynamicHub.java:579) ~[awsnativedemo:na]
        at com.amazonaws.auth.InstanceMetadataServiceCredentialsFetcher.<init>(InstanceMetadataServiceCredentialsFetcher.java:37) ~[na:na]
        at com.amazonaws.auth.InstanceProfileCredentialsProvider.<init>(InstanceProfileCredentialsProvider.java:111) ~[na:na]
        at com.amazonaws.auth.InstanceProfileCredentialsProvider.<init>(InstanceProfileCredentialsProvider.java:91) ~[na:na]
        at com.amazonaws.auth.InstanceProfileCredentialsProvider.<init>(InstanceProfileCredentialsProvider.java:75) ~[na:na]
        at com.amazonaws.auth.InstanceProfileCredentialsProvider.<clinit>(InstanceProfileCredentialsProvider.java:58) ~[na:na]
        at com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper.initializeProvider(EC2ContainerCredentialsProviderWrapper.java:64) ~[na:na]
        at com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper.<init>(EC2ContainerCredentialsProviderWrapper.java:53) ~[na:na]
        at com.amazonaws.auth.DefaultAWSCredentialsProviderChain.<init>(DefaultAWSCredentialsProviderChain.java:49) ~[awsnativedemo:na]
        at com.amazonaws.auth.DefaultAWSCredentialsProviderChain.<clinit>(DefaultAWSCredentialsProviderChain.java:43) ~[awsnativedemo:na]
        at java.base@20.0.2/java.lang.Class.ensureInitialized(DynamicHub.java:579) ~[awsnativedemo:na]
        at com.amazonaws.services.s3.AmazonS3ClientBuilder.standard(AmazonS3ClientBuilder.java:46) ~[awsnativedemo:na]
        at com.example.awsnativedemo.S3ClientConfig.s3Client(S3ClientConfig.kt:19) ~[awsnativedemo:na]
        at com.example.awsnativedemo.S3ClientConfig$$SpringCGLIB$$0.CGLIB$s3Client$0(<generated>) ~[awsnativedemo:na]
        at com.example.awsnativedemo.S3ClientConfig$$SpringCGLIB$$2.invoke(<generated>) ~[awsnativedemo:na]
        at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258) ~[awsnativedemo:6.0.12]
        at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) ~[na:na]
        at com.example.awsnativedemo.S3ClientConfig$$SpringCGLIB$$0.s3Client(<generated>) ~[awsnativedemo:na]
        at com.example.awsnativedemo.S3ClientConfig__BeanDefinitions.lambda$getSClientInstanceSupplier$1(S3ClientConfig__BeanDefinitions.java:37) ~[na:na]
        at org.springframework.util.function.ThrowingFunction.apply(ThrowingFunction.java:63) ~[awsnativedemo:6.0.12]
        at org.springframework.util.function.ThrowingFunction.apply(ThrowingFunction.java:51) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.lambda$withGenerator$0(BeanInstanceSupplier.java:167) ~[na:na]
        at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:68) ~[awsnativedemo:6.0.12]
        at org.springframework.util.function.ThrowingBiFunction.apply(ThrowingBiFunction.java:54) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.lambda$get$2(BeanInstanceSupplier.java:202) ~[na:na]
        at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58) ~[awsnativedemo:6.0.12]
        at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.invokeBeanSupplier(BeanInstanceSupplier.java:214) ~[na:na]
        at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:202) ~[na:na]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.obtainInstanceFromSupplier(DefaultListableBeanFactory.java:947) ~[awsnativedemo:6.0.12]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1214) ~[awsnativedemo:6.0.12]
        ... 34 common frames omitted
Caused by: java.lang.IllegalArgumentException: null
        at com.amazonaws.internal.config.InternalConfig.loadfrom(InternalConfig.java:260) ~[na:na]
        at com.amazonaws.internal.config.InternalConfig.load(InternalConfig.java:274) ~[na:na]
        at com.amazonaws.internal.config.InternalConfig$Factory.<clinit>(InternalConfig.java:347) ~[na:na]
        ... 69 common frames omitted

Reproduction Steps

I created a sample repo to reproduce the issue.

You can see from below link;

https://github.com/fethiyildiz/awsnativedemo

I use below command to create native application;

./mvnw native:compile -Pnative -DskipTests

And to run the application;

./target/awsnativedemo

But in a shortest version, below snippet is the cause of issue.

@Configuration
class S3ClientConfig(private val awsCredentials: AwsCredentials) {

    @Bean
    fun s3Client(): AmazonS3 {
        val basicCredentials = BasicAWSCredentials(awsCredentials.accessKey, awsCredentials.secretKey)
        val credentialsProvider = AWSStaticCredentialsProvider(basicCredentials)

        return AmazonS3ClientBuilder.standard()
            .withCredentials(credentialsProvider)
            .withRegion(Regions.EU_CENTRAL_1)
            .build()
    }
}

Possible Solution

No response

Additional Information/Context

I don't know am i missing something but just in case i also added 2 Dockerfile to make easy to test for you

One with old fashion jar application and the other one is native.

You can see from repo.

Dockerfile => native
Dockerfile_basic => jar

Also i put placeholders for access and secret keys. You can see from application.yaml file.

AWS Java SDK version used

1.12.566

JDK version used

java version "20.0.2" 2023-07-18 Java(TM) SE Runtime Environment Oracle GraalVM 20.0.2+9.1 (build 20.0.2+9-jvmci-23.0-b14) Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 20.0.2+9.1 (build 20.0.2+9-jvmci-23.0-b14, mixed mode, sharing)

Operating System and version

macOS Ventura 13.3.1

@fethiyildiz fethiyildiz added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Oct 15, 2023
@fethiyildiz fethiyildiz changed the title InternalConfig throws exception in runtime during loading awssdk_config_default.json file InternalConfig throws exception in runtime with native application Oct 15, 2023
@fethiyildiz
Copy link
Author

fethiyildiz commented Oct 24, 2023

For any future readers,

This issue isn't directly related to AWS SDK rather related to GrallVM.

I could run my application with below configs.

Hints are required for GrallVM to know your classes.

class ApplicationRuntimeHints : RuntimeHintsRegistrar {

    override fun registerHints(hints: RuntimeHints, classLoader: ClassLoader?) {
        hints.resources().registerResource(ClassPathResource("com/amazonaws/internal/config/awssdk_config_default.json"))
        hints.resources().registerResource(ClassPathResource("com/amazonaws/partitions/endpoints.json"))
        hints.resources().registerResource(ClassPathResource("com/amazonaws/sdk/versionInfo.properties"))

        HashSet::class.java.declaredConstructors.forEach { hints.reflection().registerConstructor(it, ExecutableMode.INVOKE) }
        AWSS3V4Signer::class.java.declaredConstructors.forEach { hints.reflection().registerConstructor(it, ExecutableMode.INVOKE) }
    }
}

RegisterReflectionForBinding annotation is required for serilization and deserialization of classes.

@SpringBootApplication
@ConfigurationPropertiesScan
@ImportRuntimeHints(ApplicationRuntimeHints::class)
@RegisterReflectionForBinding(
    InternalConfigJsonHelper::class,
    JsonIndex::class,
    HttpClientConfigJsonHelper::class,
    HostRegexToRegionMappingJsonHelper::class,
    Partitions::class,
    Partition::class,
)
class DemoApplication

fun main(args: Array<String>) {
    runApplication<DemoApplication>(*args)
}

And lastly, we need to add dynamic proxy config file to resources (or any path you want) and update pom.xml GrallVM plugin (or gradle if you use).

[
  [
    "org.apache.http.conn.HttpClientConnectionManager",
    "org.apache.http.pool.ConnPoolControl",
    "com.amazonaws.http.conn.Wrapped"
  ]
]
<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
    <configuration>
        <buildArgs>
            <arg>--initialize-at-build-time=org.apache.commons.logging.LogFactory</arg>
            <arg>-H:DynamicProxyConfigurationFiles=src/main/resources/proxies.json</arg>
        </buildArgs>
    </configuration>
</plugin>

@github-actions
Copy link

COMMENT VISIBILITY WARNING

Comments on closed issues are hard for our team to see.
If you need more assistance, please open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. needs-triage This issue or PR still needs to be triaged.
Projects
None yet
Development

No branches or pull requests

1 participant