Building Layered Architecture just in 3 minutes: Final Part

I am sure that you have enjoyed the part1 where just a blink of an eye we set up an in-memory database, create a Repository class using Spring Data JPA and insert data using initDataloader by Spring boot.
In this tutorial, we will expose those employee data to UI, The Classic  MVC pattern using Spring boot.
The Service Part:: In my previous article I have created an EmployeeRepository interface & Spring boot provide its implementation at runtime, now I want this data to be guided to the Service Layer. To achieve that, I need to inject that Repository to Service layer, and define the CRUD methods which are doing nothing but calls the Repositories CRUD methods, Now you may be wondering, the EmployeeRepository interface  is empty and it extends CRUDRepository, where you can only find the declaration of CRUD methods, Now the question is, where are the Implementations ?

Again the Answer is Spring-boot on the runtime it creates an Implementation class which has all the CRUD methods implementations. Interesting isn't it,  We just declare an interface and Container creates  all the stuff for us, and we save lots of our precious time, get rid of silly mistakes etc. really an IOC(Inversion of Control)
Let's see How the Service part looks like, Please note for simplicity, I print the messages in the console using Sysout, But in the real project don't ever do this, use Logger always.

package com.example.layerdArchitechture.service;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.layerdArchitechture.entity.Employee;
import com.example.layerdArchitechture.repository.EmployeeRepositiry;

@Service
public class EmployeeService {
@Autowired
EmployeeRepositiry repo;
public Employee addEmployee(Employee emp) {
emp = repo.save(emp);
System.out.println("Employee saved::" + emp);
return emp;
}
public Optional<Employee> findEmployeeById(Long empId) {
Optional<Employee> emp = repo.findById(empId);
System.out.println("Employee found::" + emp);
return emp;
}
public Iterable<Employee> findAllEmployee() {
return repo.findAll();
}
public void deleteEmployeeById(Employee emp) {
repo.delete(emp);
System.out.println("Employee deleted::" + emp);
}
}

Yeah, Our service Layer is ready, Now I need a Controller part which will act as a delegator, takes data from UI send it to Service and Vice versa, I personally recommend to use Controller as a thin layer which just porting data from UI to service and service to UI and maybe doing some data format conversion stuffs nothing more than that.
Before showing you the code of the controller let me remind you I have not use a proper Spring controller which forward the response to a view rather, I use a RestController which directly deliver the response payload in JSON / XML format, based on the Produces property. by default it is JSON.
In Controller, we map the URL pattern to a controller method bind any data coming from a form into a  Model the "M " part of MVC.
Let's see the code.
package com.example.layerdArchitechture.controller;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.layerdArchitechture.entity.Employee;
import com.example.layerdArchitechture.service.EmployeeService;
@RestController
public class EmployeeController {
@Autowired
EmployeeService service;
@RequestMapping("/TCS/employees")
public Iterable<Employee> findAllEmployee() {
return service.findAllEmployee();
}
@RequestMapping("/TCS/employee/{id}")
public Employee findbyId(@PathVariable Long id) {
Optional<Employee> emplyoeeContainer = service.findEmployeeById(id);
return emplyoeeContainer.isPresent()?emplyoeeContainer.get():null;
}
@RequestMapping("/TCS/employee/addDemoEmployee")
public Employee addEmployee() {
Employee emp = new Employee();
emp.setName("Demo Demo");
emp.setSex("M");
emp.setAddress("Demo");
return service.addEmployee(emp);
}

@RequestMapping("/TCS/employee/delete/{id}")
public String delete(@PathVariable Long id) {
Optional<Employee> emp = service.findEmployeeById(id);
if(emp.isPresent()) {
 service.deleteEmployeeById(emp.get());
 return "deleted Successfully";
}
return "Employee Not Exists, Not able to delete";
}
}

If you look at the Controller class, You can see I autowired the Service class then wrote CRUD methods(also map them with Url pattern) as a wrapper which internally calls Service Wrapper method which calls the Spring boot's Repository Implementation class.
Now If I run the spring boot application class and hit following URL in the browser
http://localhost:8080/TCS/employees
I can see the following response in Browser in JSON format.
[
  {
    "id": 1,
    "name": "Shamik Mitra",
    "address": "BagBazar",
    "sex": "M"
  },
  {
    "id": 2,
    "name": "Samir Mitra",
    "address": "BagBazar",
    "sex": "M"
  },
  {
    "id": 3,
    "name": "Swastika Basu",
    "address": "Baranagar",
    "sex": "F"
  }
]
Hope you enjoyed the post.

Spring Mock MVC and FileUpload Mocking

FileUpload Mocking using Spring Mock MVC
The aim of an Agile project is to deliver a minimum viable product to the client and based on client response we add the new functionality on that project.

Say, We have to implement a File Upload functionality, which uploads any types of files and extract metadata and content from file moreover it stores metadata into Solr/Elasticsearch for further intelligent searching.

According to agile mode, we first need to create a basic viable product.

So what is a minimum viable product in terms of  File upload functionality?

1.Create a UI which support File Upload
2. Implement a Middleware which extracts file content. (Not extract metadata)


So One UI developer starts developing the UI and You start developing the Middleware. But until UI and Middleware not finished we can’t do the Integration so should we wait for UI developer when he finishes then we start our Integration testing. No that is bad we waste our time for waiting for some other developer to finish his job.

Rather one thing we can do we Unit test our module by Mocking the UI as if files comes from UI.

In this Article, we will see How to Mock File Upload.

Here we use Spring Mock MVC for mocking MVC part
Use Junit and common File Upload.

Let create a pom.xml for resolving the dependencies

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.example</groupId>
 <artifactId>SpringWebExample</artifactId>
 <packaging>war</packaging>
 <version>0.0.1-SNAPSHOT</version>
 <name>SpringWebExample Maven Webapp</name>
 <url>http://maven.apache.org</url>
 <properties>
      <java-version>1.7</java-version>
      <org.springframework-version>4.3.0.RELEASE</org.springframework-version>
   </properties>
   <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${org.springframework-version}</version>
      </dependency>
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.0.1</version>
          <scope>provided</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
          <version>${org.springframework-version}</version>
      </dependency>
      <dependency>      
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.2</version>
      </dependency>
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
      </dependency>
       <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.12</version>
         <scope>test</scope>
          </dependency>
   </dependencies>
   <build>
      <finalName>HelloWorld</finalName>
      <pluginManagement>
          <plugins>
              <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-compiler-plugin</artifactId>
                  <version>2.3.2</version>
                  <configuration>
                      <source>${java-version}</source>
                      <target>${java-version}</target>
                  </configuration>
              </plugin>
              <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-war-plugin</artifactId>
                  <version>2.4</version>
                  <configuration>
                      <warSourceDirectory>src/main/webapp</warSourceDirectory>
                      <warName>SpringWebExample</warName>
                      <failOnMissingWebXml>false</failOnMissingWebXml>
                  </configuration>
              </plugin>
          </plugins>
      </pluginManagement>
   </build>
</project>




Here we use Spring-webmvc,Spring-test,Common-fileupload,junit jars.


Now Create Spring configuration class

package com.example.anotatedconfiguration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example")
public class SpringConfig extends WebMvcConfigurerAdapter{
   
   @Bean
   public ViewResolver viewResolver() {
      InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
      viewResolver.setViewClass(JstlView.class);
      viewResolver.setPrefix("/WEB-INF/pages/");
      viewResolver.setSuffix(".jsp");

      return viewResolver;
   }
   
   @Bean
    public CommonsMultipartResolver multipartResolver() {

       CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
       return commonsMultipartResolver;

    }

   @Override
   public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
      configurer.enable();
   }

}






Please note that here we register two Spring Beans

  1. ViewResolver
  2. Multipart Resolver


View Resolver helps to resolve the view.
Multipart Resolver helps to handle a Multipart request for File Upload.


In Next Step, we will create a Web configuration file which is use instead of web.xml because we follow annotation based spring MVC configuration.




package com.example.anotatedconfiguration;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class WebServletConfiguration implements WebApplicationInitializer{

   public void onStartup(ServletContext ctx) throws ServletException {
      AnnotationConfigWebApplicationContext webCtx = new AnnotationConfigWebApplicationContext();
      webCtx.register(SpringConfig.class);
      webCtx.setServletContext(ctx);

      ServletRegistration.Dynamic servlet = ctx.addServlet("dispatcher", new DispatcherServlet(webCtx));

      servlet.setLoadOnStartup(1);
      servlet.addMapping("/");
     
   }

}




Next, we will create a FileUpload Controller class

package com.example.controller;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

import com.example.model.FileInfo;

@Controller
public class FileUploadController {
   
   @RequestMapping(path= "/fileupload",method=RequestMethod.POST)
   public void uploadFiles(@ModelAttribute("files")FileInfo fileInfo,HttpServletRequest request) throws IOException{
     
      fileInfo.setName(request.getParameter("name"));
      fileInfo.setUplodedBy(request.getParameter("uploadedBy"));
      System.out.println(fileInfo);
      MultipartFile[] files = fileInfo.getFiles();
      for(MultipartFile file : files)
      {
          byte[] bytes = file.getBytes();
           Path path = Paths.get("/var/tmp/"+ file.getOriginalFilename());
           Files.write(path, bytes);
           System.out.println(file.getOriginalFilename() +  " :: File uploaded successFully");
      }
     
     
   }

}



Here I map the uploadFiles method with a file upload URL and tell Spring that it support post request.
Next I Bound the Files into  FileInfo files attribute using @ModelAttribute("files")FileInfo fileInfo annotation.

This tells Spring to bound Model attribute files in Fileinfo Object. SO if any value is bound under files key(Model Object) which is MutipartFile here then it will bound with FileInfo files attribute.


Next, we  fetch some information from Request and then Iterate over the files attribute to retrieve MultipartFile(We can add multiple files also ) and store them into /var/temp location on a Linux box.

FileInfo Model Class

package com.example.model;

import java.util.Arrays;

import org.springframework.web.multipart.MultipartFile;

public class FileInfo {
   
   public MultipartFile[] files;
   public String name;
   public String uplodedBy;
   public MultipartFile[] getFiles() {
      return files;
   }
   public void setFiles(MultipartFile[] files) {
      this.files = files;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getUplodedBy() {
      return uplodedBy;
   }
   public void setUplodedBy(String uplodedBy) {
      this.uplodedBy = uplodedBy;
   }
   @Override
   public String toString() {
      return "FileInfo [files=" + Arrays.toString(files) + ", name=" + name
              + ", uplodedBy=" + uplodedBy + "]";
   }
   
   
   

}




Now , our setup is complete so we test the solution using Spring Mock so without Integration with UI we can verify our FileUploadController works successfully or not.

package com.example.fileupload.test;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import com.example.anotatedconfiguration.SpringConfig;

@WebAppConfiguration
@ContextConfiguration(classes = SpringConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class FileUploadControllerTest {
   
   @Autowired
    private WebApplicationContext webApplicationContext;
   
   @Test
   public void testFileUpload() throws Exception
   {
      MockMultipartFile mockMultipartFile =
                 new MockMultipartFile("files", "FileUploadTest.txt", "text/plain", "This is a Test".getBytes());
     
      MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
         mockMvc.perform(MockMvcRequestBuilders.fileUpload("/fileupload")
                 .file(mockMultipartFile)
                 .param("name", "FileUploadTest.txt")
                 .param("uploadedBy","Shamik Mitra"));
       
         //Assert.assertTrue(true);
             
             
   }

}


Follow this class very carefully

Here I use two top-level annotations

@WebAppConfiguration
@ContextConfiguration(classes = SpringConfig.class)

It tells it a Web application and looks SpringConfig class for Spring beans.

Next, I create  MockMultipart file where I pass  name of file, Content-type and file content in the Constructor
 MockMultipartFile mockMultipartFile = new MockMultipartFile("files", "FileUploadTest.txt", "text/plain", "This is a Test".getBytes());


Next line I create a MockMVC object which acts as a Mock Spring MVC then I create a request by passing file, and some parameters into Mock Request.

mockMvc.perform(MockMvcRequestBuilders.fileUpload("/fileupload")
                 .file(mockMultipartFile)
                 .param("name", "FileUploadTest.txt")
                 .param("uploadedBy","Shamik Mitra"));






If we run the Junit

We see that a file named “FileUploadTest”  will create in /var/tmp folder and in console it prints

INFO: Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@49ba4a47: startup date [Thu Jan 26 11:09:47 IST 2017]; root of context hierarchy
Jan 26, 2017 11:09:48 AM org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping registerHandlerMethod
INFO: Mapped "{[/fileupload],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public void com.example.controller.FileUploadController.uploadFiles(com.example.model.FileInfo,javax.servlet.http.HttpServletRequest) throws java.io.IOException
Jan 26, 2017 11:09:48 AM org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping registerHandlerMethod
INFO: Mapped "{[/greet/{name}],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.example.controller.GreetController.greet(java.lang.String,org.springframework.ui.ModelMap)
Jan 26, 2017 11:09:48 AM org.springframework.web.servlet.handler.SimpleUrlHandlerMapping registerHandler
INFO: Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler]
Jan 26, 2017 11:09:48 AM org.springframework.mock.web.MockServletContext log
INFO: Initializing Spring FrameworkServlet ''
Jan 26, 2017 11:09:48 AM org.springframework.test.web.servlet.TestDispatcherServlet initServletBean
INFO: FrameworkServlet '': initialization started
Jan 26, 2017 11:09:48 AM org.springframework.test.web.servlet.TestDispatcherServlet initServletBean
INFO: FrameworkServlet '': initialization completed in 28 ms
FileInfo [files=[org.springframework.mock.web.MockMultipartFile@547e6f03], name=FileUploadTest.txt, uplodedBy=Shamik Mitra]
FileUploadTest.txt :: File uploaded successFully
Jan 26, 2017 11:09:48 AM org.springframework.web.context.support.GenericWebApplicationContext doClose
INFO: Closing org.springframework.web.context.support.GenericWebApplicationContext@49ba4a47: startup date [Thu Jan 26 11:09:47 IST 2017]; root of context hierarchy