Saturday, August 18, 2018

Upload File on AWS S3 Using Java

Most of us know nowadays that AWS  is used for almost everything because of its cheap price as well its availability.

AWS S3 is an online storage for storing file and images and zip, literally everything you want to put. 

Most of us have some use cases where we want to upload the image to aws s3 so that it can we used anywhere we want.

#Usercase we need to get the file or Image from UI and need to upload it to AWS S3 using java.

#Approach To Achieve it 
  • first, need to add the AWS SDK for Java 
  • Then we need to Get the client of AWS which is basically creating a connection with AWS 
  • After successfully getting the connection we will use s3 API to put the image as an object in AWS.

We first need to Add the dependency of AWS SDK in our project ( maven dependency as below )

  <dependency>
   <groupId>com.amazonaws</groupId>
   <artifactId>aws-java-sdk</artifactId>
   <version>1.11.388</version>
 </dependency>

After this, we need to have the AWS Account Access key and access_id
you can get it from https://console.aws.amazon.com/iam/home?#/security_credential

Access key file will look like below

[default]
aws_access_key_id=<Your-Access-key_id>
aws_secret_access_key=<Your Secret_access_key>
Note change <Your-Access-key_id> and <Your Secret_access_key> values with your access key.

Now you need to save the access key file at a location below.

~/.aws/credentials on Linux, macOS, or Unix
C:\Users\USERNAME \.aws\credentials on Windows

Now let see the Code for the Uploading of Image /File on AWS.  (Ref : here )
 we will create one jsp file where we create upload file and call the spring controller , under the controller, you can see the file and it will store to the aws s3.




Thyemleaf Html Code

<!DOCTYPE html>
<html xmlns:th="http://thymeleaf.org">
<head>
<title>File Upload Example</title>
<link href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"
 rel="stylesheet" />
<script type="text/javascript" src="webjars/jquery/3.3.1/jquery.min.js"></script>
<script src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</head>
<script th:inline="javascript">
 /*<![CDATA[*/
 var _validFileExtensions = [ ".csv", ".zip" ,".png" ];
 function Validate(oForm) {
  var arrInputs = oForm.getElementsByTagName("input");
  for (var i = 0; i < arrInputs.length; i++) {
   var oInput = arrInputs[i];
   if (oInput.type == "file") {
    var sFileName = oInput.value;
    if (sFileName.length == 0) {

     alert("Please select a file to upload");
     return false;
    }
    if (sFileName.length > 0) {
     var blnValid = false;
     for (var j = 0; j < _validFileExtensions.length; j++) {
      var sCurExtension = _validFileExtensions[j];
      if (sFileName.substr(
        sFileName.length - sCurExtension.length,
        sCurExtension.length).toLowerCase() == sCurExtension
        .toLowerCase()) {
       blnValid = true;
       break;
      }
     }

     if (!blnValid) {
      alert("Invalid File Extension");
      return false;
     }
    }
   }
  }

  return true;
 }
  
 /*]]>*/
</script>

<body>

 <div class="container-fluid padding-0">
  <div class="row padding-0">
   
   <div class="col-md-4">
    <h2>File Upload Example</h2>
   </div>
   <div class="col-md-4" align="right"></div>
  </div>
 </div>
 <nav role="navigation" id="trainingset-container-id"
  class="navbar navbar-default">
  <div class="row" style="margin-top: 10px;">
   <div class="col-md-2">
    <B>Upload File</B>
   </div>
   <div class="col-md-6">
    <form method="POST" action="/upload"
     onsubmit="return Validate(this);" enctype="multipart/form-data">
     <div class="col-sm-6">

      <input type="file" name="file"  />
     </div>
     <div class="col-sm-6">
      <input type="submit" class="btn btn-success btn-sm" value="Upload data" />
     </div>
    </form>
   </div>
   
  </div>
 </nav>
  <div id="messageboxid">
   <div id="uploadstatus" th:if="${message}">
    <B>Status Of Uploaded File</B>
    <h6 th:text="${message}" />
   </div>
  </div>
  
</body>
</html>
This will see like this

Now we will see the Upload Controller Code.

Upload Controller.java

package com.programinjava.learn.controller;

import java.io.InputStream;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;

@Controller
public class UploadController {
 
 @PostMapping("/upload")
 public String singleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {


  if (file.isEmpty()) {
   redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
   return "redirect:uploadStatus";
  }
//  bucket name 
  String bucketName ="atserve-photos";
//  get it from user or change it 
  String nameOffile ="myPhoto";
//  getting aws access 
  AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                .withRegion(Regions.AP_SOUTH_1)
                .withCredentials(new ProfileCredentialsProvider())
                .build();
  boolean isBucketExist =s3Client.doesBucketExist(bucketName);
  if(!isBucketExist) {
   s3Client.createBucket(bucketName);
  }
  try {
   InputStream is = file.getInputStream();
   s3Client.putObject(new PutObjectRequest(bucketName,nameOffile,is,new ObjectMetadata()).withCannedAcl(CannedAccessControlList.PublicRead));
   redirectAttributes.addFlashAttribute("message", "SuccessFully Uploaded On AWS S3");
  }catch(Exception e) {
   e.printStackTrace();
  }
  return "redirect:/uploadStatus";
 }
 
 @GetMapping("/uploadStatus")
 public String uploadStatus(ModelMap m) {
  return "Homepage";
 }
 
 @GetMapping("/upload")  
 public String displayHomePageForAlarm() {
  return "Homepage";
 }

}

Let see what we get on AWS S3

So this is how we can see the myPhoto is now uploaded on AWS S3.

DOWNOAD THE CODE :


Also, learn

Wednesday, August 8, 2018

Mocking of static method in unit testing


While we do unit testing, we mostly encounter the situation where we need to do the unit testing of a method which is calling a static method. if we are using mockito for doing mocking, We will have to suffer as mockito don't provide Static method mocking.


Let's see in a simple manner what is required and how we achieve it.

# Objective: We need to mock the static class which is being used in a method for which we are writing unit test.

# Solution: We have to use Powermockito for that 

What is PowerMockito?
PowerMockito is a PowerMock’s extension API to support Mockito. It provides capabilities to work with the Java Reflection API in a simple way to overcome the problems of Mockito, such as the lack of ability to mock final, static or private methods.

Getting Start with Powermockito

Also read: JUnit Tests Basics and how to do unit testing in java

First, you need to add the dependency in pom.xml

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.6.4</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.6.4</version>
    <scope>test</scope>
</dependency>
Now as you are using powermockito , you need to change the JUNIT Runner class as
@RunWith(PowerMockRunner.class)
@PrepareForTest(<StaticClassName>.class)
<StaticClassName> will be replace with you static class Name.

Now let see the example.


Project Structure
Now let see the class for with we will write test case.

public class Rectangle {
 
 public int getAreaOfRectangle(int length , int breadth) {
  return AreaFinder.findArea("rectangle", length, breadth);
 }

}

The Static Class

public class AreaFinder {
 public static int findArea(String type , int length , int breadth) {
  if(type.equals("rectangle")) {
   return length*breadth;
  }else if(type.equals("square")) {
   return length*length;
  }else {
   return 0;
  }

 }

}

Test Class

@RunWith(PowerMockRunner.class)
@PrepareForTest(AreaFinder.class)      // need to add the static class for which you mock the method
public class RectangleTest {

 @Test
 public void getAreaOfRectangleTest() {
  Rectangle rec = new Rectangle();
  int length =10;
  int breadth =20;

  PowerMockito.mockStatic(AreaFinder.class);   // mocking of static class
  PowerMockito.when(AreaFinder.findArea("rectangle", length, breadth)).thenReturn(200); // defining behaviour
  Assert.assertEquals(200, rec.getAreaOfRectangle(length, breadth));
 }

}

When you run this you will be able to see the test will be run successfully and it will get passed.

If you have any issue regarding the above concept, please let us know.

I hope this will help you in understand how to do mocking of static method in  unit testing.

Thanks for reading
Noeik