Passing and validating RequestParam in spring-boot rest api

In my previous article Creating first rest api in spring-boot we learned how you can create rest api. Now lets learn how you can pass parameters to api and validate it. In this example I'm going to use code from my previous article or you can head to Spring Tutorials page.

@RequestParam
Annotation which indicates that a method parameter should be bound to a web request parameter.

Source code (HelloWorldController.java)
import javax.validation.constraints.Size;

import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author javaQuery
 * @since 2018-01-31
 * @github https://github.com/javaquery/spring-boot-examples
 */
@RestController
@RequestMapping("/api")
@Validated
public class HelloWorldController {
 
 /**
  * This will send Hello {name-from-parameter} in response with HTTP status code 200.
  * @since 2018-02-01
  * @param firstname
  * @param lastname
  * @return
  */
   @GetMapping("/hello")
   public ResponseEntity<?> sayHello(
     @RequestParam @Size(min= 1, max = 5, message = "firstname length must be between 1 and 5") String firstname,
     @RequestParam String middlename,
     @RequestParam(required = false) String lastname){
    /* check lastname value */
    lastname = lastname != null ? lastname : "{lastname-is-optional}";
    return ResponseEntity.ok("Hello " + firstname + " " + middlename + " " + lastname);
   }
}
Request parameter syntax
Using @RequestParam spring rest api accept parameters from the request. You can also use various annotation from package javax.validation.constraints with @RequestParam.
@RequestParam <data_type> <variable_name>;

Lets quickly understand annotations used in HelloWorldController.java. As we already discussed few annotations in Creating first rest api in spring-boot so we will talk about new annotations only.

  • @Validated - To perform validation on each method of controller if any.
  • @RequestParam - To accept web request parameter in variable. (Note: All variable annotated with @RequestParam are compulsory/mandatory for request, until you set required = false @RequestParam(required = false) for that parameter)
Request parameter variations
@RequestParam @Size(min= 1, max = 5 , message = "firstname length must be between 1 and 5") String firstname
- @Size of package javax.validation.constraints is used to validate length of parameter in request and will throw ConstraintViolationException if data is not valid. You can read more about Constraints validation for user inputs.
@RequestParam String middlename
- Accept mandatory parameter in variable middlename. If parameter is not present in request then spring will throw MissingServletRequestParameterException.
@RequestParam(required = false) String lastname
- Accept optional parameter in variable lastname.

Exception Handling
For exception org.springframework.web.bind.MissingServletRequestParameterException and javax.validation.ConstraintViolationException, spring will send 500 (Internal Server Error) in response so we'll catch those exception and send customized response.

Source code (RestExceptionHandler.java)
Used to catch exception thrown.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

/**
 * @author javaQuery
 * @since2018-02-01
 */
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice()
public class RestExceptionHandler extends ResponseEntityExceptionHandler{
 
   @Override
   protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers,
     HttpStatus status, WebRequest request) {
    String error = ex.getParameterName() + " parameter is missing.";
    return new ResponseEntity<Object>(new ErrorResponse<>(Arrays.asList(error)), HttpStatus.BAD_REQUEST);
   }
 
   /**
    * Exception thrown when {@link org.springframework.validation.annotation.Validated} is used in controller.
    * @param ex
    * @param request
    * @return
    */
   @ExceptionHandler(ConstraintViolationException.class)
   protected ResponseEntity<?> handleConstraintViolationException(ConstraintViolationException ex, HttpServletRequest request) {
    try {
     List<String> messages = ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.toList());
     return new ResponseEntity<>(new ErrorResponse<>(messages), HttpStatus.BAD_REQUEST);
    } catch (Exception e) {
     return new ResponseEntity<>(new ErrorResponse<>(Arrays.asList(ex.getMessage())), HttpStatus.INTERNAL_SERVER_ERROR);
    }
   }
}
Source code (ErrorResponse.java)
Used to wrap the error message for response.
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

/**
 * @author javaQuery
 * @since 2018-02-01
 * 
 * @param <T>
 */
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_NULL)
public class ErrorResponse<T> {
   private List<T> errors = new ArrayList<>(1);
 
   public ErrorResponse(List<T> errors) {
    this.errors = errors;
   }
 
   public List<T> getErrors() {
    return errors;
   }
}

Request/Response
cURL GET http://localhost:8080/api/hello
-code 400
-body {"errors":["firstname parameter is missing."]}
cURL GET http://localhost:8080/api/hello?firstname=&middlename=v
-code 400
-body {"errors":["firstname length must be between 1 and 5"]}
cURL GET http://localhost:8080/api/hello?firstname=vicky&middlename=v
-code 200
-body Hello vicky v {lastname-is-optional}
cURL GET http://localhost:8080/api/hello?firstname=vicky&middlename=v&lastname=thakor
-code 200
-body Hello vicky v thakor

Creating first rest api in spring-boot

spring-boot
Today we are going to learn how to create rest api in spring-boot. This example is created using gradle, if you are not familiar with how to setup gradle project in eclipse follow the steps stated in Setup first gradle project in eclipse

build.gradle
update your build.gradle as follow and refresh the project, gradle will download the required dependencies(jar files).
buildscript {
    ext {
        springBootVersion = '1.5.7.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-web')
}

Source code (HelloWorldController.java)
Spring follows Model-View-Controller so we'll use widely used package structure and filenames. Now create package like com.example.package.rest.controller
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author javaQuery
 * @since 2018-01-31
 * @github https://github.com/javaquery/spring-boot-examples
 */
@RestController
@RequestMapping("/api") 
public class HelloWorldController {
 
 /**
  * This will send Hello World in response with HTTP status code 200.
  * @return
  */
 @GetMapping("/helloworld")
 public ResponseEntity sayHello(){
  /* return response */
  return ResponseEntity.ok("Hello World");
 }
}
Lets quickly understand annotations used in HelloWorldController.java

  • @RestController - To denote class will be service as rest service
  • @RequestMapping("/api") - default/root path for all apis created under HelloWorldController.java
  • @GetMapping("/helloworld") - sayHello method will serve for GET http request made for path /api/helloworld

Source code (Application.java)
Create Application.java (main-class) in package best suited your project,
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * @author javaQuery
 * @since 2018-01-31
 * @github https://github.com/javaquery/spring-boot-examples
 */
@SpringBootApplication
@ComponentScan(basePackages = { "com.javaquery.examples.springboot.rest" })
public class Application {
 public static void main(String[] args) {
  SpringApplication.run(Application.class, args);
 }
}
Lets quickly understand annotations used in Application.java

  • @SpringBootApplication - denotes entry point of spring-boot application
  • @ComponentScan - files under given package(s) are part/component of spring application so spring will process the annotations.
Now run Application.java like any other java application with main method. It'll start local server and your rest API is ready to test. Open up localhost:8080/api/helloworld in your browser.

Project Structure

Source code is also available on my github repository: https://github.com/javaquery/spring-boot-examples. You can also check spring tutorials on http://www.javaquery.com/p/spring-tutorials.html and new you can do Passing and validating RequestParam in spring-boot rest api

What is the difference between HQL and Criteria in Hibernate?

HQL (Hibernate Query Language)

  • HQL can be used to perform SELECT, INSERT, UPDATE, DELETE.
  • SQL injection possible if not used parameterized query.
  • SELECT STATEMENT: You've to manually write the long queries, take care of where and other syntax.

Criteria

  • Criteria can be used to perform only SELECT.
  • SQL injection is not possible with Criteria because hibernate will take care of it while generating SQL query.
  • SELECT STATEMENT: Criteria interface comes with handy methods and take care of where and other syntax.

These are the basic difference between HQL (Hibernate Query Language) and Criteria. Do comment if other important difference is there.

Check out the stackoverflow thread for performance of Hibernate Criteria vs HQL: which is faster?

Hibernate one to many mapping example [Annotation]

We are going to understand hibernate one-to-many relationship on following table structure...

country table holds one-to-many relationship with state table. Where relationship id resides in state table.

Hibernate One to Many mapping

Before we see the complete code, lets first understand how to define relationship in code.

Country.java, State.java

one to many hibernate

Source code (Country.java)
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

/**
 * @author javaQuery
 * @date 11th April, 2017
 * @Github: https://github.com/javaquery/Examples
 */
@Entity
@Table(name = "country")
public class Country implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @OneToMany(mappedBy = "country" /*, fetch = FetchType.LAZY*/)
    private Set<State> states = new HashSet<State>();
    
    //getter-setter
}

Source code (State.java)
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
 * @author javaQuery
 * @date 15th June, 2017
 * @Github: https://github.com/javaquery/Examples
 */
@Entity
@Table(name = "state")
public class State implements Serializable{

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "country_id")
    private Country country;

    @Column(name = "name")
    private String name;
    
    //getter-setter
}

Source code (OneToManyMappingExample.java)
import com.javaquery.bean.Country;
import com.javaquery.bean.State;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * Hibernate one to many example.
 * 
 * @author javaQuery
 * @date 15th June, 2017
 * @Github: https://github.com/javaquery/Examples
 */
public class OneToManyMappingExample {

    public static void main(String[] args) {
        try {
            /* Create hibernate configuration. */
            Configuration configuration = new Configuration();
            configuration.configure("com\\javaquery\\database\\hibernate\\hibernate.cfg.xml");

            /* Open session and begin database transaction for database operation. */
            SessionFactory sessionFactory = configuration.buildSessionFactory();
            Session session = sessionFactory.openSession();

            Country country = session.load(Country.class, 1L);
            if(!country.getStates().isEmpty()){
                for (State state: country.getStates()) {
                    System.out.println(state.getName());
                }
            }else{
                System.out.println("No states found!");
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Output
Hibernate: 
    select
        country0_.id as id1_1_0_,
        country0_.name as name2_1_0_ 
    from
        country country0_ 
    where
        country0_.id=?
Hibernate: 
    select
        states0_.country_id as country_3_3_0_,
        states0_.id as id1_3_0_,
        states0_.name as name2_3_1_ 
    from
        state states0_ 
    where
        states0_.country_id=?
  
Banglore
Gujarat
Mumbai

Hibernate one to one mapping example [Annotation]

We all understand one-to-one relation in database but when it comes to Hibernate I always stuck at which annotation to use and where should I place it?

We are going to understand the hibernate one-to-one relationship on following table structure.
- country table holds the one-to-one relationship with languages table. Where relationship id resides in country table.
- country table holds the one-to-one relationship with capital table. Where relationship id resides in capital table.


Before we see the complete code, lets first understand how to define relationship in code.

Country.java (country - languages)


Capital.java (country - capital)


Source code (Country.java)
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

/**
 * @author javaQuery
 * @date 11th April, 2017
 * @Github: https://github.com/javaquery/Examples
 */
@Entity
@Table(name = "country")
public class Country implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "country")
    private Capital capital;

    @OneToOne
    @JoinColumn(name = "primary_language_id", referencedColumnName = "id")
    private Language language;
 
    //getter-setter
}

Source code (Language.java)
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * @author javaQuery
 * @date 1th April, 2017
 * @Github: https://github.com/javaquery/Examples
 */
@Entity
@Table(name = "languages")
public class Language implements Serializable{
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;
    
    @Column(name = "language")
    private String language;
 
    //getter-setter
}

Source code (Capital.java)
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

/**
 * @author javaQuery
 * @date 11th April, 2017
 * @Github: https://github.com/javaquery/Examples
 */
@Entity
@Table(name = "capital")
public class Capital implements Serializable{
    
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;
    
    @Column(name = "name")
    private String name;

    
    @OneToOne
    @JoinColumn(referencedColumnName = "id", name = "country_id")
    private Country country;
 
    //getter-setter
}

Source code (OneToOneMappingExample.java)
import com.javaquery.bean.Country;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * @author javaQuery
 * @date 11th April, 2017
 * @Github: https://github.com/javaquery/Examples
 */
public class OneToOneMappingExample {

    public static void main(String[] args) {
        try {
            /* Create hibernate configuration. */
            Configuration configuration = new Configuration();
            configuration.configure("com\\javaquery\\database\\hibernate\\hibernate.cfg.xml");

            /* Open session and begin database transaction for database operation. */
            SessionFactory sessionFactory = configuration.buildSessionFactory();
            Session session = sessionFactory.openSession();
            
            Country country = session.load(Country.class, 1L);
            System.out.println(country);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Output
Hibernate: 
    select
        country0_.id as id1_1_0_,
        country0_.primary_language_id as primary_3_1_0_,
        country0_.name as name2_1_0_,
        language1_.id as id1_2_1_,
        language1_.language as language2_2_1_,
        capital2_.id as id1_0_2_,
        capital2_.country_id as country_3_0_2_,
        capital2_.name as name2_0_2_ 
    from
        country country0_ 
    left outer join
        languages language1_ 
            on country0_.primary_language_id=language1_.id 
    left outer join
        capital capital2_ 
            on country0_.id=capital2_.country_id 
    where
        country0_.id=?

Country{id=1, name=India, capital=Capital{id=2, name=Delhi}, language=Language{id=2, language=Hindi}}

Google Gson for converting Java object to / from JSON

Following code snippet shows how you can convert Java object to JSON string and vice versa.

Source code (Item.java)
public class Item {

    private Long id;
    private String name;
    private Double price;

    public Item() {
    }
    
    public Item(String name, Double price) {
        this.name = name;
        this.price = price;
    }
    
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }

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

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
    
    @Override
    public String toString() {
        return "Item{" + "name=" + name + ", price=" + price + '}';
    }
}

Source code (ObjectToJSON.java)
import com.google.gson.Gson;
import com.javaquery.bean.Item;
import java.util.Arrays;
import java.util.List;

/**
 * Convert Java object to json using gson.
 * @author javaQuery
 * @date 24th March, 2017
 * @Github: https://github.com/javaquery/Examples
 */
public class ObjectToJSON {
    public static void main(String[] args) {
        /* Java object */
        Item iPhone = new Item("iPhone 7", 100.12);
        Item blackBerry = new Item("Black Berry", 50.12);
        List<Item> items = Arrays.asList(iPhone, blackBerry);
        
        Gson gson = new Gson();
        
        /* Convert single Object to JSON */
        String jsonObjectString = gson.toJson(iPhone);
        System.out.println(jsonObjectString);
        
        /* Convert List of Object to JSON */
        String jsonArrayString = gson.toJson(items);
        System.out.println(jsonArrayString);
    }
}

Output
{"name":"iPhone 7","price":100.12}
[{"name":"iPhone 7","price":100.12},{"name":"Black Berry","price":50.12}]

Source code (JSONToObject.java)
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.javaquery.bean.Item;
import java.lang.reflect.Type;
import java.util.List;

/**
 * Convert json string to java object using gson.
 * @author javaQuery
 * @date 24th March, 2017
 * @Github: https://github.com/javaquery/Examples
 */
public class JSONToObject {
    public static void main(String[] args) {
        String jsonObjectString = "{\"name\":\"iPhone 7\",\"price\":100.12}";
        String jsonArrayString = "[{\"name\":\"iPhone 7\",\"price\":100.12},{\"name\":\"Black Berry\",\"price\":50.12}]";
        
        Gson gson = new Gson();
        
        /* Convert JSONObject String to Object */
        Item item = gson.fromJson(jsonObjectString, Item.class);
        System.out.println(item);
        
        /* Convert JSONArray String to Object */
        Type type = new TypeToken<List<Item>>(){}.getType();
        List<Item> items = gson.fromJson(jsonArrayString, type);
        System.out.println(items);
    }
}

Output
Item{name=iPhone 7, price=100.12}
[Item{name=iPhone 7, price=100.12}, Item{name=Black Berry, price=50.12}]

Autoboxing and unboxing conversions in Java

Autoboxing and unboxing in java

Autoboxing and Unboxing
Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called Unboxing.

Autoboxing
Converting primitive values (int, long, float, double...) into an object of the corresponding wrapper class (Integer, Long, Float, Double...) is called autoboxing. The compiler applies autoboxing when a primitive value is:

  • Passed as a parameter to a method that expects an object of the corresponding wrapper class.
  • Assigned to a variable of the corresponding wrapper class.

Autoboxing Example
The given code
/* Passed as a parameter to a method that expects an object of the corresponding wrapper class. */
List<Integer> listIntegers = new ArrayList<>();
for (int i = 1; i < 10; i++){
 listIntegers.add(i); 
}
=====
/* Assigned to a variable of the corresponding wrapper class. */
int x = 10;
Integer y = x;
will be converted by compiler as follow, Here i is autoboxed by Integer.valueOf(i).
List<Integer> listIntegers = new ArrayList<>();
for (int i = 1; i < 10; i++){
 listIntegers.add(Integer.valueOf(i));
}
=====
int x = 10;
Integer y = Interger.valueOf(x);

Unboxing
Converting an object of a wrapper type (Integer, Long, Float, Double...) to its corresponding primitive (int, long, float, double...) value is called unboxing. The compilere applied unboxing when an object of a wrapper class is:

  • Passed as a parameter to a method that expects a value of the corresponding primitive type.
  • Assigned to a variable of the corresponding primitive type.

Unboxing Example
The given code
/* Assigned to a variable of the corresponding primitive type. */
int sum = 0;
for (Integer i : listIntegers){
 if (i % 2 == 0){
  sum += i;
 }    
}
=====
/* Passed as a parameter to a method that expects a value of the corresponding primitive type. */
Integer a = new Integer(10);
Integer b = new Integer(10);

int summation = sum(a, b);

public int sum(int x, int y){
  return x + y;
}
will be converted by compiler as follow because remainder (%) and unary plus (+=) don't apply on wrapper class Integer. Here i % 2 unboxed by i.intValue() % 2 and sum += i unboxed by sum += i.intValue().
int sum = 0;
for (Integer i : listIntegers){
 if (i.intValue() % 2 == 0){
  sum += i.intValue();
 }    
}
=====
Integer a = new Integer(10);
Integer b = new Integer(10);

int summation = sum(a.intValue(), b.intValue());

public int sum(int x, int y){
  return x + y;
}