[英]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.