Exception handling with RestTemplate

Spring framework offers RestTemplate for consuming RESTful services. Recently I used RestTemplate for consuming one of the third party RESTful service.

RestTemplate offers 'ResponseErrorHandler'; which you can extend to decide which are errors for you and how to handle those error. You can override hasError and handleError methods of ResponseErrorHandler.
In handleError you can throw customException if you want, as outlined in below code.

import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.ResponseErrorHandler;

import java.io.IOException;

public class RestTemplateErrorHandler implements ResponseErrorHandler {

    @Override
    public void handleError(ClientHttpResponse response) throws IOException
    {
        throw new MyCustomException(response.getStatusText(), response.getStatusCode());
    }

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException
    {
        if ( (response.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR)
                || (response.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR))
        {
            return true;
        }
        return false;
    }
}

But there is caveat with this error handler. If the server is down or not accessible, RestTemplate throws 'ResourceAccessException'. Internally RestTemplate encounters 'IOException' when server is not accessible. RestTemplate catches 'IOException' and throws 'ResourceAccessException'. In this process error handler doesn't  get invoked hence the custom exception will not be thrown.

So to avoid this situation I handled 'RestClientException' in code where RestTemplate was being invoked, and returned proper error message.

Related Posts:
Exception handeling for RESTful service

Exception handling for RESTful service in Spring framework

In last couple of posts we have seen how to create RESTful service using Spring framework. Here we will see how can we handle error conditions and return appropriate status code and message.


  • Use @ResponseStatus on custom exception

In case of error, throw custom exception annotate with @ResponseStatus. Code below shows how to define CustomException. 


@ResponseStatus(value = HttpStatus.SERVICE_UNAVAILABLE, reason = "The service is unavailable")
class CustomException extends RuntimeException{
 //...   
}


  • Return ResponseEntity<> with appropriate error code

ResponseEntity can be used as below.


@RestController
public class HelloController {
    @RequestMapping("/hello")
    public ResponseEntity sayHello(@RequestParam(value="name", required = false, defaultValue = "World") String name) {
        try {
            return new ResponseEntity<>(String.format("Hello %s with Spring Boot !!!", name), HttpStatus.OK);
        }catch (RuntimeException excp){
            //log error excp
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}


  • You also throw RuntimeException which will return with error code "Internal Server Error" always. 

Path variable with Spring Boot

In the last post "Query parameter handling with Spring Boot"  we have seen how to provide the query parameter . I will be using same project and extending HelloController for this.

For RESTful service to access specific resource via their Id/name we would also need path variable so that those can be accessed with specific path like "hello/{id}".

This can be achieved with @ PathVariable annotation. Replace the HelloController.java with below code.

package hello;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @RequestMapping("/hello/{id}")
    public String sayHello(@PathVariable("id") String id) {
        return  String.format("Hello world with Spring Boot !!! Id used here %s", id);
    }
}

Run the application and hit http://localhost:8080/hello/myId in your browser. You should get "Hello world with Spring Boot !!! Id used here myId" in return. 

Query parameter handling with Spring Boot

In last post, Hello World with Spring Boot we have seen how to create REST service with Spring Boot. Now we will extend the same HelloController to work on query parameters.

Here we will get the "name" as query parameter, and respond with updated message. Update HelloController.java file with below code. 

  
package hello;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String sayHello(@RequestParam(value="name") String name) {
        return  String.format("Hello %s with Spring Boot !!!", name);
    }
}

We have added @RequestParam annotation which will assign value of query parameter 'name' to variable name. Now run you application and hit "http://localhost:8080/hello?name=XYZ" on browser. You should get "Hello XYZ with Spring Boot !!!" in return.
But with this code the "http://localhost:8080/hello" URL will return error "bad request" as query parameter is missing. This is helpful when you want the query parameter as mandatory input.

In order to support optional query parter, you can have default value for parameters as below.
 
package hello;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String sayHello(@RequestParam(value="name", defaultValue="World") String name) {
        return  String.format("Hello %s with Spring Boot !!!", name);
    }
}

'defaultValue' allows the query parameter to be optional. Optional query parameters can be handled using 'required = false' as code below.  'defaultValue' will assign default value to variable 'name', if it's not specified value of 'name' would be null. 


@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String sayHello(@RequestParam(value="name", required = false, defaultValue = "World") String name) {
        return  String.format("Hello %s with Spring Boot !!!", name);
    }
}

Hello World REST Service with Spring boot

Recently I tried creating RESTful service with Spring Boot.  Its very easy to create RESTful service using Spring Boot, and also it removes lots of boilerplate code.

I will be walking through creating a simple hello world service. I have used Intellij Idea 15 and Java SDK 1.8, Maven 4.0.0 to build and run the project.

Lets start by creating a maven based project in Intellij. Specified required  SDK, groupId, artifactId and project name.

Now create a directory named "hello" under src->main->java.  Create a new Java class named HelloController (under directory 'hello'). Add below code to HelloController.Java

package hello;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String sayHello() {
        return "Hello World with Spring Boot !!!";
    }
}
Your hello REST controller is ready now.
Create Application.Java file under src->main->java->hello directory. Update Application.java with below code.

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

locate your pom.xml it should be under parent directory of project.
Update pom.xml with below dependencies.

    
        1.8
    

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

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

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

Now to run the application, create application run configuration. Select project and click on edit configuration (Under Run menu). Add new configuration for "Application", for Main class select hello.Application. Set the working directory as project root and OK.

Now run the application and go to your browser and hit "http://localhost:8080/hello"

You should see the service returns with "Hello World with Spring Boot!!!".

Reference : Rest-service with Spring

Golang: Http POST Request with JSON Body example

Go standard library comes with "net/http" package which has excellent support for HTTP Client and Server.   In order to post JSON ...