24 February 2013

JSON dan Swing Framework

Pembaca yang budiman, berjumpa lagi dengan tulisan-tulisan saya di blog ini. Tak habis-habis saya mencoba mengeksplorasi Java Swing, secara ini adalah satu hal yang baru buat saya. Dalam tulisan kali ini saya akan mencoba memadukan JSON dan Swing Framework dengan menggunakan library GSON sebagai parser JSON-nya.
JSON atau Java Script Object Notation adalah sebuah teknologi yang sedang marak di dalam internet data exchange, dalam penggunaannya JSON digunakan sebagai pengganti XML dalam pertukaran data dengan salah satu alasan bahwa JSON lebih ringan daripada XML. Atas dasar ini pula penerapan JSON dalam aplikasi yang memiliki data exchange semakin banyak dipakai menggantikan XML.
Ketika kita membuat sebuah file yang datanya merupakan data JSON, kita harus memvalidasi dahulu data tersebut apakah data tersebut merupakan data JSON yang valid atau tidak. Ada beberapa cara memeriksa validitas sebuah data JSON, salah satunya adalah menggunakan http://jsonlint.com/, dengan URL tersebut kita bisa mengetahui apakah sebuah data JSON valid atau tidak.
Sekarang mari kita coba membuat sebuah data JSON, perhatikan source JSON berikut ini:
{
    "studentList": [
        {
            "id": 1,
            "studentName": "mojo",
            "age": 30
        },
        {
            "id": 2,
            "studentName": "Nida",
            "age": 15
        },
        {
            "id": 3,
            "studentName": "Eko Andrian",
            "age": 25
        }
    ]
}

Seperti itulah data JSON yang valid, dan jika diterjemahkan dalam bahasa XML akan menjadi seperti ini:
<?xml version="1.0" encoding="windows-1250"?>
<studentList>
  <student>
     <id>1</id>
     <studentName>mojo</stundetName>
     <age>30</age>
  </student>
  <student>
     <id>2</id>
     <studentName>Nida</stundetName>
     <age>15</age>
  </student>
  <student>
     <id>3</id>
     <studentName>Eko Andrian</stundetName>
     <age>325</age>
  </student>
</studenList>
Silahkan anda periksa sendiri ke http://jsonlint.com/ apakah data tersebut merupakan data JSON yang valid atau tidak.
Sekarang mari kita mencoba membuat sebuah program menggunakan java untuk membaca file tersebut. Dari contoh file di atas kita bisa membuat sebuah object java seperti source code berikut ini:

public class Student {
    private Integer id;
    private String studentName;
    private Integer age;
   //getter, setter, constructor, dan toString dibawahnya
}
Kemudian mari kita mencoba membaca data JSON dari file tersebut dengan cara memasukkannya dalam List of object dari student, perhatikan full source code berikut ini:
package org.josescalia.jsonswing.application;

import com.google.gson.Gson;
import org.josescalia.jsonswing.model.Student;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: Josescalia
 * Date: 2/24/13
 * Time: 6:10 PM
 * To change this template use File | Settings | File Templates.
 */
public class JsonConsoleParser {

    public static void main(String[] args) {
        String json = "";
        BufferedReader br = null;
        try {
            String sCurLine;
            br = new BufferedReader(new FileReader("E:\\localJsonFile.json"));
            while ((sCurLine = br.readLine()) != null) {
                json += sCurLine;
            }
        } catch (FileNotFoundException fnf) {
            fnf.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();  
        } finally {
            try {
                if (br != null) br.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        StudentList stList= new Gson().fromJson(json, StudentList.class);
        for(Student st: stList.getStudentList()){
            System.out.println(st);
        }

    }
}
class StudentList{
    private List<Student> studentList;

    public List<Student> getStudentList() {
        return studentList;
    }

    public void setStudentList(List<Student> studentList) {
        this.studentList = studentList;
    }
}

Ok, mari kita perhatikan baris demi baris source code tersebut. pada baris ke 1 s/d 10, baris-baris tersebut merupakan baris dimana aplikasi ini diletakkan dalam package dan library apa saja yang digunakan dalam aplikasi ini. Yang harus kita garis bawahi adalah penggunaan library com.google.gson.GSON disini,  silahkan download terlebih dahulu library ini dan kemudian men-setting library tersebut ke dalam environment project kita.  Atau jika anda menggunakan maven sebagai otomatisasi development anda tinggal menambahkan baris berikut ini dalam file pom.xml anda:
<dependency>
   <groupId>com.google.code.gson</groupId>
   <artifactId>gson</artifactId>
   <version>2.1</version>
   <type>jar</type>
</dependency>
Kemudian mulai dari baris 22 s/d 41 dari source code di atas adalah baris-baris dimana kita mencoba membaca file tersebut secara manual menggunakan Class BufferedReader, dan menampung isi dari file yang kita baca ke dalam String json.
Sebelum kita melangkah lebih lanjut, coba kita perhatikan baris 51 s/d 61, dimana kita membuat sebuah class yang berfungsi sebagai List Of Object Student, class itulah yang nantinya akan kita pakai sebagai media penampung deserialize JSON object yang dilakukan oleh library GSON seperti tertulis dalam baris 43. Nah sementara baris 44 s/d 46 adalah cara kita meng-cast dan kemudian mencetak object-object student yang kita dapat dari data JSON tersebut. Silahkan dicoba source-code tersebut dengan cara meng-compile dan menjalankannya, jika berhasil maka kita akan segera melaju ke percobaan berikutnya.
Percobaan berikutnya adalah kita akan memadukannya dengan Swing Framework sehingga mungkin akan lebih berguna pemanfaatan library GSON yang sedang kita pakai ini. Langkah selanjutnya adalah buatlah sebuah form menggunakan seperti gambar berikut ini:


Form ini terdiri dari 2 buah JLabel, 2 buah JButton (btnFetchHttp dan btnFetchLocalFile sebagai masing-masing nama button tersebut) dan 1 buah JTable, kita juga akan mengimplementasikan metode binding ke dalam JTable tersebut, bagi yang belum mengerti metode binding dalam Swing Framework, silahkan dibuka kembali post saya dalam blog ini sebelumnya. Sementara untuk flow dari form ini kita tentukan seperti ini: Form akan tampil pada saat program dijalankan dan ketika tombol Get JSON data from HTTP diklik, form akan mengambil data dari http://localhost/data/data2.json, dan jika tombol GET JSON data from Local File diklik sebuah file dialog akan keluar sebagai sarana untuk memilih file yang ada dalam drive komputer kita, dan setelah file JSON dipilih maka secara otomatis file tersebut di-parsing menjadi list of object student, dan kemudian menempatkannya ke dalam JTable.
Dalam flow diatas, kita mencoba membaca data JSON yang berasal dari URL sehingga kita memerlukan sebuah metode yang memungkinkan pembacaan file melalui http (read file over http). Singkatnya kita akan membuat sebuah file yang berisi metode-metode pembacaan file JSON baik dari local file maupun dari http, perhatikan source code berikut ini:

package org.josescalia.jsonswing.util;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

/**
 * Created with IntelliJ IDEA.
 * User: Josescalia
 * Date: 2/24/13
 * Time: 5:02 PM
 * To change this template use File | Settings | File Templates.
 */
public class JsonProcessors {

    static URL url;

    public static String fetchJsonURL(String sUrl) {
        String sReturn = "";
        try {
            url = new URL(sUrl);
            URLConnection connection = url.openConnection();
            connection.connect();
            BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String myString;
            while ((myString = br.readLine()) != null) {
                sReturn += myString;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();  //
        } catch (IOException e) {
            e.printStackTrace();  
        }

        return sReturn;
    }

    public static String fetchJsonLocalFile(String sPath) {
        String sReturn = "";
        BufferedReader br = null;
        try {
            String sCurLine;
            br = new BufferedReader(new FileReader(sPath));
            while ((sCurLine = br.readLine()) != null) {
                sReturn += sCurLine;
            }
        } catch (FileNotFoundException fnf) {
            fnf.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();  
        } finally {
            try {
                if (br != null) br.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return sReturn;
    }
}

Ok, dalam source code diatas kita memiliki dua buah fungsi, fungsi yang pertama akan memproses pembacaan file JSON melalui http, dan fungsi yang kedua akan melakukan proses pembacaan file JSON secara local, kedua fungsi tersebut memiliki kembalian (return value) yang sama yaitu String, yang mana nilai kembalian ini nantinya yang akan kita deserialize menjadi object Java menggunakan library GSON.
Sekarang kita kembali ke source code form yang sudah kita buat diatas, saya akan mencoba mempersingkat penjelasan source code dalam form ini, sebab jika kita menggunakan netbeans, beberapa source code sudah di generate oleh netbeans. Kita harus membuat definisi variable pada baris atas source-code form ini seperti screenshot dibawah ini:


public class StudentView extends javax.swing.JFrame {

    private StudentList studentList;
    
    private List<Student> listOfStudent = ObservableCollections.observableList(new ArrayList<Student>());
    /**
     * Creates new form StudentView
     */
    public StudentView() {
        initComponents();
    }
...

Kita membuat dua buah variable diatas dimana variable pertama adalah class StudentList yang sudah kita definisikan pada source code sebelumnya, disini saya mengekstrak class StudentList menjadi sebuah file tersendiri agar lebih mudah memahaminya. Variable ke-dua adalah listOfStudent yang merupakan sebuah List yang harus di Observable agar List tersebut bisa di-binding ke dalam JTable. Dan salah satu syarat binding komponen swing adalah dengan cara membuat getter-setter variable tersebut kemudian menambahkan metode firePropertyChange ke dalam masing-masing setter method dari variable tersebut, sehingga ketika kita merubah isi data variable tersebut, secara otomatis akan bisa tampil ke dalam komponen JTable.
Mari kita coba melihat source code berikutnya yang ada dalam form tersebut:

private void btnFetchHttpActionPerformed(java.awt.event.ActionEvent evt) {                                             
        String sContent = JsonProcessors.fetchJsonURL("http://localhost/data/data2.json");
        studentList = new Gson().fromJson(sContent,StudentList.class);
        
        List<Student> studList = new ArrayList<Student>();
        for(Student st: studentList.getStudentList()){
            studList.add(st);
        }
       
        setListOfStudent(studList);
        
    }                                            

    private void btnFetchLocalFileActionPerformed(java.awt.event.ActionEvent evt) {                                                  
        File jsonLocalFile = null;
        int returnValue = jFileChooser1.showOpenDialog(this);
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            jsonLocalFile = jFileChooser1.getSelectedFile();
            String path = jsonLocalFile.getAbsolutePath();
            lblPathLocalFile.setText("Local File Path : " + path);
            String sContent = JsonProcessors.fetchJsonLocalFile(path);
            studentList = new Gson().fromJson(sContent, StudentList.class);
            List<Student> studList = new ArrayList<Student>();
            for (Student st : studentList.getStudentList()) {
                studList.add(st);
            }
            setListOfStudent(studList);
        }
    } 

Source code di atas menggambarkan bahwa kita punya 2 metode, yang pertama adalah metode ketika btnFetchHttp diklik, kemudian metode yang kedua adalah metode ketika btnFetchLocalFile diklik. Dari dua method tersebut yang harus kita perhatikan adalah ketika library GSON mem-parse String dan baris paling akhir pada tiap-tiap metode tersebut, dimana perubahan data pada listOfStudent, dilakukan dengan cara cukup memanggil setter dari property listOfStudent-nya saja, sebab setter dari listOfStudent sudah mengandung firePropertyChange, sehingga penulisan code akan jadi lebih sederhana.
Oh ya, oleh karena salah satu flow dari form ini membaca data dari HTTP, tentunya kita harus membuat sebuah server dengan URL http://localhost/data/, dimana nanti file data2.json akan kita letakkan dalam direktori data ini. Web server bisa kita buat dengan menggunakan xampp, atau apache, atau web server lainnya, dan untuk mengetes bisa tidaknya URL tersebut dipanggil, gunakan browser dalam pengecekan pemanggilan URL tersebut.
Silahkan compile semua program tersebut dan kemudian jalankan file Form Student tersebut, dan lakukan flow yang kita sudah definisikan diatas sehingga form tersebut setelah dijalankan akan tampil seperti berikut ini:


Fetch Data From HTTP







Fetch Data From Local File




Ok, demikianlah percobaan kita kali ini, saya harap kita bisa lebih mengembangkannya untuk pemanfaatan yang lebih luas lagi, dan link ini adalah source lengkap dari percobaan kita diatas. Silahkan download jika sudi.
 

Semoga Bermanfaat

Menteng, 25 Februari 2013


Josescalia


No comments: