Saturday, June 13, 2020

How to convert the JSON file to Map and List in Java using Gson.

In this post, we are going to convert the JSON file to Map or List. Here, we are using the Gson library which provides a clean way to do so. You can download the Gson jar file from here.


Now, load the jar file from your IDE.

For IntelliJ Idea:

Go to: File >> Project Structure(Ctr + Alt + Shift + s) >> Libraries and click the + icon on the top left corner and select library file that we downloaded. Apply and save. If you are using in an existing project like Gradle or Maven: 

For Gradle:

Inside build.gradle file under dependencies,
compile 'com.google.code.gson:gson:2.8.6'



For Maven:

Inside pom.xml
<dependency>
  <groupid>com.google.code.gson</groupid>
  <artifactid>gson</artifactid>
  <version>2.8.6</version>
</dependency>

Create a Class that converts a JSON file to Map or List.
package jsonToMap;

import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Map;


public class JsonConverter {

    public static void main(String[] args) {
        String baseDir = System.getProperty("user.dir");
        String jsonPath = baseDir+"/src/jsonToMap/resources/sample.json";
        //convert json map to Map
        Map jsonMap = getMapFromJson(jsonPath);
        System.out.println(jsonMap);
       
    }

    private static Map getMapFromJson(String filePath){
        Gson gson = new Gson();
        JsonReader reader = null;
        try {
            reader = new JsonReader(new FileReader(filePath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return gson.fromJson(reader, Map.class);
    }

}

Also, the sample.json file contains the JSON map under the directory provided.

//sample.json
{
  "text":"first text",
  "digit":1234,
  "boolean":true
}

In the above example, first, it will read the JSON file using JsonReader and we used Gson to convert to Map.

If you want to convert the file which contains the JSON list to List, you can provide the class to convert as below.
//sample.json
[
  {
    "text":"first text",
    "digit":1234,
    "boolean":true
  },
  {
    "text":"second text",
    "digit":1234,
    "boolean":true
  },
  {
    "text":"third text",
    "digit":1234,
    "boolean":true
  }
]


/JsonConverter.java
private static List getListFromJson(String filePath){
        Gson gson = new Gson();
        JsonReader reader = null;
        try {
            reader = new JsonReader(new FileReader(filePath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return gson.fromJson(reader, List.class);
    }
If you want to convert to Custom class, create a class compatible with the fields from the JSON file and provide that class while converting. For e.g:
//sample.json
{
  "text":"first text",
  "digit":1234,
  "aBoolean":true
}


//Sample.java
public class Sample {

    private String text;
    private Double digit;
    private Boolean aBoolean;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public Double getDigit() {
        return digit;
    }

    public void setDigit(Double digit) {
        this.digit = digit;
    }

    public Boolean getaBoolean() {
        return aBoolean;
    }

    public void setaBoolean(Boolean aBoolean) {
        this.aBoolean = aBoolean;
    }
}


//JsonConverter.java
private static Sample getSampleFromJson(String filePath){
        Gson gson = new Gson();
        JsonReader reader = null;
        try {
            reader = new JsonReader(new FileReader(filePath));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return gson.fromJson(reader, Sample.class);
    }
Here, we pass the class Sample while converting from the JSON. Make sure your JSON file and class structure match.



Share:

Sunday, June 7, 2020

Create a Self-Signed free SSL certificate for Tomcat on CentOS Linux using Let's Encrypt.

How to Install and configure a free SSL/TLS certificate for Tomcat using Let's Encrypt on Centos Linux.





In this tutorial, we are going to create and set up a free SSL/TLS certificate on the Linux CentOS server. We are using Let's Encrypt for this which provides the free SSL and is valid for 90 days. You can renew it during that time duration. We will show how to renew it too. You can find about Let's Encrypt from here.

This service is used by many people to secure their website worldwide so, it's totally trust-worthy and supported if you can't afford from other paid service provider.


2. prerequisites:

We consider you already have the following setup.

  1. Running CentOS server
  2. Running tomcat server
  3. Domain pointed to the server Ip address


3. Install Certbort and create an SSL certificate:

First, SSH into to the running CentOS server where you want to create your SSL certificate. To create an SSL certificate, we need to first install Certbort on the server so, let's do it. I recommend selecting the desired version from here, which will give the command to install Certbot.


Install Certbot:
yum -y install yum-utils
     yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional 
     sudo yum install certbot

Create a certificate:

If you have already running service which uses port 80 stop it. To obtain an SSL certificate for your domain using a built-in "standalone" webserver type the following command:
sudo certbot certonly --standalone -d example.com
Here, replace the domain name you want to secure instead of example.com 

which will create the following certificate file to the directory:"/etc/letsencrypt/live/example.com/"
cert.pem, chain.pem, fullchain.pem, privkey.pem.

Now, logged in as root user and go to that directory

sudo -i
cd /etc/letsencrypt/live/example.com/

Next step is to convert those certificate PEM file to password-based PFX format so that we can use in tomcat configuration. We can do this by using the OpenSSL command as below.
openssl pkcs12 -export -out bundle.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem -password pass:password
Replace the password with your desired one. It will create a password-protected file bundle.pfx under the same directory "/etc/letsencrypt/live/example.com/" which we need to use in tomcat configuration.

 



4. Tomcat configuration for HTTPs:

Go to your tomcat directory, and backup the server.xml file; as we are going to change the file.
cp conf/server.xml conf/server-copy.xml
Edit the server.xml file.
sudo vi conf/server.xml  // no need to type sudo if you are logged in as root user
You can see the following commented XML tag, which we are going to change:

For Tomcat 7:


For tomcat 8:



Add the following changes near to the above XML tag or you can simply change that XML tag as below.



Here, we are changing port 8443 to 443, keystoreType as "PKCS12", keystoreFile as the path of the pfx file created previously and keystorePass as your password that we used while creating PFX file. 

Change the port 8080 to 80:

Under server.xml you can find the following tag.



change the above XML tag as below:



Here, we are changing the port from 8080 to 80 and 8443 to 443. By doing so, if your domain running with port 8080 i.e example.com:8080, now it will open with port 80 i.e example.com. If you type your domain in the browser then you can run it with both HTTP and https i.e http://example.com and https://example.com.

Save the server.xml file by clicking "Esc" key and type ":wq!" and hit Enter.

As we want to always redirect our domain to https. To do so, open the web.xml file under conf/web.xml.

 
sudo vi conf/web.xml
Click "Shift + G" to go the end of the file and add the below code at the end of the file as below.
<security-constraint>
  <web-resource-collection>
  <web-resource-name>Entire Application</web-resource-name>
   <url-pattern>/*</url-pattern>
 </web-resource-collection>
  <!--auth-constraint goes here if you requre authentication-->
 <user-data-constraint>
 <transport-guarantee>CONFIDENTIAL</transport-guarantee>
 </user-data-constraint>
 </security-constraint>
 


Save the file. This will always redirect to HTTPs.

 
5. Renew certificate:

The certificate is valid for only 90 days so we need to renew before expiry. For this, stop tomcat and type the following command:
sudo certbot renew
sudo -i
cd /etc/letsencrypt/live/example.com/
openssl pkcs12 -export -out bundle.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem -password pass:password
Don't forget to use your existing password. And restart the tomcat server.



Share:

Friday, June 5, 2020

IntelliJ Idea doesn't detect existing Java project.

What to do if your IntelliJ Idea doesn't detect your existing project. Sometimes it may be due to it doesn't find the JDK on you configure path. If you have such a problem reconfigure the JDK.
 
For this, go to: File >> Project Structures(Ctr + Alt + Shift + s) >> Project




Click New >> JDK and provide the path and select JDK. Sometimes it may be due to other versions of JDK setup, in that case, click and select the desired version of java from dropdown menu. Then click apply and ok. That may solve the issue with java not detecting.

Sometimes, although Java is detected we are not able to use the feature of Intellij idea like, run and debug classes, step in step out from class by ctr + click on method or class, find the usage of class and method by click on it. In this case, simply close the project and import it again. For this,

Go to: File >> Close Project >> Import Project




Select your desired project, and select "create from existing source", select the desired library and java version and finish the setup. This will resolve the issues 


Share:

Thursday, June 4, 2020

How to create thumbnail Image using Java.

In this tutorial, I will show you how we can create thumbnail images using Java. Thumbnails are the reduced size of images or videos. Basically, if your website is loading a lot of images with larger pixel values i.e larger size then, the performance of the website will be poor. 

So, while loading web pages with images first showing thumbnails of images and when the user clicks on it then load the original images will increase the user experience and performance of the website.

Here, in order to do so, we are using the library called " thumbnailator" which will help to generate high-quality thumbnails.





Add Dependency:

Download the jar file from here. Load the downloaded jar file on your project.

For IntelliJ Idea:

Go to: File >> Project Structure(Ctr + Alt + Shift + s) >> Libraries  and click the + icon on the top left corner and select library file that we downloaded. Apply and save, now we are ready to write code. If you are using in an existing project like Gradle or Maven:

For Gradle:

Inside build.gradle file under dependencies, 
compile 'net.coobird:thumbnailator:0.4.8'

For Maven:

Inside pom.xml
<dependency>
  <groupid>net.coobird</groupid>
  <artifactid>thumbnailator</artifactid>
  <version>0.4.8</version>
</dependency>

Create thumbnail from image file:

Let's create a class called Thumbnail.java:
import net.coobird.thumbnailator.Thumbnails;
import java.io.File;
import java.io.IOException;

    public class Thumbnail {

    public static void main(String[] args) {
        String inputImagePath = "E:/image.jpg"; //input image path
        File inputFile = new File(inputImagePath);
        String fileName = inputFile.getName();
        String outputPath = "E:" + "/T_"+fileName; //output path to write thumbnail image
        Thumbnail.createFromImageFile(inputFile, outputPath);
    }

    private static void createFromImageFile(File inputFile, String outputPath){
        try {
            Thumbnails.of(inputFile)
                    .size(500, 500)
                    .toFile(outputPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Here, the image is resized to the square of size 500*500 i.e width*height.


Create thumbnail from Buffered image:

private static void createFromBufferedImage(BufferedImage image, String outputPath){
        try {
            Thumbnails.of(image)
                    .size(500, 500)
                    .toFile(outputPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Create thumbnail Image by scaling:

private static void createByScaling(File inputFile, String outputPath){
        try {
            Thumbnails.of(inputFile)
                    .scale(0.25)
                    .toFile(outputPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
Here, it creates a thumbnail that is 25% of the original image.



Share:

Wednesday, June 3, 2020

Convert Tiff file to JPG/PNG using Java.

How to convert a tiff(tif) file to JPG/PNG using Java.

While dealing with the tiff file, we may have the problem that some browser doesn't support it. Please visit for image format support for different browser here. In this tutorial, we are going to convert the tiff file to a jpg or png file format in an efficient way.



Dependencies required.

In order to convert tiff to other image formats, we are using Jai image i/o  library. Download the jar file from here. As we are using lib version "jai-imageio-core-1.4.0" here, you can find jar file under Assets. Load the jar file in your IDE or if you have existing projects like Maven or Gradle add the dependency as below.

For Gradle:

Add in build.gradle under "dependencies"
compile 'com.github.jai-imageio:jai-imageio-core:1.4.0'

For Maven:

Add in pom.xml
 <dependencies>
    <dependency>
        <groupid>com.github.jai-imageio</groupid>
        <artifactid>jai-imageio-core</artifactid>
        <version>1.4.0</version>
    </dependency>
</dependencies>

Convert Tiff to PNG/JPG

Let's create a class called "TiffConverter.java"

TiffConverter.java:
public static void main(String[] args) {
        File tiffFile = new File("/home/360learntocode/im.tif"); //input path to tif file
        String outputPath = "/home/360learntocode/"; //output path to write file
        String convertFormat = "jpg"; //jpg, png, bmp
        try {
            TiffConverter.convertTiff(tiffFile, outputPath, convertFormat);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Provide the appropriate input and output path. You can provide the desired conversion format. As the conversion will reduce the pixel value of the image for jpg, png although BMP conversion doesn't reduce the pixel value.
private static File convertTiff(File tiffFile, String outputPath, String convertFormat) throws IOException {
        String fileName = tiffFile.getName();
        String ext = getFileExtension(fileName);
        fileName = fileName.replace(ext, "."+convertFormat);
        BufferedImage tiff = ImageIO.read(tiffFile);
        File output = new File(outputPath + fileName);
        ImageIO.write(tiff, convertFormat, output);
        return output;
    }





We are using the library to manipulate and convert the tif file. BufferedImage is used to handle and manipulate the image data. For more visit here.

  //get file extension from file name
    private static String getFileExtension(String fileName) {
        int lastIndexOf = fileName.lastIndexOf(".");
        return fileName.substring(lastIndexOf).toLowerCase();
    }
 

Finally, we successfully converted the Tiff/Tif File to the desired format like jpg, png, BMP.

The overall implementation looks like as below:
 import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;


public class TiffConverter {

    public static void main(String[] args) {
        File tiffFile = new File("/home/360learntocode/im.tif"); //input path to tif file
        String outputPath = "/home/360learntocode/"; //output path to write file
        String convertFormat = "jpg"; //jpg, png, bmp
        try {
            TiffConverter.convertTiff(tiffFile, outputPath, convertFormat);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static File convertTiff(File tiffFile, String outputPath, String convertFormat) throws IOException {
        String fileName = tiffFile.getName();
        String ext = getFileExtension(fileName);
        fileName = fileName.replace(ext, "."+convertFormat);
        BufferedImage tiff = ImageIO.read(tiffFile);
        File output = new File(outputPath + fileName);
        ImageIO.write(tiff, convertFormat, output);
        return output;
    }

    //get file extension from file name
    private static String getFileExtension(String fileName) {
        int lastIndexOf = fileName.lastIndexOf(".");
        return fileName.substring(lastIndexOf).toLowerCase();
    }
}
Share:

Tuesday, June 2, 2020

Hot reloading the resources file for changes in Grails.


How to hot reload the resources file when the changes happened in Grails.


I was working on Grails 3.3.0 and hot reloading was not working while changing in the resources files. So, I found some workaround which is worth sharing here. There are the following steps to resolve the issue.

  1. Configure to watch the directory.
  2. Watch the directory for code changes
  3. Reload spring resources config
  4. Load from the application

Configure to watch the directory:




Here I am creating a class BeanWatcher.groovy to watch the config file changes.


import grails.spring.BeanBuilder
import grails.util.Environment
import grails.util.Holders
import groovy.util.logging.Slf4j
import org.grails.core.exceptions.GrailsConfigurationException
import org.grails.spring.DefaultRuntimeSpringConfiguration
import org.grails.spring.RuntimeSpringConfigUtilities
import org.springframework.beans.factory.support.BeanDefinitionRegistry

import java.nio.file.FileSystems
import java.nio.file.FileVisitResult
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.SimpleFileVisitor
import java.nio.file.StandardWatchEventKinds
import java.nio.file.WatchEvent
import java.nio.file.WatchKey
import java.nio.file.WatchService
import java.nio.file.attribute.BasicFileAttributes
import java.util.concurrent.atomic.AtomicBoolean
    
    class BeanWatcher extends Thread{
    
    
    private final WatchService watchService
    private long sleepTime = 1000
    private AtomicBoolean stop = new AtomicBoolean(false)
    
    public BeanWatcher(Path path){
        watchService = FileSystems.getDefault().newWatchService()
        walkAndRegisterDirectories(path)

    }
    

    private void walkAndRegisterDirectories(final Path start){
        // register directory and sub-directories
        Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs){
                registerDirectory(dir)
                return FileVisitResult.CONTINUE
            }
        })
    }
    

    private void registerDirectory(dir){

        dir.register(
                watchService,
                StandardWatchEventKinds.ENTRY_MODIFY)
    }
    
    
     @Override
    void run() {

       
    }
    
     static void configureBeanWatcher(){
        Environment environment = Environment.current
        File baseDir = new File(environment.getReloadLocation()).canonicalFile
        String location = baseDir.canonicalPath
        File watchDir = new File(location, "grails-app/conf/spring")
        Path path = watchDir.toPath()
        BeanWatcher beanWatcher = new BeanWatcher(path)
        beanWatcher.start()
    }
    
    
    }

I want to watch the config spring file so I provided the path: "grails-app/conf/spring" under the project directory. As we are running in the thread so the current thread will not be interrupted for each time file changes. Here, we are registering directories and sub-directories.


Watch the directory for code changes:

    @Override
    void run() {

        try {
            WatchKey key
            try {
                while ((key = watchService.take()) != null) {
                    List<WatchEvent <?>> watchEvents = key.pollEvents()
                    for (WatchEvent <?> event : watchEvents) {
                        WatchEvent.Kind <?> kind = event.kind()
                        WatchEvent <Path> pathWatchEvent = cast(event)
                        Path name = pathWatchEvent.context()
                        Path dir = (Path) key.watchable()
                        Path child = dir.resolve(name).toAbsolutePath()
                        File childFile = child.toFile()
                        if(kind == StandardWatchEventKinds.ENTRY_MODIFY){
                            onChange(childFile)
                        }
                    }
                    key.reset()
                }
            } catch (InterruptedException e) {
                e.printStackTrace()
            }
        } catch (IOException e) {
            e.printStackTrace()
        }

    }
        

    @SuppressWarnings("unchecked")
    private static <T> WatchEvent<T> cast(WatchEvent<?> event) {
        return (WatchEvent<T>)event
    }
        
The above code will listen to the file changes and call the method onChange for each time the file changes. Now, it's time to reload our resources file while changes occurred.


Reload spring resources config:

   private static void onChange(File file) { // the changed file 
        processBeanDefinitionRegistry()
    }
    
    public static void processBeanDefinitionRegistry(){
        def springConfig = new DefaultRuntimeSpringConfiguration()
        def application = Holders.grailsApplication
        def context = application.mainContext
        def beanResources = context.getResource(RuntimeSpringConfigUtilities.SPRING_RESOURCES_GROOVY)
        if (beanResources?.exists()) {
            def gcl = new GroovyClassLoader(application.classLoader)
            try {
                RuntimeSpringConfigUtilities.reloadSpringResourcesConfig(springConfig, application, gcl.parseClass(new GroovyCodeSource(beanResources.URL)))
            } catch (Throwable e) {
                throw new GrailsConfigurationException("Error loading spring/resources.groovy file: ${e.message}", e)
            }
        }
        def bb = new BeanBuilder(null, springConfig, application.classLoader)
        bb.registerBeans((BeanDefinitionRegistry)application.getMainContext())
    }
    


This is the code snippet that I found in the grails where they used to reload the file. This will reload and re-configure the resources file.






Load from the application:

We set up all the necessary config and necessary code inside BeanWatcher.groovy now lets load the file from application for this add the following code.

Application.groovy

    if (Environment.current == Environment.DEVELOPMENT){
            BeanWatcher.configureBeanWatcher()
        }
    
This is only for the development env so we did the same.
Share:

Monday, December 24, 2018

Create Simple Secured Restful Web Services Application Using Spring Boot.​

How to create simple restful web services with spring security using Spring Boot.


Prerequisites:

  • Java JDK 1.8
  • IDE 

Introduction:

In this tutorial, we are going to create simple restful web services with spring security included. We are using spring boot scaffolding mechanism, from which we can simply generate the application prototype with its project structure. Simply visit start.spring.io here.

We are using maven project with java and spring boot 2.1.1 with dependencies Web, Security and DevTools.


Generate Project and extract it and open with your favorite Ide. It may take some time to download selected dependencies.

Project Structure:


Here, inside LearntocodeApplication.java there is the main method which will run spring boot application. As we have already added spring boot starter like "Web" inside dependencies section so it has autoconfiguration for tomcat and other feature configuration for running the application.

Make sure required dependencies are in pom.xml file.
  
<dependency>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-boot-starter-security</artifactid>
  </dependency>
  <dependency>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-boot-starter-web</artifactid>
  </dependency>

  <dependency>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-boot-devtools</artifactid>
   <scope>runtime</scope>
  </dependency>
  <dependency>
   <groupid>org.springframework.boot</groupid>
   <artifactid>spring-boot-starter-test</artifactid>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupid>org.springframework.security</groupid>
   <artifactid>spring-security-test</artifactid>
   <scope>test</scope>
  </dependency>

Run the application:

In order to run your application you can simply run via your editor or via command line. If you are trying to run via command line simply go to project's root directory and type the following command in your terminal.

mvn spring-boot:run
Now you can find spring security generated password in your terminal in order to access the application.
Using generated security password: 0fbaa489-e991-4920-a84d-a9710741c378



Create End Point:

In order to test our application, we need to create some Controller with a specified endpoint.

HelloController.java

package com.example.learntocode.restTest;

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

@RestController
public class HelloController {

    @GetMapping("/")
    public String hello(){
        return "Hello";
    }

}
Here we are creating rest controller HelloController which is wrapped by annotation @RestController and Get mapping to hello action i.e whenever "${baseUrl}/" endpoint request it will hit this "hello" action.

Test:

I am using postman for a testing endpoint. If we hit endpoint "http://localhost:8080" with Get request we will get Unauthorized message as follows.


Now lets test with the credential provided by spring security as discussed above with generated password.

Note: The default username is "user" and password is generated one. It will generate a new password for each time when we run our application.



Here we have successfully secured our application.

In order to customize the username and password go to "application.properties" and configure as follows.

spring.security.user.name=yourUserName
spring.security.user.password=yourPassword

Share:

Wednesday, September 19, 2018

Issue With Tomcat Catalina Permission Denied.

For Tomcat situated on root directory in Linux O.S, tomcat Catalina needs to have permission, and for the user who has run the tomcat may face the issue who does not have required permission to do so. So while running tomcat we may face the similar issues as below:

Using CATALINA_BASE:   /opt/tomcat
Using CATALINA_HOME:   /opt/tomcat
Using CATALINA_TMPDIR: /opt/tomcat/temp
Using JRE_HOME:        /home/kchapagain/spark/jdk1.8.0_101
Using CLASSPATH:       /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar
touch: cannot touch '/opt/tomcat/logs/catalina.out': Permission denied
tomcat/bin/catalina.sh: 415: tomcat/bin/catalina.sh: cannot create /opt/tomcat/logs/catalina.out: Permission denied
In order to resolve this issues one's need to give the permission for that user as:
sudo chown -R kchapagain:kchapagain /opt/tomcat/
Where "kchapagain" is my os user. And my apache-tomcat location is under /opt and apache-tomcat name is "tomcat".

 

Now start tomcat:
sudo kill -9 `pgrep java || echo 1` //run if java is already in used for specific port to avoid address already bind issue.
sh /opt/tomcat/bin/startup.sh
The output will be similar as:
Using CATALINA_BASE:   /opt/tomcat
Using CATALINA_HOME:   /opt/tomcat
Using CATALINA_TMPDIR: /opt/tomcat/temp
Using JRE_HOME:        /home/kchapagain/spark/jdk1.8.0_101
Using CLASSPATH:       /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar
Tomcat started.
Share:

Sunday, March 19, 2017

How to create facebook messenger bot part 2

Setup Welcome Screen For Greeting Text and Get Started Button 

This will be the welcome screen for the new conversation. It will appear only for the first time. This will be similar like this.


For this, we have to make the post request. I am using postman for the post request, you can simply add postman extension in your chrome.

Example
curl -X POST -H "Content-Type: application/json" -d '{
  "setting_type":"greeting",
  "greeting":{
    "text":"Welcome to shopping bot" //you can text whatever you want
  }
}' "https://graph.facebook.com/v2.6/me/thread_settings?access_token=PAGE_ACCESS_TOKEN"   // PAGE_ACCESS_TOKEN = previously generated page access token
  1. Select Post option from drop down of a postman. Enter request url = https://graph.facebook.com/v2.6/me/thread_settings?access_token=PAGE_ACCESS_TOKEN
  2. In headers tab set key=Content-Type and value=application/json
  3. In body tab select raw radio button and enter 
{
  "setting_type":"greeting",
  "greeting":{
    "text":"Welcome to shopping bot" 
  }
}
After sending you can see output as
{
  "result": "Successfully updated greeting"
}
Similarly, you can set for get started button.

Example


curl -X POST -H "Content-Type: application/json" -d '{
  "setting_type":"call_to_actions",
  "thread_state":"new_thread",
  "call_to_actions":[
    {
      "payload":"InitialPayload"
    }
  ]
}' "https://graph.facebook.com/v2.6/me/thread_settings?access_token=PAGE_ACCESS_TOKEN"      
After setting you can see like

After click Get Started button you can see JSON format where we check for "IntialPayload" in order
"postback": {
                        "payload": "InitialPayload"
                    }
to replay some message for that user.

Now it's time to handle JSON format.
Here we are going to create Class for each object.



MessageRequest.java


public class MessageRequest {
    String object;
    List<entry> entry = new ArrayList<entry>();

    public String getObject() {
        return object;
    }

    public void setObject(String object) {
        this.object = object;
    }

    public List<entry> getEntry() {
        return entry;
    }

    public void setEntry(List<entry> entry) {
        this.entry = entry;
    }
}

Entry.java
public class Entry {
    String id;
    String time;
    List<messaging> messaging = new ArrayList<messaging>();

    public String getId() {
        return id;
    }

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

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public List<messaging> getMessaging() {
        return messaging;
    }

    public void setMessaging(List<messaging> messaging) {
        this.messaging = messaging;
    }
}



Sender.java
public class Sender {
    String id;

    public String getId() {
        return id;
    }

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

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
Message.java
public class Message {
    String mid;
    String seq;
    String text;
    Long stickerId;
    List<attachment> attachments;
    Attachment attachment;
    QuickReplies quick_reply;
    List<quickreplies> quick_replies;
    public String getMid() {
        return mid;
    }

    public void setMid(String mid) {
        this.mid = mid;
    }

    public String getSeq() {
        return seq;
    }

    public void setSeq(String seq) {
        this.seq = seq;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public Long getStickerId() {
        return stickerId;
    }

    public void setStickerId(Long stickerId) {
        this.stickerId = stickerId;
    }

    public List<attachment> getAttachments() {
        return attachments;
    }

    public void setAttachments(List<attachment> attachments) {
        this.attachments = attachments;
    }

    public Attachment getAttachment() {
        return attachment;
    }

    public void setAttachment(Attachment attachment) {
        this.attachment = attachment;
    }

    public QuickReplies getQuick_reply() {
        return quick_reply;
    }

    public void setQuick_reply(QuickReplies quick_reply) {
        this.quick_reply = quick_reply;
    }

    public List<quickreplies> getQuick_replies() {
        return quick_replies;
    }

    public void setQuick_replies(List<quickreplies> quick_replies) {
        this.quick_replies = quick_replies;
    }

    
}

Postback.java
public class Postback {
    String payload;
    Referral referral;
    public String getPayload() {
        return payload;
    }

    public void setPayload(String payload) {
        this.payload = payload;
    }

    public Referral getReferral() {
        return referral;
    }

    public void setReferral(Referral referral) {
        this.referral = referral;
    }

}

Referral.java
public class Referral {
    String ref;
    String source;
    String type;

    public String getRef() {
        return ref;
    }

    public void setRef(String ref) {
        this.ref = ref;
    }

    public String getSource() {
        return source;
    }

    public void setSource(String source) {
        this.source = source;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}


Attachment.java
public class Attachment {
    String type;
    Payload payload;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Payload getPayload() {
        return payload;
    }

    public void setPayload(Payload payload) {
        this.payload = payload;
    }
}
QuickReplies.java
public class QuickReplies {
    String content_type;
    String title;
    String payload;

    public String getContent_type() {
        return content_type;
    }

    public void setContent_type(String content_type) {
        this.content_type = content_type;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getPayload() {
        return payload;
    }

    public void setPayload(String payload) {
        this.payload = payload;
    }
}
Messaging.java
public class Messaging {
    Sender sender;
    Recipient recipient;
    String timestamp;
    Message message;
    Postback postback;
    Referral referral;

    public Sender getSender() {
        return sender;
    }

    public void setSender(Sender sender) {
        this.sender = sender;
    }

    public Recipient getRecipient() {
        return recipient;
    }

    public void setRecipient(Recipient recipient) {
        this.recipient = recipient;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }

    public Message getMessage() {
        return message;
    }

    public void setMessage(Message message) {
        this.message = message;
    }

    public Postback getPostback() {
        return postback;
    }

    public void setPostback(Postback postback) {
        this.postback = postback;
    }

    public Referral getReferral() {
        return referral;
    }

    public void setReferral(Referral referral) {
        this.referral = referral;
    }
}

Element.java

public class Element {
    String title;
    String subtitle;
    String image_url;
    List<Button> buttons;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getSubtitle() {
        return subtitle;
    }

    public void setSubtitle(String subtitle) {
        this.subtitle = subtitle;
    }

    public String getImage_url() {
        return image_url;
    }

    public void setImage_url(String image_url) {
        this.image_url = image_url;
    }

    public List<Button> getButtons() {
        return buttons;
    }

    public void setButtons(List<Button> buttons) {
        this.buttons = buttons;
    }
}
Button.java
public class Button {
    String type;
    String title;
    String payload;
    String url;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getPayload() {
        return payload;
    }

    public void setPayload(String payload) {
        this.payload = payload;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

Payload.java

public class Payload {
        String template_type;
        String text;
        List<element> elements;
    List<button> buttons;
    
    public String getTemplate_type() {
    return template_type;
    }
    
    public void setTemplate_type(String template_type) {
    this.template_type = template_type;
    }
    
    public String getText() {
    return text;
    }
    
    public void setText(String text) {
    this.text = text;
    }
    
    public List<element> getElements() {
    return elements;
    }
    
    public void setElements(List<element> elements) {
    this.elements = elements;
    }
    
    public List<button> getButtons() {
    return buttons;
    }
    
    public void setButtons(List<button> buttons) {
    this.buttons = buttons;
    }
    }

Now its time to reply some text when user click Get Started button. All the callback messages should be listen in POST request. Lets make one helper class for making format of message to send. Here I am going to make FacebookHelper.java.
def private processMessages(){
        //make post request as readable
        String payload = FacebookHelper.readRequest(request);
        //convert json format to java readable format
        MessageRequest messageRequest = new Gson().fromJson(payload,MessageRequest.class)
        List<messaging> messagings = messageRequest.entry.get(0).messaging;
        for (Messaging event:messagings){
            try {
                if (event.postback != null){
                    sendPostbackMessge(event);
                }
            }catch (Exception e){
                e.printStackTrace();
                response.status = 200;
                render(true);
                return ;
            }

        }
        response.status = 200;
        render(true);
    }



Here line 3 will convert the JSON post request format to readable form which we will create in FacebookHelper.java.
public class FacebookHelper {

public static String readRequest(HttpServletRequest request){
        String line = null;
        StringBuffer stringBuffer = new StringBuffer();
        try {
            BufferedReader bufferedReader = request.getReader();
            while ((line = bufferedReader.readLine())!=null){
                stringBuffer.append(line);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return stringBuffer.toString();
    }
}
Line 9 check wheather the callback message is postback or not. If it is postback message then it will call sendPostbackMessge() method for checking and reply message.


private static sendPostbackMessge(Messaging event){
        List<string> postbackReplies =  testAndGetPostBackReplies(event)
        if (postbackReplies.size()>0){
            for (String postrep:postbackReplies){
                FacebookHelper.sendPostRequest(postrep);
            }
        }
    }

private static testAndGetPostBackReplies(Messaging event){
        List<string> postback = new ArrayList();
        String payload = event.postback.payload
        switch (payload){
            case "InitialPayload":
               postback = FacebookHelper.getInitialPostbackTemplate(event)
                break;
        }
        return postback
    }


public class FacebookHelper {
public static List<string> getInitialPostbackTemplate(Messaging event){
        List<string> replies = new ArrayList<string>();
        Message message = getMessage("Hello how can i help you?");
        String jsonReply = getJsonReply(event.getSender().getId(),message);
        replies.add(jsonReply);
        return replies;
    }
}


private static Message getMessage(String messg){
        Message message = new Message();
        message.setText(messg);
        return message;
    }



private static String getJsonReply(String senderId, Message message){
        Recipient recipient = new Recipient();
        recipient.setId(senderId);
        Messaging reply = new Messaging();
        reply.setRecipient(recipient);
        reply.setMessage(message);
        String replyJson = new Gson().toJson(reply);
        System.out.println("reply json------------------"+replyJson);
        return replyJson;
    }




getJsonReply method simply convert reply message in Json Format to post to client. In order to send message you have to call sendPostRequest() method.

public static String sendPostRequest(String payload){
        StringBuffer jsonString;
        try {
            URL url = new URL("https://graph.facebook.com/v2.6/me/messages?access_token=YOUR-PAGE-ACCESS-TOKEN");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
            OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
            writer.write(payload);
            writer.close();
            BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            jsonString = new StringBuffer();
            String line;
            while ((line = br.readLine()) != null) {
                jsonString.append(line);
            }
            br.close();
            connection.disconnect();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return jsonString.toString();

    }


Now you can see the output when Get Started button is clicked for the first time.


In the next tutorial we will create a final shopping bot, which have image attachment, buttons, quick replies button, option menu and payment system.

Share:

Monday, March 6, 2017

How to create facebook messenger bot part 1

Facebook gives the large platform for the messenger. In this tutorial series, we are going to create our own facebook messenger bot.  Please refer facebook developer messenger platform here for the documentation. We are going to create simple messenger bot for shopping.



Step 1: The first thing is to create a facebook app and page if you don't have. so let's create facebook app and page.


Click to create the app and fill the pop up modal and create app id. This will create the page with app id number. Here click +add product to add messenger.


Now create facebook page of your own which is the identity of your bot so, include the appropriate name and image for the page. 

Step 2: Setup Webhook

In order to get the update or handle and process the messages of conversation between bot and the client, we required to setup callback Url to process messages. With the live server its fine but we have to develop on the local server, as our local server is not a live one so we have to tunnel our local server to live one. For this, we are using ngrok. Please refer my youtube video to set up ngrok.


Create bot application in your editor, run the application and tunnel it using ngrok. The tunneled url will be similar like this http://849ac456.ngrok.io/. 



1.Generate a page access token: Use the page created to generate page access token.


2.Setup Webhook(Callback URL):


Here callback ULR is where we process post and get request. we need to verify this token later. Subscription field messages is subscribed to get the update when the message has been sent to your page and messaging_postback is for postback replies. In order to verify we need to write verify code in the get request of callback URL.

class MessengerController {

   def verifyAndProcess(){
        if (request.getMethod() == 'GET'){
            if (request.getParameter('hub.mode') == 'subscribe' &&
                    request.getParameter('hub.verify_token') == "bot") {
                log.info("Validating webhook");
                response.setStatus(200)
                 render(request.getParameter('hub.challenge'))
            } else {
                log.error("Failed validation. Make sure the validation tokens match.")
                response.setStatus(403)
                render(false)
            }
        }else {
            processMessages() //for processing messages
        }

    }
}
Finally, click verify and save. Here I am using grails application if you are using servlet then you have to verify it in doGet method and process post request message in doPost method.

Now you have to subscribe your page.


Step 3: Create link to messenger
In order to chat with a bot, we have to simply provide the link to the messenger for this use following view.
<div class="jumbotron">
<div class="container">
<div class="page-header">
<h1>
Messenger Chat bot</h1>
</div>
<div class="fb-messengermessageus" color="blue" messenger_app_id="your app-id" page_id="your PAGE_ID" size="standard">
</div>
</div>
</div>
<script>

    window.fbAsyncInit = function() {
        FB.init({
            appId: "1201209609977381", //your app-id
            xfbml: true,
            version: "v2.6"
        });

    };

    (function(d, s, id){
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) { return; }
        js = d.createElement(s); js.id = id;
        js.src = "//connect.facebook.net/en_US/sdk.js";
        fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));

</script>





If you type some text in messenger after clicking message us button you  can see post response in ngrok history console as bellow.





In the next tutorial, we are going to learn how to handle this JSON format and make a bot to reply.


Share: