Labels

Java (10) Spring (10) Spring MVC (6) Web Services (5) Rest (4) Javascript (3) Nodejs (3) Spring Batch (3) Angular (2) Angular2 (2) Angular6 (2) Expressjs (2) Passportjs (2) SOAP (2) SOAPUI (2) Spring Boot (2) AJAX (1) H2 (1) JQuery (1) JUnit (1) Npm (1) Puppeteer (1) Python (1) RaspberryPi (1) Raspbian (1) SQL (1) SQLite (1) Scripts (1) html (1)

Sunday, July 23, 2017

JQuery AJAX requests in Spring MVC example

In this tutorial I will show you how to create a controller handles AJAX requests and how to invoke it from your jsp (or .html) view inside a Spring MVC application.

Sketch of the example

I will start with a basic template, very similar to the one we constructed in this previous tutorial.

This will be the basic structure of our Spring MVC project:


The files MvcConfig.java and SpringMvcAjaxExampleApplication.java are the basic configuration classes of our project. Since the configuration of this example is very simple I will not paste their code in this post, but you have all of it here.


The controllers

We will have two controllers, one for the home page and another for the AJAX requests.


HomeController will just handle the view home.jsp to the user:

/src/main/java/com/hjbello/config/HomeController.java

package com.hjbello.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HomeController {

 private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
 
 @RequestMapping(value = "/", method = RequestMethod.GET)
 public ModelAndView home(Model model) { 
  ModelAndView mv = new ModelAndView();
  mv.setViewName("home");
  return mv;
 } 
}


To handle AJAX request, we will need two POJO's, one for the request objects and another for the response objects:
(I will not include constructors, getters and setters to make this post shorter, but they are necessary)


\src\main\java\com\hjbello\config\AjaxRequest.java

package com.hjbello.config;

public class AjaxRequest {
 private String text1;
 private String text2;

//setters, getters and constructors:
[...]  


\src\main\java\com\hjbello\config\AjaxResponse.java


package com.hjbello.config;

public class AjaxResponse {
 private String text1;
 private String text2;
 private String date;

//setters, getters and constructors:
[...]  

And the ajax controller:

\src\main\java\com\hjbello\config\AjaxController.java


package com.hjbello.config;

import java.util.Date;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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 org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.core.JsonProcessingException;
 
@RestController
public class AjaxController {
 @RequestMapping(value = "/ajaxEndpoint", method = RequestMethod.POST)
 public @ResponseBody ResponseEntity<AjaxResponse> capture (@RequestBody AjaxRequest request) throws JsonProcessingException{
  System.out.println("modifying");
  AjaxResponse response = new AjaxResponse();
  response.setText1(request.getText1() + "MODIFIED");
  response.setText2(request.getText2() + "MODIFIED");
  Date date = new Date();
  response.setDate(date.toString());
   return new ResponseEntity<AjaxResponse>(response, HttpStatus.OK);
 }

}
 


As you see, this very simple controller will just add the string "MODIFIED" to the two text fields in the request and will also give us the date in which it was invoked.

The view, calling  the AJAX controller with JQuerry


Finally, let us take a look at the home.jsp view, to see how to invoke the previous RestController using the ajax method of the JQuerry library.


<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<script src="<c:url value="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" />"></script>
<link href="<spring:url value="css/app.css" />" rel="stylesheet"
 type="text/css">
<title>Welcome</title>
</head>
<body class="app">

 <div>
  <h1>Welcome!</h1>
   Click the button to send the form and recieve the response via ajax:
    </div>
 
 <h2>Ajax request:</h2>
 <form id="callAjax">
        <table>
    <tr>
     <td>Text 1:</td>
     <td><input type=text id="text1"></td>
    </tr>
    <tr>
     <td>Text 2:</td>
     <td><input type=text id="text2"></td>
    </tr>
    <tr>
     <td></td>
     <td><button type="submit">Send Ajax request</button></td>
    </tr>
   </table>
  </form> 
  <h2>Ajax response:</h2>
          <table>
    <tr>
     <td>Text 1 (response):</td>
     <td><div id="text1_response"></div></td>
    </tr>
    <tr>
     <td>Text 2 (response):</td>
     <td><div id="text2_response"></div></td>
    </tr>
    <tr>
     <td>Date (response):</td>
     <td><div id="date_response"></div></td>
    </tr>
   </table> 
   
<%--          <input type="hidden" id="csrfToken" value="${_csrf.token}"/>
            <input type="hidden" id="csrfHeader" value="${_csrf.headerName}"/>  --%> 
            
<script type="text/javascript">
jQuery(document).ready(function($) {
 $("#callAjax").submit(function(event) {
  // Prevent the form from submitting via the browser.
  event.preventDefault();
  callAjax();

 });
});

function callAjax() {
 
 /* var token = $('#csrfToken').val();
 var header = $('#csrfHeader').val(); */ 
 var data = {}
 data["text1"] = parseInt($("#text1").val());
 data["text2"] = parseInt($("#text2").val());


 $.ajax({
  type : "POST",
  contentType : "application/json",
  url : "${home}/ajaxEndpoint/",
  data : JSON.stringify(data),
  dataType : 'json',
  /* beforeSend: function(xhr) {
         xhr.setRequestHeader("Accept", "application/json");
         xhr.setRequestHeader("Content-Type", "application/json");
         xhr.setRequestHeader(header, token);
     }, */
  timeout : 100000,
  success : function(data) {
   console.log("SUCCESS: ", data);
   display(data);
  },
  error : function(e) {
   console.log("ERROR: ", e);
   display(e);
  },
  done : function(e) {
   console.log("DONE");
  }
 });
}

function display (data){
  var text1_response = data.text1;
  var text2_response = data.text2;
  var date = data.date;
 
    $("#text1_response").html(text1_response); 
    $("#text2_response").html(text2_response);
    $("#date_response").html(date);
}
</script>
</body>
</html>


Since I am realizing that the code looks all mixed up, and it is kind of difficult to follow I will summarize it here.

What home.jsp does is the following:

  • First, we construct a basic form that we want to send to the controller via AJAX. This form looks like this:
    <form id="callAjax">
            <table>
        <tr>
         <td>Text 1:</td>
         <td><input type=text id="text1"></td>
        </tr>
        <tr>
         <td>Text 2:</td>
         <td><input type=text id="text2"></td>
        </tr>
        <tr>
         <td></td>
         <td><button type="submit">Send Ajax request</button></td>
        </tr>
       </table>
      </form> 
    


  • Then in the script tag, we write a listener for onClick event of the button of the form callAjax:
    <script type="text/javascript">
    jQuery(document).ready(function($) {
     $("#callAjax").submit(function(event) {
      // Prevent the form from submitting via the browser.
      event.preventDefault();
      callAjax();
    
     });
    });
    [...]


  • Every time the button is clicked, the fuction callAjax() is invoked. This function is the one that actually calls our controller:
    function callAjax() {
     /* var token = $('#csrfToken').val();
     var header = $('#csrfHeader').val(); */ 
     var data = {}
     data["text1"] = parseInt($("#text1").val());
     data["text2"] = parseInt($("#text2").val());
    
     $.ajax({
      type : "POST",
      contentType : "application/json",
      url : "${home}/ajaxEndpoint/",
      data : JSON.stringify(data),
      dataType : 'json',
      /* beforeSend: function(xhr) {
             xhr.setRequestHeader("Accept", "application/json");
             xhr.setRequestHeader("Content-Type", "application/json");
             xhr.setRequestHeader(header, token);
         }, */
      timeout : 100000,
      success : function(data) {
       console.log("SUCCESS: ", data);
       display(data);
      },
      error : function(e) {
       console.log("ERROR: ", e);
       display(e);
      },
      done : function(e) {
       console.log("DONE");
      }
     });
    }
    


  • If the call is successful the function display(data) is invoked. This function just adds the obtained information inside two
    tags in our view:
    function display (data){
      var text1_response = data.text1;
      var text2_response = data.text2;
      var date = data.date;
     
        $("#text1_response").html(text1_response); 
        $("#text2_response").html(text2_response);
        $("#date_response").html(date);
    }
    


As a last comment, if we were using Spring Security (through a login form for instance) we would need to uncomment the commented lines in home.jsp. That is, we would need to add two hidden forms:


<input type="hidden" id="csrfToken" value="${_csrf.token}"/>
<input type="hidden" id="csrfHeader" value="${_csrf.headerName}"/> 

Then we would also need to include the content of these two inputs in the call of the function $.ajax like this


 var token = $('#csrfToken').val();
 var header = $('#csrfHeader').val(); 
$.ajax({
  type : "POST",
  contentType : "application/json",
  url : "${home}/ajaxEndpoint/",
  data : JSON.stringify(data),
  dataType : 'json',
  beforeSend: function(xhr) {
         xhr.setRequestHeader("Accept", "application/json");
         xhr.setRequestHeader("Content-Type", "application/json");
         xhr.setRequestHeader(header, token);
     }, 
  timeout : 100000,
[...]



Let us test it














Download the code here:

Sunday, July 16, 2017

How to invoke a POST method in a RESTFul Web service with basic authentication

As an example of how to do this I will invoke the restful web service that we built here.

If you want to call a web service from a Java Spring application, the best way to go around the problem is (in my opinion) by creating:


  •  A POJO for the request and a POJO for the response. You could avoid these by working directly with JSON strings but I think this could go wild.
  • A bean that invokes the web service, with the password and user as attributes. This bean will use the previous POJO's to build the invocation to the ws.




Request and Response POJO's


In my example I have a web service that takes an object with the webcam parameters (number of seconds to wait until the webcam detects movement), and a response object with the images obtained by the server.

This will be my request:

\src\main\java\com\hjbello\restfulws\RequestCapture.java

package com.hjbello.restfulws;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public class RequestCapture {

 private int seconds;

 public RequestCapture(int seconds) {
  super();
  this.seconds = seconds;
 }

 public int getSeconds() {
  return seconds;
 }

 public void setSeconds(int seconds) {
  this.seconds = seconds;
 }

 public RequestCapture() {
  super();
  }
 
}

And this the response:

\src\main\java\com\hjbello\restfulws\CapturedMovement.java

package com.hjbello.restfulws;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import java.util.ArrayList;
import java.util.Date;

@JsonIgnoreProperties(ignoreUnknown = true)

public class CapturedMovement {

 private String dateOfCapture;

 private ArrayList<String> imagesPath;

 private ArrayList<byte[]> imagesBase64;

 public String getDateOfCapture() {
  return dateOfCapture;
 }

 public void setDateOfCapture(String dateOfCapture) {
  this.dateOfCapture = dateOfCapture;
 }

 public ArrayList<byte[]> getImagesBase64() {
  return imagesBase64;
 }

 public void setImagesBase64(ArrayList<byte[]> imagesBase64) {
  this.imagesBase64 = imagesBase64;
 }

 public CapturedMovement(String dateOfCapture, ArrayList<byte[]> imagesBase64) {
  super();
  this.dateOfCapture = dateOfCapture;
  this.imagesBase64 = imagesBase64;
 }

 public CapturedMovement() {
  super();
 }

 public ArrayList<String> getImagesPath() {
  return imagesPath;
 }

 public void setImagesPath(ArrayList<String> imagesPath) {
  this.imagesPath = imagesPath;
 }
 
}


Invoker


Now we create the bean that we will autowire every time we need to invoke the restful web service in our application


\src\main\java\com\hjbello\restfulws\WebcamRestWS.java


package com.hjbello.restfulws;

import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultHttpClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class WebcamRestWS {

 private String url = "http://localhost:8080/capture/";
 private String user = "user";
 private String password = "1234";

 
 public CapturedMovement invokeWecamRestWS ( RequestCapture requestCapture) throws JsonProcessingException{
  //First we prepare the authentification
  DefaultHttpClient httpClient = new DefaultHttpClient();
  BasicCredentialsProvider credentialsProvider =  new BasicCredentialsProvider();
  credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, password));
  httpClient.setCredentialsProvider(credentialsProvider);
  ClientHttpRequestFactory rf = new HttpComponentsClientHttpRequestFactory(httpClient);

  //Here we convert the request to json, and then to httpEntity
  ObjectMapper mapper = new ObjectMapper();
  String requestCaptureJson = mapper.writeValueAsString(requestCapture);
  HttpHeaders headers = new HttpHeaders();
  headers.setContentType(MediaType.APPLICATION_JSON);
  HttpEntity request= new HttpEntity(requestCaptureJson, headers);

  //We invoke the web service
  RestTemplate restTemplate = new RestTemplate(rf);
  CapturedMovement response = restTemplate.postForObject(url,request, CapturedMovement.class);
  return response;
 }

}


Be aware that you will need the following dependencies in your pom.xml file:



  <!-- Restful web services -->
  <dependency>
   <groupId>org.codehaus.jackson</groupId>
   <artifactId>jackson-jaxrs</artifactId>
   <version>1.9.13</version>
  </dependency>
  <dependency>
   <groupId>com.sun.jersey</groupId>
   <artifactId>jersey-client</artifactId>
   <version>1.19</version>
  </dependency>
  <dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   </dependency>

If you want to invoke a GET method, instead of restTemplate.postForObject you will need something like


CapturedMovement response = restTemplate.getForObject(url, CapturedMovement.class);

in the Getting Started Spring tutorial you have a complete example regarding GET methods.


Tests with JUnit4



Now that we have our invoker class (or client), we can test it with JUnit4. For that purpose create a src/main/test folder in your classpath and click on New -> JUnit Test Case



And add the following code to the newly created class




\src\main\tests\com\hjbello\tests\TestWebcamRestWS.java


package com.hjbello.tests;

import static org.junit.Assert.*;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.hjbello.restfulws.RequestCapture;
import com.hjbello.restfulws.WebcamRestWS;



public class TestWebcamRestWS {

 @Test
 public void test() throws JsonProcessingException {
  WebcamRestWS wr = new WebcamRestWS();
  RequestCapture request = new RequestCapture(1);
  System.out.println("testing web service client");
  System.out.println(wr.invokeWecamRestWS(request));
  assertNotNull("Asserting that return class is not null", wr.invokeWecamRestWS(request));
 }

}


To run it we will click on Run As -> JUnit Test





Or alternatively in Run Configurations:




We will see that it Runs OK and it gives us JSON response down in the console:



here you have more info regarding JUnit4.

Tuesday, July 11, 2017

Using SQLite in a Java Spring project with jdbc

Recording the activity of our app using SQLite and jdbc



Let us see how to set up a simple SQLite database and how to insert data in it using jdbc. As an example we will use the restful server that we created in a previous post

So suppose that you have a rest controller and you want to record each request of data into a simple table created in a SQLite database.

Setting up the SQLite database


The first thing you need to know is how SQLite works. The magic of SQLite is that you do not need an actual server to communicate with a SQLite database, you just use a *.db file.

SQLite databases are perfect for environments in which you do not want to communicate with an actual database server but you want the advantages of using queries to store and retrieve data. This technology allows  you to create a *.db file and use jdbc to post and extract data into that file. In case that your application grows bigger you later can replace this setting for an actual connection to a MySQL or Oracle SQL database.


So first you need to create the database. For that I recommend you install a simple SQLite IDE, for instance I have used SQLiteStudio with success in the past.

Once in SQLiteStudio go to Database -> Create database, and choose a name. For instance I called mine activity_log.




Then create a new query and run the following code:


CREATE  TABLE app_activity_log (
  log_id  INTEGER PRIMARY KEY AUTOINCREMENT,
  username VARCHAR(45) not null,
  user_ip VARCHAR(45),
  photos_sent VARCHAR(100),
  date_accessed DATETIME);


This will create the table that we will need. The idea is that every time the user calls the Spring Controller that shots the camera, we will record the user data and the list of photos taken in our table app_ativity_log

Inside your sqlitestudio folder you will find the database that you just created (activity_log.db).




Connect with a SQLite database using spring and jdbc


The right way to connect to any database from a spring application is to create a DAO (data access object), and make it into a spring bean.

In this section we will create the following classes inside our spring app






Before creating the DAO we need a POJO (plain old java object, TAppActivityLog) that imitates the structure of our table app_activity_log:

\src\main\java\com\hjbello\dao\TAppActivityLog.java
package com.hjbello.dao;

import java.util.Date;

public class TAppActivityLog {
 private String username;
 private String userIp;
 private String photosSent;
 private Date dateAccessed;
 
 public TAppActivityLog(String username, String userIp, String photosSent, Date dateAccessed) {
  super();
  this.username = username;
  this.userIp = userIp;
  this.photosSent = photosSent;
  this.dateAccessed = dateAccessed;
 }
 public TAppActivityLog() {
  super();
 }
 public String getUsername() {
  return username;
 }
 public void setUsername(String username) {
  this.username = username;
 }
 public String getUserIp() {
  return userIp;
 }
 public void setUserIp(String userIp) {
  this.userIp = userIp;
 }
 public String getPhotosSent() {
  return photosSent;
 }
 public void setPhotosSent(String photosSent) {
  this.photosSent = photosSent;
 }
 public Date getDateAccessed() {
  return dateAccessed;
 }
 public void setDateAccessed(Date dateAccessed) {
  this.dateAccessed = dateAccessed;
 }

}



Now, since we will use injection of dependencies, we will need an interface for the DAO:

\src\main\java\com\hjbello\dao\RecordActivityDAO.java
package com.hjbello.dao;

import java.sql.Connection;

public interface RecordActivityDAO {
 public Connection connect();
 
 public void save(TAppActivityLog tAppActivityLog);

}


And finally the implementation of the previous interface, which we will declare as a bean using the annotation @Component

\src\main\java\com\hjbello\dao\RecordActivityDAOImpl.java
package com.hjbello.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
 
@Component
public class RecordActivityDAOImpl implements RecordActivityDAO {
 final static Logger logger = LoggerFactory.getLogger(RecordActivityDAOImpl.class);

 public Connection connect() {
  // SQLite connection string
  String dbFile = System.getProperty("user.home") + "/sqlite_databases/activity_log.db";
  String url = "jdbc:sqlite:"+dbFile;
  Connection conn = null;
  try {
   conn = DriverManager.getConnection(url);
   logger.info("Connected to database");
  } catch (SQLException e) {
   logger.info(e.getMessage());
  }
  return conn;
 }

 public  void save(TAppActivityLog tAppActivityLog) {
  String sql = "INSERT INTO app_activity_log (username, user_ip, date_accessed,photos_sent) "
    + "values (?,?,?,?)";

  try (Connection conn = this.connect();
    PreparedStatement pstmt = conn.prepareStatement(sql)) {

   pstmt.setString(1,tAppActivityLog.getUsername());
   pstmt.setString(2,tAppActivityLog.getUserIp());
   pstmt.setString(3,  tAppActivityLog.getDateAccessed().toString());
   pstmt.setString(4,tAppActivityLog.getPhotosSent());
   pstmt.executeUpdate();
   logger.info("Activity recorded");
  } catch (SQLException e) {
   System.out.println(e.getMessage());
  }
 }


}


As you see, in order to connect with the database, we just need to use the usual jdbc statement:

         DriverManager.getConnection(url);


And inside the string url we put the local route to the file activity_log.db. In my case is a little messy because I wanted to use the folder of the active user, for which I needed to add:

        String dbFile = System.getProperty("user.home") + "/sqlite_databases/activity_log.db";
        String url = "jdbc:sqlite:"+dbFile;


instead of just writing 

        String url = "C:/Users/hugo/sqlite_databases/activity_log.db



In that I make it more crossed platform. If you were using a MySQL database you would need an actual url to the server where you have you database.

in the function save you have the insert that we will need. Similar queries would be analogous. As you see is the same jdbc statements as you use for other SQL dialects.

Have in mind that for this to work you will need the SQLite driver inside your buildpath, so if you are using maven you will need the following dependency in your pom.xml file:


  <dependency>
   <groupId>org.xerial</groupId>
   <artifactId>sqlite-jdbc</artifactId>
   <version>3.15.1</version>
  </dependency>



Invoke the DAO

Now inside the spring rest controller I want to invoke the DAO. For that, I will inject it using @Autowired and use it right away with the adequate parsing. I will put here snippets instead of the whole class, If you want the complete code check here.

So we declare the DAO like this


 @Autowired 
 RecordActivityDAOImpl recordActivityDao;

And then


// we record this request in the database
     TAppActivityLog tAppActivityLog = new TAppActivityLog();
     tAppActivityLog.setDateAccessed(new Date());
     tAppActivityLog.setPhotosSent(imagesPath.toString());   
     
     Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
     String username = authentication.getName();
     tAppActivityLog.setUsername(username);
     tAppActivityLog.setUserIp(httpRequest.getRemoteAddr());
     
       recordActivityDao.save(tAppActivityLog);

I obtain the user using the spring context and the ip using the httpRequest, which is an input of our controller.


Check that the data has been stored

If you run a test you can go back to your SQLite IDE and run a simple query:


select * from app_activity_log;


You will see that everything has worked well



Download the full project here


https://github.com/HugoJBello/java-projects-tutorials/tree/master/spring-rest-security-webcam