Monday, 12 March 2018

How to get the database size of the MySQL DB ?



mysql -e "SELECT table_schema AS 'Database Name', SUM((data_length+index_length)/1024/1024) AS 'Database Size in MB
FROM information_schema.TABLES where table_schema='dbname';"

EXAMPLE
mysql -e "SELECT table_schema AS 'Database Name', SUM((data_length+index_length)/1024/1024) AS 'Database Size in MB
FROM information_schema.TABLES where table_schema='employee';"


ANSWER


+---------------+---------------------+
| Database Name | Database Size in MB |
+---------------+---------------------+
| employee      |       7224.01562500 |
+---------------+---------------------+

Spring security : How to configure Spring security ?


Add dependency with Spring boot :
 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>


OR
 
Add dependency without Spring boot :
 <dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
</dependency>





Security config 1 : Using properties


Add the basic properties in app.props
security.user.name=user1
security.user.password=pwd1

security.basic.authorize-mode=authenticated
security.basic.path=/**



It will provide the popup for authentication.
You can use configured credentials to access application.


Security config 2 : Without properties
Define a Security adapter class :
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdaptor {
   @Autowired
   public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
      auth

          .inMemoryAuthentication()
          .withUser("user1")
          .password("pwd1")
          .roles("USER");
   }
}



Define the Security adapter class with main application class :
@SpringBootApplication
public class TrainingApplication {
    public static void main(String[] args) {
       ApplicationContext ctx = SpringApplication.run(

                    new Class[] { TrainingApplication.class, MySecurityConfig.class}, args);
    }
}


It auto-creates a form with login and password.
For incorrect credentials, it provides default error messages.


Thursday, 8 March 2018

What is the flow of Spring application ?


Client
> Front controller (Dispatcher Servlet)
    > Handler mapping (holds mapping of all the URLs with controller) returns Controller
       > Controller
           > Return the view

                View resolver resolves the view type (ModelAndView/Jasper(JSP)/text/JSON)
                     > If modelAndView response, return View

                        else return data (JSON, text etc.)
  
Image result for spring flow

Monday, 5 March 2018

How to provide XML response instead of JSON from your API ?


By default, @Entity annotation provides JSON compatibility.

In order to return XML format, you must define your entity class as a XML root element also.
Use @XmlRootElement to indicate the root element of the XML.
If your entity name is different in the XML than in the entity class, use name attribute.
@XmlRootElement(name = "emp")

@XmlAccessorType annotation is used to indicate XML fields are inside the entity class.

You can use @XmlElement annotation with the field, if the XML field name is different than in the entity class. 

EXAMPLE
@XmlRootElement
@XmlAccessorType(XMLAccessType.FIELD)@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)

    private Long id;

    @NotNull
    @Size(min = 2, max = 10)
    @Column(length=60, updatable=false)

    private String name;
    

    @XmlElement(name = "monthly_salary")
    private double salary;


    // Getters and setters
       
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
    }

 }


@Controller vs. @RestController


@Controller defines a Spring controller, which is not necessarily returning a HTTP response. You must use @ResponseBody to indicate the HTTP response.

@RestController annotations are used to define the APIs to be exposed over HTTP(s) and returns a HTTP response.
So, implicitly it is equals to defining 2 annotations.
@RestController = @Controller + @ResponseBody

How to use values in sessions ?


Use @SessionScope annotation.

EXAMPLE
@SessionScope(proxyMode=ScopedProxyMode.TARGET_CLASS)
public class User {
    private int value = new Random().nextInt(1000);

    // Getters and setters
}

Data inside User class will be available for the specific session.
For example, Request from same user browser instance will be considered in same session by default.

What is use of Actuators for Spring application ?


Actuators are used to get important indicators and stats of the Spring application.
It exposes many paths, which are displayed on application start logs.

Just add dependency in pom.xml and on the application startup you will get all the available actuator URLs in the logs.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency> 


You can see indicators in JSON format by using different paths / URLs : 
  • /beans : Displays a complete list of all the Spring beans in your application
    • All the loaded beans can be seen in application startup logs
  • /health : Shows application health information
  • /machine : Shows machine health information
  • /info : Displays arbitrary application information
  • /loggers : Shows and modifies the configuration of loggers in the application
  • /metrics : Shows 'metrics' information for the current application (like, No. of hits)
  • /mappings : Displays a collated list of all @RequestMapping paths (Exposed APIs)
  • /scheduledtasks : Displays the scheduled tasks in your application
  • /threaddump : Performs a thread dump
  • /trace : Request information, Properties from application.properties
  • /shutdown : Lets the application be gracefully shutdown
EXAMPLES
http://localhost:8080/health http://localhost:8080/loggers


Sunday, 4 March 2018

@RequestMapping vs. GetMapping


@RequestMapping is generic annotation which can define path mapping with request methods (GET/POST/PUT/DELETE etc.)

It can be applied to class and methods.
By default request method will be GET.

EXAMPLE

@Component
@RequestMapping("emp")public class EmpController {

   
   
@RequestMapping("hello")
    @ResponseBody

    public String hello() {
        return "Hello !";
    }
}

Calling URL http://localhost:8080/emp/hello will call hello method.

To define request method and path together with @RequestMapping :
@RequestMapping(path="hello", method=RequestMethod.GET)





Apart from @RequestMapping, there are several annotations specific to each request method :
  • @GetMapping
  • @PostMapping
  • @PutMapping
etc.


EXAMPLE
When exposing REST APIs, single @RequestMapping can indicate main verb and multiple methods using different annotations can indicate different operations like, get all records, get by ID, save, update etc.

@Component
@RequestMapping("emp")
public class EmpController {


    @Resource
    private EmployeeRepository employeeRepository;


    @GetMapping
    public ResponseEntity<List<Employee>> getAllEmp() {
        return ResponseEntity.ok((List<Employee>) employeeRepository.findAll());
    }

   
    @GetMapping("{id}")
    public ResponseEntity<Employee> emp(@PathVariable long id) {
        return ResponseEntity.ok(employeeRepository.findOne(id));
    }

   
    @PostMapping
    public ResponseEntity<Employee> emp(@RequestBody Employee emp) {
        return ResponseEntity.ok(employeeRepository.save(emp));
    }

   
    @PutMapping
    public ResponseEntity<Employee> emp(@PathVariable long id, @Valid @RequestBody Employee emp) {
        return ResponseEntity.ok(employeeRepository.save(emp));
    }

}


Different URLs can be used for different operations :
GET http://localhost:8080/emp

POST http://localhost:8080/emp
Request Body = { "name" : "shaan", "salary" : 12 }
Header = Content-Type : application/json


Saturday, 3 March 2018

How to make API calls using RestTemplate ?


Using RestTemplate
  • Create a service / facade class to call the API.
  • Inject new bean of RestTemplate (A Spring class) in this class using @Bean annotation.
  • Call methods : getForObject, postForObject (Best one is to use exchange method)
Below example uses a global API available on internet for getting data.


@Component
public class EmployeeService {
    @Resource
    private RestTemplate restTemplate;


    private String baseUrl = "https://jsonplaceholder.typicode.com/";
   
    @Bean
    RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
   
    public User getApiUsers() {
        User user = restTemplate.getForObject(baseUrl + "users/1", User.class);
        return user;
    }
}



Create required POJOs to hold data models
public class User {
    private Long id;
    private String name;
    private String username;
    private String email;


    // getters and setters
    // toString
}


Create Controller to inject and call the service to get API data
Used @RestController to expose API and provide request mapping
@RestController
@RequestMapping("emp")

public class EmpController {
    @Resource
    private EmployeeService employeeService;
   
    @GetMapping
    public User getUsers() {
        User user = employeeService.getApiUsers();
        System.out.println("USER : " + user);
        return user;
    }
}


How to create a Controller advice to manipulate the response from every controller ?


Define Controller advice by providing @ControllerAdvice, implement ResponseBodyAdvice and implement all the required methods.

Below example Controller advice will be called after each controller, and add the headers.

EXAMPLE
@ControllerAdvice
public class ResponseHandler implements ResponseBodyAdvice<Object> {
    @Override
    public Object beforeBodyWrite(Object arg0, MethodParameter arg1, MediaType arg2,
            Class<? extends HttpMessageConverter<?>> arg3, ServerHttpRequest arg4, ServerHttpResponse response) {
        System.out.println("Inside ResponseHandler : Contoller advice manipulating response... Adding headers !");
        response.getHeaders().add("MyHead", "Shaan");
        return response;
    }

    // Check the content type and return true, if matches

    @Override
    public boolean supports(MethodParameter arg0, Class<? extends HttpMessageConverter<?>> arg1) {
        return true;
    }
}


How to implement a global exception handler used by all the controllers ?


Create a Controller advice, which will be called on each controller.
  • Implement ResponseBodyAdvice
    (methods : beforeBodyWrite,
    supports)
    OR / AND
     
  • Implement RequestBodyAdvice
    (methods : beforeBodyRead, afterBodyRead, handleEmptyBody, supports)
supports method can be used to check proper content type and return boolean.

For a global exception handler, create a Controller advice and check request or manipulate the response.

How to use local exceptional handler in a Controller ?


Inside controller, provide specific methods for exception handling.
  • Define it using @ExceptionHandler annotation and provide exception class to handle.
  • Use exception object inside exception handler.
  • Return HTTP status and error message in response body using ResponseEntity

EXAMPLE
@Component
@RequestMapping("emp")

public class EmpController {


    @Resource
    private EmployeeRepository employeeRepository;

    @GetMapping
    public ResponseEntity<List<Employee>> getAllEmp() {
        return ResponseEntity.ok((List<Employee>) employeeRepository.findAll());
    }


    @PostMapping
    public ResponseEntity<Employee> emp(@RequestBody Employee emp) {
        return ResponseEntity.ok(employeeRepository.save(emp));
    }


    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> exceptionHandler(final Exception exception) {
        System.out.println("Exception handler inside controller...");
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Invalid data");
    }

}

Whenever any of the method inside controller throws the specific exception, this exception handler will be called.

Thursday, 1 March 2018

How to use JPA and Repository with Spring application ?


Let 's suppose, we need to serve data using DB on HTTP URLs.
For this example, we are using an in-memory DB (like, H2)
  • Provide dependencies of Data JPA and H2 DB in maven config
  • Define DB properties in application.properties
  • Create a Repository for data entity by extending CrudRepository.
  • Inside controller, expose different APIs, inject this repository and call its CRUD methods

1. Add dependencies of data-jpa and h2 DB along with data-rest for exposing APIs.
        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>



2. Define DB properties in application.properties
spring.datasource.url=jdbc:h2:file:~/training;DB_CLOSE_ON_EXIT=TRUE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.show-sql=true



3. Create a POJO - Data model
@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)

    private Long id;

    @NotNull
    @Size(min = 2, max = 10)
    @Column(length=60, updatable=false)

    private String name;
       
    private double salary;


    // Getters and setters
       
    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + "]";
    }

 }


4. Create repository
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
    // Optional : Customized methods

    // List<Employee> findByName(String name);
 
    // @Query("SELECT e from Employee e where e.salary=:salary")
    // List<Employee> fetchData(@Param("Salary") double salary);

}





5. Create controller and methods (exposed APIs) and access the repository
@Component
@RequestMapping("emp")

public class EmpController {

    @Resource
    private EmployeeRepository employeeRepository;
   
    @GetMapping
    public ResponseEntity<List<Employee>> getAllEmp() {
        return ResponseEntity.ok((List<Employee>) employeeRepository.findAll());
    }
   
    @GetMapping("{id}")
    public ResponseEntity<Employee> emp(@PathVariable long id) {
        return ResponseEntity.ok(employeeRepository.findOne(id));
    }
   
    @PostMapping
    public ResponseEntity<Employee> emp(@RequestBody Employee emp) {
        return ResponseEntity.ok(employeeRepository.save(emp));
    }
   
    @PutMapping
    public ResponseEntity<Employee> emp(@PathVariable long id, @Valid @RequestBody Employee emp) {
        return ResponseEntity.ok(employeeRepository.save(emp));
    }
}


 
6. Start the application and Test using Postman / RESTClient :
1. GET http://localhost:8080/emp

2. POST http://localhost:8080/emp
Request Body = { "name" : "shaan", "salary" : 12 }
Header = Content-Type : application/json