简体   繁体   English

Spring AmazonS3 客户端的序列化错误

[英]Spring serialization error for AmazonS3 client

I've got a weird problem which I can't really understand.我有一个奇怪的问题,我无法真正理解。

I've a got a code to upload a file to AWS S3 bucket using AmazonS3 client.我有一个代码可以使用 AmazonS3 客户端将文件上传到 AWS S3 存储桶。 I've got a try-catch block where I catch any exception and in catch block I throw my defined exception which is handled by controller method @ExceptionHandler and should return thymeleaf template errorUpload.html.我有一个 try-catch 块,我在其中捕获任何异常,并在 catch 块中抛出我定义的异常,该异常由 controller 方法 @ExceptionHandler 处理,应该返回 thymeleaf 模板 errorUpload.html。

@Service
public class UploadService {
    private final AmazonS3 amazonS3;
    private final String bucketName;

    public UploadService(AmazonS3 amazonS3, @Value("${aws.bucketName}") String bucketName) {
        this.amazonS3 = amazonS3;
        this.bucketName = bucketName;
    }

    public void manualUpload(MultipartFile file) {
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(file.getContentType());
        metadata.setContentLength(file.getSize());

        try {
            amazonS3.putObject(new PutObjectRequest(bucketName, file.getName(), file.getInputStream(), metadata));
        } catch (Exception e) {
            throw new UploadException(e.getMessage());
        }
    }
}

Exception handler:异常处理程序:

@ExceptionHandler({UploadException.class})
public String uploadError() {
    return "errorPages/errorUpload";
}

When I simply throw exception in manualUpload method without any logic it works fine.当我在没有任何逻辑的情况下简单地在 manualUpload 方法中抛出异常时,它工作正常。 But when AmazonS3 object is used and it throws exception then logic goes to ExceptionHandler but it thorws below error:但是,当使用 AmazonS3 object 并抛出异常时,逻辑会转到 ExceptionHandler,但会引发以下错误:

org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.Object] to type [byte[]] for value 'com.amazonaws.services.s3.AmazonS3Client@4b0ac28c'; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.amazonaws.services.s3.AmazonS3Client]
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47) ~[spring-core-5.3.9.jar:5.3.9]
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192) ~[spring-core-5.3.9.jar:5.3.9]
    at org.springframework.session.jdbc.JdbcIndexedSessionRepository.serialize(JdbcIndexedSessionRepository.java:623) ~[spring-session-jdbc-2.5.1.jar:2.5.1]
    at org.springframework.session.jdbc.JdbcIndexedSessionRepository.access$400(JdbcIndexedSessionRepository.java:133) ~[spring-session-jdbc-2.5.1.jar:2.5.1]
    at org.springframework.session.jdbc.JdbcIndexedSessionRepository$1.setValues(JdbcIndexedSessionRepository.java:487) ~[spring-session-jdbc-2.5.1.jar:2.5.1]
    at org.springframework.jdbc.core.JdbcTemplate.lambda$batchUpdate$4(JdbcTemplate.java:1042) ~[spring-jdbc-5.3.9.jar:5.3.9]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:651) ~[spring-jdbc-5.3.9.jar:5.3.9]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:691) ~[spring-jdbc-5.3.9.jar:5.3.9]
    at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:1034) ~[spring-jdbc-5.3.9.jar:5.3.9]
    at org.springframework.session.jdbc.JdbcIndexedSessionRepository.insertSessionAttributes(JdbcIndexedSessionRepository.java:479) ~[spring-session-jdbc-2.5.1.jar:2.5.1]
    at org.springframework.session.jdbc.JdbcIndexedSessionRepository.access$1200(JdbcIndexedSessionRepository.java:133) ~[spring-session-jdbc-2.5.1.jar:2.5.1]
    at org.springframework.session.jdbc.JdbcIndexedSessionRepository$JdbcSession.lambda$save$10(JdbcIndexedSessionRepository.java:854) ~[spring-session-jdbc-2.5.1.jar:2.5.1]
    at org.springframework.transaction.support.TransactionOperations.lambda$executeWithoutResult$0(TransactionOperations.java:68) ~[spring-tx-5.3.9.jar:5.3.9]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.3.9.jar:5.3.9]
    at org.springframework.transaction.support.TransactionOperations.executeWithoutResult(TransactionOperations.java:67) ~[spring-tx-5.3.9.jar:5.3.9]
    at org.springframework.session.jdbc.JdbcIndexedSessionRepository$JdbcSession.save(JdbcIndexedSessionRepository.java:836) ~[spring-session-jdbc-2.5.1.jar:2.5.1]
    at org.springframework.session.jdbc.JdbcIndexedSessionRepository$JdbcSession.access$200(JdbcIndexedSessionRepository.java:665) ~[spring-session-jdbc-2.5.1.jar:2.5.1]
    at org.springframework.session.jdbc.JdbcIndexedSessionRepository.save(JdbcIndexedSessionRepository.java:422) ~[spring-session-jdbc-2.5.1.jar:2.5.1]
    at org.springframework.session.jdbc.JdbcIndexedSessionRepository.save(JdbcIndexedSessionRepository.java:133) ~[spring-session-jdbc-2.5.1.jar:2.5.1]
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:226) ~[spring-session-core-2.5.1.jar:2.5.1]
    at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:193) ~[spring-session-core-2.5.1.jar:2.5.1]
    at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:145) ~[spring-session-core-2.5.1.jar:2.5.1]
    at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:82) ~[spring-session-core-2.5.1.jar:2.5.1]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:103) ~[spring-web-5.3.9.jar:5.3.9]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:711) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:461) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:385) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:313) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:398) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:257) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:352) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:177) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
    at java.base/java.lang.Thread.run(Thread.java:831) ~[na:na]
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.amazonaws.services.s3.AmazonS3Client]
    at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:64) ~[spring-core-5.3.9.jar:5.3.9]
    at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:33) ~[spring-core-5.3.9.jar:5.3.9]
    at org.springframework.core.convert.support.GenericConversionService$ConverterAdapter.convert(GenericConversionService.java:386) ~[spring-core-5.3.9.jar:5.3.9]
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ~[spring-core-5.3.9.jar:5.3.9]
    ... 47 common frames omitted
Caused by: java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.amazonaws.services.s3.AmazonS3Client]
    at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:43) ~[spring-core-5.3.9.jar:5.3.9]
    at org.springframework.core.serializer.Serializer.serializeToByteArray(Serializer.java:56) ~[spring-core-5.3.9.jar:5.3.9]
    at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:60) ~[spring-core-5.3.9.jar:5.3.9]
    ... 50 common frames omitted

I think it might be related with storing SPRING_SECURITY_CONTEXT in spring_session_attributes table so because AmazonS3 is not serialiazed it throws that error.我认为这可能与将 SPRING_SECURITY_CONTEXT 存储在 spring_session_attributes 表中有关,因为 AmazonS3 未序列化它会抛出该错误。 Any ideas how this can be solved?任何想法如何解决这个问题?

I found a solution.我找到了解决办法。 Any not serializable object cannot be created as a bean and used because in this case when this particular bean is going to be stored in in SPRING_SECURITY_CONTEXT the serialization exception occurs.任何不可序列化的 object 都不能创建为 bean 并使用,因为在这种情况下,当这个特定的 bean 将要存储在 SPRING_SECURITY_CONTEXT 中时,会发生序列化异常。 So the solution for that is simply not creating Bean but instead just create object using "new" keyword in place when we want to use it.因此,解决方案就是不创建 Bean,而是在我们想要使用它时使用“new”关键字创建 object。

@Service
public class UploadService {
    private final String bucketName;
    private final S3Client s3Client;

    public UploadService(@Value("${aws.bucketName}") String bucketName,
                         @Value("${aws.accessKey}") String awsAccessKey,
                         @Value("${aws.secretKey}") String awsSecretKey) {
        this.s3Client = S3Client.builder()
                .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(awsAccessKey, awsSecretKey)))
                .region(Region.US_EAST_1)
                .build();
        this.bucketName = bucketName;
    }

    public void manualUpload(MultipartFile file) {
        try {
            s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(file.getName()).build(),
                    RequestBody.fromBytes(file.getBytes()));
        } catch (Exception e) {
            throw new UploadException(e.getMessage());
        }
    }
}

The error is indeed strange.错误确实很奇怪。 It seems to me that you are using the old version of AWS SDK for Java ( https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 ), so I would suggest you updating it to the new version ( https://mvnrepository.com/artifact/software.amazon.awssdk/s3 ) and check if the issue persists.在我看来,您正在为 Java 使用旧版本的 AWS SDK( https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 ),所以我建议您将其更新为新版本版本 ( https://mvnrepository.com/artifact/software.amazon.awssdk/s3 ) 并检查问题是否仍然存在。

For more and detailed information check AWS documentation on how to migrate https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html .有关更多详细信息,请查看有关如何迁移的 AWS 文档https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 mockito 模拟 AmazonS3 getObject 方法 - How to mock AmazonS3 getObject method using mockito 是否可以使用 AmazonS3 将序列化的 object(以字符串形式)写入用户元数据? - Is it possible to write a serialized object (in String) into the user meta data using AmazonS3? 如何检查 AmazonS3Client 连接是否处于活动状态 - how to check if AmazonS3Client connection is active or not 如何使用 AmazonS3EncryptionClientV2 客户端加密从 AWS S3 存储桶下载 object? - How do you download object from AWS S3 bucket using AmazonS3EncryptionClientV2 client side encryption? Beam 写入 avro 文件序列化错误 - Beam write to avro file serialization error AmazonS3ClientBuilder 没有响应 - AmazonS3ClientBuilder not responding 在 node.js 中删除 object 时出现 aws/sdk 错误,即使在 AmazonS3FullAccess 之后,更正存储桶策略并且不阻止任何公共访问 - aws/sdk error on deleting object in node js even after AmazonS3FullAccess, correct bucket policy and not blocking any public access AmazonS3ClientBuilder 卡在构建 function 上 - AmazonS3ClientBuilder is stuck on build function 带有 Spring Data Elasticsearch 的 Elasticsearch Rest 客户端 - Elasticsearch Rest Client with Spring Data Elasticsearch client = boto3.client('eventbridge') 出现错误 - getting error for client = boto3.client('eventbridge')
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM