Melakukan Publish-Subscribe Lookup pada Netbeans Platform

Masih tentang NetPla Guyzzz…. Sekarang, tentang lookup. Lookup tuh maksudnya liat2… yoaaaaa, jadi ada 1 modul yang liat2 modul lainnya. Tuh modul kasi kode atau enggak… terus gimana si modul yang dikasi kode bakal nanggapin itu semua… kebat kebit? Doki doki? Uhhmmm… tapi… kita bicarain tentang NetPla kan yah… bukan yang lain?! Arrgggghh… fokus B!! fokus!!

Fokus ke inti tulisan kita, singkatnya, ada satu modul ngasi broadcast hasilnya ke modul lain buat dipake jadi hal lain lagi. Kalo contoh yang bakal gw kasi itu mirip sama alur dari proses langganan koran/tv kabel. Yap!! Bener banget… kalo secara paradigma pemrograman, cara kerjanya mirip sama observer pattern. Apa itu observer pattern?! Uhhmmm… kamu cari tau sendiri ajah lha yah. Gw c mau fokus ajah :p

Supaya lebih jelas, langsung dimulai ajah tulisan tentang lookup-nya…

Yang namanya lookup di Netbeans platform, pasti berhubungan sama yang namanya lookup API… dan pastinya kita musti jugak nyediain API di sana. Tapi, kadang yang kita butuhin bukan cuma sekedar modul yang berhubungan satu sama lain via API… Justru yang kita butuhin sebuah mekanisme satu modul melakukan publikasi terhadap perubahan apapun yang ada buat modul tersebut. Trus ada modul lain yang subscribe jugak buat perubahan2 itu…

Yap… mirip banget sama fungsi kelas Observer di java. Cuma, kalo di java itu kan kalo antar kelas.. gimana kasusnya kalo pake framework netbeans platform, dan keterhubungannya antar modul?! Jawabannya bisa dilihat di https://platform.netbeans.org/tutorials/nbm-quick-start.html di bagian “publish lookup”.

Di sini, gw bakal tulisin hal yang sama dengan cara gw… pastinya dunk! Gw kan beda!
kedip sambil acung jempol ala Rock Lee

Jadi.. anggap, sekarang kita mau bikin 2 modul dari aplikasi netbeans platform. Yang satu jadi observer, dan satu lagi jadi observable. Yang observable (yang publish lookup) tampilan kayak gini:

1. Hasil Observable

Yang observer (yang nerima/subscribe lookup) tampilannya gini:

2. Hasil Observable

Jadi skenarionya, ada program untuk mengecek kegantengan secara random di satu modul, trus hasil ini di-publish hasilnya. Hasil ini ditangkap sama modul lain dan ditampilkan hasilnya ke layar via text area…

Langsung mulai, buat satu aplikasi netbeans platform (Pilih File→ New Project) atau tekan Ctrl+Shift+N… Muncul window, di sebelah kiri pilih “Netbeans Module”, di sebelah kanan pilih “Netbeans Platform Application”.

3. NPA Baru

Kasih nama aplikasinya apapun…

4. NPA Baru-nama

Kalo udah, pastiin ada aplikasi itu muncul di bagian project… kayak gambar di bawah ini… Cuma, yang di gambar itu, gw udah ada modulnya 2 biji. Abaikan ajah 2 hal itu (ExplorerBeanTreeView sama SimpleGui).

Di bagian “Modules” di aplikasi NPA yang udah kita bikin sebelumnya, klik kanan… pilih “Add New”, karena kita bikin module baru. Kalo kamu udah ada module-nya pilih “Add Existing”, tapi kan ceritanya belum ada apapun… Jadi bikin baru yak.

Pilih “Add New”, muncul window baru, kasi namanya sesukamu

5. Module Baru

Masukin juga code name base sebagai identitas unik dari module-nya. Ikutin ajah contohnya… itu terserah sebenernya, gak musti gitu jugak.

6. Module Baru Code Base

Tekan “Finish”… Sekarang, kita udah punya module yang bakal mem-publish lookup. Tinggal tambahin sesuatu ajah di dalamnya.

7. NPA-Module

Karena, kita mau bikin sebuah tampilan yang nampil di layar (semacam aplikasi desktop), artinya kita butuh “Window” baru. Di bagian project, pas “WindowObservable” klik kanan, pilih “New → Window”.

8. New Window

Kalo gak nemu, pilih “New → Other”. Di sini, muncul window baru… di bagian kiri pilih “Module Development”, di bagian kiri pilih “Window”.

8-2. New Window

Isi informasi yang dibutuhkan… Ini c terserah yah.. cuma masalah peletakan sama aksi yang bisa diubah2 nantinya sama nama ajah. Gw c bikinnya gini:

9. Window Config

9-2. Window Name

Bakal muncul sebuah frame baru, kayak kamu make matisse builder dari Netbeans. Tinggal tarik ajah komponen yang ada di Palette ke kanvasnya. Gw jadinya gini:

10. Palette

Ituh gw pake flow layout… Kalo kamu pake Absolute Layout, juga gak masalah kok… Bedanya kalo kamu nge-resize aplikasinya ajah ntar… coz basisnya, aplikasi dengan frame NPA bukan buat diilangin pilihan resize-nya (at least, di gw… gw yang gak tau caranya gimana).

Sehabis bikin window, aplikasinya udah bisa dijalanin… Coba pergi ke bagian NPA (yang gambar puzzle-nya kuning), klik kanan.. pilih “Run”. Tapi kalo kamu lakuin di module jugak boleh c… Dan inilah yang bakal kamu dapatin:

11. Hasil Observable

Sekarang, kita bikin modul berikutnya. Lakukan hal yang sama kayak di atas (gw gak ngulang lagi yah langkah2nya). Gw tulisin gini… Nama module “WindowObserver”, code name base “org.arby.window.observer”, window position “explorer”, “open on application start” dipilih, Class Name Prefix diisi “HistoryApp”. Terus di kanvasnya, gw penuhin kanvas sama “text area” dari palette. O iya, gw juga pake border layout buat gampangnya menuhin tuh text area.

Intinya, ada window baru dan jadinya gini kalo dijalanin:

12. Hasil NPA

Btw… kalo kamu bermasalah sama nama window-nya, bisa buka bagian source trus ubah field “CTL_HistoryAppTopComponent” di bagian “@Messages”. Atau mau ubah langsung di bagian setName() juga boleh…

Lajoooott!

Langkah selanjutnya, bikin logika plus publikasi hasil cek kegantengan. Dimulai dari modul yang nge-publish lookup, module “WindowObservable”. Di window tersebut, buka window “CekGantengTopComponent”. Pilih tab source di kanvas… ntar keliatan deh kodenya. Deklarasikan sebuah variabel sebagai tempat meletakkan content yang akan di-publish.

private InstanceContent konten;

Terus buat objek “konten” di bagian konstruktor, sama asosiasikan/hubungkan konten ke kelas AbstractLookup.

konten = new InstanceContent();
associateLookup(new AbstractLookup(konten));

Lengkapnya:

    private InstanceContent konten;

    public CekGantengTopComponent() {
        initComponents();
        setName(Bundle.CTL_CekGantengTopComponent());
        setToolTipText(Bundle.HINT_CekGantengTopComponent());
        konten = new InstanceContent();
        associateLookup(new AbstractLookup(konten));
    }

Balik ke kanvas bagian design, klik 2x di tombol “Hitung”. Otomatis, kanvas itu bakal ngebalikin ke mode source. Di sini, bisa ditulisin logika pemrograman kalo udah nge-klik tombol “Hitung”.

Jadi, di sini… kita kasi logikanya gini… Ada satu bilangan random, terus bilangan random itu digabung ke dalam bentuk “%Nama%, persen kegantengan kamu %random%”. Persen2 itu maksutnya, variabel. Abis itu, kita publish deh via “konten” yang udah dideklarasiin sebelumnya.

Lengkapnya:

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        Random r = new Random();
        int bil = r.nextInt(100);
        String kontenKata = tNama.getText()+
                ", persen kegantengan kamu: "+bil+"%";
        konten.add(kontenKata);
    }

Bagian warna biru, itu yang gw maksudin sebagai kode buat naruh hal2 yang bisa di-publish. Setiap ada perubahan dari isi “konten”, hal ini yang ditangkap sama si window observer.

Daaannn… window observale/subjek udah jadi. Lanjut ke window untuk observer, karena kita perluin ini sebagai penerima, kita harus implements interface “LookupListener” terlebih dahulu. Jadi, di class-nya kita pakein gini:

public final class HistoryAppTopComponent extends TopComponent implements LookupListener{

Pastinya, kodingan kita bakal error. Kenapa?! Karena kita perlu nulisin lagi method2 terkait si interface LookupListener. Method2 itu inih nih isinya:

public void resultChanged(LookupEvent le);

Method di atas berfungsi untuk menjalankan suatu logika ketika terjadi perubahan state yang di-observe (dalam hal ini atribut “konten” tadi). Gituu… dan, balik ke program kita sebenernya… ringkasnya, ini yang musti diubah di kelas “HistoryAppTopComponent”:

  1. Deklarasikan sebuah atribut untuk menerima hasil Lookup (karena tipe yang dikirimin String, jadi kita pake tipe String sebagai generic-nya).
    private org.openide.util.Lookup.Result result;
  2. Ubah isi method “componentOpened”, “componentClosed”, “resultChanged”
     @Override
        public void componentOpened() {
            result = org.openide.util.Utilities.actionsGlobalContext().
                    lookupResult(String.class);
            result.addLookupListener(this);
        }
    
        @Override
        public void componentClosed() {
            result.removeLookupListener(this);
        }
    
        @Override
        public void resultChanged(LookupEvent le) {
            Collection<? extends String> hasil = result.allInstances();
    
            StringBuilder sb = new StringBuilder();
            for (String string : hasil) {
                sb.append(string).append("\n");
            }
            jTextArea1.setText(sb.toString());
        }

Di atas, gw pake StringBuilder supaya string yang diterima bisa diubah2… bisa mutable gitu. Kalo String kan sifatnya amutable…. Lihat dokumentasi java ajah ya biar jelas. Kalo mau pake String bisa ubah gini:

    @Override
    public void resultChanged(LookupEvent le) {
        Collection<? extends String> hasil = result.allInstances();

        for (String string : hasil) {
            jTextArea1.append(string);
        }
    }

Kalo kenapa pake Collection<? extends String>, yaaa itu karena memang tipe itulah yang dikembalikan ama fungsi “allInstances”. Dan… yang perlu kamu perhatikan, gak ada pemisahan apapun di sini. Gak tergantung modul, gak tergantung kelas. Semuanya ada di lookup. Jadi, hati2 kalo mau ngegunain lookup ini. Semuanya di-publish, dan kamu gak tau lookup mana yang bakal berubah dan kepilih untuk ditampilin ama si subscriber/observer.

Kalo seandainya, yang kamu kirim ada 2 tipe, nama sama integer doank gimana?! Ada cara ngebedainnya?! Well, sayangnya enggak. Semuanya bakal numpuk jadi 1 di mari (dan kalo seingat gw, ini bakal berubah tipenya jadi String deh…) jadi butuh pemrosesan String seandainya kamu pengen ngedapetin angka sama hurufnya.

Tapi… kayaknya bisa deh diakalin pake getClasses. Jadi kira2 tipenya gini:

        Set allClasses = result.allClasses();

        for (Iterator it = allClasses.iterator(); it.hasNext();) {
            Object o = it.next();
            System.out.println(o);
        }

Tapi gw lum nyoba jugak c…. Okeh, segitu ajah guyzzzz. Moga ngebantu yak…

Btw… ini hasil akhirnya:

13. Hasil Akhir

 

PS: Selain pake “add”, kamu bisa juga pake “set”, bedanya “add” nambah, “set” itu ngeganti.

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s