diff --git a/aws-modules/aws-s3-update-object/pom.xml b/aws-modules/aws-s3-update-object/pom.xml deleted file mode 100644 index 3cf7b657b0..0000000000 --- a/aws-modules/aws-s3-update-object/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - 4.0.0 - aws-s3-update-object - 0.0.1-SNAPSHOT - aws-s3-update-object - Project demonstrating overwriting of S3 objects - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-test - test - - - com.amazonaws - aws-java-sdk - ${aws-java-sdk-version} - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - 1.12.523 - - diff --git a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/AwsS3UpdateObjectApplication.java b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/AwsS3UpdateObjectApplication.java deleted file mode 100644 index 24866c287b..0000000000 --- a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/AwsS3UpdateObjectApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.awss3updateobject; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class AwsS3UpdateObjectApplication { - - public static void main(String[] args) { - SpringApplication.run(AwsS3UpdateObjectApplication.class, args); - } - -} diff --git a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/controller/FileController.java b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/controller/FileController.java deleted file mode 100644 index e87358ef56..0000000000 --- a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/controller/FileController.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.awss3updateobject.controller; - -import com.baeldung.awss3updateobject.service.FileService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -@RestController -@RequestMapping("api/v1/file") -public class FileController { - - @Autowired - FileService fileService; - - @PostMapping("/upload") - public String uploadFile(@RequestParam("file") MultipartFile multipartFile) throws Exception { - return this.fileService.uploadFile(multipartFile); - } - - @PostMapping("/update") - public String updateFile(@RequestParam("file") MultipartFile multipartFile, @RequestParam("filePath") String exitingFilePath) throws Exception { - return this.fileService.updateFile(multipartFile, exitingFilePath); - } -} diff --git a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/service/FileService.java b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/service/FileService.java deleted file mode 100644 index 23eaad7913..0000000000 --- a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/service/FileService.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.baeldung.awss3updateobject.service; - -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.regions.Regions; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import com.amazonaws.services.s3.model.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.PostConstruct; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -@Service -public class FileService { - - private static final Logger logger = LoggerFactory.getLogger(FileService.class); - - public AmazonS3 amazonS3; - - @Value("${aws.s3bucket}") - public String awsS3Bucket; - - @PostConstruct - private void init(){ - AWSCredentials credentials = new BasicAWSCredentials( - "AWS AccessKey", - "AWS secretKey" - ); - this.amazonS3 = AmazonS3ClientBuilder.standard() - .withRegion(Regions.fromName("us-east-1")) - .withCredentials(new AWSStaticCredentialsProvider(credentials)) - .build(); - } - - public String uploadFile(MultipartFile multipartFile) throws Exception { - String key = "/documents/" + multipartFile.getOriginalFilename(); - return this.uploadDocument(this.awsS3Bucket, key, multipartFile); - } - - public String updateFile(MultipartFile multipartFile, String key) throws Exception { - return this.uploadDocument(this.awsS3Bucket, key, multipartFile); - } - - private String uploadDocument(String s3bucket, String key, MultipartFile multipartFile) throws Exception { - try { - ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentType(multipartFile.getContentType()); - Map attributes = new HashMap<>(); - attributes.put("document-content-size", String.valueOf(multipartFile.getSize())); - metadata.setUserMetadata(attributes); - InputStream documentStream = multipartFile.getInputStream(); - PutObjectResult putObjectResult = this.amazonS3.putObject(new PutObjectRequest(s3bucket, key, documentStream, metadata)); - - S3Object s3Object = this.amazonS3.getObject(s3bucket, key); - logger.info("Last Modified: " + s3Object.getObjectMetadata().getLastModified()); - return key; - } catch (AmazonS3Exception ex) { - if (ex.getErrorCode().equalsIgnoreCase("NoSuchBucket")) { - String msg = String.format("No bucket found with name %s", s3bucket); - throw new Exception(msg); - } else if (ex.getErrorCode().equalsIgnoreCase("AccessDenied")) { - String msg = String.format("Access denied to S3 bucket %s", s3bucket); - throw new Exception(msg); - } - throw ex; - } catch (IOException ex) { - String msg = String.format("Error saving file %s to AWS S3 bucket %s", key, s3bucket); - throw new Exception(msg); - } - } -} diff --git a/aws-modules/aws-s3-update-object/src/main/resources/application.properties b/aws-modules/aws-s3-update-object/src/main/resources/application.properties deleted file mode 100644 index c840d970a8..0000000000 --- a/aws-modules/aws-s3-update-object/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -aws.s3bucket=baeldung-documents; diff --git a/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/controller/FileControllerUnitTest.java b/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/controller/FileControllerUnitTest.java deleted file mode 100644 index 823391c139..0000000000 --- a/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/controller/FileControllerUnitTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.baeldung.awss3updateobject.controller; - -import com.baeldung.awss3updateobject.service.FileService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.multipart.MultipartFile; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; - -public class FileControllerUnitTest { - - private MockMvc mockMvc; - - @Mock - private FileService fileService; - - @InjectMocks - private FileController fileController; - - @BeforeEach - public void setUp() { - MockitoAnnotations.openMocks(this); - this.mockMvc = MockMvcBuilders.standaloneSetup(fileController).build(); - } - - @Test - public void givenValidMultipartFile_whenUploadedViaEndpoint_thenCorrectPathIsReturned() throws Exception { - MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain", "sample file content".getBytes()); - String expectedResult = "File Uploaded Successfully"; - - when(fileService.uploadFile(multipartFile)).thenReturn(expectedResult); - - mockMvc.perform(multipart("/api/v1/file/upload").file(multipartFile)) - .andExpect(status().isOk()) - .andExpect(content().string(expectedResult)); - } - - @Test - public void givenValidMultipartFileAndExistingPath_whenUpdatedViaEndpoint_thenSamePathIsReturned() throws Exception { - MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain", "updated file content".getBytes()); - String filePath = "some/path/to/file"; - String expectedResult = "File Updated Successfully"; - - when(fileService.updateFile(multipartFile, filePath)).thenReturn(expectedResult); - - mockMvc.perform(multipart("/api/v1/file/update") - .file(multipartFile) - .param("filePath", filePath)) - .andExpect(status().isOk()) - .andExpect(content().string(expectedResult)); - } -} \ No newline at end of file diff --git a/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/service/FileServiceUnitTest.java b/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/service/FileServiceUnitTest.java deleted file mode 100644 index 90ed77b148..0000000000 --- a/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/service/FileServiceUnitTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.baeldung.awss3updateobject.service; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.AmazonS3Exception; -import com.amazonaws.services.s3.model.PutObjectRequest; -import com.amazonaws.services.s3.model.S3Object; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.io.InputStream; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - -public class FileServiceUnitTest { - - @Mock - private AmazonS3 amazonS3; - - @Mock - private MultipartFile multipartFile; - - @InjectMocks - private FileService fileService; - - @BeforeEach - public void setup() { - MockitoAnnotations.openMocks(this); - fileService = new FileService(); - fileService.awsS3Bucket = "test-bucket"; - fileService.amazonS3 = amazonS3; - } - - @Test - public void givenValidFile_whenUploaded_thenKeyMatchesDocumentPath() throws Exception { - when(multipartFile.getName()).thenReturn("testFile"); - when(multipartFile.getOriginalFilename()).thenReturn("testFile"); - when(multipartFile.getContentType()).thenReturn("application/pdf"); - when(multipartFile.getSize()).thenReturn(1024L); - when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class)); - - S3Object s3Object = new S3Object(); - when(amazonS3.putObject(any())).thenReturn(null); - when(amazonS3.getObject(anyString(), anyString())).thenReturn(s3Object); - - String key = fileService.uploadFile(multipartFile); - - assertEquals("/documents/testFile", key); - } - - @Test - public void givenValidFile_whenUploadFailsDueToNoBucket_thenExceptionIsThrown() throws Exception { - when(multipartFile.getName()).thenReturn("testFile"); - when(multipartFile.getOriginalFilename()).thenReturn("testFile"); - when(multipartFile.getContentType()).thenReturn("application/pdf"); - when(multipartFile.getSize()).thenReturn(1024L); - when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class)); - - AmazonS3Exception exception = new AmazonS3Exception("Test exception"); - exception.setErrorCode("NoSuchBucket"); - when(amazonS3.putObject(any(PutObjectRequest.class))).thenThrow(exception); - - assertThrows(Exception.class, () -> fileService.uploadFile(multipartFile)); - } - - @Test - public void givenExistingFile_whenUpdated_thenSameKeyIsReturned() throws Exception { - when(multipartFile.getName()).thenReturn("testFile"); - when(multipartFile.getContentType()).thenReturn("application/pdf"); - when(multipartFile.getSize()).thenReturn(1024L); - when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class)); - - S3Object s3Object = new S3Object(); - when(amazonS3.putObject(any(PutObjectRequest.class))).thenReturn(null); - when(amazonS3.getObject(anyString(), anyString())).thenReturn(s3Object); - - String key = "/documents/existingFile"; - String resultKey = fileService.updateFile(multipartFile, key); - - assertEquals(key, resultKey); - } - - @Test - public void givenFileWithIOException_whenUpdated_thenExceptionIsThrown() throws Exception { - when(multipartFile.getName()).thenReturn("testFile"); - when(multipartFile.getContentType()).thenReturn("application/pdf"); - when(multipartFile.getSize()).thenReturn(1024L); - when(multipartFile.getInputStream()).thenThrow(new IOException("Test IO Exception")); - - assertThrows(Exception.class, () -> fileService.updateFile(multipartFile, "/documents/existingFile")); - } -} \ No newline at end of file diff --git a/aws-modules/aws-s3/README.md b/aws-modules/aws-s3/README.md index 9b862c8685..f3b34b584e 100644 --- a/aws-modules/aws-s3/README.md +++ b/aws-modules/aws-s3/README.md @@ -11,3 +11,4 @@ This module contains articles about Simple Storage Service (S3) on AWS - [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects) - [Update an Existing Amazon S3 Object Using Java](https://www.baeldung.com/java-update-amazon-s3-object) - [How To Rename Files and Folders in Amazon S3](https://www.baeldung.com/java-amazon-s3-rename-files-folders) +- [Update an Existing Amazon S3 Object Using Java](https://www.baeldung.com/java-update-amazon-s3-object) diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java index abf570f0d0..3328006bc0 100644 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java @@ -45,6 +45,13 @@ public class S3Application { new File("/Users/user/Document/hello.txt") ); + s3Service.updateObject( + AWS_BUCKET, + "Document/hello2.txt", + new File("/Users/user/Document/hello2.txt") + ); + + //listing objects s3Service.listObjects(AWS_BUCKET); diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java index f4f768d1b4..dfc8e9de5f 100644 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java @@ -24,6 +24,7 @@ import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.HeadBucketRequest; import software.amazon.awssdk.services.s3.model.HeadObjectRequest; +import software.amazon.awssdk.services.s3.model.HeadObjectResponse; import software.amazon.awssdk.services.s3.model.ListBucketsResponse; import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; @@ -99,7 +100,13 @@ class S3Service { .key(key) .build(); - return s3Client.putObject(request, Path.of(file.toURI()) ); + + return s3Client.putObject(request, Path.of(file.toURI())); + } + + //updating object + public PutObjectResponse updateObject(String bucketName, String key, java.io.File file) { + return this.putObject(bucketName, key, file); } //listing objects @@ -110,6 +117,7 @@ class S3Service { ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request); for(S3Object os : listObjectsV2Response.contents()) { + System.out.println(os.key()); } } diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java index bf24bcaa43..15db15831c 100644 --- a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java +++ b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java @@ -11,6 +11,8 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import java.io.File; +import java.nio.file.Path; import java.util.Collections; import software.amazon.awssdk.services.s3.S3Client; @@ -23,6 +25,7 @@ import software.amazon.awssdk.services.s3.model.HeadBucketRequest; import software.amazon.awssdk.services.s3.model.ListBucketsResponse; import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; class S3ServiceIntegrationTest { @@ -38,6 +41,8 @@ class S3ServiceIntegrationTest { private final String AWS_BUCKET = "baeldung-tutorial-s3"; + private File file = new File("/Users/user/Document/hello2.txt"); + @BeforeEach public void setup() { MockitoAnnotations.openMocks(this); @@ -75,6 +80,17 @@ class S3ServiceIntegrationTest { verify(s3Client).createBucket(bucketRequest); } + @Test + void whenVerifyingUploadOfS3Object_thenCorrect() { + PutObjectRequest request = PutObjectRequest.builder() + .bucket(BUCKET_NAME) + .key(KEY_NAME) + .build(); + + s3Service.putObject(BUCKET_NAME, KEY_NAME, file); + verify(s3Client).putObject(request, Path.of(file.toURI()) ); + } + @Test void whenVerifyingListBuckets_thenCorrect() { when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build()); diff --git a/aws-modules/pom.xml b/aws-modules/pom.xml index 66fa4bffa1..06cea2f260 100644 --- a/aws-modules/pom.xml +++ b/aws-modules/pom.xml @@ -28,7 +28,6 @@ aws-miscellaneous aws-reactive aws-s3 - aws-s3-update-object