Membuka Window dari Node Bean Tree pada Netbeans Platform

Pengen buka window dari suatu node?! Simple, pake ajah kode:

TopComponent tc = new NamaTopComponentYangDibuka();

Atau, karena top component udah di-set sebagai suatu singleton ama netbeans platform, manggilnya bisa gini:

TopComponent tc = WindowManager.getDefault().findTopComponent("NamaTopComponentYangDibuka ");

Dan jangan lupa nambahin kode:

tc.open();

Begitulaaahh~~ gampang kan?! Tambahin kode2 di atas di aksi yang udah dibikin sebelumnya.

Tulisan Terkait:

  1. Bean Tree View
  2. Aksi Bean Tree View

Valid: Yap!
Kadaluarsa: Teruji efektif di versi 7.4-8.0; Diyakinkan jalan di versi 6.9 ke atas.
Sumber:
Milis Netbeans
Situs Geertjan

Menambahkan Aksi pada Node BeanTreeView Netbeans Platform

Ngelanjutin postingan sebelumnya… agak aneh c yah kalo Node di BeanTreeView tuh gitu2 ajah. Enaknya ada aksinya gitu. Aksi dari Node bisa kamu dapatin dengan meng-override method “getActions” dari kelas “Node”. Dari kelas “Node” lhoh yah. Bukan dari kelas “AbstractNode”. Kalo dari kelas “AbstractNode”, emang ada jugak method yang sama (beda parameter sama tipe balikan tapinya), tapi method ituh udah deprecated kalo gak salah. Untuk method “getActions”, contoh hasilnya bisa kamu lihat di situs tutorial node netpla.

Kalo kamu mau aksi-nya dijalanin pas nge-klik 2x di node-nya, yang perlu kamu override bukan “getActions”, tapi “getgetPreferredAction” dari kelas “AbstractNode”. Gampang kan…

Okeh, best practice-nya gini… Dari project yang kemaren… Kamu punya kan 2 kelas utama. Yang atu berupa top component (Window), tempat ada BeanTreeView, plus satu class lagi yang merupakan class untuk membuat node anak (nama class-nya “SimpulAnak”).

Sekarang, tentuin dulu mau nambahin action di mana. Kalo kamu mau nambahin aksi di “root” (yang dikasi lambang segitiga ke bawah), kamu perlu tambahin method “getPreferredAction” pas deklarasiin Abstract node-nya. Deklarasi abstract node ini ada di bagian konstruktor top component (Window), yang kemaren kita kasi nama “SimpulExplorerTopComponent”:

    public SimpulExplorerTopComponent() {
        initComponents();
        setName(Bundle.CTL_SimpulExplorerTopComponent());
        setToolTipText(Bundle.HINT_SimpulExplorerTopComponent());

        associateLookup(ExplorerUtils.createLookup(mgr, getActionMap()));
        SimpulAnak ecv = new SimpulAnak();
        AbstractNode an = new AbstractNode(Children.create(ecv, true));
        an.setIconBaseWithExtension("/org/seleksi/view/down-rectangle.png");
        mgr.setRootContext(an);        
    }

Kalo mau kasi aksi di node itu, kamu tinggal bikin pendeklarasian objek AbstractNode (yang gw kasi warna biru) jadi gini:

    public SimpulExplorerTopComponent() {
        initComponents();
        setName(Bundle.CTL_SimpulExplorerTopComponent());
        setToolTipText(Bundle.HINT_SimpulExplorerTopComponent());

        associateLookup(ExplorerUtils.createLookup(mgr, getActionMap()));
        SimpulAnak ecv = new SimpulAnak();
        AbstractNode an = new AbstractNode(Children.create(ecv, true)){

        };
        an.setIconBaseWithExtension("/org/seleksi/view/down-rectangle.png");
        mgr.setRootContext(an);   
    }

Jadi jangan langsung ditutup pake titik koma. Tapi dikasi kurung kerawal dulu, baru kasi titik koma. Letakkin kursor kamu di space kosong antara kurung kerawal buka plus tutup, trus tekan “Alt+Insert”. Kamu bakal nemu beberapa menu kayak gini:

1. Override Method

Pilih “Override Method”. Kalo kamu sulit nemuin tombol yang gw maksud di keyboard kamu, bisa pake klik kanan di space kosong tadi, pilih “Insert Code”. Dan kamu mendapatkan hal yang sama kayak nekan “Alt + Insert”

2. Insert Code

Ingat! Posisi kursor sangat menentukan di sini. Kamu pastiin cursornya ada di antara kurung kerawal buka sama kurung kerawal tutup pas ngedeklarasiin objek AbstractNode. Nanti, kamu bakal nemuin semacam window gini:

3. Override Class

Perhatiin, di sana kamu bisa nge-override beberapa method dari beberapa class yang tersedia. Seperti yang gw bilang, method “getPreferredAction” adanya di class “AbstractNode”. Jadi, breakdown (tekan tanda tambahnya). Cari method yang mau di-override, centang method itu. Dan pilih “Generate”.

3. Override Method

Kamu bakal dapatin pendeklarasian jadi gini kamu gini:

    public SimpulExplorerTopComponent() {
        initComponents();
        setName(Bundle.CTL_SimpulExplorerTopComponent());
        setToolTipText(Bundle.HINT_SimpulExplorerTopComponent());

        associateLookup(ExplorerUtils.createLookup(mgr, getActionMap()));
        SimpulAnak ecv = new SimpulAnak();
        AbstractNode an = new AbstractNode(Children.create(ecv, true)){

            @Override
            public Action getPreferredAction() {
                return super.getPreferredAction(); 
                //To change body of generated methods, 
                //choose Tools | Templates.
            }

        };
        an.setIconBaseWithExtension("/org/seleksi/view/down-rectangle.png");
        mgr.setRootContext(an);
        
    }

Okeh, sekarang tinggal kamu ubah ajah isi dari method “getPreferredAction”. Ingat yah, balikannya “Action”, jadi pastiin kamu bikin Action dari method ini. Kalo gw c nambahin inner class yang nge-extends AbstractAction gini:

        AbstractNode an = new AbstractNode(Children.create(ecv, true)){

            @Override
            public Action getPreferredAction() {
                return super.getPreferredAction(); 
                //To change body of generated methods, 
                //choose Tools | Templates.
            }      
            class Aksi extends AbstractAction{
                
            }
        };

Kamu bakal diminta buat nge-implements method abstract yang terkandung di class “AbstractAction”, yaitu method “actionPerformed”. Ubah actionPerformed-nya, dan isi dari method “getPreferredAction” ubah jadi mengembalikan objek dari kelas “Aksi”. Intinya, kamu ubah jadi gini deh:

        AbstractNode an = new AbstractNode(Children.create(ecv, true)){

            @Override
            public Action getPreferredAction() {
                return new Aksi();
            }
            class Aksi extends AbstractAction{

                @Override
                public void actionPerformed(ActionEvent ae) {
                    JOptionPane.showMessageDialog(null, "Hello");
                }    
            }
        };

Nanti hasilnya gini:

4. Hasil Root

Kalo kamu tekan menu 1, menu 2 atau menu 3… itu gak bakal ngaruh apapun. Kamu belum nambahin “getPreferredAction”-nya masalahnya. Dan sekali lagi, method tersebut adanya Cuma di class “AbstractNode”. Sedangkan, yang kamu punya Cuma class ChildFactory sebagai extends dari class “SimpulAnak”. Jadi, bisa dibilang kamu gak bisa nge-override method ini langsung.

Hal ini bisa kamu akalin dengan ngubah struktur codingan program, dengan ngedeklarasiin Node bentukan kamu yang nge-extends “AbstractNode”. Terus, di class Anak (SimpulAnak), di method “createNodeForKey”, isinya kamu ubah dari yang awalnya gini:

BeanNode bn = new BeanNode(key);

Jadi gini:

NodeBentukanSendiri bn = new NodeBentukanSendiri(key);

Tapi… berhubung gw malas nambah 1 class, gw bikinnya gini… yang awalnya isi dari “createNodeForKey” ituh gini:

    @Override
    protected Node createNodeForKey(String key) {
        try {
            BeanNode bn = new BeanNode(key);
            bn.setIconBaseWithExtension
               ("/org/seleksi/view/right-rectangle.png");
            bn.setDisplayName(key);
            System.out.println();
            return bn;
        } catch (IntrospectionException ex) {
            Exceptions.printStackTrace(ex);
            return null;
        }
    }

Gw ubah jadi gini:

    @Override
    protected Node createNodeForKey(String key) {
        try {
            BeanNode bn = new BeanNode(key){

            };
            bn.setIconBaseWithExtension
               ("/org/seleksi/view/right-rectangle.png");
            bn.setDisplayName(key);
            System.out.println();
            return bn;
        } catch (IntrospectionException ex) {
            Exceptions.printStackTrace(ex);
            return null;
        }
    }

Gw tambahin lagi kurung kerawal buka ama kurung kerawal tutup baru dikasi titik koma. Di bagian yang kosong, kamu tekan “Alt+Insert”, terus pilih “Override Method”. Dan… samaan deh kayak sebelumnya. Akhirnya, methodnya berubah jadi gini:

    @Override
    protected Node createNodeForKey(String key) {
        try {
            BeanNode bn = new BeanNode(key) {

                @Override
                public Action getPreferredAction() {
                    return new AksiChild();
                }

                class AksiChild extends AbstractAction {

                    @Override
                    public void actionPerformed(ActionEvent ae) {
                        JOptionPane.showMessageDialog(null, "Child Anak");
                    }

                }
            };
            bn.setIconBaseWithExtension
               ("/org/seleksi/view/right-rectangle.png");
            bn.setDisplayName(key);
            System.out.println();
            return bn;
        } catch (IntrospectionException ex) {
            Exceptions.printStackTrace(ex);
            return null;
        }
    }

Dan hasilnya gini:

5. Hasil Child

Dan perlu diperhaitkan, kalo aksi ini, mau neken node yang manapun, hasilnya pasti sama. Coz semuanya gw bikin seragam. Kalo kamu mau filter, boleh di bagian “actionPerformed”-nya.

Begitulaaaahhh~~~ semoga membantu kamu.

Valid: Yap!
Kadaluarsa: Teruji efektif dari versi 7.4 sampe 8.0
Sumber:
– https://platform.netbeans.org/tutorials/nbm-nodesapi2.html#actions
– http://netbeans-org.1045718.n5.nabble.com/Double-click-a-node-to-open-different-components-td5015328.html

Menambahkan Open File pada Netbeans Platform

Yang namanya ngegunain framewok emang menyenangkan… Ada banyak alasan buat itu. Salah satu alasan yang paling sering digunain buat alasan pas sidang TA yaitu tentang pengembangan lebih lanjut. Well, gw menganggap itu bukan keuntungan sama sekali. Yang jelas, kalo gw, seperti ajaran senpai… nganggap kalo framework itu kerangka kerja. Setiap orang punya cara kerja dan pola pikirnya masing-masing. Dan framework menyamaratakan persepsi dan pikiran itu. Simple! Dan yang paling penting, framework itu memudahkan segalanya. Ada beberapa modul yang gak harus dibuat ulang dari awal. Tinggal make fungsi yang udah disediakan… dan jadi!

Hal itu juga kejadian di Netbeans Platform. Ada modul yang bisa kamu gunain gitu ajah buat hal2 tertentu dan umum. Salah satunya modul buat ngebuka file. Di sini, kamu bisa langsung pilih file, dan ngebuka file itu. Gampang!

Hasil akhirnya kira2 gini:

1. Hasil Akhir

Ada satu module “Open File” ama “Open Recent File” di sana. Defaultnya hal ini gak ada c yah… Defaultnya kan kayak gini:

2. Hasil Sebelumnya

Jadi… nambahin hal itu… caranya gampang ajah. Kamu gak usah nambahin 1 action buat menu yang bakal nampil “Open File” terus ngebikin objek File Chooser. Gak usaaaaahh…

Cara nambahinnya gini, klik kanan di NPA yang kamu mau ada Netbeans Platform-nya. NPA lhoh yah. NPA! Bukan module NPA. Pilih Properties, muncul 1 window, di bagian “Categories”, pilih “Libraries”.

3. Module NPA

Di bagian “Node”, ada beberapa module udah jadi yang bisa kamu gunain. Karena fokusnya buat nambahin “Open File” tadi, jadi coba pilih/breakdown bagian “ide”, cari module “User Utilities”. Dan langsung ajah centang…

4. Module NPA-2

Klik OK, dan hasilnya seperti yang udah kamu liat sebelumnya. Sekarang, kalo kamu berniat buat nambahin filter, kayak gini:

5. Filter

Bisa banget! Caranya jugak gampang… tinggal pake annotasi dari MIMEResolver.Registration. Bikin 1 top component (Window). Kalo belum tau caranya, liat postingan gw sebelumnya yak. Terus, tambahin 1 buat file Java. Yap! File java biasa.

Bikin file-nya jadi kayak gini:

import org.openide.filesystems.MIMEResolver;

@MIMEResolver.Registration(
        displayName = "Nama",
        resource = "mime-resolver-html.xml",
        showInFileChooser ={"Web Page"}
)

public class WebFilter{

}

Yuhuuuu~~ isinya emang gak ada. Tapi kamu nambahin satu annotasi “@MIMEResolver.Registration”. Annotasi ini sebenernya bisa ditambahin di top component tadi. Tapi gw pisahin ke kelas lain. Di kelas ini, kamu bisa lakukan beberapa logika… Contohnya, apa yang mau kamu lakuin terhadap file yang kamu buka. Pastinya gak plain kayak di atas. Kamu jugak musti make module lain dari netbeans platform buat itu. Karena sulit, jadi gw gak nulisin dah di mari :p

Balik lagi ke kelas tadi, kemungkinan kamu bakal dapat error di baris “resource”. Ini kejadian, coz XML tempat ngatur filternya gak ada. Jadi kamu bikin 1 file dulu… namanya “mime-resolver-html.xml”. Yap! Lagi2 kamu benar… itu file XML emang. Isinya gini:

<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE MIME-resolver PUBLIC
          "-//NetBeans//DTD MIME Resolver 1.0//EN" 
          "http://www.netbeans.org/dtds/mime-resolver-1_0.dtd">
<MIME-resolver>
    <!-- Skip anything marked as definitely not ours. -->
    <file>
        <fattr name="known-ant-project-file" text="false"/>
        <exit/>
    </file>
    <!-- Accept immediately anything known as definitely ours. -->
    <file>
        <fattr name="known-ant-project-file" text="true"/>
        <resolver mime="text/x-ant+txt"/>
    </file>
    <!-- For other XML, look for <project default="..."/> -->
    <file>
        <ext name="htm"/>
        <resolver mime="text/x-ant+htm">
            <xml-rule>
                <element name="project">
                    <attr name="default"/>
                </element>
            </xml-rule>
        </resolver>
    </file>
    <file>
        <ext name="html"/>
        <resolver mime="text/x-ant+html">
            <xml-rule>
                <element name="project">
                    <attr name="default"/>
                </element>
            </xml-rule>
        </resolver>
    </file>
    <file>
        <ext name="shtml"/>
        <resolver mime="text/x-ant+shtml">
            <xml-rule>
                <element name="project">
                    <attr name="default"/>
                </element>
            </xml-rule>
        </resolver>
    </file>
    <file>
        <ext name="xhtml"/>
        <resolver mime="text/x-ant+xhtml">
            <xml-rule>
                <element name="project">
                    <attr name="default"/>
                </element>
            </xml-rule>
        </resolver>
    </file>
</MIME-resolver>

Gw gak bakal jelasin apapun terkait hal diatas, tapi gw Cuma mau bilang… perhatiin kode warna biru.

Yang bakal kamu dapatin dari kelas di atas, yaaa… Cuma filter buat web page. Kalo mau filter buat XML jugak kayak di contoh awal, kamu musti tambah 1 kelas lagi. Ulangi lagi kayak hal di atas. Sebenernya ada cara lain, Cuma gw gak ngerti. Jadi yaaa sudah… Yang penting jadi kan 😀

6. Filter Akhir

Jadi gw tambahin 1 file XML gini:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE MIME-resolver PUBLIC
          "-//NetBeans//DTD MIME Resolver 1.0//EN" 
          "http://www.netbeans.org/dtds/mime-resolver-1_0.dtd">
<MIME-resolver>
    <!-- Skip anything marked as definitely not ours. -->
    <file>
        <fattr name="known-ant-project-file" text="false"/>
        <exit/>
    </file>
    <!-- Accept immediately anything known as definitely ours. -->
    <file>
        <fattr name="known-ant-project-file" text="true"/>
        <resolver mime="text/x-ant+xml"/>
    </file>
    <!-- For other XML, look for <project default="..."/> -->
    <file>
        <ext name="xml"/>
        <resolver mime="text/x-ant+xml">
            <xml-rule>
                <element name="project">
                    <attr name="default"/>
                </element>
            </xml-rule>
        </resolver>
    </file>
</MIME-resolver>

Terus 1 kelas lagi gini:

import org.openide.filesystems.MIMEResolver;

@MIMEResolver.Registration(
        displayName = "Nama",
        resource = "mime-resolver-xml.xml",
        showInFileChooser ={"XML Document"}
)

public class XMLFilter {
    
}

Struktur direktori:

7. Direktori

Begitulaaaahhh~~ gampang, kan?! 😀

Valid: Banget!
Kadaluarsa: Paling gak, teruji dari versi 7.4 sampe 8.0
Sumber:
https://blogs.oracle.com/geertjan/entry/open_file_dialog_in_the
– Javadoc MIMERegistration.

Menggunakan BeanTreeView pada Netbeans Platform

Buat sebuah NPA baru, tambah 1 modul (name-nya kalo gak ada ide, bikin aja “SeleksiSimpul”, base “org.seleksi.view”).

1. Modul-NPA

Trus tambahin sebuah top component (Window). Kalo belum tau, caranya…. Klik kanan di package “org.seleksi.view”, pilih “New –> Other”. Muncul 1 window, pilih “Window”.

2. BeanTree

3. Bean Tree-Next

4. Bean Tree-Next-1

Muncul  sebuah form, atur di form kemunculan BeanTreeView. Ambil BeanTreeView dari Palette. Kalo belum ada, di Palette, klik kanan pilih “Palette Manager”.

5. Palette Manager

Pilih “Add From JAR”.

5. Add From JAR

Cari jar “org-openide-explorer.jar” di folder /platform/modules dari direktori tempat nginstall netbeans. Kalo yang windows, kemungkinan alamatnya: “C:\Program Files\NetBeans 8.0\platform\modules”, kalo linux kemungkinan “/home/ NetBeans 8.0/platform/modules”.

6. Jar Explorer

Pilih “BeanTreeView”, masukkan kemunculannya ke kategori yang kamu mau.

6. Category

6. Category Place

Nanti bakal muncul gini:

7. Palette Bean Tree View

Tarik BeanTreeView ke form… sebelumnya layout kalo mau diatur jugak boleh.

8. Panel

 Kalo gw pake border layout, naruh BeanTreeView di bagian center. Class-nya bakal ada merah2 tanda error. Itu wajar, coz defaultnya Cuma ada 5 modul dependency yang dipakai di sini (kalo udah bikin Window):

  1. Lookup API
  2. Settings API
  3. UI Utilities API
  4. Utilities API
  5. Window System API

Liat ajah di bagian library dari module terkait. Bakal muncul gini:

9. Error Dependency

Dependency BeanTreeView ada di “Explorer & Property Sheet API”. Trus buat bikin simpul/node-nya pake dependency dari “Nodes API”. Jadi, sekalian kita tambahin ajah. Di bagian “Libraries”, klik kanan, pilih “Add Module Dependency…” Cari 2 module tadi. Bisa kamu masukin nama, atau komponen yang kamu perluin.

10. Explorer Dependency

11. Nodes Dependency

Buat sebuah class untuk membuat child atau node2 yang bisa dieksplor nanti. Bentuk dasar yang tampil, gw bikinnya String ajah. Kamu bisa ganti pake class bentukan sendiri.

Jadi, di package yang sama (org.seleksi.view), bikin sebuah class gini:

import java.util.List;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
public class SimpulAnak extends ChildFactory<String>{

    @Override
    protected boolean createKeys(List toPopulate) {
        return true;
    }

    @Override
    protected Node createNodeForKey(String key) {
        return null
    }   
}

Berhubung di atas Cuma outline, kita isi masing2 method yang ada. Udah tau ya maksut kode di atas. Cuma 1 method abstract dari kelas “ChildFactory” (<String>, bisa kamu ganti kelas lain), yaitu createKeys(). Method yang ini gunanya buat mem-populate data yang bakal ditampilin. Terus method yang satu lagi buat bikin node-nya.

Jadi… ganti methodnya jadi gini:

    @Override
    protected boolean createKeys(List toPopulate) {
        ArrayList al = new ArrayList();
        al.add("Menu 1"); al.add("Menu 2"); al.add("Menu 3");
        toPopulate.addAll(al);
        return true;
    }

    @Override
    protected Node createNodeForKey(String key) {
        try {
            BeanNode bn = new BeanNode(key);
            bn.setDisplayName(key);
            System.out.println();
            return bn;
        } catch (IntrospectionException ex) {
            Exceptions.printStackTrace(ex);
            return null;
        }
    }

Pastikan import-nya gini:

import java.beans.IntrospectionException;
import java.util.ArrayList;
import java.util.List;
import org.openide.nodes.BeanNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;

Sekarang, karena node bakal ditampilin di window, buka window yang tadi (SimpulExplorerTopComponent), tambahkan signature gini di bagian class:

public final class SimpulExplorerTopComponent extends TopComponent implements ExplorerManager.Provider{

Nanti, bakal ada error, ikutin suggestion-nya (implement all abstract method) yang artinya harus ada 1 method yang ditambahin. Kita bikin gini:

    private final ExplorerManager mgr = new ExplorerManager();
    @Override
    public ExplorerManager getExplorerManager() {
        return mgr;
    }

Yap, memang ada 1 atribut “mgr” yang gw tambahin di sana. Terus gw ubah isi method-nya. Dan masih di window yang tadi, ubah konstruktornya jadi gini:

    public SimpulExplorerTopComponent() {
        initComponents();
        setName(Bundle.CTL_SimpulExplorerTopComponent());
        setToolTipText(Bundle.HINT_SimpulExplorerTopComponent());

        associateLookup(ExplorerUtils.createLookup(mgr, getActionMap()));
        SimpulAnak ecv = new SimpulAnak();
        AbstractNode an = new AbstractNode(Children.create(ecv, true));
        mgr.setRootContext(an);
    }

Di sana, emang kita pake yang namanya “Lookup”, gw gak tau kenapa… tapi kalo pake explorer manager emang pake create2 lookup gitu… Yah begitulah… Dan hasil akhirnya:

12. Hasil

Kamu bisa ganti icon dan lain2 di bagian deklarasi abstract node (buat parent) atau di bagian pengembalian node buat child…

Contoh:

@Override
    protected Node createNodeForKey(String key) {
        try {
            BeanNode bn = new BeanNode(key);
            bn.setIconBaseWithExtension("/org/seleksi/view/right-rectangle.png");
            bn.setDisplayName(key);
            System.out.println();
            return bn;
        } catch (IntrospectionException ex) {
            Exceptions.printStackTrace(ex);
            return null;
        }
    }
    public SimpulExplorerTopComponent() {
        initComponents();
        setName(Bundle.CTL_SimpulExplorerTopComponent());
        setToolTipText(Bundle.HINT_SimpulExplorerTopComponent());

        associateLookup(ExplorerUtils.createLookup(mgr, getActionMap()));
        SimpulAnak ecv = new SimpulAnak();
        AbstractNode an = new AbstractNode(Children.create(ecv, true));
        an.setIconBaseWithExtension("/org/seleksi/view/down-rectangle.png");
        mgr.setRootContext(an);
        
    }

Path:

13. Path

Hasil:

14. Hasil Akhir

Gambar bisa diambil di situs tutorial netbeans

Valid: Yap!
Versi non-Kadaluarsa: Netbeans 7.2-8.0
Sumber:
https://platform.netbeans.org/tutorials/nbm-selection-2.html
https://platform.netbeans.org/tutorials/nbm-crud.html

Menggunakan JUnit di Netbeans

Intinya, JUnit merupakan framework buat nge-tes sebuah kode. Gitu… Ada banyak definisi testing yang di-handle sama framework ini, dan itu gak gw tulisin di mari coz ini jugak tulisan repost… hihihihi :p

Okeh, langsung mulai… Buat sebuah kelas kayak gini:

public class Kalkulator {
    public int bagi(int x, int y){
        return 0;
    }
    public void tampil(String x){
        int hasil = Integer.valueOf(x) + 5;
        System.out.println("Hasil: "+hasil);
    }
}

Sekarang… yang kita lakukan adalah bertanya2… gimana cara nge-tes aplikasi itu udah jalan benar atau enggak… Yooo-a! Cara gampang, tinggal bikin Main kayak yang di bawan ini… Kalo hasilnya benar, berarti benar… kalo salah yaaa.. salah!

public class Main {
    public static void main(String[] args) {
        Kalkulator k = new Kalkulator();
        int x = k.bagi(4, 2);
        System.out.println("4 /2 = "+x);
    }
}

Dan ternyataaaa…

1. Hasil Salah

HASILNYA SALAH!!!

Dan, salahnya dimana??? Tinggal liat ajah fungsi di kelas lain… fungsi “bagi” itu. Ternyata kesalahannya, yang di-return tetap ajah angka 0. Gak ngaruh input atau output. Dan kayaknya, kalo nyoba beberapa kemungkinan lain, bisa jadi ada salah jugak… contohnya kalo Main-nya gini:

public class Main {
    public static void main(String[] args) {
        Kalkulator k = new Kalkulator();
        int x = k.bagi(4, 0);
        System.out.println("4 /0 = "+x);
    }
}

Dan gw udah ubah class-nya jadi gini:

public class Kalkulator {
    public int bagi(int x, int y){
        return x/y;
    }
    public void tampil(String x){
        int hasil = Integer.valueOf(x) + 5;
        System.out.println("Hasil: "+hasil);
    }
}

Hasilnya….

2. Exception

EXCEPTION!!

Yah, gak ngaruh c ya… itu error exception… beda penangan emang.

Intinya, kita butuh semua scenario pengujian dari pembagian. Itu masih pembagian, belum masalah casting kayak yang di method lain. Gimana coba kalo ternyata dia harus casting huruf yang non-angka?!

Itulah gunanya JUnit… sebuah framework untuk menangani setiap kasus dari sebuah class… Kira2 gitu… tapi gw jugak gak tau ding. Gw kan repost ceritanya… :p Tapi kalo yang gw tangkep c, kalo mau testing, gak usah jalanin keseluruhan aplikasi… cukup dengan jalanin kasus unit-nya ajah… Dan ingat, ini entah benar entah enggak… coz dari gw c… 😀

Jadi, untuk JUnit, bisa dibikin class kayak gini:

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

public class KalkulatorTest {
    
    public KalkulatorTest() {
    }
    
    @BeforeClass
    public static void setUpClass() {
    }
    
    @AfterClass
    public static void tearDownClass() {
    }
    
    @Before
    public void setUp() {
    }
    
    @After
    public void tearDown() {
    }

    /**
     * Test of bagi method, of class Kalkulator.
     */
    @Test
    public void testBagi() {
        System.out.println("bagi");
        int x = 0;
        int y = 0;
        Kalkulator instance = new Kalkulator();
        int expResult = x/y;
        int result = instance.bagi(x, y);
        assertEquals(expResult, result); 
    }

    /**
     * Test of tampil method, of class Kalkulator.
     */
    @Test
    public void testTampil() {
        System.out.println("tampil");
        String x = "";
        Kalkulator instance = new Kalkulator();
        instance.tampil(x);
    }
    
}

Penjelasan dari beberapa hal di atas:

  • @Test: anotasi buat mengidentifikasi test method
  • @Before: menyatakan method yang dieksekusi sebelum test dilakukan. Jadi kayak tahap preparation gitu…
  • @After: ini kebalikan dari @Before… method yang dieksekusi seabis test. Gunanya biasanya buat cleanup the test environment (contoh, hapus temporary data, restore defaults dll).
  • @BeforeClass: method ini dieksekusi sekali, sebelum test dimulai. Contoh kegunaannya yaitu buat konekin database.
  • @AfterClass: method kebalikan dari @BeforeClass, contoh kegunaan… buat diskonek!

Apapun yang gw tulis di atas, hasil translate dari situs ini… Hihihi… :p

Balik lagi, Kelas “KalkulatorTest” di atas, bisa di-run jugak layaknya class biasa. Dan, hasilnya adalah performa dari kelas awal yang gw bikin, class “Kalkulator”. Gini nih hasilnya:

3. JUnit

Dan kalo di-breakdown, hasilnya ternyata ada 2 method yang berkemungkinan error:

4. JUnit Break

Dengan kata lain, gak ada 1 method pun yang bener yang gw bikin… keduanya berkemungkinan error (dari kasus 0 dan string kosong)…  Dan ini terkait sama Jadi gimana cara gw harus nanganin ini?! Bisa ngasi trycatch c yah…

public class Kalkulator {
    public int bagi(int x, int y){
        int hasil = 0;
        try {
            hasil = x/y;
        } catch (ArithmeticException e) {
            System.out.println(e.getMessage());
        }
        return hasil;
    }
    public void tampil(String x){
        int hasil = Integer.valueOf(x) + 5;
        System.out.println("Hasil: "+hasil);
    }
}

Dan ini, gak bakal ngaruh ke apapun… coz kasus uji gw masih pake angka 0… ketika gw run lagi (class KalkulatorTest-nya… dan ini gak gw ubah), hasilnya gak berubah:

5. Error JUnit

Gitu…. Tapi at least, udah tau bakal ada kemungkinan error.

Jadi walo secara compile berhasil, tapi kasus pengujian bisa jadi ada error. Dan, kalo mau lebih spesifik lagi… gw bisa ubah kode-nya per-kasus yang gw punya…

Jadi gw ubah kasus uji-nya:

package coba.uji;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

public class KalkulatorTest {
    
    public KalkulatorTest() {
    }
    
    @BeforeClass
    public static void setUpClass() {
    }
    
    @AfterClass
    public static void tearDownClass() {
    }
    
    @Before
    public void setUp() {
    }
    
    @After
    public void tearDown() {
    }

    /**
     * Test of bagi method, of class Kalkulator.
     */
    @Test
    public void testBagi() {
        System.out.println("bagi");
        int x = 4;
        int y = 2;
        Kalkulator instance = new Kalkulator();
        int expResult = x/y;
        int result = instance.bagi(x, y);
        assertEquals(expResult, result);
        
    }

    /**
     * Test of tampil method, of class Kalkulator.
     */
    @Test
    public void testTampil() {
        System.out.println("tampil");
        String x = "6";
        Kalkulator instance = new Kalkulator();
        instance.tampil(x);
        
    }
    
}

Hasilnya:

6. JUnit Success

Dan sekarang… kasusnya, gw salah kode… Contohnya, gw punya “Kalkulator” gini:

public class Kalkulator {
    public int bagi(int x, int y){
        int hasil = 0;
        try {
            hasil = x*y;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return hasil;
    }
    public void tampil(String x){
        int hasil = Integer.valueOf(x) + 5;
        System.out.println("Hasil: "+hasil);
    }
}

Dan diuji pake kasus yang sama, hasilnya:

7. JUnit Warning

Lihat kan yah… ada yang salah di sana… Ada warning-nya… hasilnya gak sesuai! Harapannya hasil yang jadi output itu, 2… tapi malah keluar 8… itu kan gak sesuai… Jadi pasti ada yang salah ama kodenya.

Begitulah… itulah gunanya JUnit Testing… menge-tes suatu system dari unit2-nya… Jadi gak perlu jalanin setiap test-case dengan ngejalanin system secara keseluruhan. Dan satu lagi, kelebihan JUnit, test-nya punya file yang berbeda. Jadi kita nge-test tanpa ngotak-ngatik file yang kita tes. Kita bikin scenario dari test case kita sendiri…

O iya, kalo mau gampang, test case ini bisa di-generate kalo pake IDE semacam Netbeans (Eclipse gw gak tau)… Caranya, di kelas yang kita mau bikin JUnit-nya, pilih “Tools” –> “Create/Update Test”.

8. Create Tst

Nanti muncul pop-up, bisa kamu atur apa yang kamu mau di sana. Kalo udah, tinggal OK trus apusin method “failed()” atau kalo gak mau apus, bisa kasi komentar… Dan hasil yang kamu dapatin tinggal kamu sesuaiin ama kasus uji yang kamu mau.

Selesai…

PS: buat kamu yang make XP (eXtreme Programming), test case ini dibikin dulu baru dikodein… Jadi tipe generate dari netbeans mungkin gak cocok buat kamu… Coz gw gak tau ada mekanisme generate class dari test class. Yang nemu, kasi tau yak…

Sumber:

http://agung-setiawan.com/java-testing-aplikasi-menggunakan-junit/
http://www.vogella.com/tutorials/JUnit/article.html
http://kikiahmadi.com/2008/08/27/simple-unit-test-with-netbeans-61-and-junit/

Mengenali Penggunaan Apache Ant

Intinya, Apache Ant itu kata senior gw, buat ngatur struktur file dari aplikasi java. Mirip sama Netbeans yang ada peletakan folder2 tertentu buat class, source java, library atau buid direktori. Atau fungsinya mirip Maven. Cuma ajah Maven itu lebih ke suatu framework disbanding tool layaknya Ant. Yang gitu2 deh. Dan kabar2 yang gw dapat dari senior gw yang lain… (gw berasa junior banget dah di mari) si Netbeans itu pake struktur Ant jugak… Hmmm… Hmmm…
*angguk-anguk*

Jadi, buat demo-nya yang gampang ajah yak… Kalo yang sulit, ntar ajah pas kamu dapat proyek beneran (btw…di gw,  hal2 kecil kadang jugak baru ketauan ada pas harus ngerjain sesuatu—jadi ngerasa minim banget ilmu yang didapat pas kuliah).

Langsung ajah… Install Apache Ant dengan meng-extract archive file dari situs ant. Trus atur path Ant biar dikenali ama command prompt.

Trus, buat 2 kelas java:

AksesNama.java

public class AksesNama {

    public void tampil(String nama) {
        System.out.println("Hai " + nama);
    }

    public void tampil(String nama, String jk) {
        if (jk.equalsIgnoreCase("Pria")) {
            System.out.println("Hai " + nama + " Ganteng");
        } else if (jk.equalsIgnoreCase("Wanita")) {
            System.out.println("Hai " + nama + " Ganteng");
        } else {
            tampil(nama);
        }
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        AksesNama an = new AksesNama();
        an.tampil("Arby", "pria");
    }
}

Kita bisa ajah kan ya compile 2 class itu jadi .class yang bisa dijalanin pake command “java”. Tapi, file class yang kebentuk bakal ada di class yang sama dengan file java. Bayangin kalo kamu punya project gede… hal ini katanya gak banget (kata senior gw—gw c iya2 ajah—gw gak ngerti pas dia nyebut file WAR, JAR de el el de es be).

Makanya di-compile pake struktur ant…

Dan dari contoh di atas, kita bisa bikin suatu file XML (build.xml) gini:

<?xml version="1.0" encoding="UTF-8"?>
<project name="NameProject" default="src" basedir=".">
 
 <property name="src.dir" value="src" />
 <property name="build.dir" value="build" />
 <property name="build.dir.classes" value="build/classes" />
 <property name="build.dir.jar" value="build/jar" />

 <target name="compile">
 <mkdir dir="${build.dir.classes}" />
 <javac srcdir="${src.dir}" destdir="${build.dir.classes}" />
 </target>

 <target name="package" depends="compile">
 <jar destfile="${build.dir.jar}/NameAccess.jar" basedir="${build.dir.classes}">
 <manifest>
 <attribute name="Main-Class" value="Main" />
 </manifest>
 </jar>
 </target>

 <target name="run" depends="package">
 <java jar="${build.dir.jar}/NameAccess.jar" fork="true" />
 </target>

 <target name="clean">
 <delete dir="${build.dir}" />
 </target>
</project>

XML di atas maksutnya…. Compile maksutnya ngumpulin semua file class yang kebentuk di dir terkait. Compile semua file dari direktori “${src.dir}” trus class-nya ditaruh di “${build.dir.classes}”. Setiap dolar2 itu, terkait ke property dengan nama yang sama. Contohnya, “${src.dir}”maksutnya direktori “src” dan seterusnya.

Package, maksutnya ngebikin file jar (runnable dari file java) dan diletakin di direktori “${build.dir.jar}”. Nama jar-nya itu “NameAccess.jar” dan dibikin dari class yang ada di direktori “${build.dir.classes}”. Terakhir… run, maksutnya ngejalanin yang udah kebentuk di “package”.

Jadi, dari struktur direktori gw gini (build.xml ada di NameProject):

1. Struktur Direktori Project

Dan jalanin command gini:

ant compile

2. Ant Compile

Dan struktur direktori jadi:

1. Struktur Direktori Project Baru

Ada build yang kebentuk… dan ada folder class jugak.

Terus, target berikutnya… package

ant package

Dan folder jar-nya bakal kebentuk

1. Struktur Direktori Project Baru Package

Dan target terakhir… run!

ant run

3. Ant Run

Yaaaiiiyyy!! Jalan!

Dan begitulah cara dasar menggunakan ant. Dan… yap! Target itu bisa kamu ubah2 sesukamu, dan jalanin tergantung target yang ditulisin. Contohnya ajah gini… Ada file build.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project name="NameProject" default="src" basedir=".">
 
 <property name="src.dir" value="src" />
 <property name="build.dir" value="build" />
 <property name="build.dir.classes" value="build/classes" />
 <property name="build.dir.jar" value="build/jar" />

 <target name="kompail">
 <mkdir dir="${build.dir.classes}" />
 <javac srcdir="${src.dir}" destdir="${build.dir.classes}" />
 </target>

 <target name="paket" depends="kompail">
 <jar destfile="${build.dir.jar}/NameAccess.jar" basedir="${build.dir.classes}">
 <manifest>
 <attribute name="Main-Class" value="Main" />
 </manifest>
 </jar>
 </target>

 <target name="jalankan" depends="paket">
 <java jar="${build.dir.jar}/NameAccess.jar" fork="true" />
 </target>

 <target name="clean">
 <delete dir="${build.dir}" />
 </target>
</project>

Gw pake kata “jalankan” buat ngegantiin run… dan yaaa… dia berjalan 😀

4. Jalankan

Sumber: http://catatankecilsalman.blogspot.com/2012/04/compile-hellowordjava-menggunakan.html

Membuat Wizard Menggunakan Netbeans Platform (+Create Data)

Wizard Dialog di Netbeans Platform bisa kamu liat hasilnya pas waktu bikin project baru. Ada Next, ada Back, de el el, de es be. Itulah Wizard!

Sekarang, gw bakal liatin pemanfaatan Wizard buat masukin data ke tabel. Yap! Ini lanjutan dari tulisan gw yang terakhir tentang Netbeans Platform. Artinya, ngelanjutin modul yang kemarin… dan gak ada modul baru untuk tulisan kali ini. Bukannya kenapa2, malas ajah c yah. Lagian pengelompokannya menurut gw udah tepat. Sama2 buat ngakses data. Jadi sekalian ajah 😀

Jadi, di modul kemaren, yang bernama “AksesDatabase”, tempat ngeletakin “DataMemberTopComponent”, bikin satu hal baru… yaitu “Wizard”! Wizard di sini, kita manfaatin buat minta input data. Biasanya, wizard ini gunanya buat ngebikin suatu pembaharuan atau penambahan hal baru di aplikasi, bisa file baru, folder baru atau aksesori lainnya. Dan sekarang, biar agak beda, gw gabungin wizard ama pengaksesan database.

Lanjut ke langkah yang tadi, bikin wizard-nya gini:

Selection_012

Registration Type itu maksutnya cara ngeregistrasiin menu dari c wizard. Pilih ajah “Custom”, coz gw gak ngerti cara gunain yang “New File”. Untuk wizard step sequence, pilihnya “Static” ajah. Ini maksutnya bukan c wizard bisa diakses tanpa ngebentuk objek dari kelas-nya kayak make keyword “static”. Maksutnya, window yang dimunculkan urutannya itu2 ajah. Gak pake suatu skenario pemilihan. Terus kalo “Number of Wizard Panel”, jelas maksutnya jumlah panel dari wizard itu.

Lanjut!

Tekan “Next”, masukin nama class sesuai yang kamu mau. Kalo gw, gini:

Selection_013

Perhatikan file2 yang bakal terbentuk. Ini penting yah… Biar kamu tau kamu musti ngutak-ngatik bagian mana. Di sini, bakal terbentuk 4 file:

  1. MemberMasukVisualPanel1 (.form & .java): ini analoginya kayak window (top component) gitu. Tempat desain2 button, teks, label dan logika (kalo ada).
  2. MemberMasukWizardAction.java: file ini gunanya buat ngatur config (terutama action—buat ngatur muncul menu) dari c Wizard secara keseluruhan. Plus, mau ngedaftarin wizard di menu yang mana… letaknya ya di sini. Kalo kamu pilih bagian “Dynamic” pas awal bikin wizard, di sini kamu nentuin skenario window yang muncul (tapi kalo gak salah namanya bedaan gitu…ada “iterator”2 gitu).
  3. MemberMasukWizardPanel1.java: file terakhir ini merupakan file yang mengatur config khusus “MemberMasukVisualPanel1”. Jadi, di sini bakal ada method “store” atau “load” yang gunanya mirip sama “store” dan “load” dari option panel.

Yap! Itulah 4 file dengan tugasnya masing2.

Lanjut!! Di sini, sebenernya kamu udah bisa ngejalanin c wizard dengan nge-run c NPA. Tapi, kamu pasti gak nemu menu buat munculin c wizard. Alasannya, karena kita belum nge-registrasiin c menu itu bakal muncul di mana…

Buat munculin menu-nya, buka file “MemberMasukWizardAction”, ada 3 baris yang dikomen kan… yang ada tanda “@”-nya:

// @ActionID(category="...", id="org.akses.data.MemberMasukWizardAction")
// @ActionRegistration(displayName="Open MemberMasuk Wizard")
// @ActionReference(path="Menu/Tools", position=...)

Selection_014

Kode di atas gunanya buat nge-daftarin kemunculan menu buat ngakses c wizard. Jadi, kode di atas bisa kamu uncomment, atau bikin baru. Kalo gw, gw bikin baru ajah.

@ActionID(category = "File", id="org.akses.data.MemberMasukWizardAction")
@ActionRegistration(displayName = "Input Member")
@ActionReference(path="Menu/File", position = 1)

Dan… buat ngelengkapin kode di atas, ada import package yang harus kamu lakukan:

import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;

Untuk isi category, kamu bisa masukin macam2. Untuk id, harus ngacu ke WizardAction, trus buat path, itu harus ngikut kamu mau munculin menu-nya di bagian mana dan ada di posisi berapa buat position.

Kode di atas, defaultnya di-comment, coz memang kemunculan wizard bagusnya diaturnya di “Action” buat module netbeans platform (bayangin ajah kamu punya banyak wizard yang mau dimunculin.. Bakal repot buka WizardAction atu2 cuma buat ngatur kemunculannya). Tapi, sebagai fleksibilitas, registrasi Action bisa dilakukan di Wizard-nya langsung.

Di sini, kamu bisa explore beberapa hal setelah pendeklarasian “WizardDescriptor”. Di sana, bilangnya kan ada setTitle… ada juga setTitleFormat… Bisa kamu ubah2. Terus kalo mau nambahin gambar, juga bisa di sini. Contohnya, gw mau nambahin gambar gini di wizard (sorry, alay-nya gw muncul lagi.. harap maklum dengan gambarnya :p):

HaeHyung

Selection_024

Gw bisa pake kode:

String alamat ="/pic/HaeHyung.jpg";
wiz.putProperty(WizardDescriptor.PROP_IMAGE, ImageUtilities.loadImage(alamat));

Dan… untuk property apapun, itu sifatnya static, jadi bisa kamu akses dari nama kelas asal diikutin nama property-nya. Contohnya ajah yang di atas, gw panggil PROP_IMAGE dari kelas WizardDescriptor. Dan kalo kamu nanya ukuran tinggi ideal, jawabannya adalah “tergantung tinggi wizard yang nanti ditampilin”. Berhubung wizard gw tampilnya standar, tinggi idealnya 400 piksel.

Terus, saatnya men-desain! Buka “MemberMasukVisualPanel1”, pilih bagian “Design”, dan desain panel sebagai berikut (bebas c yah, sesuaiin ajah ama database kamu):

Selection_015

Dan… wizard ini udah bisa kamu jalanin. Jalanin NPA-nya, buka “File → Input Member” (Ini tergantung path yang kamu atur di atas sama title-nya), dan bakal muncul gini:

Selection_016

Sekarang, kita coba fungsi store-nya.

Buka file “MemberMasukVisualPanel1.java”, di sini (di bagian source), tambahkan suatu get untuk nilai yang dimasukkan ke textfield “nama”. Kamu bisa jugak nambahin yang lain, tapi kalo gw cukup nama ajah.

    public String getNamaMember(){
        return jTextField2.getText();
    }

Buka file “MemberMasukWizardPanel1.java”, di method “storeSettings”, kita bikin gini:

wiz.putProperty("nama member", component.getNamaMember());

Untuk component sendiri, itu udah dideklarasikan dulu dengan tipe “MemberMasukVisualPanel1”. Pendekatan ini bisa kamu lakuin kalo kamu make Netbeans seenggaknya 7.2 ke atas—sampe 7.4 (gw gak nyoba 7.1 ke bawah sama 7.4 ke atas).

Kalo udah, coba jalanin wizard kamu, masukin suatu nama, terus tekan “Finish”!

Seharusnya, ada satu variabel global kesimpan dengan nilai sesuai dengan hal yang udah diinputin di textfield nama. Dan ini, bisa dipanggil pake “getProperty”. Jadi kita balik ke “MemberMasukWizardAction.java”, di kelas ini, kita bakal panggil c wizard property tadi. Dengan kode:

String x = (String) wiz.getProperty("nama member");

Dan nantinya, si “x” bisa ditampilin pake option pane. Kode di atas, diletakin di bagian kondisi if ketika udah finish ajah. Jadi pas tekan finish, bakal keluar si “x” itu

        wiz.setTitleFormat(new MessageFormat("{0}"));
        wiz.setTitle("Masukkan Member");
        String alamat ="/pic/HaeHyung.jpg";
        wiz.putProperty(WizardDescriptor.PROP_IMAGE, ImageUtilities.loadImage(alamat));
        if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) {
            // do something
            String x = (String) wiz.getProperty("nama member");
            JOptionPane.showMessageDialog(null, x);
        }

Selection_017

Selection_018

Dan… kalo kamu bertanya, kenapa gak ada user variable-nya di bagian “dist” kayak di option panel, yaaaa memang ini tipenya beda yah. Kalo kamu mau keluarin kayak kemaren, bisa pake NbPreferences kayak kemaren.

Okeh, jadi intinya, kamu udah ngerti lhah ya… cara dasar make wizard. Dan sekarang, masuk ke bagian database-nya. Logikanya gini, ambil setiap nilai dari textfield, terus langsung simpan ke database pake JPA pas tekan “finish”! Jadi, sekarang, gw maen2nya di “MemberMasukVisualPanel1”… kalo tadi gw cuma punya nama, sekarang gw jugak punya pengembalian buat id-reg sama umur:

    public String getIdReg(){
        return jTextField1.getText();
    }
    
    public String getUmur(){
        return jTextField3.getText();
    }

Buka WizardPanel, ubah storeSettings jadi:

    @Override
    public void storeSettings(WizardDescriptor wiz) {
        // use wiz.putProperty to remember current panel state
        wiz.putProperty("nama member", component.getNamaMember());
        wiz.putProperty("id reg", component.getIdReg());
        wiz.putProperty("umur", component.getUmur());
    }

Pergi ke “MemberMasukWizardAction.java”, ubah kode pas nekan finish jadi gini:

        if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) {
            // do something
            String nama = (String) wiz.getProperty("nama member");
            String id = (String) wiz.getProperty("id reg");
            String umur = (String) wiz.getProperty("umur");

//            JOptionPane.showMessageDialog(null, nama+" "+id+" "+umur);
            try {
                EntityManager entityManager = Persistence.createEntityManagerFactory("DataLibraryPU").createEntityManager();
                entityManager.getTransaction().begin();
                MemberC m = new MemberC();
                m.setIdReg(id);
                m.setNama(nama);
                m.setUmur(Integer.parseInt(umur));
                entityManager.persist(m);
                entityManager.getTransaction().commit();
                JOptionPane.showMessageDialog(null, "Data Berhasil Dimasukkan");
                DataMemberTopComponent.refresh();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(null, "Pesan Kesalahan "+ex);
            }

        }

Yang gw kasi biru muda, kemungkinan bakal menimbulkan error… apus ajah kalo kamu mau nyontoh. Dan jangan lupa import package terkait:

import datalibrary.MemberC;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import org.openide.DialogDisplayer;
import org.openide.WizardDescriptor;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.util.ImageUtilities;

Kalo udah, bisa dijalanin gini:

Selection_019

Selection_020

Selection_021

Selection_022

Khusus untuk hasil yang di text area (DataMemberWindow), aslinya gak langsung ngapdet. Itu gw ngubah kodingannya dikit… dan ada hubungannya ama kode biru muda yang ada di wizard action di atas. Kira2 modifikasinya gini:

public DataMemberTopComponent() {
        initComponents();
        setName(Bundle.CTL_DataMemberTopComponent());
        setToolTipText(Bundle.HINT_DataMemberTopComponent());
        entityManager = Persistence.createEntityManagerFactory("DataLibraryPU").createEntityManager();
        refresh();
    }
    
    public static void refresh(){
        Query query = entityManager.createNamedQuery("MemberC.findAll");
        List resultList = query.getResultList();
        jTextArea1.setText("");
        for (MemberC m: resultList) {
            String nama = m.getNama();
            jTextArea1.append(nama+ "\n");
        }
    }

Dan, text area-nya dibikin “static”. Klik kanan di text area, pilih “Customized Code”, silang bagian “static”.

Selection_023

Dan begitulah caranya bagian create…

Sumber: Pribadi ama situs netbeans
Valid: Yap!
Batas Berlaku: Kayaknya cuma Netbeans 7.2-7.4 (Netbeans 8 gak termasuk)

Membuat Primary Option Panel pada Netbeans Platform

Di tulisan kemarin, kita udah bahas caranya bikin option panel, tapi yang secondary. Jadi sekarang gw kasi liat hasil jadi yang primary… Hasil akhir:

Selection_003

See?! Ada sebuah panel bernama “Pengaturan”, terus ada 1 label “nama” dan 1 textfield untuk memasukkan nama. Seperti yang udah kamu tahu, option panel biasanya digunain buat nyimpan variabel2 global dari sebuah aplikasi, termasuk setting-an. Contoh, pengaturan ukuran font yang bakal digunain, pengaturan proxy jaringan kalo seandainya aplikasinya pake jaringan, dan lainnya.

Oke, langsung bikin yak! Pertama, bikin 1 modul terlebih dahulu di NPA yang udah kamu sediain sebelumnya (cara bikin NPA baru sama module, bisa liat di sini). Di modul ini, klik kanan package yang kamu inginkan, pilih “New → Other”. Dan pas muncul window berikutnya, di bagian kiri pilih “Module Development”, di bagian kanan pilih “Options Panel”.

Selection_004

Selection_005

Perhatiin kalo “Allow Secondary Panels”-nya gak dicentang. Tekan Next, dan perhatiin file apa ajah yang bakal dibikin… Yang ada “Controller”-nya, itu fungsi-nya sebagai tempat control dari si option, terus kalo ekstensi-nya .form sama .java (dengan nama yang sama), itu tempat nge-desain penampilan si control panel.

Buat icon-nya, kalo sulit cari ikon 32×32, coba cari di sini, atau ambil dari tulisan sebelumnya.

Selection_006

Abis itu, buka file PengaturanPanelPanel.java, di sini, kita bakal desain tampilannya jadi kayak gini (gw pake-nya flow layout):

Selection_007

Artinya, kita bakal simpan suatu nama di sebuah variabel. Buat melakukan yang namanya penyimpanan, kita pake kode:

NbPreferences.forModule(PengaturanPanel.class).put(<nama_var>, <teks_yg_disimpan>);

Dan kode di atas, butuh import esuatu, yaitu package:

import org.openide.util.NbPreferences;

Berhubung biasanya penyimpanan dilakukan setelah kita tekan “OK” atau “Apply” di window option, jadinya kita musti naruh kode tersebut di method yang pasti dijalanin kalo option panel udah ditutup. Ada method2 khusus yang bakal dijalankan untuk hal2 gitu:

  • load: dijalanin pas option panel dibuka
  • store: dijalanin pas option panel ditutup
  • valid: gak tau fungsinya… gw gak pernah make

Method2 itu bakal keliatan kalo pilih mode “source” dari “PengaturanPanelPanel.java”.
Jadi, nanti ubah bagian source jadi kayak gini:

import org.openide.util.NbPreferences;

final class PengaturanPanelPanel extends javax.swing.JPanel {

    private final PengaturanOptionsPanelController controller;

    PengaturanPanel(PengaturanOptionsPanelController controller) {
        this.controller = controller;
        initComponents();
    }

    (+) private void initComponents() 
    
    void load() {
        
    }
    void store() {
        NbPreferences.forModule(PengaturanPanel.class).put("nama", jTextField1.getText());
    }

    boolean valid() {
        true;
    }

    private javax.swing.JLabel jLabel1;
    private javax.swing.JTextField jTextField1;

}

Yang berubah, cuma yang gw kasi warna biru.

Kalo udah gitu, bisa lo jalanin aplikasinya. Nantinya pilih menu “Tools →Option”. Di sana, bakal muncul 1 tab dengan ikon yang udah kamu pilih pas ngebangun option ini.

Seandainya gak sukak ama icon itu, coba buka file yang ada kata2 “Controller”-nya, kalo gw jadinya “PengaturanPanelOptionsPanelController.java”. Nanti lihat bagian ini:

@OptionsPanelController.TopLevelRegistration(
        categoryName = "#OptionsCategory_Name_Pengaturan",
        iconBase = "org/demo/arby/1394093583_Tools.png",
        keywords = "#OptionsCategory_Keywords_Pengaturan",
        keywordsCategory = "Pengaturan"
)

Yang warna biru, itu yang diubah… Sesuaiin path-nya sama nama file yang dimau.

Balik ke bagian option panel yang udah dijalanin, kalo udah masukin suatu nama, terus tekan “OK”, artinya udah ada satu variabel global yang disimpen, adanya di bagian build dari NPA. NPA lhoh yah… kan kita bicaranya variabel global dari aplikasi… bukan per-modul. Tepatnya di bagian build dari folder project, “build → testuserdir → config → Preferences → org → demo”.

Selection_008

Selection_009

Kalo dibuka “arby.properties” itu, isinya variabel yang kita simpan…

nama=Arby

“nama” diambil dari put(“nama”, x), trus yang “Arby” diambil dari harga x yang diambil dari textfield. Dan kalo bertanya2 tentang cara ngambilnya, bisa pake get. Sekarang, coba tambahin kode gini di method “load”:

    void load() {
        String x = NbPreferences.forModule(PengaturanPanelPanel.class).get("nama","");
        jTextField1.setText(x);
    }

Kode diatas, maksudnya, ambil variabel yang disimpan via class “PengaturanPanelPanel” dengan nama variabel “nama”, dan seandainya variabel itu gak ada, ganti pake string kosong (“”)… gitu… Seabisnya diambil variabel itu, simpen dalam “x”, terus tampilin si “x” di text field.

Trus jalanin lagi NPA-nya, pasti ada nilai di aplikasi yang udah dijalanin… tapi inget.. pas ngejalanin, jangan pake “Clean and Build” dulu… coz ntar variabel global-nya bakal ke-clean, jadi variabelnya gak kebaca sama sekali.

Sumber: situs netbeans.org
Valid: Sejauh ini.. yap!
Masa Kadaluarsa: sampe beda versi netbeans

Old-Singleton VS New-Singleton

Berhubung gw udah gak jelas di postingan sebelumnya, jadi sekarang gw tulisin dah yang benerannya… Walo sebenernya ini cuma buat ngilangin rasa penasaran kamu yang ngerasa gak nyambung ama tulisan gw sebelumnya.

Intinya, ada 2 cara buat ngeaplikasiin singleton di sebuah kelas. Kalo cara lama gini:

Tunggal.java:

public class Tunggal {
    private static Tunggal objek;
    private int a;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
    private Tunggal(){

    }
    public static Tunggal getObjek(){
        if(objek == null){
            objek = new Tunggal();
        }
        return objek;
    }
}

Main.java:

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        Tunggal t = Tunggal.getObjek();
        t.setA(8);
        System.out.println("Nilai atribut: "+t.getA());
    }

}

Sedangkan kalo pake cara baru:

Tunggal.java

public enum Tunggal {
    INSTANCE;
    private int x;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }
    public void methodA(){
        System.out.println("Haiiii");
    }
}

Main.java

public class Main {
    public static void main(String[] args) {
        //bentuk objek
        Tunggal.INSTANCE.methodA();
        Tunggal.INSTANCE.setX(5);
        System.out.println("Harga x: "+Tunggal.INSTANCE.getX());
    }
}

Buat ngeyakinin kalo udah singleton, bisa di-trace ajah dari lokasi alamat memori-nya. Terus, kalo kamu penasaran… yaaa, enum memang mengharuskan konstruktor bersifat private. Jadi kamu gak mungkin bikin konstruktor bertipe public di enum. Jadi kemungkinan buat diakses dari luar gak ada kecuali dari pemanggilan variabel-nya (yang sebenernya konstanta). Dan yaaa… khusus singleton, kamu harus bikin single-enum type. Artinya enum di atas, jangan kamu tambahin elemen konstanta lain. Cukup “INSTANCE” ajah. Kalo mau yang lain, pakein penulisan atribut bertipe private. Ini namanya “one-element enum”.

Begitulaaahhh… sekedar menjawab rasa penasaran kamu kenapa posting sebelumnya berjudul Singleton VS Singleton, walo awalnya itu cuma curhatan gw yang lagi patah hati ajah… Owhh Alyssa…….kenapa kamu lebih milih Dude Herlino dibanding aa’-mu yang keren ini…. 😥

Membuat Aplikasi CRUD dengan Netbeans Platform

Sekarang, gw bakal bahas gimana caranya bikin semacam pengaksesan data pake Netbeans Platform. Berhubung gw pengennya simple, jadi ini cuma hasil translasi dari situs netbeans-nya dengan beberapa perubahan yang gw anggap gampang dan gak memperhitungkan konsekuensi ke depannya.

Di sini, gw bakal pake JPA buat pengaksesan datanya. Jadi gak pake ala JDBC lagi…

Buat mempersingkat tulisan yang sepertinya bakalan panjang ini, gw langsung mulai yak… Hal pertama yang harus lo lakukan adalah bikin java project untuk mendapatkan library (.jar) dari setiap entity classes yang dibutuhkan nantinya. Lo gak bisa bikin entity classes di module-nya NPA. Gw gak tau kenapa, tapi kayaknya beda core. Jadi yang bisa lo lakukan cuma masukin jar-nya ajah.

Sooo… bikin satu java application,

1. New Java App

2. Java App Name

Hapus class java yang udah terbentuk otomatis (seharusnya kita uncheck pilihan “Create Main Class” dari langkah sebelumnya—tapi gw lupa, jadi yaaa sudah :p).

Udah dihapus, langkah selanjutnya bikin entity classes dari data yang diinginkan. Kebetulan gw cuma punya 1 data… jadi gw langkah2nya gini:

Pilih package yang udah ada, klik kanan di sana, pilih New → Entity Classes from Database… Abis itu muncul satu window, pilih database yang mau dipakai di bagian “Database Connection”, pindahin tabel yang dibutuhkan dari bagian “Available” (sebelah kiri) ke bagian “Selected Table” (sebelah kanan). Pindahinnya pake tombol “Add >”. Kebetulan gw cuma punya 1 tabel doank, jadi gw pake itu ajah.

3. New Entity Classes

4. New Entity Classes-2

Klik finish, ntar terbentuk beberapa class POJO, dan 1 package META-INF sebagai tempat konfigurasi pengaksesan data dalam bentuk file XML. Langkah ini mirip sama tulisan blog balita yang ini.

Karena yang kita butuhin itu jar-nya dan bukan class-nya, jadi kita bikin jar dari project yang tadi. Caranya… klik kanan di bagian project “DataLibrary”, pilih “Properties”, Pilih “Build JAR after Compiling”. Kalo udah kepilih, biarin ajah gitu.

5. Project Porperties

Terus di project yang tadi, klik kanan, pilih “Build” atau “Clean and Build”. Sama ajah itu… cuma bedanya di proses ajah… yang atu pake proses Clean yang atu enggak… hehehe :p Nantinya, cek di bagian file, dan ada

6. Jar Created

Yang gw kasi kotak biru, itu jar yang bakal kita pake. Ditambah 1 jar lagi, yaitu Driver Connector JDBC. Apah?! Katanya gak pake JDBC tapi gw malah pake Driver-nya?!!! Well, gw bilang gak make JDBC maksudnya pengaksesannya. Kalo driver-nya c masi… Driver JDBC MySQL Connector itu bisa lo temui di “/home/<nama_user>/netbeans-7.4/ide/modules/ext” namanya “mysql-connector-java-5.1.23-bin.jar”. Tapi kalo kamu pake Windows, sesuaiin ajah… adanya di direktori tempat peng-instalan netbeans-nya biasanya ada di “C:\Program Files\Netbeans\7.4\ide\modules\ext”, dan nama file-nya c sama (kalo gak salah).

Tapi kalo kamu males, ada cara gampang (at least ini berhasil di gw, tapi gak di temen gw dulunya). Pertama, klik kanan di bagian library dari project yang tadi, pilih “Add Library”, muncul window baru trus pilih “MySQL JDBC Driver” tekan “Add Library”.

7. Add Library

8. Add MySQL JDBC Driver

Trus abis itu, project-nya di “Clean and Build” lagi. Ntar muncul dah si driver jdbc di bagian lib.

9. JDBC Jar Created

Okeh, tahap awal udah dilalui… Jadi kita udah punya jar yang diperlukan. Sekarang, masuk ke bagian NPA-nya.

Buat NPA yang baru (Di Netbeans pilih File → New Project, pilih Netbeans Module di kiri, Netbeans Platform Application di sebelah kanan, tekan “Next”, kasih nama-nya trus “Finish”). Atau kalo mau pake NPA yang lama jugak boleh2 ajah c…

10. New NPA

Di NPA itu, bagian module, klik kanan, pilih “Add New”. Bikin module baru, masukin nama terserah kamu, code base name jugak terserah kamu ajah. Gw, namanya “AksesDatabase”, code name base “org.akses.data”.

Modul-nya udah kebentuk, yang kamu perluin sekarang nge-konfigurasi modul itu supaya ada library jar, berupa 5 file jar yang udah gw tunjukin di atas. Caranya, klik kanan di bagian library, terus pilih “Add New Library”.

11. Add Library Wrapper

Di sini, pilih 5 library (file jar) yang gw kasih tau di atas… Pilih library-nya ke file tempat library tersimpan, terus tekan “Next”. Ngelakuin hal ini, secara gak langsung, artinya lo bikin sebuah “library wrapper module”. Singkatnya, nanti bakal ada gini dah:

12. Add Library Wrapper 2

Itu ikutin ajah… tekan next ajah, trus next, kalo minta code base name, masukin terserah… bisa apapun, tapi kalo gw, masukinnya “org.lib.all”. Nanti, dalam library, ada 1 module dependency gitu…

13. Data Library

Liat kan?! Di atas, ada 1 module kebikin, namanya “DataLibrary”, dan module itu dipake di module “AksesDatabase”. Sekarang, maen2nya di module yang lain… Kita bakal bikin 1 module kayak “DataLibrary”. Mulai lagi dari module “AksesDatabase”, klik kanan di bagian “Libraries”, pilih “Add New Library”. Sekarang, browse bagian jar 4 yang lainnya… (3 eclipse link, 1 jdbc driver).

14. Lib

Pilihnya, langsung ke-empatnya yah… Jangan atu2… Boleh ajah c atu2, cuma ntar kebanyakan module. Itu ajah… Tekan “Next”, nama gw ubah jadi “eclipselink-jdbc”, code base name jadi “org.lib.eclipsejdbc”.

Nanti, hirarkis file-nya jadi gini:

15. Library Hirarchies

Jadi kesimpulannya, gw butuh 2 wrapper module, yang atu buat entitas database, yang atu buat eclipse link plus jdbc. Module terakhir digunain buat ngakses Persistence sama JDBC, kalo yang pertama sebagai entitas database-nya. Hal ini musti kamu pahamin bener, dan bandingin sama tutorial di situs sumber. Situs sumber itu pemakaian yang efektif (buat pengembangan ke depan), kalo gw, menurut gw ini pemakaian yang gampang walo gak diketahui tentang keefektifannya.

Segala hal tentang library udah beres, tapi ada yang belum beres jugak… yang belum beresi itu dependency antara “DataLibrary” ke “eclipselink-jdbc”. Module yang pertama disebutkan butuh keberadaan module yang kedua. Jadi, untuk ngehubunginnya bisa klik kanan di bagian “Libraries” di module “DataLibrary”. Pilih “Add Module Dependency”, ketikin “eclipselink-jdbc” di kotak search. Kalo module-nya nemu, pilih “OK”. Ntar bagian “Libraries”-nya bakal nambah deh…

16. Eclipselink lib

17. Library Hirarchies 2

Sekarang, ngelanjutin hal yang belum tersentuh… yaitu GUI-nya. Kita bakal pake JtextArea ajah buat nampilinnya sekarang. Biar gampang… Di module “AksesDatabase”, bagian package, klik kanan, pilih New → Other. Muncul window baru, bagian kiri pilih “Module Development”, bagian kanan pilih “Window”.

18. New Window

Yappp… ini mau bikin window baru… kemunculannya di bagian “explorer” ajah.

18. New Window-2

Class Name Prefix isi terserah, kalo gw ngisinya “DataMember”.

18. New Window-3

Desain Window TopComponent dengan text area full (gw pake layout border di panel/frame-nya). Mau pake Absolute/Free Design jugak boleh, yang penting text area menuhin window itu… kayak gambar di bawah ini. Sebenernya gak musti gitu jugak c yah… itu suka2nya gw ajah.

19. Design Panel

Udah?! Sekarang… waktunya akses data!! Ahhh… akhirnya yah… Pergi ke bagian source, di bagian akhir konstruktor, tambahin kode gini:

        EntityManager entityManager = Persistence.createEntityManagerFactory("CustomerLibraryPU").createEntityManager();
        Query query = entityManager.createNamedQuery("Customer.findAll");
        List<MemberC> resultList = query.getResultList();
        for (MemberC m: resultList) {
            String nama = m.getNama();
            jTextArea1.append(nama+ "\n");
        }

Jangan lupa buat tambahin import ini:

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.Query;
import datalibrary.MemberC;

Yang perlu kamu perhatiin itu adalah package yang terakhir gw import. Package itu bentukan kita dari library “DataLibrary”. Dan, di sana, ada package “datalibrary”. Kebetulan, class yang gw gunain cuma MemberC ajah… dan ini bisa menyesuaikan tergantung library database yang kamu punya.

20. Data Library Dependency

Sekarang… tinggal dijalanin ajah… Run NPA-nya, dan nanti bakal muncul kayak gini:

21. Hasil Akhir

Yaaaiiyyy… keprok2 jadiiii!!! Insert, Delete sama Update-nya bisa diliat di situs sumber atau analogiin ke tulisan gw tentang JPA (link ada di awal tulisan)… Gak gw tulisin yak! Capek… tapi hobi c… maklum, masih ngejalanin hobi setengah2 😀 Jadi maav ajah kl kamu ngerasa ketipu baca tulisan inih… Kan gw judulnya CRUD, kenyataannya yang gw tulis cuma read-nya doank. Maap yak…

Sumber: Link di atas + pribadi
Valid: Yap!
Kadaluarsa: sampe beda versi netbeans (gw pake 7.4)