Sunday, June 21, 2015

Spring Boot Angular Part 3

Under Construction... In part 3 of the Spring Boot Angular series, we are going to add some global exception handling with AspectJ and also some RESTful validation with the java validation framework. AspectJ is great for proxying a global try/catch block around all of your services.  This allows you to do things like error handling, logging, auditing, marking up requests with session info, etc. globally in your application.  We'll start off by adding in the Spring Boot AOP dependencies in your pom.xml.



    org.springframework.boot
    spring-boot-starter-aop

  

    org.springframework
    spring-aspects



Next, we'll create a new package called aspect and a new class called ControllerAspect. The ControllerAspect will be our class where we can put our global try/catch block where will we log out the input and output parameters of the method being called and also print any exception messages that might occur. I'll just be using standard output for now and leave setting up log4j for a future post or leave it for you to setup.

package com.herzog.boot.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Configurable;

/**
 * @author dherzog
 *
 * Controller Aspect for all public controller methods.
 */
@Aspect
@Configurable
public class ControllerAspect {
 
 /**
     * Proxy method to log before and after service method calls.
     *
     * @param joinPoint ProceedingJoinPoint
     * @return object
     * @throws Throwable throw exception
     */
 @Around("execution(public * com.herzog.boot.controller.*ControllerImpl.*(..))")
    public final Object logAround(final ProceedingJoinPoint joinPoint) throws Throwable {

        Object request = null;
        Object response = null;

        try {
            Object[] params = joinPoint.getArgs();
            request = params[0];

            response = joinPoint.proceed(params);
            System.out.println("\n\n\t\t"
                    + "The class " + joinPoint.getSignature().getDeclaringTypeName()
                    + " with the method " + joinPoint.getSignature().getName()
                    + "()"
                    + " \n\t\t\t begins with " + params[0]
                    + " \n\t\t\t ends  with " + response + "\n");
        } catch (Exception e) {
         Object[] params = joinPoint.getArgs();
         System.out.println("\n\n\t\t"
                    + "Class " + joinPoint.getSignature().getDeclaringTypeName()
                    + " with the method " + joinPoint.getSignature().getName()
                    + "()"
                    + " \n\t\t\t begins with " + params[0]
                    + " \n\t\t\t and failed with the exception " + e + "\n");
            throw e;
        } 
        
        return response;
    } 

}


In this class we defined the AspectJ @Around annotation. The code here will proxied around all the RESTful services. The code before the joinPoint.proceed will be invoked before the service and the code after joinPoint.proceed will be invoked after the service. The execution in the the @Around annotation proxies the code around all public methods that accept all parameters and return anything for classes that have the naming pattern of *ControllerImpl in the package com.herzog.boot.controller. You'll want to make sure that all your request and response objects have toString's defined so that useful information may be logged about your services. For example, the toString for AlbumListRequest looks like the following:

 @Override
 public String toString() {
  return String.format("AlbumListRequest [artist=%s]", artist);
 }


Now we will add some server side validation to our services. We'll use the java validation framework. In the AlbumListRequest class we will add two annotations to the getArtist method. First, we will add the @NotNull annotation to make sure that the artist value in the request object is not null. Next we will add the @Size annotation to make sure the artist value passed has a size of 1 to 100 characters. If the validation fails, Spring will through a MethodArgumentNotValidException exception.

 @NotNull
 @Size(min = 1, max = 100)
 public String getArtist() {
  return artist;
 }
For Spring to perform the validation, you'll need to add the @Valid annotation to the request of the controller method. So in AlbumControllerImpl, we will add @Valid to the beginning of the request parameter in the list method.

public AlbumListResponse list(@Valid @RequestBody final AlbumListRequest request) throws Exception {


Lastly, we are going to create a new class called ErrorHandlerAspect in the aspect package. This class will take advantage of the @ControllerAdvice feature that was introduced around Spring 3.2.5. You can setup different exception handlers for different types of exceptions. This gives you the flexibility to return different HTTP responses based on the different types of errors that might be thrown. As I mentioned before, Spring will throw a MethodArgumentNotValidException exception when server side validation fails. Using the @ConrollerAdvice, you can catch that exception, return a specific type of error message (in this case, a simple class called ErrorResponse) and set the HTTP status to 400 for a bad request. In other cases, you can create a catch all method that returns an error 500 for unexpected errors. In my ControllerAspect, I always re-throw the errors I have caught so that I can send them through the @ControllerAdvice mechanism.

package com.herzog.boot.aspect;

import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import com.herzog.boot.dtos.ErrorResponse;

/**
 * @author dherzog
 *
 * Error Handler Aspect
 */
@ControllerAdvice
public class ErrorHandlerAspect {
 
 /**
     * Method that catches java validation errors
     *
     * @param ve - Method Argument Not Valid Exception being thrown
     * @return - ErrorResponse
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @ResponseBody
 public ErrorResponse validationError(final MethodArgumentNotValidException ve) {

     ErrorResponse response = new ErrorResponse();

        BindingResult result = ve.getBindingResult();
        List objectErrors = result.getAllErrors();
        ObjectError objectError = objectErrors.get(0);
        
        response.setMessage(objectError.getDefaultMessage());
     
        return response;
    }
    
    /**
     * Method that catches non application errors
     *
     * @param e - Exception being thrown
     * @return - ErrorResponse
     */
    @ExceptionHandler(Throwable.class)
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public ErrorResponse serverError(final Throwable e) {
        e.printStackTrace();
        
        ErrorResponse response = new ErrorResponse();
     response.setMessage("General Service exception - please contact customer support");
        
        return response;
    }

}


import java.io.Serializable;

/**
 * @author dherzog
 *
 * Error Response
 */
public class ErrorResponse implements Serializable {

    private static final long serialVersionUID = 1L;

    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(final String message) {
        this.message = message;
    }

 @Override
 public String toString() {
  return String.format("ErrorResponse [message=%s]", message);
 }
}


You can find the existing source code for part 3 at https://bitbucket.org/davidjherzog/spring-boot-angular. The code is under branch 0.0.3-SNAPSHOT.

Saturday, June 20, 2015

Spring Boot Angular Part 2

In part 2 of the Spring Boot Angular series, we are going to add some RESTful services. We'll first start off by creating two new packages.  One package will be controller and the other will be dtos under com.herzog.boot.  We are going to create two RESTful APIs.  One will be to retrieve a list of albums and the other will be to retrieve information about a specific album.  Retrieving a list of albums will be a HTTP POST and retrieving an album will be a HTTP GET so we can have an example of both.  We'll first start with retrieving a list of albums by creating request and response objects.  We want to search for a specific artist so the request object will have a artist attribute.

package com.herzog.boot.dtos;

public class AlbumListRequest {

 private String artist;

 public String getArtist() {
  return artist;
 }

 public void setArtist(final String artist) {
  this.artist = artist;
 }

}

The response object is just going to return a list of strings for now.  We are not going to hook up to the iTunes API just yet.


package com.herzog.boot.dtos;

import java.util.List;

public class AlbumListResponse {

 private List albums;

 public List getAlbums() {
  return albums;
 }

 public void setAlbums(final List albums) {
  this.albums = albums;
 }

}


For retrieving an album, we are going to use an HTTP GET so we will only have a response object.  We'll use a path variable for the request.  The album response object will just return the name and the number of tracks in the album.

package com.herzog.boot.dtos;

public class AlbumResponse {

 private String name;
 private int tracks;

 public String getName() {
  return name;
 }

 public void setName(final String name) {
  this.name = name;
 }

 public int getTracks() {
  return tracks;
 }

 public void setTracks(final int tracks) {
  this.tracks = tracks;
 }

}

Now that the DTOs have been created, it is time to create the interface for the RESTful APIs.  We'll have two methods.  The list method will be used to retrieve a list of albums and the find method will be used to retrieve information about a specific album.

package com.herzog.boot.controller;

import com.herzog.boot.dtos.AlbumListRequest;
import com.herzog.boot.dtos.AlbumListResponse;
import com.herzog.boot.dtos.AlbumResponse;

public interface AlbumController {
 
 /**
  * Return a list of albums by a specific artist
  * 
  * @param request AlbumListRequest
  * @return AlbumListResponse
  * @throws Exception - throw all exceptions
  */
 public AlbumListResponse list(final AlbumListRequest request) throws Exception;
 
 /**
  * Return the properties of a specific album
  * 
  * @param id - Album ID
  * @return AlbumResponse
  * @throws Exception - throw all exceptions
  */
 public AlbumResponse find(final int id) throws Exception;


}

Lastly, we need to create the implementation class.  We'll leverage all of Spring's MVC components.  If you have worked with REST in Spring before, this should all look familiar to you.  If you haven't, I recommend that you look into Spring MVC.  I will not go into that since it is out of the scope of this tutorial.

package com.herzog.boot.controller;

import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.herzog.boot.dtos.AlbumListRequest;
import com.herzog.boot.dtos.AlbumListResponse;
import com.herzog.boot.dtos.AlbumResponse;

@Controller("albumController")
@RequestMapping(value = "/api/album", consumes = "application/json", 
 produces = "application/json")
public class AlbumControllerImpl implements AlbumController {
 
 @Override
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    @ResponseBody
 public AlbumListResponse list(@RequestBody final AlbumListRequest request) throws Exception {
  
  AlbumListResponse response = new AlbumListResponse();
  List albums = new ArrayList();
  for (int i = 0; i < 10; i++) {
   albums.add(request.getArtist() + " Album " + i); 
  }
  response.setAlbums(albums);

        return response;
    }

 @Override
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @ResponseBody
 public AlbumResponse find(@PathVariable(value = "id") final int id) throws Exception {
  
  AlbumResponse response = new AlbumResponse();
  response.setName("Album " + id);
  response.setTracks(10);
  
  return response;
 }

}

If you have worked with the Spring framework before, you are probably thinking what happened to all the configuration steps.  That is the beauty of Spring Boot.  All the configuration steps are done for you by default by Spring Boot.

Now it is time to build and run the application. We can build the application by running the following command:

 mvn package

Lastly, run the application:

 java -jar target/spring-boot-angular-0.0.2-SNAPSHOT.war 

You'll need to use your favorite REST Client to invoke the RESTful services. Make sure that you set the HTTP headers for Accept and Content-type to application/json. The URLs for the two RESTful APIs we just created are as follows:

List Albums (POST) - http://localhost:8080/api/album/list
Retrieve Album (GET) - http://localhost:8080/api/album/:id

You can find the existing source code for part 2 at https://bitbucket.org/davidjherzog/spring-boot-angular.  The code is under branch 0.0.2-SNAPSHOT.

In Part 3 of this series, we will add some RESTful services.

Sunday, June 7, 2015

Spring Boot Angular Part 1

In a multi-part series, I will discuss how to build a Spring Boot web application leveraging AngularJS for the front end and using Maven and Grunt for the build process.  I've been using the Spring framework for years and wanted to start learning about Spring Boot.  What I found was that it made it developing java based web applications even easier.  We are going to build a web application using the Apple iTunes API.

We'll first start creating a maven pom file.  Inside the pom.xml file, you'll have inherit from the spring-boot-starter-parent project.  This will include all the core dependencies that you will need.  You will also have to include the spring-boot-maven-plugin.  Lastly, since I plan on building a web project, I'll include the spring-boot-starter-web dependency.  The great thing about Spring Boot is that it handles many of the dependencies and standard configuration for you.


 4.0.0
 com.herzog
 spring-boot-angular
 0.0.1-SNAPSHOT
 war

 
  org.springframework.boot
  spring-boot-starter-parent
  1.1.4.RELEASE
 

 
  
   org.springframework.boot
   spring-boot-starter-web
  
 
 
 
  
   
    org.springframework.boot
    spring-boot-maven-plugin
   
  
 

Spring Boot handles most of the configuration out of the box for you. However, you do need to create a entry point into your application. You'll need to create a class that invokes the run method of the SpringApplication class. I've created an Application class under src/main/java/com/herzog/boot.
package com.herzog.boot;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan
@EnableAutoConfiguration
public class Application {
 
 public static void main(String[] args) {
  SpringApplication.run(Application.class, args);
 }
}
Now we will create a simple HTML file for our web application. We'll create a index.html file under src/main/webapp. Add the following to the body of the html.

Spring Boot

Now it is time to build and run the application. We can build the application by running the following command:

 mvn package

 Lastly, run the application:

 java -jar target/spring-boot-angular-0.0.1-SNAPSHOT.war 

An embedded Jetty server will start up. Open your browser and go to the following address:

http://localhost:8080/

That's it. You can find the existing source code for part 1 at https://bitbucket.org/davidjherzog/spring-boot-angular.  The code is under branch 0.0.1-SNAPSHOT.

In Part 2 of this series, we will add some RESTful services.