Friday, August 17, 2018

Create a REST API with Spring Boot

In this post, I will explain how to create a simple a REST API with Spring Boot

Spring Boot
Spring Boot is a framework that provides inbuilt configuration that a Java web application can run without the XML configurations that come with a typical Spring application and it does not require a traditional WAR deployment. Spring Boot makes it easy Spring based Applications that you can just run.


REST Endpoints

Our application will expose the following endpoints:

GET /bookstore/book - Retrieves all books
GET /bookstore/book{id}  - Retrieves a specific boo based on ID
POST /bookstore/book  - Creates a new book
PUT /bookstore/book{id}  - Updates an existing book
DELETE /bookstore/book/{id} - Removes a specific book based on ID
DELETE /bookstore/book - Removes all books

Creating SpringBootApplication class

package com.libmgmt.app;

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

@SpringBootApplication(scanBasePackages={"com.libmgmt"})
public class MySpringBootApplication {

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

Creating BookController

package com.libmgmt.model;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
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 org.springframework.web.util.UriComponentsBuilder;
import com.libmgmt.exception.BookException;
import com.libmgmt.model.Book;
import com.libmgmt.service.BookService;

@RestController
@RequestMapping("/")
public class BookController {

@Autowired
BookService bookService;

@RequestMapping(value = "/book", method = RequestMethod.GET)
public ResponseEntity<List<Book>> findAllBooks() {
List<Book> books = bookService.findAllBooks();
if (books.isEmpty()) {
return new ResponseEntity<List<Book>>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<Book>>(books, HttpStatus.OK);
}

@RequestMapping(value = "/book/{id}", method = RequestMethod.GET)
public ResponseEntity<?> findBook(@PathVariable("id") long id) {
Book book = bookService.findById(id);
if (book == null) {
return new ResponseEntity<BookException>(
new BookException("ERROR: Book Id " + id
+ " not found"), HttpStatus.NOT_FOUND);
}
return new ResponseEntity<Book>(book, HttpStatus.OK);
}

@RequestMapping(value = "/book", method = RequestMethod.POST)
public ResponseEntity<?> createBook(@RequestBody Book book,
UriComponentsBuilder ucBuilder) {

if (bookService.isBookExist(book)) {
return new ResponseEntity<BookException>(
new BookException("ERROR: Book name ="
+ book.getName() + " already exist."),
HttpStatus.CONFLICT);
}
bookService.saveBook(book);

HttpHeaders headers = new HttpHeaders();
headers.setLocation(ucBuilder.path("/api/book/{id}")
.buildAndExpand(book.getId()).toUri());
return new ResponseEntity<String>(headers, HttpStatus.CREATED);
}

@RequestMapping(value = "/book/{id}", method = RequestMethod.PUT)
public ResponseEntity<?> updateBook(@PathVariable("id") long id,
@RequestBody Book book) {

Book currentBook = bookService.findById(id);

if (currentBook == null) {
return new ResponseEntity<BookException>(
new BookException("ERROR: Id =" + id
+ " not found."), HttpStatus.NOT_FOUND);
}

currentBook.setName(book.getName());
currentBook.setAuthor(book.getAuthor());
currentBook.setPrice(book.getPrice());
return new ResponseEntity<Book>(currentBook, HttpStatus.OK);
}

@RequestMapping(value = "/book/{id}", method = RequestMethod.DELETE)
public ResponseEntity<?> deleteBook(@PathVariable("id") long id) {

Book book = bookService.findById(id);
if (book == null) {
return new ResponseEntity<BookException>(
new BookException("ERROR: Id =" + id
+ " not found."), HttpStatus.NOT_FOUND);
}
bookService.deleteBookById(id);
return new ResponseEntity<Book>(HttpStatus.NO_CONTENT);
}

@RequestMapping(value = "/book", method = RequestMethod.DELETE)
public ResponseEntity<Book> deleteAllBooks() {

bookService.deleteAllBooks();
return new ResponseEntity<Book>(HttpStatus.NO_CONTENT);
}

}

Creating Book Model

package com.libmgmt.model;

public class Book {
private long id;
private String name;
private String author;
private float price;

public Book() {
id = 0;
}

public Book(long id, String name, String author, float price) {
this.id = id;
this.name = name;
this.author = author;
this.price = price;
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAuthor() {
return author;
}

public void setAuthor(String author) {
this.author = author;
}

public float getPrice() {
return price;
}

public void setPrice(float price) {
this.price = price;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if (id != other.id)
return false;
return true;
}


}

Creating Book Service 

package com.libmgmt.service;

import java.util.List;
import com.libmgmt.model.Book;

public interface BookService {

public Book findById(long id);
public Book findByName(String bookName);
public void saveBook(Book book);
public void updateBook(Book book);
public void deleteBookById(long id);
public List<Book> findAllBooks();
public void deleteAllBooks();
public boolean isBookExist(Book Book);


}

Creating Book Mock Service Implementation

package com.libmgmt.service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.stereotype.Service;
import com.libmgmt.model.Book;

@Service
public class BookServiceImpl implements BookService {

private static final AtomicLong counter = new AtomicLong();

private static List<Book> books;

static {
init();
}

private static void init() {
List<Book> bookList = new ArrayList<Book>();
bookList.add(new Book(counter.incrementAndGet(), "Java", "Andrew",
100.0f));
bookList.add(new Book(counter.incrementAndGet(),
"Data Structure & Algorithm", "John", 200.f));
books = bookList;
}

public Book findById(long id) {
for (Book book : books) {
if (book.getId() == id) {
return book;
}
}
return null;
}

public void saveBook(Book book) {
book.setId(counter.incrementAndGet());
books.add(book);
}

public void updateBook(Book book) {
int index = books.indexOf(book);
books.set(index, book);
}

public void deleteBookById(long id) {
for (Iterator<Book> iter = books.iterator(); iter.hasNext();) {
Book book = iter.next();
if (book.getId() == id) {
iter.remove();
}
}
}

public List<Book> findAllBooks() {
return books;
}

public void deleteAllBooks() {
books.clear();
}

public boolean isBookExist(Book book) {
return findByName(book.getName()) != null;
}

public Book findByName(String bookName) {
for (Book book : books) {
if (book.getName().equalsIgnoreCase(bookName)) {
return book;
}
}
return null;
}

}

Creating Book Exception 

package com.libmgmt.exception;

public class BookException {
private String errorMessage;

public BookException(String errorMessage) {
this.errorMessage = errorMessage;
}

public String getErrorMessage() {
return errorMessage;
}

}


Book Services Curl

Get All books
curl -X GET -i 'http://127.0.0.1:8080/bookstore/book'

Get Single Book
curl -X GET -i 'http://127.0.0.1:8080/bookstore/book/1'

Create Book
curl -X POST -H 'Content-Type: application/json' -i 'http://127.0.0.1:8080/bookstore/book' --data '{"id":3,"name":"C++","author":"E Balagrusamy","price":100.0}'

Update Book 
curl -X PUT -H 'Content-Type: application/json' -i 'http://127.0.0.1:8080/bookstore/book/3' --data '{"id":3,"name":"C++","author":"E Balagrusamy","price":120.0}'

Delete Single Book
curl -X DELETE -H 'Content-Type: application/json' -i 'http://127.0.0.1:8080/bookstore/book/5'

Delete All Books

curl -X DELETE -H 'Content-Type: application/json' -i 'http://127.0.0.1:8080/bookstore/book/3' --data '{"id":4,"name":"Angular JS","author":"E Balagrusamy","price":120.0}'

Wednesday, April 25, 2018

Locking in JPA


PESSIMISTIC_WRITE

Locking is used for protecting mutable shared data. An PESSIMISTIC_WRITE lock is acquired to prevent any other transaction from acquiring a PESSIMISTIC_READ or a PESSIMISTIC_WRITE lock.


String strSql = "Select person FROM Person person WHERE person.id =:id" +
"AND person.historyNo = (Select Max(person2.historyNo)from Person person2
WHERE person2.id =:id)"; 

TypedQuery<Person> query = entityManager.createQuery(strSql, Person.class);

query.setParameter("id", p.id);
query.setLockMode(LockModeType.PESSIMISTIC_WRITE); query.setHint("javax.persistence.lock.timeout", 0);

Long historyNo = new Long(0); historyNo = query.getSingleResult().getHistoryNo(); p.setHistoryNo(historyNo + 1);

entityManager.persist(p);

Tuesday, February 20, 2018

How to remove duplicate using overriding equals and hashCode methods in Java

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class Person {
private String id;
private String name;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return id + "-" + name;
}

@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}

if (!(object instanceof Person)) {
return false;
}
final Person person = (Person) object;
return person.id.equals(id);
}

@Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + (this.id != null ? this.id.hashCode() : 0);
return hash;
}

public static void main(String args[]) {
Set<Person> personSet = new HashSet<Person>();
List<Person> personList = new ArrayList<Person>();

Person person1 = new Person();
person1.setId("101");
person1.setName("Ravi");
personList.add(person1);

Person person2 = new Person();
person2.setId("101");
person2.setName("Raja");
personList.add(person2);

System.out.println("Original Elements:");
for (Iterator<Person> iterator = personList.iterator(); iterator
.hasNext();) {
System.out.println((Person) iterator.next());
}

personSet.addAll(personList);
System.out.println("Elements after removing duplicate id element:");
for (Iterator<Person> iterator = personSet.iterator(); iterator
.hasNext();) {
System.out.println((Person) iterator.next());
}
}
}

Saturday, October 28, 2017

Algorithm

BinaryGap

binary gap within a positive integer N is any maximal sequence of consecutive zeros that is surrounded by ones at both ends in the binary representation of .N. 

public int solution(int N) {
String binaryNo = Integer.toBinaryString(N);
int firstIndex = binaryNo.lastIndexOf("1");
int currentGap = 0;
int biggestGap = 0;
for (int i = firstIndex; i >= 0; i--) {
if (getNthDegit(binaryNo, i) == 0) {
currentGap++;
} else {
if (biggestGap < currentGap) {
biggestGap = currentGap;
}
currentGap = 0;
}
}
return biggestGap;
}

public static int getNthDegit(String number, int position) {

String numberString = "" + number;
char c = numberString.charAt(position);
return Character.getNumericValue(c);
}


OddOccurrencesInArray


Find value that occurs in odd number of elements.

public int solution(int[] A) { int num = 0; int max = 0; for (int i = 0; i < A.length; i++) { if (max <= A[i]) { max = A[i]; } } int[] B = new int[max]; for (int i = 0; i < A.length; i++) { if (B[A[i] - 1] == 0) { B[A[i] - 1] = A[i]; } else { B[A[i] - 1] = 0; } } for (int i = 0; i < B.length; i++) { if (B[i] != 0) { num = B[i]; break; } } return num; }



CyclicRotation

Each element is shifted right by one index, and the last element of the array is also moved to the first place.


public int[] solution(int[] A, int K) { if (K > 0 && A.length > 0) { K = K % A.length; int[] B = new int[A.length]; for (int i = 0; i < A.length; i++) { if ((i + K) > (A.length - 1)) { B[i + K - A.length] = A[i]; } else { B[i + K] = A[i]; } } return B; } else { return A; } }


FrogJmp


Count minimal number of jumps from position X to Y.


public int solution(int X, int Y, int D) { if (X == Y) return 0; else if ((Y - X) % D == 0) return ((Y - X) / D); else return ((Y - X) / D) + 1; }


Distinct

Compute number of distinct values in an array.


public int solution(int[] A) { Set<Integer> s = new HashSet<>(); for (int i = 0; i < A.length; i++) { s.add(A[i]); } return s.size(); }


CountDiv


Compute number of integers divisible by k in range [a..b].


public int solution(int A, int B, int K) {

return (B / K) - (A / K) + ((A % K) == 0 ? 1 : 0); }


TapeEquilibrium

Minimize the value |(A[0] + ... + A[P-1]) - (A[P] + ... + A[N-1])|. The difference between the two parts is the value of: |(A[0] + A[1] + ... + A[P − 1]) − (A[P] + A[P + 1] + ... + A[N − 1])|.

public int solution(int[] A) {
int N = A.length; int leftsum = 0; int difference; int rightSum; int min = Integer.MAX_VALUE; int sum = 0; for (int i = 0; i < N; i++) { sum = sum + A[i]; } for (int i = 0; i < N - 1; i++) { leftsum = leftsum + A[i]; rightSum = sum - leftsum; difference = Math.abs(rightSum - leftsum); min = Math.min(min, difference); } return min; }


Friday, July 14, 2017

Simple JSP Ajax Tutorial

In this blog post, a simple JSP Ajax sample for adding two numbers.  Ajax is a method for returning a result without reloading the HTML page using JavaScript, DOM, XMLHttpRequest and CSS technologies.

ajaxsample.html


<html>

<head>
<script type="text/javascript">
var request;
function addnum() {
var num1 = document.addform.num1.value;
var num2 = document.addform.num2.value;
var url = "sum.jsp?num1=" + num1 + "&num2=" + num2;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
} else if (window.ActiveXObject) {
request = new ActiveXObject("Microsoft.XMLHTTP");
}

try {

request.onreadystatechange = getsum;
request.open("GET", url, true);
request.send();
} catch (e) {
alert("Unable to process");
}
}

function getsum() {

if (request.readyState == 4) {
var sum = request.responseText;
document.getElementById("sumvalue").innerHTML = sum;
}
}
</script>
</head>
<body>
<h1>JSP Ajax Simple Example</h1>
<form name="addform">
<input type="text" name="num1"> + <input type="text"
name="num2"> <input type="button" value="Add"
onclick="addnum()">
</form>
<span id="sumvalue"></span>
</body>
</html>


sum.jsp


<%

int num1 = Integer
.parseInt(request.getParameter("num1").toString());
int num2 = Integer
.parseInt(request.getParameter("num2").toString());
int sum = num1 + num2;
out.print("Sum is " + sum);
%>

web.xml


<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
   <session-config>
        <session-timeout>
            30
   </session-timeout>
 </session-config>
 <welcome-file-list>
        <welcome-file>ajaxsample.html</welcome-file>
        </welcome-file-list>
 </web-app>

Wednesday, September 14, 2016

Email OTP Two Factor Authentication through Identity Server

In this post, I will explain how to use Email OTP two authenticator through WSO2 Identity server. In this demonstration, I am using SMTP mail transport which was used to send the OTP code via email at the time authentication happens.






















Add the authenticator configuration  <IS_HOME>/repository/conf/identity/application-authentication.xml file under the <AuthenticatorConfigs> section.

<AuthenticatorConfig name="EmailOTP" enabled="true">
     <Parameter name="GmailClientId">gmailClientIdValue</Parameter>
     <Parameter name="GmailClientSecret">gmailClientSecretValue</Parameter>
     <Parameter name="SendgridAPIKey">sendgridAPIKeyValue</Parameter>
     <Parameter name="EMAILOTPAuthenticationEndpointURL">https://localhost:9443/emailotpauthenticationendpoint/emailotp.jsp</Parameter>
     <Parameter name="EmailOTPAuthenticationEndpointErrorPage">https://localhost:9443/emailotpauthenticationendpoint/emailotpError.jsp</Parameter>
     <Parameter name="EmailAddressRequestPage">https://localhost:9443/emailotpauthenticationendpoint/emailAddress.jsp</Parameter>
     <Parameter name="GmailRefreshToken">gmailRefreshTokenValue</Parameter>
     <Parameter name="GmailEmailEndpoint">https://www.googleapis.com/gmail/v1/users/[userId]/messages/send</Parameter>
     <Parameter name="SendgridEmailEndpoint">https://api.sendgrid.com/api/mail.send.json</Parameter>
     <Parameter name="accessTokenRequiredAPIs">Gmail</Parameter>
     <Parameter name="apiKeyHeaderRequiredAPIs">Sendgrid</Parameter>
     <Parameter name="SendgridFormData">sendgridFormDataValue</Parameter>
     <Parameter name="SendgridURLParams">sendgridURLParamsValue</Parameter>
     <Parameter name="GmailAuthTokenType">Bearer</Parameter>
     <Parameter name="GmailTokenEndpoint">https://www.googleapis.com/oauth2/v3/token</Parameter>
     <Parameter name="SendgridAuthTokenType">Bearer</Parameter>
     <Parameter name="usecase">association</Parameter>
     <Parameter name="secondaryUserstore">primary</Parameter>
     <Parameter name="EMAILOTPMandatory">true</Parameter>
     <Parameter name="sendOTPToFederatedEmailAttribute">false</Parameter>
     <Parameter name="federatedEmailAttributeKey">email</Parameter>
     <Parameter name="EmailOTPEnableByUserClaim">true</Parameter>
     <Parameter name="CaptureAndUpdateEmailAddress">true</Parameter>
     <Parameter name="showEmailAddressInUI">true</Parameter>
</AuthenticatorConfig>

Configure the Service Provider and Identity Provider Configuration as we normally configure for Two factor authentication. Now we will configure EmailOTP Identity provider for SMTP transport.






 
 
 
 
 
 
 
SMTP transport sender configuration.
   Add the SMTP transport sender configuration in the <IS_HOME>/repository/conf/axis2/axis2.xml file.
  Here you need to replace {USERNAME}, {PASSWORD} and {SENDER'S_EMAIL_ID} with real values.

<transportSender name="mailto" class="org.apache.axis2.transport.mail.MailTransportSender">
       <parameter name="mail.smtp.host">smtp.gmail.com</parameter>
       <parameter name="mail.smtp.port">587</parameter>
       <parameter name="mail.smtp.starttls.enable">true</parameter>
       <parameter name="mail.smtp.auth">true</parameter>
       <parameter name="mail.smtp.user">{USERNAME}</parameter>
       <parameter name="mail.smtp.password">{PASSWORD}</parameter>
       <parameter name="mail.smtp.from">{SENDER'S_EMAIL_ID}</parameter>
</transportSender>

Comment <module ref="addressing"/> module from axis2.xml in <IS_HOME>/repository/conf/axis2.
Email Template configuration.
Add the email template in the <IS_HOME>/repository/conf/email/email-admin-config.xml file.

    <configuration type="EmailOTP">
           <targetEpr></targetEpr>
           <subject>WSO2 IS EmailOTP Authenticator One Time    Password</subject>
           <body>
       Hi,
       Please use this OTP {OTPCode} to go with EmailOTP authenticator.
           </body>
           <footer>
       Best Regards,
       WSO2 Identity Server Team
       http://www.wso2.com
           </footer>
           <redirectPath></redirectPath>
    </configuration>


When authentication is happening in second step, the code will be sent to email  which is saved in email claim of  user's user profile.
If the user apply the code, WSO2 IS will validate the code and let the user sign in accordingly.

Create a REST API with Spring Boot

In this post, I will explain how to create a simple a REST API with Spring Boot Spring Boot Spring Boot is a framework that provides inbuil...