Tuesday, 8 December 2015

What methods are available in RestTemplate?

/**
 * <strong>The central class for client-side HTTP access.</strong> It simplifies communication with HTTP servers, and
 * enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible
 * template variables) and extract results.
 *
 * <p>The main entry points of this template are the methods named after the six main HTTP methods:

 * <table>
 * <tr><th>HTTP method</th><th>RestTemplate methods</th></tr>
 * <tr><td>DELETE</td><td>{@link #delete}</td></tr>
 * <tr><td>GET</td><td>{@link #getForObject}</td></tr>
 * <tr><td></td><td>{@link #getForEntity}</td></tr>
 * <tr><td>HEAD</td><td>{@link #headForHeaders}</td></tr>
 * <tr><td>OPTIONS</td><td>{@link #optionsForAllow}</td></tr>
 * <tr><td>POST</td><td>{@link #postForLocation}</td></tr>
 * <tr><td></td><td>{@link #postForObject}</td></tr>
 * <tr><td>PUT</td><td>{@link #put}</td></tr>
 * <tr><td>any</td><td>{@link #exchange}</td></tr>

 * <tr><td></td><td>{@link #execute}</td></tr> </table>

How to write Spring Rest Client with SSL

Step-1
create rest-template.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
            http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

<bean id="crestTemplate" class="org.springframework.web.client.RestTemplate">
</bean>          
</beans>  

Step-2
Create client side keystore

E:\CERTIFICATE>keytool -genkey -keyalg RSA -alias calbum  -keystore  ckeystore.jks  -validity 360
Enter keystore password:
Re-enter new password:
What is your first and last name?
  [Unknown]:  localhost
What is the name of your organizational unit?
  [Unknown]:  client
What is the name of your organization?
  [Unknown]:  CL
What is the name of your City or Locality?
  [Unknown]:  Delhi
What is the name of your State or Province?
  [Unknown]:  Delhi
What is the two-letter country code for this unit?
  [Unknown]:  IN
Is CN=localhost, OU=client, O=CL, L=Delhi, ST=Delhi, C=IN correct?
  [no]:  yes

Enter key password for <calbum>
        (RETURN if same as keystore password):

Step-3
We need server side certificate  for client side keystore
Exporting the service side certifcate into a file=frog.cer

E:\CERTIFICATE>keytool -export -alias album -file frog.cer -keystore keystore.jks
Enter keystore password:root@123
Certificate stored in file <frog.cer>


Step-4
Importing the server side certificate(frog.cer) into client side keystore

E:\CERTIFICATE>keytool -importcert -noprompt -trustcacerts  -file frog.cer   -keystore ckeystore.jks
Enter keystore password:root@123
Certificate was added to keystore


Step-5
Write Rest client program using RestTemplate to access restful web service running over HTTPS

Client side change in java code

add below line to enable certificate information for client

System.setProperty("https.protocols", "TLSv1");
System.setProperty("javax.net.debug", "ssl");
System.setProperty("javax.net.ssl.trustStore", "E:/CERTIFICATE/ckeystore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "root@123");


// //////////Write code to access the restful web service//////////// // Write a client code to access the restful web service ApplicationContext applicationContext = new ClassPathXmlApplicationContext( "rest-template.xml"); RestTemplate restTemplate = (RestTemplate) applicationContext .getBean("crestTemplate"); Scanner scanner = new Scanner(System.in); System.out.println("Enter the fruitid please"); String fruitid = scanner.next(); List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>(); acceptableMediaTypes.add(MediaType.APPLICATION_JSON); HttpHeaders headers = new HttpHeaders(); // what output we are expecting headers.setAccept(acceptableMediaTypes); // /We are setting the format of data which will from client to server headers.setContentType(MediaType.TEXT_PLAIN); HttpEntity requestEntity = new HttpEntity(headers); // Java Http Client ResponseEntity<FruitForm> response = restTemplate.exchange( "https://localhost:8443/spring-app-fruit/rest/v1/fruit/" + fruitid, HttpMethod.GET, requestEntity,FruitForm.class); FruitForm result = response.getBody(); System.out.println(response.getHeaders());
  System.out.println(result);


}



What methods are available in RestTemplate?


How to access Restful web service using Java Http Client


Step-1

First we need to add these dependencies in pom.xml
<!-- GSON -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>

<!-- http client -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.1.1</version>
</dependency>


class ProgramService {

     @Override
public void addProgram(ProgramVO programVo) {

DefaultHttpClient client = new DefaultHttpClient();

//This code converting Java Object into JSON String
String json = new GsonBuilder().create().toJson(programVo, ProgramVO.class);

HttpResponse response =null;
try{

      //Define a postRequest request
        HttpPost postRequest = new HttpPost("http://www.gpsprogramys.co.in/com.gps.quiz/android/v1/program/padd");
         
        //Set the API media type in http content-type header
         //Here we are setting content-type & Accept as JSON
        postRequest.setHeader("content-type", "application/json");
        postRequest.setHeader("Accept", "application/json"); 
       
        //Set the request post body
        postRequest.setEntity(new StringEntity(json));
         
        //Send the request; It will immediately return the response in HttpResponse object if any
        response = client.execute(postRequest);
        System.out.println(response.toString());
       
        //verify the valid error code first
        int statusCode = response.getStatusLine().getStatusCode();
       
        System.out.println(statusCode);
        System.out.println(statusCode);
         /*if (statusCode != 201)
        {
            throw new RuntimeException("Failed with HTTP error code : " + statusCode);
        }*/
}
catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
finally
    {
        //Important: Close the connect
        client.getConnectionManager().shutdown();
    }
}
}

Rest Provider code :-

@Controller
@Scope("request")
@RequestMapping(value = "/v1/program")
public class ProgramController {

@Autowired
@Qualifier("ProgramService")
private IProgramService iProgramService;

public ProgramController() {
}

@RequestMapping(value =ProgramURIConstant.GET_PROGRAM, method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody
ProgramVO findProgramById(@PathVariable("pid") String programid) {
ProgramVO result = iProgramService.findProgramByQId(programid);
return result;
}

@RequestMapping(value = ProgramURIConstant.ADD_PROGRAM, method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody
String addProgram(@RequestBody ProgramVO programVO) {
programVO.setTimestamp(DateUtils.getCurrentTimeIntoTimestamp());
String result = iProgramService.addProgram(programVO);
return result;
}

@RequestMapping(value = "padd", method = RequestMethod.POST)
@ResponseStatus(value=HttpStatus.OK)
public @ResponseBody
String addProgramText(@RequestBody ProgramVO programVO) {
programVO.setTimestamp(DateUtils.getCurrentTimeIntoTimestamp());
String result = iProgramService.addProgram(programVO);
return result;

}
}

Accessing Restful web service using RestTemplate or How does RestTemplate work?


Questions : How does RestTemplate work?

Rest Client Program using RestTemplate

Spring configuration file......
rest-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
            http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
</bean>   
</beans>



@Service("ProgramServiceImpl")
public class ProgramServiceImpl implements IProgramService{
    
    @Autowired
    @Qualifier("restTemplate")
   private  RestTemplate restTemplate;

    @Override

    public void addProgram(ProgramVO programVo) {

       //Defining what output we are expecting from rest web service
       List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
        acceptableMediaTypes.add(MediaType.APPLICATION_JSON);

        //Here we are creating header object......................
        HttpHeaders headers = new HttpHeaders();
        
        // what output we are expecting from server = ie. rest provider
        headers.setAccept(acceptableMediaTypes);
        
         //the format of data which we are sending from client to server
        headers.setContentType(MediaType.APPLICATION_JSON);

       // setting header
       HttpEntity<ProgramVO> requestEntity = new HttpEntity<ProgramVO>(programVo,      headers);

       ResponseEntity<String> response = restTemplate.exchange(
                "http://www.gpsprogramys.co.in/com.gps.quiz/android/v1/program/padd", HttpMethod.POST,          requestEntity,String.class);

      String output = response.getBody();

}

ProgramVOWrapper .java (Wrapper class)

public class ProgramVOWrapper {

    List<ProgramVO> programVOs;
    public List<ProgramVO> getProgramVOs() {
        return programVOs;
    }
    public void setProgramVOs(List<ProgramVO> programVOs) {
        this.programVOs = programVOs;
    }
    @Override
    public String toString() {
        return "ProgramVOWrapper [programVOs=" + programVOs + "]";
    }

}

public class ProgramVO {

    private String id;
    private String programTiitle;
    private String code;
    private String topic;
    private String language;
    private String level;
    private Timestamp timestamp;
    private String userid;
     private Date cdate;
     
     //getter and setter of all above attributes.............. 
}


Accessing image in Rest web service client 

// Prepare acceptable media type
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.IMAGE_JPEG);
// Prepare header
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
HttpEntity<String> entity = new HttpEntity<String>(headers); 
// Send the request as GET
//                /http://localhost:8090/ImageProvider/rest/images/bella
//This is calling restful web service
             
RestTemplate restTemplate = new RestTemplate();

ResponseEntity<byte[]> result = restTemplate.exchange(ApplicationConstants.APPLICATION_BASE_URL+"/images/"+imageName, HttpMethod.GET, entity, byte[].class);


Note: In above URI we are sending "imageName" as a part of rest URI 







Monday, 7 December 2015

Adding Validation to a REST API with Spring MVC

We want to use the JSR-303 backed validation with Spring Framework, we have to add a JSR-303 provider to our classpath. Here we are using Hibernate Validator 4.2.0 which is the reference implementation of the Bean Validation API (JSR-303).

Step-1
Add below dependency.....

<!-- Form Validation using Annotations
        JSR 303 - Bean 
        -->  
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>

</dependency>

Step-2
Enable the validation
Add below entry inside the spring web application context file....


<!-- it enable rest annotation +Validation + Support JSON and XML Response if their lib are in the classpath -->

     <mvc:annotation-driven/>


Step-3
define resource bundle for error message

<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:message" />
<property name="defaultEncoding" value="UTF-8" />

</bean>

Step-4
message_en.properties

#application defined error messsages
id.required=Employee ID is required
name.required=Employee Name is required
role.required=Employee Role is required

negativeValue={0} can't be negative or zero

Step-5
Applying annotation for validation on bean class
public class LoginVO {
@Size(min=6,max=15)
@NotEmpty
private String phone;
private String token;

public String getPhone() {
return phone;
}

public void setPhone(String phone) {

}
}

Step-6
Applying annotation in restful web service.
@RequestMapping(value = LevelURIConstant.VALIDATE_LOGIN, method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody
UserMessage authUserByPhoneValidate(@Valid @RequestBody LoginVO phone) {
String pphone="";
Pattern p = Pattern.compile("[0-9]+");
Matcher m = p.matcher(phone.getPhone());
if(m.find()){
pphone=m.group();
}
if(LOG.isDebugEnabled()) 
LOG.debug("Executing the method findLevel.."+phone);
String result=iUserService.authUserByPhone(phone.getPhone());
UserMessage userMessage=new UserMessage();
if(!"fail".equals(result)){
userMessage.setStatus("success");
userMessage.setMessage("Login Successfully");
userMessage.setToken(phone.getPhone());
}else{
userMessage.setStatus("failed");
userMessage.setMessage("Login Failed");
   userMessage.setToken("unknown");
}
return userMessage;
}


Step-7
Define pojo for error message
public class QuizErrorInfo {
private String status;
private String code;
private String message;
private String ex;
private String moreInfo;
         public QuizErrorInfo(String status, String code, String message, String ex,
String moreInfo) {
this.status = status;
this.code = code;
this.message = message;
this.ex = ex;
this.moreInfo = moreInfo;
}
}



Step-8
Define global exception handler for handling error message
using spring annotation @ControllerAdvice since spring 3.2

@ControllerAdvice
public class GPSGlobalExceptionHandler { 

@ExceptionHandler(MethodArgumentNotValidException.class)
 @ResponseStatus(HttpStatus.BAD_REQUEST)
 @ResponseBody
 public QuizErrorInfo processValidationError(HttpServletRequest req,MethodArgumentNotValidException ex) {
   BindingResult result = ex.getBindingResult();
   List<FieldError> fieldErrors = result.getFieldErrors();
   String errors= processFieldErrors(fieldErrors);
   QuizErrorInfo errorInfo=new QuizErrorInfo(HttpStatus.BAD_REQUEST.toString(),"3000" , errors, ex.getClass().toString(), req.getRequestURL().toString());
   return errorInfo;
 }

private String processFieldErrors(List<FieldError> fieldErrors) {
StringBuilder builder=new StringBuilder();
        for (FieldError fieldError: fieldErrors) {
        builder.append(fieldError.getField()+" = "+fieldError.getDefaultMessage()+" , ");
        }
        return builder.toString();

    }

}

http://localhost:5050/app-name/android/v1/vlogin

Input for above rest web service
{"phone":"02","token":"9873003702"}

output :
{
  "status": "400",
  "code": "3000",
  "message": "phone = size must be between 6 and 15 , ",
  "ex": "class org.springframework.web.bind.MethodArgumentNotValidException",
  "moreInfo": "http://localhost:5050/com.gps.quiz/android/v1/vlogin"

}