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)

Tuesday, June 27, 2017

Spring Restful example with Spring Security

Spring Restful example with Spring Security. Capturing images with the webcam.


I am going to describe here how to build a simple rest web service with a post and a get method using Spring. In our example, our application will detect movement and take photos with the webcam when the user orders it. We will use Spring Security for the authentication.

The basic schema of our application will be the following



Configuring Spring Boot and Spring Security

Let's start with CaptureImageConfiguration which will contain the configuration details:

/spring-rest-security-webcam/src/main/java/com/hjbello/CaptureImageConfiguration.java

package com.hjbello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import com.hjbello.security.CustomBasicAuthenticationEntryPoint;
 
@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = "com.hjbello")
public class CaptureImageConfiguration extends WebSecurityConfigurerAdapter {

    private static String REALM="MY_TEST_REALM";
     
    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password("1234").roles("ADMIN");
        auth.inMemoryAuthentication().withUser("tom").password("abc123").roles("USER");
    }
     
    @Override
    protected void configure(HttpSecurity http) throws Exception {
  
      http.csrf().disable()
        .authorizeRequests()
        .antMatchers("/user/**").hasRole("ADMIN")
        .and().httpBasic().realmName(REALM).authenticationEntryPoint(getBasicAuthEntryPoint())
        .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//We don't need sessions to be created.
    }
     
    @Bean
    public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint(){
        return new CustomBasicAuthenticationEntryPoint();
    }
     
    /* To allow Pre-flight [OPTIONS] request from browser */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }
}

The previous class contains the roles and users that will be necessary to access the app. The annotation @ComponentScan(basePackages = "com.hjbello") tells spring where to look for the rest controllers.

In order to configure the servlets (without the usual web.xml), we will need the following class:

/spring-rest-security-webcam/src/main/java/com/hjbello/CaptureImageInitializer.java
package com.hjbello;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class CaptureImageInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
 
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { CaptureImageConfiguration.class };
    }
  
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }
  
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
 
}

Apart from the previous class (if we want to avoid using a file web.xml), the following dependencies shall be added in the pom.xml file:


<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-web</artifactId>
 <version>${org.springframework.version}</version>
</dependency>

<dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>javax.servlet-api</artifactId>
 <version>${javax.servlet-api.version}</version>
 <scope>provided</scope>
</dependency>


Spring security also needs a class that specifies the entry point. This class was referenced in the configuration class that we wrote above.

/spring-rest-security-webcam/src/main/java/com/hjbello/security/CustomBasicAuthenticationEntryPoint.java

package com.hjbello.security;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
 
public class CustomBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
 
    @Override
    public void commence(final HttpServletRequest request, 
            final HttpServletResponse response, 
            final AuthenticationException authException) throws IOException, ServletException {
        //Authentication failed, send error response.
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.addHeader("WWW-Authenticate", "Basic realm=" + getRealmName() + "");
         
        PrintWriter writer = response.getWriter();
        writer.println("HTTP Status 401 : " + authException.getMessage());
    }
     
    @Override
    public void afterPropertiesSet() throws Exception {
        setRealmName("MY_TEST_REALM");
        super.afterPropertiesSet();
    }
}


Capturing Movement with the webcam in the server

Our the package com.hjbello.webcam contains the classes that activate the webcam and start detecting movement capturing one photo each time something moves.



 I will not go into detail here, I will just say that the package that these classes use is in this dependency:


<dependency>
 <groupId>com.github.sarxos</groupId>
 <artifactId>webcam-capture</artifactId>
 <version>0.3.10</version>
</dependency>

(see the github repository by Sarxos)



Rest Controller. Post and Get Methods

Before we set up the controller, we need two POJOs, one for the input of the operation and another for the output.

Here is the input (or request):

/spring-rest-security-webcam/src/main/java/com/hjbello/RequestCapture.java
package com.hjbello;

public class RequestCapture {

 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();
  }
 
}


Here is the output:

/spring-rest-security-webcam/src/main/java/com/hjbello/CapturedMovement.java

package com.hjbello;

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

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;
 }
 
}


Basically, in the input we put the number of seconds during which we want the application to detect the movement (in the server). The output will give us a list with the images in base 64 that it has obtained and the date.




Our rest controller will be in the following class:

/spring-rest-security-webcam/src/main/java/com/hjbello/CaptureImageRestController.java
package com.hjbello;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
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.RestController;

import com.hjbello.webcam.DetectMotion;
 
 
@RestController
public class CaptureImageRestController {
 
    @RequestMapping("/")
    public String welcome() {//Welcome page, non-rest
        return "Welcome to RestTemplate Example.";
    }
 
    @RequestMapping("/captureStopIn/{seconds}")
    public ResponseEntity<CapturedMovement> captureGet(@PathVariable String seconds) {//REST Endpoint.
     RequestCapture request = new RequestCapture();
     request.setSeconds(Integer.parseInt(seconds));
        
        return capturePost(request);
    }
    
    @RequestMapping(value = "/capture/", method = RequestMethod.POST)
    public ResponseEntity<CapturedMovement> capturePost(@RequestBody RequestCapture request)  {//REST Endpoint.
     int seconds = request.getSeconds();
     Date date = new Date();
     DetectMotion detector = new DetectMotion("" + seconds);
     try {
   detector.record();
  } catch (IOException e) {
   e.printStackTrace();
  }
      ArrayList<String> imagesPath = detector.getListOfObtaiedImages();
      ArrayList<byte[]> imagesBase64 = detector.getListOfObtainedImageBase64(); 
     
     CapturedMovement response = new CapturedMovement();
     response.setImagesPath(imagesPath);
     response.setImagesBase64(imagesBase64);
     response.setDateOfCapture(date.toString());
        return new ResponseEntity<CapturedMovement>(response, HttpStatus.OK);
    }
}


The basic idea of this class is that.


The first method captureGet will take the string seconds from the path /captureStopIn/{seconds} and will use it to invoke the post method, returning the class CapturedMovement with the images.

The second method  capturePost is the one that will invoke the class that captures the images and mount the output class. It will recieve the number of seconds in which it has to detect movement through the class RequestCapture.



Testing the application

Once we have launched the application using spring boot, we start testing with postman




We introduce the user and the password in the tab Authorization





We translate the response into json and we introduce it in the Body tab. We we click send it will take some time, take the photos and give then to us encoded and inside the json response.






Similarly with the Get method:





Download the code here:

https://github.com/HugoJBello/webcam-mvc-controller
https://github.com/HugoJBello/webcam-mvc-controller/tree/master/spring-rest-security-webcam














Sunday, May 28, 2017

Automatically tag audio files using python

Problem


I have been listening to audiobooks lately. If you try to listen long audiobooks you will normally have to handle a lot of mp3 files in your phone or mp4 device. If these files are not well tagged, you will struggle jumping from one chapter to the next and you will end up mad.

One solution is to tag them manually by clicking one file after the next and changing one label after another (tittle, artist, track...). I solved this by automatically assigning the title as the filename using python. 

Changing audio tags using python

There are many python libraries out there that allow you to read and edit audio tags. The one that has given me better results is mutagen. To use it you will need to install it with


pip install mutagen


The following script takes all the files inside the folder where it its contained and sets their title tag as their respective filename (without extension)

Before changing the tags it renames the file so that it has a cleaner name (removing rare characters).


import os
from mutagen.mp3 import MP3
from mutagen.id3 import ID3, TIT2

def clean_filename(filename):
 keepcharacters = (' ','.','-','_')
 return "".join(c for c in filename if c.isalnum() or c in keepcharacters).rstrip()


def rename_cleaning_filename(filename):
 os.rename(filename, clean_filename(filename))

def extension(filename):
 return '.' + filename.split('.')[len(filename.split('.'))-1]
 
def remove_extension(filename):
 return filename.split(extension(filename))[0]

for filename in os.listdir('.'):
  rename_cleaning_filename(filename)

music_folder = os.path.dirname(os.path.realpath(__file__))

for file in os.listdir(music_folder):
 if os.path.isfile(file): 
  filename = os.path.join(music_folder, file)
  if (extension(file) != '.py'):
   tags = ID3(filename)
   print('Changing title of ' + filename + ' to ' + remove_extension(file))
   tags["TIT2"] = TIT2(encoding=3, text = remove_extension(file))
   tags.save(filename)


If for you want to change other tags you can do it similarly, here you have more examples.


Tagging files across subfolders


If you want to do the same thing as before, but tagging all the files inside all the subfolders of a folder, you can use this python code instead:


import os
from mutagen.mp3 import MP3
from mutagen.id3 import ID3, TIT2

def clean_filename(filename):
 keepcharacters = (' ','.','-','_')
 return "".join(c for c in filename if c.isalnum() or c in keepcharacters).rstrip()


def rename_cleaning_filename(filename):
 os.rename(filename, clean_filename(filename))

def extension(filename):
 return '.' + filename.split('.')[len(filename.split('.'))-1]
 
def remove_extension(filename):
 return filename.split(extension(filename))[0]

for filename in os.listdir('.'):
  rename_cleaning_filename(filename)

music_folder = os.path.dirname(os.path.realpath(__file__))

for root, subdirs, files in os.walk(music_folder):
 for file in files:
  filename = os.path.join(root, file)
  if (extension(file) != '.py'):
   tags = ID3(filename)
   print('Changing title of ' + filename + ' to ' + remove_extension(file))
   tags["TIT2"] = TIT2(encoding=3, text = remove_extension(file))
   tags.save(filename)


The main difference is that here we are using the line


for root, subdirs, files in os.walk(music_folder):

which goes inside subfolders too.

Sample




Download the code here:



Saturday, May 27, 2017

SoapUI mock web services tricks

In a previous article I explained how to create and deploy a mock web service using SOAPUI.

In the process of testing applications sometimes you need to do quick changes in a mock web service and deploy it shiftly.

XML project file in SoapUI

When you export a SoapUI project you will get an xml that contains all the information and configuration of your project. Furthermore, if your project contains a mock service with its responses, those will be inside that xml.

For instance I have created this simple project


I have added three very simple responses:



You can save it with Project --> Save project as




 Then, if you open that xml flile, you will see that at the end of it are the responses that I created above.


So If you change the data in those responses and import the project again you will see that the responses have changed accordingly.

This is a method that I found out for doing quick small changes across several SoapUI projects that I use frequently. 

Nevertheless I still have not figured out how tho add responses using only this xml file. I do not fully understand the headings of the responses.


Deploying a SoapUI mock web service as a war file using the command line.


So if you have saved your soapui project into a xml as we did above, you can create a .war from it using the command line. I have troubles finding information about this and I think it is a great trick.

This is the .bat file that I use:



set war_file=D:\hugo_documentos\mock2.war
set war_dir=D:\hugo_documentos
set xml_dir=D:\hugo_documentos\mock-example-soapui-project.xml
set soapui-settings=C:\Users\hugo\soapui-settings.xml

cd /d C:\Program Files (x86)\SmartBear\SoapUI-5.3.0\bin

wargenerator.bat -f %war_file% -d %war_dir% -w true -x true -s %soapui-settings% %xml_dir%

pause

The trick is to use an executable called wargenerator that you will find inside the bin folder of your SoapUI installation folder. You will have to give it as inputs the place where you want the war file, the war directory, the SoapUI settings xml and the xml of your project.

I hope this helps!




Thursday, April 13, 2017

Basic Spring MVC project with fom handling part 2 (ModelAttribute)


Using Forms with ModelAttribute in Spring MVC


In a previous post I explained how to use html forms in Spring MVC passing data to the server using the annotation RequestParam in the controller. I will explain now how to do the same thing but using the annotation ModelAttribute, which is more convenient and more standard.

Configuration


We can obtain the basic template with Spring Starter in our STS:



This is our file structure:



as you see, the layout is basically the one that we used in the other example

Lets start with the views so that we see where we are going.

Views

Imagine that we want to create an html Form with two input fields: text1 and text2, that the user will introduce.  This is how our jsp will look like:

/spring-mvc-forms-example-ModelAttribute/src/main/webapp/WEB-INF/jsp/form_page.jsp


<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>
<html>
<head>
<link href="<c:url value="css/app.css" />" rel="stylesheet"
 type="text/css">
<title>Hello World!</title>
</head>
<body > 
 <div class="lc-block">
  <form:form method="post" action=""
   modelAttribute="formBean">
   <h3>introduce text here</h3>
   <table>
    <tr>
     <td>text 1:</td>
     <td><form:input type="text" path="text1" /></td>
    </tr>
    <tr>
     <td>text 2:</td>
     <td><form:input type="text" path="text2" /></td>
    </tr>
   </table>
   <p>
    <input type="submit" value="Start" />
   </p>
  </form:form>
 </div>
</body>
</html>

Two things to notice:

  • The form has the label modelAttribute ="formBean" which will tell spring that the ata posted by this form will go to an object which will be a bean called formBean. The inputs have labels like path="text1" which will make spring look for attributes called text1 and text2 inside formBean.
  • Although we have inserted the label action="" in our form, when the html gets generated, it will contain the path to the correct page or action.


The following code corresponds to the jsp that we will use to display the strings that we have introduced (just to prove that the server has received them):


/spring-mvc-forms-example-ModelAttribute/src/main/webapp/WEB-INF/jsp/response_page.jsp


<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>
<html>
<head>
<link href="<c:url value="css/app.css" />" rel="stylesheet"
 type="text/css">
<title>Hello World!</title>
</head>
<body >
 
 <div class="lc-block">
<h1> you introduced</h1>
<p> "${text1}" and "${text2}"</p>
 </div>

</body>
</html>

Controller and Form spring bean

The first thing that we have to do is to create a java POJO class that will contain these two strings. This class will also be an spring bean and should have the annotation @XmlRootElement.

/spring-mvc-forms-example-ModelAttribute/src/main/java/com/hjbello/Form.java


package com.hjbello;

import javax.xml.bind.annotation.XmlRootElement;

import org.springframework.stereotype.Component;


@Component(value="formBean")
@XmlRootElement
public class Form {

 private String text1 = "";
 private String text2 = "";
 public Form() {
  
 }
 public Form(String text1, String text2) {
  super();
  this.text1 = text1;
  this.text2 = text2;
 }
 
 public String getText1() {
  return text1;
 }

 public void setText1(String text1) {
  this.text1 = text1;
 }

 public String getText2() {
  return text2;
 }

 public void setText2(String text2) {
  this.text2 = text2;
 }

}

It is important that our class has the right constructors (one empty and the other with the strings) otherwise we will have problems.



The controller should know that we are using the previous spring bean:

/spring-mvc-forms-example-ModelAttribute/src/main/java/com/hjbello/HomeController.java


package com.hjbello;


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

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

 private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

 @RequestMapping(value = "/", method = RequestMethod.GET)
 public String home(Model model) {  
  logger.info(".....");
  
  return "home";
 }

 @RequestMapping(value = "/send-form", method=RequestMethod.GET)
 public ModelAndView formGet() {
      ModelAndView mv = new ModelAndView();
  Form form = new Form();
  mv.addObject("formBean", form);
  mv.setViewName("form_page");
  return mv;
     }
 @RequestMapping(value = "/send-form", method=RequestMethod.POST)
 public ModelAndView formPost(@ModelAttribute("formBean") Form form) {
      ModelAndView mv = new ModelAndView();
      mv.addObject("text1",form.getText1());
      mv.addObject("text2",form.getText2());  
  mv.setViewName("response_page");
  return mv;
     }

}


In HomeController we have created two RequestMappings one for the Post method and one for the Get method. Inside the one for the GET method it is important that we pass the object form into the view, otherwise we will get errors.

Using the input

@ModelAttribute("formBean") Form form

we pass our form to the controller.



Testing the application









Download the code: