Sample REST program

You will use a simple approach to building a stand-alone application. It packages everything into a single, executable JAR file, driven by a main() method. Along the way, you use Spring's support for embedding the Jetty servlet container as the HTTP runtime, instead of deploying it to an external instance. Therefore, we would create the executable JAR in place of the war that needs to be deployed on external web servers.

Now, as you are ready with Spring Boot in NetBeans IDE, you could create your sample web service. You will create a Math API that performs simple calculations and generates the result as JSON.

Let's discuss how we can call and get responses from REST services.

The service will handle GET requests for /calculation/sqrt or /calculation/power and so on. The GET request should return a 200 OK response with JSON in the body that represents the square root of given number. It should look something like this:

{
  "function": "sqrt",
  "input": [
    "144"
  ],
  "output": [
    "12.0"
  ]
}

The input field is the input parameter for the square root function, and the content is the textual representation of the result.

You could create a resource representation class to model the representation by using Plain Old Java Object (POJO) with fields, constructors, setters, and getters for the input, output, and function data:

package com.packtpub.mmj.restsample.model;

import java.util.List;

public class Calculation {

    String function;
    private List<String> input;
    private List<String> output;

    public Calculation(List<String> input, List<String> output, String function) {
        this.function = function;
        this.input = input;
        this.output = output;
    }

    public List<String> getInput() {
        return input;
    }

    public void setInput(List<String> input) {
        this.input = input;
    }

    public List<String> getOutput() {
        return output;
    }

    public void setOutput(List<String> output) {
        this.output = output;
    }

    public String getFunction() {
        return function;
    }

    public void setFunction(String function) {
        this.function = function;
    }

}

Writing the REST controller class

Roy Fielding defined and introduced the term REST, Representational State Transfer in his doctoral dissertation. REST is a style of software architecture for a distributed hypermedia system such as WWW. RESTful refers to those systems that conform to REST architecture properties, principles, and constraints.

Now, you'll create a REST controller to handle the calculation resource. The controller handles the HTTP requests in the Spring RESTful web service implementation.

@RestController

@RestController is a class-level annotation used for the resource class introduced in Spring 4. It is a combination of @Controller and @ResponseBody, and because of it, class returns a domain object instead of a view.

In the following code, you can see that the CalculationController class handles GET requests for /calculation by returning a new instance of the calculation class.

We will implement two URLs for a calculation resource – the square root (Math.sqrt() function) as /calculations/sqrt URL, and power (Math.pow() function) as /calculation/power URL.

@RequestMapping

@RequestMapping annotation is used at class-level to map the /calculation URI to CalculationController class that is, it ensures that the HTTP request to /calculation is mapped to the CalculationController class. Based on the path defined using the annotation @RequestMapping of the URI (postfix of /calculation, for example, /calculation/sqrt/144), it would be mapped to respective methods. Here, the request mapping /calculation/sqrt is mapped to the sqrt() method and /calculation/power is mapped to the pow() method.

You might have also observed that we have not defined what request method (GET/POST/PUT, and so on) these methods would use. The @RequestMapping annotation maps all the HTTP request methods by default. You could use specific methods by using the method property of RequestMapping. For example, you could write a @RequestMethod annotation in the following way to use the POST method:

@RequestMapping(value = "/power", method = POST)

For passing the parameters along the way, the sample demonstrates both request parameters and path parameters using annotations @RequestParam and @PathVariable respectively.

@RequestParam

@RequestParam is responsible for binding the query parameter to the parameter of the controller's method. For example, the QueryParam base and exponent are bound to parameters b and e of method pow() of CalculationController respectively. Both of the query parameters of the pow() method are required since we are not using any default value for them. Default values for query parameters could be set using the defaultValue property of @RequestParam for example @RequestParam(value="base", defaultValue="2"), here, if the user does not pass the query parameter base, then the default value 2 would be used for the base.

If no defaultValue is defined, and the user doesn't provide the request parameter, then RestController returns the HTTP status code 400 with the message 400 Required String parameter base is not present. It always uses the reference of the first required parameter if more than one of the request parameters is missing:

{
  "timestamp": 1464678493402,
  "status": 400,
  "error": "Bad Request",
  "exception": "org.springframework.web.bind.MissingServletRequestParameterException",
  "message": "Required String parameter 'base' is not present",
  "path": "/calculation/power/"
}

@PathVariable

@PathVariable helps you to create the dynamic URIs. @PathVariable annotation allows you to map Java parameters to a path parameter. It works with @RequestMapping where placeholder is created in URI then the same placeholder name is used either as a PathVariable or a method parameter, as you can see in the CalculationController class's method sqrt(). Here, the value placeholder is created inside the @RequestMapping and the same value is assigned to the value of the @PathVariable.

Method sqrt() takes the parameter in the URI in place of the request parameter. For example, http://localhost:8080/calculation/sqrt/144. Here, the 144 value is passed as the path parameter and this URL should return the square root of 144 that is, 12.

To use the basic check in place, we use the regular expression "^-?+\d+\.?+\d*$" to allow only valid numbers in parameters. If non-numeric values are passed, the respective method adds an error message in the output key of the JSON.

Tip

CalculationController also uses the regular expression .+ in the path variable (path parameter) to allow the decimal point(.) in numeric values - /path/{variable:.+}. Spring ignores anything after the last dot. Spring default behavior takes it as a file extension.

There are other alternatives such as adding a slash at the end (/path/{variable}/) or overriding the method configurePathMatch() of WebMvcConfigurerAdapter by setting the useRegisteredSuffixPatternMatch to true, using PathMatchConfigurer (available in Spring 4.0.1+).

package com.packtpub.mmj.restsample.resources;

package com.packtpub.mmj.restsample.resources;

import com.packtpub.mmj.restsample.model.Calculation;
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/calculation")
public class CalculationController {

    private static final String PATTERN = "^-?+\d+\.?+\d*$";

    @RequestMapping("/power")
    public Calculation pow(@RequestParam(value = "base") String b, @RequestParam(value = "exponent") String e) {
        List<String> input = new ArrayList();
        input.add(b);
        input.add(e);
        List<String> output = new ArrayList();
        String powValue = "";
        if (b != null && e != null && b.matches(PATTERN) && e.matches(PATTERN)) {
            powValue = String.valueOf(Math.pow(Double.valueOf(b), Double.valueOf(e)));
        } else {
            powValue = "Base or/and Exponent is/are not set to numeric value.";
        }
        output.add(powValue);
        return new Calculation(input, output, "power");
    }

    @RequestMapping(value = "/sqrt/{value:.+}", method = GET)
    public Calculation sqrt(@PathVariable(value = "value") String aValue) {
        List<String> input = new ArrayList();
        input.add(aValue);
        List<String> output = new ArrayList();
        String sqrtValue = "";
        if (aValue != null && aValue.matches(PATTERN)) {
            sqrtValue = String.valueOf(Math.sqrt(Double.valueOf(aValue)));
        } else {
            sqrtValue = "Input value is not set to numeric value.";
        }
        output.add(sqrtValue);
        return new Calculation(input, output, "sqrt");
    }
}

Here, we are exposing only the power and sqrt functions for the Calculation resource using URI /calculation/power and /calculation/sqrt.

Tip

Here, we are using sqrt and power as a part of the URI, which we have used for demonstration purposes only. Ideally, these should have been passed as value of a request parameter "function"; or something similar based on endpoint design formation.

One interesting thing here is that due to Spring's HTTP message converter support, the Calculation object gets converted to JSON automatically. You don't need to do this conversion manually. If Jackson 2 is on the classpath, Spring's MappingJackson2HttpMessageConverter converts the Calculation object to JSON.

Making a sample REST app executable

Create a class RestSampleApp with the annotation SpringBootApplication. The main() method uses Spring Boot's SpringApplication.run() method to launch an application.

We will annotate the RestSampleApp class with the @SpringBootApplication that adds all of the following tags implicitly:

  • The @Configuration annotation tags the class as a source of Bean definitions for the application context.
  • The @EnableAutoConfiguration annotation indicates that Spring Boot is to start adding beans based on classpath settings, other beans, and various property settings.
  • The @EnableWebMvc annotation is added if Spring Boot finds the spring-webmvc on the classpath. It treats the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
  • The @ComponentScan annotation tells Spring to look for other components, configurations, and services in the given package:
    package com.packtpub.mmj.restsample;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class RestSampleApp {
    
        public static void main(String[] args) {
            SpringApplication.run(RestSampleApp.class, args);
        }
    }

This web application is 100 percent pure Java and you didn't have to deal with configuring any plumbing or infrastructure using XML; instead it uses the Java annotation, that is made even simpler by Spring Boot. Therefore, there wasn't a single line of XML except pom.xml for Maven. There wasn't even a web.xml file.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset