Mengubah Format Currency dan Format Rupiah ke dalam Number pada Bahasa Java

Berawal dari lebih dari 1 orang yang nanyain di kotak komentar postingan ini, gw akhirnya bikin dah post ini. Mayan… buat nambah2in isi blog yang agak guna biar ga curcolan mulu isinya…

Singkat cerita, ada yang nanyain gimana cara ngubah format dalam bentuk duit balik lagi ke sifat aslinya (number) biar bisa dioperasiin. Well… buat gw, itu pertanyaan yang bikin gw bingung. Banget! Karena… faktanya, kalau kamu udah punya suatu “a” yang kamu ubah jadi “b”, buat apa kamu ngubah “b” jadi “a”. Toh nilai “a” dari awal udah kamu punya dan nilainya sama sekali ga ketimpa. Beda tipe data gitu… gimana cara isinya bisa ditimpa jadi nilai lain kan yah… Makanya gw bingung.

Tapi apapun itu… ada satu alasan buat para programmer-pemberi-isi-kotak-komentar-di-postingan-asal biar ga ambil lagi nilai awalnya. Dan mereka bingung gimana cara balikinnya. Untuk itu… disinilah gw sebagai pencerah bagi mereka yang kebingungan… Hohoho.

Seperti yang gw tulisin di kotak balasan, ada beberapa langkah yang musti dilakukan:

  1. Parse formatted String ke tipe Number pakai method parse dari objekDecimalFormat
  2. Konversi bentuk Number ke byte/double/float/long/int/short pakai byteValue/doubleValue dst.

Simple kan… buat yang bingung, kodenya gini:

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;

public class KurensiIndonesia {

    public static void main(String[] args) {
        double harga = 250000000;

        DecimalFormat kursIndonesia = (DecimalFormat) DecimalFormat.getCurrencyInstance();
        DecimalFormatSymbols formatRp = new DecimalFormatSymbols();

        formatRp.setCurrencySymbol("Rp. ");
        formatRp.setMonetaryDecimalSeparator(',');
        formatRp.setGroupingSeparator('.');

        kursIndonesia.setDecimalFormatSymbols(formatRp);
        String x = kursIndonesia.format(harga);
        System.out.println("Harga Rupiah: "+x);
//konversi balik String --> number type
        try {
            Number number = kursIndonesia.parse(x);
            double nilai = number.doubleValue();
            System.out.println("Nilai dari rupiah: "+String.format("%.2f", nilai));
        } catch (ParseException ex) {
            System.out.println("Kesalahan Parsing");
        }
    }
}

Hasil:

Capture

Contoh kode yang lebih singkat… cuma buat konversi rupiah ke angka itu gini:

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;

public class KurensiIndonesia {

    public static void main(String[] args) {

        String x = "Rp. 250.000.000,00";
        DecimalFormat kursIndonesia = (DecimalFormat) DecimalFormat.getCurrencyInstance();
        DecimalFormatSymbols formatRp = new DecimalFormatSymbols();

        formatRp.setCurrencySymbol("Rp. ");
        formatRp.setMonetaryDecimalSeparator(',');
        formatRp.setGroupingSeparator('.');

        kursIndonesia.setDecimalFormatSymbols(formatRp);
        try {
            Number number = kursIndonesia.parse(x);
            double nilai = number.doubleValue();
            System.out.println("Nilai dari rupiah: "+String.format("%.2f", nilai));
        } catch (ParseException ex) {
            System.out.println("Kesalahan Parsing");
        }
    }
}

Intinya, pastiin objek DecimalFormat sama DecimalFormatSymbols yang dibentuk itu sama jenisnya. Gampangnya, objek yang digunain buat nge-format sama nge-parse itu sama. Jangan sampe beda. Kalau beda, ada kemungkinan kamu dapat nilai yang salah bahkan kegagalan eksepsi.

Dan karena banyak yang nanya juga terkait swing dan lainnya… hal di atas gw juga udah coba ke swing (pakai jtextfield biasa) sama akses database (nyimpen ke Access–biar gw ga usah nginstall dbms lagi)…. dan berhasil.

Moga ngebantu urusan kamu masing-masing…

Baca juga: Mengubah nilai double –> rupiah.

Memberi Input Argument Pada Netbeans

Di tulisan perdana pasca recovery, ternyata gw ga nyeritain tentang kondisi gw. Hohoho… ntar ajah… abis gw checkup beberapa hari lagi.

Jadi sekarang, ceritanya gw mau kasih tau gimana cara nge-set argument kalo pake IDE Netbeans. Hal remeh c sebenernya. Tapi berhubung ga ada yang mau ditulisin lagi, dan masih banyak temen junior gw yang bingung caranya…. Jadi aja gw tulis di mari.

Buat kamu yang belajar Java pertama kali, kemungkinan kamu dikasih tau sama pelatihnya, kalo masukannya bisa dimasukin via argumen java. Argumen ini ditulisin pas kita mau ngejalanin programnya. Contohnya, anggap gw punya kode kayak gini:

public class Main {

    public static void main(String[] args) {
        int a = Integer.parseInt(args[0]);
        int b = Integer.parseInt(args[1]);
        int c = a + b;
        System.out.println("Jumlah " + a + " + " + b + " = " + c);
        System.out.println(args[0]);
    }
}

yang bakal gw eksekusi pake kode ini di command line interface (CLI):

java Main 10 20

trus ngehasilin hasil kayak gini:

Jumlah 10 + 20 = 30
10

Buat pengguna Netbeans, biasanya bakal bingung… gimana cara ngetik tambahan input parameter berupa angka 10 sama 20 itu. Sebenernya, dari sejak jaman Netbeans tercipta, fitur ini tuh udah ada. Cuma, pas awal2… parameternya cuma bisa buat 1 main class yang dijalanin buat 1 project. Kalo kamu punya 2 main class di 1 project (dalam rangka eksperimen atau apapun), main class yang kedua ga bakal bisa dijalanin. Tapi herannya, para senior (maksudnya asprak pas nguli) dulu ga ngajarin kita hal ini. Dosen juga enggak. Mungkin karena gampang kali yah… Apapun alasannya, di sini, gw bakal kasih tau caranya biar bisa tambahin argument ini di Netbeans. Jadi berterima kasihlah kamu semua ke gw yang lebih baik dari kaka asprak juga dosennya kamu… XD

Cara pertama yang gw kasih tau… yaitu cara awal pas running Netbeans dari jaman dulu.

Awalnya,  konfigurasi dilakukan dari Run -> Set Project Configuration -> Customize…

konfigurasi-run

Setelah muncul pop-up window, masukkan nilai yang ingin diberikan untuk argumen pada text field Arguments.

konfigurasi-argumen

Kalau udah di-OK, pas tekan F6 untuk Run File, bakal muncul hal kayak gini:

hasil-run

Cara kedua… kalo ga salah baru muncul pas Netbeans versi 7. Gw ga tau tepatnya kapan… tapi mulai dari versi 7.4 sampe 8.2 (yang gw pake sekarang), udah muncul nih fitur. Caranya, di layar output, pilih segitiga kuning dari bagian output… terus, bakal muncul kan satu window pop-up… kasih tambahan tulisan gini:

konfigurasi-argumen-output

Terus dampaknya mirip sama output di atas, bedanya masukan argumen jadi 20 ama 30… Bukan kayak awal (10 dan 20).

Hal yang perlu diperhatikan dari cara kedua, kamu semua bener2 harus nulisin “application.args”. Jangan sekali2 kamu nuker “args” jadi “arg” atau yang lain gara2 kamu ga nulis “public static void main(String[] args)” tapi malah nulis “public static void main(String[] arg)”. Best practice yang lain, pengaturan ini munculnya dari window output. Jadi, gampangnya… pastiin kamu udah nge-running minimal 1x error… baru kamu tekan kuning2nya. Pas running pertama, pasti bakal error… kecuali kamu udah ngelakuin cara pertama untuk class yang mau kamu running.

Sooo… gitu ajah. Kalau ada masukan plus koreksi, boleh banget tulisin di kotak komentar…

Menggunakan notify Pada NotifyDescriptor Netbeans Platform

Gw agak2 heran c yah… kenapa beberapa waktu terakhir banyak banget yang nanyain tentang Netbeans Platform ke gw. Padahal kan gw jugak dah lumayan lama gak nyentuh2 NetPla. Tapi ya sudahlah yah… Reader tetep ajah reader yang bisa jadi inspirasi blogger buat nulis sesuatu.

Okeh! Jadi, berangkat dari tujuan itu, gw nulisin nih tulisan.

Topik yang ditanyain yaitu terkait NotifyDescriptor plus temennya DialogDisplayer. Terkait 2 hal itu, gw asumsiin kamu semua dah pada tau dua hal itu apa yah… Intinya, NotifyDescriptor itu komponen di NetPla yang punya fungsi mirip sama JOptionPane. Bedanya, kalo di JOptionPane, kamu cuma nentuin konten (gambar, kata2, judul, tombol de el el). Sedangkan di NotifyDescriptor, kamu bisa desain sendiri apa yang kamu tampilin. Mulai dari jumlah masukan yang kamu mau, tombol apa yang ditampilin, bahkan warna panel yang kamu sukak buat ditampilin ke pengguna aplikasi yang kamu bikin. Itu gunanya si NotifyDescriptor. Terus, si DialogDisplayer punya fungsi buat munculin si NotifyDescriptor biar bisa muncul di hadapan pengguna. Okeh.. itu intinya.

Pertanyaan aslinya, yaitu tentang menampilkan objek NotifyDescriptor dari DialogDisplayer. Faktanya, di sini kamu bisa nampilin dengan menggunakan 2 method, yaitu “notify” sama “notifyLater”. Dan yaaa… itulah pertanyaannya. Apa bedanya cara nampilin pake “notify” sama “notifyLater”?

Jawaban gw c singkat ajah ya… Bedanya… kamu baca deh netbeans doc. Ntar juga ketemu. Atau kalo males, nih gw kutip dokumentasinya.

public abstract Object notify(NotifyDescriptor descriptor)

Notify the user of something in a message box, possibly with feedback.

To support both GUI and non-GUI use, this method may be called from any thread (providing you are not holding any locks), and will block the caller’s thread. In GUI mode, it will be run in the AWT event thread automatically. If you wish to hold locks, or do not need the result object immediately or at all, please make this call asynchronously (e.g. from the request processor).

Parameters:
descriptor – description of the notification

Returns:
the option that caused the message box to be closed

Yang atas buat notify, yang bawah buat notifyLater

public void notifyLater(NotifyDescriptor descriptor)

Notify the user of something in a message box, possibly with feedback, this method method may be called from any thread. The thread will return immediately and the dialog will be shown later, usually when AWT thread is empty and can handle the request.

Implementation note: Since version 7.3, implementation improved to work also before main window is opened. For example: When method is called from ModuleInstall.restored, then modal dialog is opened and blocks main window until dialog is closed. Typical use case is login dialog.

Parameters:
descriptor – description of the notification

Since:
7.0

Jadi intinya, yang atu method berupa prosedur (notifyLater), atunya berupa function (notify). Jadi yang satunya mengharapkan adanya nilai balikan pas pemanggilannya, satunya lagi enggak. Sesuai sama sifat fungsi atau prosedur. Terus, kapan kita musti ngegunain salah satunya dibanding yang lain?! Jawabannya juga bisa kamu liat di atas. Kalo seandainya kamu musti nampilin sesuatu sebelum main window muncul, bisa pake notifyLater.

Gak ada salahnya juga kamu make notify. Tapi ati2 ajah ama kode kamu. Karena ga sekali dua kali gw nemu kejadian kalo aplikasinya masih jalan secara background walo main window-nya udah ditutup karena programmernya (iya, gw c maksudnya) make notify, dan bukannya notifyLater.

Kalo seandainya ada satu kondisi yang ngeharusin kamu pake notify dan bukannya notifyLater, padahal kamu musti nampilin message box-nya sebelum main window ke-load, kamu bisa kasih aksi ke si objek NotifyDescriptor-nya gini:

        DialogDisplayer.getDefault().notify(nd);

        nd.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getNewValue().equals(NotifyDescriptor.CLOSED_OPTION)) {
                    LifecycleManager.getDefault().exit();
                } else if (evt.getNewValue().equals(NotifyDescriptor.OK_OPTION)) {
                    //logika
                } else {
                    LifecycleManager.getDefault().exit();
                }
            }
        });

Cukup jelas kan yah? Hal di atas perlu kamu lakuin. Kenapa?! Karena kalo enggak, pas nutup message box-nya, program kamu ada kemungkinan masih jalan sebagai proses background. Gak bagus buat pengguna kamu. Tiba2 memorinya penuh gara2 aplikasi yang kamu bikin. Command exit() gak bakal ngaruh dalam pengkondisian penyamaan objek yang merupakan balikan dari pemanggilan notify(). Jadi ati2 yah…

Dan begitulah caranya… maaf yak kalo ternyata ga terlalu jelas. Cuma segitu yang bisa gw bagi. Maaf jugak, buat kali ini gw gak nyantumin sumber plus info kevalidan buat hal di atas. Yah… gitu deh…

Membuka Actived TopComponent pada Action Netbeans Platform

Jadi… yang namanya action di Netbeans Platform, emang dimaksudkan buat hal2 yang sifatnya universal, kayak copy-paste, nampilin Wizard, dan hal2 sejenis lainnya. Cuma ajah, kadang kita nemu kasus khusus yang musti ngebikin kita ngebentuk satu tombol buat beberapa aksi berbeda, tergantung window yang aktif.

Kalo udah kayak gini, banyak hal bisa kamu lakuin, salah satu caranya gini:

  1. Ambil window yang aktif dari registry terlebih dahulu.
  2. Cek apakah instance dari TopComponent yang diambil sesuai dengan yang diinginkan.
  3. Lakukan aksi yang diperlukan.

Buat kamu yang pengin detail, sayangnya gw gak bakal publish di mari. Tapi bakal gw kasih sedikit source buat ngebantu. Langkah pertama: ambil TopComponent window yang aktif:

TopComponent tc = WindowManager.getDefault().getRegistry().getActivated();

Langkah kedua: cek instance dari TopComponent

if(tc instanceof UtamaTopComponent){
}

Buat langkah ketiga, lakukan seperlunya. Kamu bisa casting plus manggil method terkait dari TopComponent yang udah diambil tadi. Contohnya gini:

        if(tc instanceof UtamaTopComponent){
            UtamaTopComponent uc = (UtamaTopComponent) WindowManager.getDefault().findTopComponent("UtamaTopComponent");
            uc.cekHasilMod();
        }    

Begitulaahhh… sorry kalo gak terlalu ngebantu.

Membatasi Input Angka pada JTextField

Kita bahas trik lawas yak… trik apa?! Ya… sesuai judul postingan aja. Biar agak beda, di sini, gw pake 2 cara dan ngebahas beberapa hal terkait 2 cara tersebut. Langsung ajah, bentuk GUI kayak gini:

1. Contoh AplikasiKlik kanan di bagian teks buat Key Event, Pilih “Events” → “Key” → “Key Typed”, ntar muncul satu kode kayak gini:

2. Kode Key EventDalam logikanya, tulisin gini:

        char c = evt.getKeyChar();
        if (!((Character.isDigit(c) || (c == KeyEvent.VK_BACK_SPACE) || (c == KeyEvent.VK_DELETE)))) {
            evt.consume();
        }

Seperti yang kamu semua liat, di sana dipakein 3 kondisi:

  1. Cek kalo karakter yang di-type ama user gak termasuk ke dalam bentuk digit. Digit yang dimaksud masuk dalam ISO-LATIN, Arabic-Indic, Extended Arabic-Indic, Devanagari, dan Fullwidth.
  2. Cek karakter yang ditekan itu merupakan karakter backspace.
  3. Cek karakter yang ditekan itu merupakan karakter delete.

Kalo aja salah satu kondisi tersebut terpenuhi, yaaa… bakal dimasukin ke teks field. Kalo gak, yaaa… gak bakal kebaca sebagai karakter yang dimasukin. Kelemahannya apa?! Kelemahannya, karakter lain tetep bisa dimasukin. Caranya?! Simple… Copy-Paste… Nih yah, gambarnya gw tunjukin. Text field-nya dah gw pakein key event, tapi tetep bisa masuk karakter lain.

3. Kelemahan Event Type

Cara ngatasinya?! Yaaaa.. kamu cari tau aja sendiri. Tapi kalo emang kamu segitu mohon2nya ama gw, baiklah… gw kasi tau caranya. Caranya, cukup setTransferHandle jadi null untuk komponen terkait. Kode ini, bisa diletakin di bagian konstruktor.

Best practice-nya gini, anggap text field yang mau kamu pake namanya jTextField1, jadi di bagian konstruktor, tambahin kode gini:

jTextField1.setTransferHandler(null);

Tapi kode di atas jugak gak memungkinkan kamu buat ngelakuin copy yah. Ati2 ajah. Terus gimana alternatifnya?! Solusi lain yang bisa kamu lakukan, dengan tidak melakukan apa pun ketika tombol Ctrl+V ditekan. Ini punya kelemahan juga c… Bayangin kalo di suatu mesin, paste gak di-peta-in pake tombol Ctrl+V, ini bakal jadi masalah. Tapi, beruntungnya… copy/paste sifatnya universal untuk tiap mesin. Jadi… moga aman lhah… 😀

Oke… best practice-nya, bikin suatu key stroke, dan petain ke aksi yang gak ngelakuin apa pun. Kalo gw, nambahin kodenya deket2 konstruktor. Gini nih kodenya. Yang warnanya biru, itu yang gw tambahin. Lebihnya, itu standar bentuk JFrame awal.

    public NewJFrame() {
        initComponents();
        KeyStroke ks = KeyStroke.getKeyStroke("control V");
        jTextField1.getInputMap().put(ks, "dummy");

    }
    Action dummy = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            //do nothing
        }
    };

4. Key Stroke
Kalo udah nambahin kayak yang di atas, copy bisa dilakuin, tapi paste udah gak bisa. Jangan lupa buat uncomment kode setTransferHandle, plus import package terkait yak… Paling gak, kamu musti import 5 class ini:

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.KeyStroke;

Okeh… itu cara pertama yah… Cara yang kedua, pake PlainDocument.

Deklarasiin sebuah objek dari PlainDocument, kayak gini:

    PlainDocument pd = new PlainDocument() {
        @Override
        public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
            if (str.matches("[0-9]*")) {
                super.insertString(offs, str, a);
            } else {
                // do nothing
            }
        }
    };

Terus, kalo udah deklarasiin satu dokumen, berikutnya hubungkan objek PlainDocument ke text field yang diinginkan (di tulisan ini, maksudnya jTextField2). Jadi, gw tambahin kode kayak gini, di baris paling akhir sebelum kurung kerawal tutup dari konstruktor.

jTextField2.setDocument(pd);

Kekurangannya?! Hummm… hampir gak ada c, copy/paste udah terlarang di sini. Karena bukan cuma key event yang ditangani, tapi konten dokumennya jugak. Yang jadi permasalahan, even gak bisa paste, tapi kalo kamu blok semua karakter (pake Ctrl+A), terus kamu tekan Ctrl+V, dokumen semuanya bakal ilang. Cara nanganin?! Hmmm… pake aja cara penanganan sebelumnya. Selesai deh.

Oke, segitu ajah.. Moga ngebantu yak.

Sumber:
https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
http://www.coderanch.com/t/341695/GUI/java/enable-CTRL-perform-action-coping
http://stackoverflow.com/questions/316673/disabling-paste-in-a-jtextfield
http://www.atwiwit.net/2013/10/java-programming-cara-membuat-input.html
http://khannedy.com/2010/06/28/agar-jtextfield-tidak-menerima-input-selain-angka/

Valid: Yap
Kadaluarsa: (?)

Menyimpan Objek Java ke dalam File

Minnaaaa~~~, akhirnya blog balita balik lagi. Sekarang, bakal dibahas caranya gimana buat nyimpan data dalam bentuk objek. Yap, emang kalo nyimpan data gampangnya pake database ajah. Tapi, dalam satu atau lain kesempatan, bisa ajah kita musti nyimpen bukan ke database, tapi bentuk lain. Kalo udah gini, cara paling gampang yaaa… pake penyimpanan file. Tapi, akses file sendiri biasanya yang disimpan adalah tulisan2.

Tulisan ini bisa aja dijadiin data tersendiri ke dalam file kalo ngegunain pake bahasa pemrograman Java. Tapi, pendekatan yang gw maksud gini… Pas kamu punya satu master data yang jumlahnya puluhan baris record, dan satu record-nya terdiri dari beberapa hal. Yaa.. contohnya aja kamu nyimpen data semua member JKT48 di aplikasi yang kamu bikin. Kali ajah, kan… Dan hal ini, gak bisa kamu simpan gitu aja dalam bentuk tulisan. Karena, kamu musti bikin parsing dari tulisan2 yang kamu simpan. Alternatif penyimpanan yang bisa kamu lakuin contohnya (paling gak yang kepikiran ma gw sekarang), yaitu nyimpen dalam format XML. Yap, kamu musti parsing lagi, tapi bentuknya kan dah standar. Jadi gampang… dan alternatif lainnya, merupakan hal yang bakal dibahas di postingan sekarang… yaitu nyimpen dalam bentuk objek.

Bahasa Java mengakomodir penyimpanan objek yang dibentuk ke dalam file. Untuk melakukan hal ini, kita butuh yang namanya package java.io. Bagian yang kita butuhkan nantinya yaitu “FileOutputStream” dan “ObjectOutputStream”. Dari namanya ajah dah jelas ya gunanya buat apa. Selain itu, yang kita butuhin juga, bentuk POJO dari class yang kita simpan objeknya. Gw agak gak yakin tentang POJO (yaaa, maaf2 ajah kalo gw salah ngejerumusin kamu semua ama info yang gak valid. Kalo ada yang musti diperbaikin tell2 yak), tapi intinya POJO itu kependekan dari “Plain Old Java Object”. Bentuk dari POJO itu standar… cuma satu class dengan atribut dan method set-get, ditambah meng-implements “Serializable” dari java.io.Serializable.

Okeh, kita langsung praktek yah… Pertama, bikin class POJO dari objek yang nantinya mau disimpen. Gw bikin class “Oshi”, dengan atribut nama, tim, plus tahun lahir. Konstruktornya mau ada ketiga-tiganya, trus override method toString jugak. Jadi, gw bikin 1 file java, dengan class diagram kayak gini:

Class Diagram Oshi

Class diagram di atas dibikin pake plugin EasyUML dari Netbeans, gak bikin sendiri. Jadi kalo dirasa gak sesuai ama UML yang kamu kenal, yaaa… silahkan disesuaikan ajah. Kode dari class diagram di atas ditulisin gini:

import java.io.Serializable;

/**
 *
 * @author arby
 */

public class Oshi implements Serializable{
    private String nama;
    private char tim;
    private int tahunLahir;

    public Oshi(String nama, char tim, int tahunLahir) {
        this.nama = nama;
        this.tim = tim;
        this.tahunLahir = tahunLahir;
    }

    public String getNama() {
        return nama;
    }

    public void setNama(String nama) {
        this.nama = nama;
    }

    public char getTim() {
        return tim;
    }

    public void setTim(char tim) {
        this.tim = tim;
    }

    public int getTahunLahir() {
        return tahunLahir;
    }

    public void setTahunLahir(int tahunLahir) {
        this.tahunLahir = tahunLahir;
    }

    @Override
    public String toString() {
        return "Oshi{" + "nama=" + nama + ", tim=" + tim + ", tahunLahir=" + tahunLahir + '}';
    }
}

Terus, buat nyimpen objeknya ke file, gw bikin class baru Main.java

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

/**
 *
 * @author arby
 */
public class Main {
    public static void main(String[] args) {
        //bentuk 1 objek Oshi
        Oshi o = new Oshi("Melody", 'J', 1992);
        
        //menyimpan objek oshi "o"
        try {
            FileOutputStream fos = new FileOutputStream("file_oshi.dat");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(o);
            oos.close();
            System.out.println("Tersimpan");
        } catch (IOException ex) {
            System.out.println("Gagal. Error: "+ex);
        }
    }
}

Keliatan kan urutannya… pertama, tentukan file-nya pake FileOutputStream, abis itu simpan objek ke dalam file pake ObjectOutputStream. Kalo udah ditulis, jangan lupa ditutup pake “close”. Untuk tipe data (ekstensi file), itu juga bebas c… gak dipakein ekstensi pun sebenernya gak masalah. Nanti, bakal ada file_oshi.dat yang kebentuk sesuai path class yang kamu punya. Kalo gw, berhubung pake netbeans, kebentuknya di dalam project Netbeans-nya langsung. Hirarkisnya gini:

Selection_005

Kalo kamu liat isinya pake text editor, bakal keluarnya gini:

Selection_006

Dan… selesai lah sudah. Objek kamu berhasil tersimpan. Tapi, yang perlu kamu perhatiin… cara di atas, gak cuma bisa nyimpen 1 objek per file lhoh yah.. kalo kamu bikin 2 objek, anggaplah o1 sama o2, terus kamu tulisin syntax “oos.writeObject(o1);” juga “oos.writeObject(o2);”, yang kesimpen 2 objek itu. Cara ngebuktiinnya?! Hmm… cara ngebuktiinnya, kamu musti baca file tersebut. Bisa liat di file-nya langsung pake editor semacam notepad atau wordpad (soalnya kalo gedit/netbeans langsung dah gw coba, dan berakhir dengan kegagalan buat nampilin isinya)…

O iya, yang perlu kamu perhatiin jugak, tentang konsep penyimpanannya. Konsepnya nimpa lhoh yah… bukan nambah2 data baru kayak penambahan row baris di database. Nimpa… alias replace. Jadi, tiap kamu jalanin kode di atas, isinya bakal nimpa sesuai yang kamu tulisin. Bukan nambah data di baris paling bawahnya.

Kalo buat ngebaca file-nya di program java… uhmmm… postingan berikutnya aja yak… Gw lagi males nulisin. Ditunggu ajah… 😀 Ja naaa… moga ngebantu yak…

Sumber: how-to-write-an-object-to-file-in-java/
Valid: Yap!
Kadaluarsa: Sampe method terkait dinyatain deprecated.

Menyelesaikan “Reading package lists… Error!” di Linux Mint

Jadi yah, setelah lama gak install2 via terminal (yang musti kehubung ke internet gitu), gw kemarin nyoba install sesuatu lagi. Biasanya, gw kan donlot dulu package-nya di kantor (yaaa… oportunis dikit gapapa lhah ya 😛 ), trus copy ke si eunji (nama laptop gw di rumah), trus baru dah install. Tapi sekarang ceritanya, gw lagi seneng2nya make ngabisin kuota dari nomer hape gw yang berujung pada kegiatan buat beli paket berkali2 T_T

Karena kegiatan gw yang gak lazim itu, jadilah pas butuh satu aplikasi, gw langsung pake cara standar ajah di terminal (pake apt-get install ___), dan kondisinya gw gak pake DVD repo. Di sinilah sebenernya tulisan ini bermula. Jadi, pas gw ketikin

sudo aptitude install amarok

Yang keluar malah gini:

Couldn’t find any package whose name or description matched “amarok”
Couldn’t find any package whose name or description matched “amarok”
No packages will be installed, upgraded, or removed.
0 packages upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B of archives. After unpacking 0 B will be used.

Uhmm… ini gak banget, kan… jadi gw cobalah ketikin:

$ sudo apt-get update

sama

$ sudo apt-get upgrade

ternyata… hasilnya tuh gini:

[ ERR] Reading package lists
E: Encountered a section with no Package: header
E: Problem with MergeList /var/lib/apt/lists/packages.linuxmint.com_dists_rebecca_import_i18n_Translation-en
E: The package lists or status file could not be parsed or opened.
[ ERR] Reading package lists
E: Encountered a section with no Package: header
E: Problem with MergeList /var/lib/apt/lists/packages.linuxmint.com_dists_rebecca_import_i18n_Translation-en
E: The package lists or status file could not be parsed or opened.

Gw jugak gak tau apa yang gw bikin sebelumnya sampe keluar error gitu. Yah, sebenernya gak penting2 jugak c install amarok, toh dari awal, nih linux mint dah ke-install VLC ma Banshee. Tapi yaaa.. pengen aja cari alternatif lain. Karena penasaran, nemu lah satu thread ini.

Dari sana, dibilang cara nyeleseinnya pake 3 langkah ini:

$ sudo rm /var/lib/apt/lists/* -vf

Kode di atas, gw sebenernya juga gak tau artinya. Tapi, kalo rm buat nge-remove, yaaa… mungkin maksudnya buat ngehapus semua file di bawah direktori /var/lib/apt/lists, terus tulisin progres ngapusinnya (soalnya, -v itu pendekan dari “verbose” kalo gak salah). Abis itu, masukin ini:

$ sudo apt-get update

Kalo dah keluar macam2, brarti dah selese… tinggal dieksekusi kayak biasa… Dan, FYI… gw gak jadi install amarok. Tapi ya gapapa lhah… toh ujung2nya jadi 1 tulisan di mari 😛

Moga ngebantu yah, Guyz… 🙂

Mengakses Field Date pada Database Oracle

As always… ini tulisan rekues! Sebenernya udah lama c yah… dan orangnya yang ngerikues udah nerima jawabannya. Tinggal jawaban balik buat gw dibolehin apa enggak mosting yang dia tanyain di sini… Dan jawabannya, “terserah ajah”. Berhubung kemaren2 gw lagi di luar kota, nih tulisan baru jadi sekarang. 😀

Apapun prolog di atas, intinya si Aa’ nanya ke gw, gimana caranya kerja pake database Oracle, terus di database itu ada field yang tipe-nya Date. Kalo ajah dia nyari tutorialnya di stackoverflow, percayalah… itu jawaban bakal langsung nemu! Tapi, berhubung nih si Aa’ males ngeliat apapun, jadi dia tanya gw ajah. Katanya gw kan mantan asisten OOP. Hhhh… baiklah. (-_-)

Gimana caranya ngakses field itu? Gw tulisin jawabannya singkat ajah yak… Intinya, kalo insert, pake kuerinya gini:

String kueri = "INSERT INTO pergudangan (IDBARANG, NAMA, TGL_MASUK, STOK) VALUES (?,?,to_date(?,'DD-MM-YYYY','NLS_DATE_LANGUAGE = American'),?)";

Itu si Aa’ pake PreparedStatement, makanya ada tanda tanya gitu… intinya c pas masukin tanggal, bisa masukin pake format DD-MM-YYYY pas nulisinnya. Terus pas di ResultSet pake kode:

ps.setString(3,"27-05-2014");

Atau kalau kamu gak keberatan pake format “YYYY-DD-MM”, bisa pake java.sql.Date… caranya gini:

Date d = Date.valueOf("2014-11-15");
ps.setDate(3,d);

Yang paling penting dari hal di atas, kelas Date di sana diambil untuk class Date dari package java.sql… bukan java.util, yah. Si Aa’ berkali-kali gagal nyoba, gara2 dia ngira tipe Date di atas itu tipe Date dari java.util. Dan yang paling penting jugak buat kamu ketahui, kedua class ini walo namanya sama, mereka gak bisa di-casting gitu ajah. Boleh ajah kamu berhasil ngelakuin casting… tapi tolong kasi kodenya di kotak komentar yak. Gw jugak pengen tau… 😛

Teruuuuss… kalo kamu mau tau gimana caranya ngambil sysdate (tanggal dari system), kamu bisa pake bantuan dari class Date dari package java.util. Di sini, kamu bisa mengkolaborasikan kedua class Date itu. Caranya:

java.util.Date d1 = new java.util.Date();
Date d = new Date(d1.getTime());
ps.setDate(3,d);

Intinya, kamu bikin objek java.sql.Date dengan bantuan dari objek java.util.Date, tepatnya untuk memanggil method “getTime()”, yang bisa ngambil sysdate…

Dan…. trik terakhir, kalo kamu mau ngambil tipe Date dari ResultSet, dan kamu maunya nampilin pake format “dd-MM-YYYY”, ada class yang namanya “SimpleDateFormat”. Pake class itu, kamu bisa atur format tanggalnya. Caranya gini:

Date d = rs.getDate(3);
SimpleDateFormat sm = new SimpleDateFormat("dd-MM-YYYY");
System.out.println("Tanggal: "+sm.format(d));

Dan begitulah….

Kalau kamu mau tau penggalan kode di atas sebenernya lengkapnya tuh gimana… boleh disimak kode di bawah ini:

Untuk kelas Koneksi (KoneksiDB.java)… kelas ini buat ngecek JDBC ama ngembaliin objek class Connection. Kelas ini kebiasaan aja digunain pas kuliah dulu. Gak harus c, cuma ya itu… udah kebiasa… makanya adaan.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class KoneksiDB{
	private Connection conn;
	private final String DB_DRIVER="oracle.jdbc.driver.OracleDriver";
	private final String DB_URL="jdbc:oracle:thin:@localhost:1521/XE";
	private final String USERNAME="";
	private final String PASSWORD="";
	
	public void bukaKoneksi(){
		boolean flag = false;
		try{
			Class.forName(DB_DRIVER);
		}catch(ClassNotFoundException ex){
			System.out.println(ex.getMessage());
			flag = true;
		}
		if(!flag){
			try{
				conn = DriverManager.getConnection(DB_URL,USERNAME,PASSWORD);
			}catch(SQLException ex){
				System.out.println(ex.getMessage());
			}
		}
	}
	public Connection getConn(){
		return this.conn;
	}
}

Kelas Main yang digunain buat INSERT database:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Main{
	public static void main(String args[]){
		KoneksiDB k = new KoneksiDB();
		k.bukaKoneksi();
		Connection kon = k.getConn();
		String kueri = "INSERT INTO pergudangan (IDBARANG, NAMA, TGL_MASUK, STOK) VALUES (?,?,to_date(?,'DD-MM-YYYY','NLS_DATE_LANGUAGE = American'),?)";
		int rowAffect=0;
		try{
			PreparedStatement ps = kon.prepareStatement(kueri);
			ps.setString(1,"BRG04");
			ps.setString(2,"Tisu Kering");
			ps.setString(3,"27-05-2014");
			ps.setInt(4,20);
			rowAffect = ps.executeUpdate();
			ps.close();
		}catch(SQLException ex){
			System.out.println(ex);
		}
		if(rowAffect==0){
			System.out.println("Query Gagal");
		}else{
			System.out.println("Query Berhasil");
		}
		
	}
}

Kelas Main… contoh buat ngambil value dari string dengan format “YYYY-MM-DD”:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Date;

public class Main{
	public static void main(String args[]){
		KoneksiDB k = new KoneksiDB();
		k.bukaKoneksi();
		Connection kon = k.getConn();
		String kueri = "INSERT INTO pergudangan (IDBARANG, NAMA, TGL_MASUK, STOK) VALUES (?,?,?,?)";
		int rowAffect=0;
		try{
			PreparedStatement ps = kon.prepareStatement(kueri);
			ps.setString(1,"BRG03");
			ps.setString(2,"Sabun Cuci");
			Date d = Date.valueOf("2014-11-15");
			ps.setDate(3,d);
			ps.setInt(4,100);
			rowAffect = ps.executeUpdate();
			ps.close();
		}catch(SQLException ex){
			System.out.println(ex);
		}
		if(rowAffect==0){
			System.out.println("Query Gagal");
		}else{
			System.out.println("Query Berhasil");
		}
		
	}
}

Kelas Main yang dibikin buat ngambil sysdate:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Date;

public class Main{
	public static void main(String args[]){
		KoneksiDB k = new KoneksiDB();
		k.bukaKoneksi();
		Connection kon = k.getConn();
		String kueri = "INSERT INTO pergudangan (IDBARANG, NAMA, TGL_MASUK, STOK) VALUES (?,?,?,?)";
		int rowAffect=0;
		try{
			PreparedStatement ps = kon.prepareStatement(kueri);
			ps.setString(1,"BRG03");
			ps.setString(2,"Sabun Cuci");
			java.util.Date d1 = new java.util.Date();
			Date d = new Date(d1.getTime());
        	ps.setDate(3,d);
			ps.setInt(4,100);
			rowAffect = ps.executeUpdate();
			ps.close();
		}catch(SQLException ex){
			System.out.println(ex);
		}
		if(rowAffect==0){
			System.out.println("Query Gagal");
		}else{
			System.out.println("Query Berhasil");
		}
		
	}
}

dan terakhir…. kelas Main buat nampilin tanggal pake format “dd-MM-YYYY”:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Date;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;

public class Main{
	public static void main(String args[]){
		KoneksiDB k = new KoneksiDB();
		k.bukaKoneksi();
		Connection kon = k.getConn();
		
		String kueri="SELECT * FROM pergudangan";
		ResultSet rs = null;
		try{
			PreparedStatement ps = kon.prepareStatement(kueri);
			rs = ps.executeQuery();
			while(rs.next()){
				System.out.println("ID Barang: "+rs.getString(1));
				System.out.println("Nama Barang: "+rs.getString(2));
				Date d = rs.getDate(3);
				System.out.println("Tanggal Masuk: "+rs.getString(3));
				SimpleDateFormat sm = new SimpleDateFormat("dd-MM-YYYY");
				
				System.out.println("Tanggal: "+sm.format(d));
				System.out.println("Stok: "+rs.getInt(4)+"\n");
			}
		}catch(SQLException ex){
			System.out.println(ex);
		}
		
	}
}

Begitulaaahhh~~ moga ngebantu yah, guyz….

Valid?: Banget.
Masa Kadaluarsa: Gak tau.
Sumber: stackoverflow, pribadi.

Membuat .jar File dari Kode Java

Jadi gini… lagi2 ada yang nanya… Kalo diliat polanya, pas mosting yang agak serius, itu pasti karena requirement dari seseorang. Entah itu temen, si Aa’, atau sapa lhah… Seolah gw gak bisa bikin sesuatu yang serius, kecuali berupa tanggapan. Huweeee….

Apapun itu, intinya ada yang nanya ke gw, gimana cara bikin file berekstensi jar dari codingan java yang udah dia bikin. Hmmm, gimana yah… Kalo gw biasanya nyuruh dia pake IDE, terus coding pake Netbeans, trus kalo dah selesai, klik kanan di project Netbeans-nya, pilih “Build”. Ntar bakal ada folder “dist” kebentuk dalam folder project, dan itu bisa dijalanin gitu ajah, asal mesinnya keinstal JRE. Tapi, requirement-nya dia lagi gak make Netbeans dan emang cuma pake editor sederhana, yang gak bisa generate IDE-nya langsung.

Okeh… permintaan di atas, mirip2 sama tugas kuliah… Tapi baiklah, berhubung gw baik… jadi gw jelasin aja di mari. Buat yang gak tau apa itu file berekstensi jar, gw jugak bakal jelasin di mari. Ekstensi jar merupakan file java archive. Jadi kayak kamu ngegabungin beberapa file menjadi sebuah file lain. Pernah nge-compress beberapa file jadi 1 file zip/rar? Kalo pernah, yaaa yang kamu lakuin mirip2 ama compress itu. Bedanya, file jar ini bukan berfungsi buat nge-compress, tapi buat ngegabungin semua file class (hasil compile file java) yang udah kamu buat supaya bisa jalan dan jadi sistem yang utuh, walau kesebar di beberapa file codingan. Intinya, file .jar itu merupakan executable file yang terdiri dari satu atau beberapa file yang kamu gunakan untuk membuat sebuah aplikasi berbasis java.

Cara gampang untuk meng-generate file jar yaitu dengan menggunakan editor IDE kayak Eclipse atau Netbeans. Caranya kayak yang udah gw jelasin di atas. Ada cara gampang, ada juga cara native pastinya… Cara native ini kemungkinan yang dilakukan banyak programmer sebelum IDE diciptakan oleh mereka. Cara native-nya pake command “jar” di terminal/console/command prompt. Berhubung sekarang lagi ngetik di komputer berbasis  Windows, jadi gw praktekkin di windows, yak. Yang linux sama ajah… gak ada beda.

Sebelumnya, gw bakal ngasi tau kalo command jar punya beberapa opsi, diantaranya c, m, f, x, t dll. Penjelasannya gini:

  1. c: buat “create” file jar
  2. m: buat memodifikasi file MANIFEST.MF yang ada di folder META-INF
  3. f: untuk merujuk ke sebuah file yang diberikan, jadi keluarannya bukan stdout gitu
  4. x: buat nge”eXtract” file jar
  5. t: buat melihat isi dari file jar yang dimaksud

Contoh? Oke.. gini, pertama, bikin dulu file java yang ada “public static void main(String args[])”-nya biar bisa di-running.

public class Main{
	public static void main(String args[]){
		System.out.println("Hello World");
	}
}

Kompile dan run file java itu…

1. Eksekusi dan Jalankan

Yang perlu kamu ketahui, setiap kamu nge-running java, sebenernya yang kamu jalanin adalah file .class-nya, dan bukan file java-nya. Jadi, dalam jar, kamu cukup masukin file .class yang kamu butuhin… gak usah semuanya jugak. Tapi kalo kamu mau masukin semuanya, juga gak masalah. Kamu tinggal pake command “*” ajah… Gak usah pilih2…

Jadi… langkah selanjutnya, kamu masukin file Main.class ke dalam sebuah file jar, pake command jar

2. Bentuk Jar

Command itu gak usah gw jelasin yah maksud “cf”-nya. Kan udah di atas… Kalo hai.jar, itu nama file jar yang kamu mau, dan setelahnya ada Main.class… itu file class yang mau dimasukin ke file jar-nya. File jar ini, seharusnya udah bisa kamu jalanin… tapi biasanya, yang terjadi c belum bisa dijalanin. Cobain deh gini:

3. Jalankan Jar

Bilangnya, belum ada “main” di manifest sebagai atribut. Mungkin kamu bingung, dan gw lebih bingung lagi ngejelasinnya. Tapi intinya, pas kamu bikin file jar tersebut, ada file MANIFEST.MF dari folder META-INF yang di-generate secara default oleh sistemnya, karena file ini emang dibutuhin sama si file jar-nya. Bentuk default-nya kayak gini:

Manifest-Version: 1.0
Created-By: 1.7.0_55 (Oracle Corporation)

Isi dari file MANIFEST.MF itu belum lengkap, karena kita gak specified class yang punya “public static void main(String args[])” tuh yang mana. Makanya error-nya gitu. Uhhmmm… nangkep kan maksud gw?! Okeh, nangkep atau enggak, gw bakal kasi tau solusinya. Kamu extract dulu file jar yang tadi pake command gini:

4. Jar Salah

Dan nanti, ada file tambahan di folder tempat kamu nge-ekstract file hai.jar.

5. Struktur File

Ada folder META-INF. Di dalamnya ada MANIFEST.MF. Ubah isi file MANIFEST.MF pake editor favorit kamu (bisa gedit/notepad++/notepad) jadi kayak gini:

Manifest-Version: 1.0
Created-By: 1.7.0_55 (Oracle Corporation)
Main-Class: Main

Yang gw merahin merupakan nama Class yang bisa di-running (ada public static void main(String args[])). Kalo Class gw kan namanya Main.class, jadi gw bikinnya “Main”. Save, dan tutup editornya. Gak ditutup juga gak papa c. Terus, kamu bikin lagi file jar pake MANIFEST yang udah kamu ubah isinya tadi dan running. Caranya gini:

6. Bentuk Jar

Yang perlu kamu perhatiin, kamu harus nambahin satu karakter kosong sehabis kamu ngubah file MANIFEST.MF, jangan kayak gini:

7. Manifest Salah

Kenapa?! karena kalo gak, yaaa bakal jadi kayak gini kalo kamu running, hal ini lah yang bakal kamu temuin:

8. Jar Salah

Jadi bikinnya, paling gak ada karakter space kayak gini (space lhoh yah… whitespace juga gak ngaruh):

9. Manifest Benar

Dan buat kamu yang bertanya-tanya, kenapa ngejalaninnya pake “java -jar”, bukannya klik dua kali… kan executable?? Gak ada yang bisa gw jawab kecuali “yaaa.. karena tipe aplikasi yang dibikin itu sifatnya console-based”. Jadi jalaninnya tetap di console/terminal/command prompt/cmd. Kalo kamu bikin aplikasi GUI, ntar juga bisa dijalanin pake klik 2x. Dan begitulaaahhhh…. Pertanyaan dan saran, boleh langsung di kotak komentar, yak…

PS: kalo ada yang nanya, buat library eksternal kayak JDBC kalo mau di-running, daftarinnya gimana… Jawabannya gini: “tinggal kamu tambahin atribut Class-Path di file MANIFEST.MF”. Contohnya gini:

10. Manifest dengan Path

Dan struktur folder-nya gini:

11. Bentuk Jar

Kalo library lain ada lagi yang mau ditambahin, tinggal dikasi spasi ajah kayak gini:

Manifest-Version: 1.0
Created-By: 1.7.0_55 (Oracle Corporation)
Main-Class: Main
Class-Path: lib1.jar lib2.jar lib3.jar

PPS: Kalo ada yang nanya lagi, “itu… file MANIFEST.MF sebenernya buat apa dan harus kayak di atas bikinnya? Generate dulu, extract, baru pake yang ada?” sebenernya enggak. Jawabannya: “gw gak tau yah buat apa sebenernya, tapi kayaknya buat spesifikasi pas nge-running java…kan ada atribut Main-Class gitu, terus kalo harus gitu bikinnya… enggak c yah. Kamu bisa bikin sendiri file MANIFEST.MF itu pake editor biasa, asalkan encoding-nya pake UTF-8”. Contohnya, gini.. gw bikin sendiri MANIFEST.MF kayak di atas, terus gw generate lagi kayak gini:

12. Akhir

Dan selesai… Begitulah caranya.. Moga membantu…

Valid: Iyap!
Kadaluarsa: Gak tau
Sumber: situs oracle, stackoverflow.com sama dok pribadi

Menyimpan Username & Password di Option Panel

Kemarin udah ngebahas tentang form login yang muncul sebelum aplikasi dijalanin kan yah… Tapi username sama passwordnya kesimpan di sistem. Sebenernya, kamu bisa ubah2 supaya uname ma passwordnya kesimpen di database. Tapi, kalo kamu gak niat bikin aplikasi yang pake database, uname ma passwordnya, bisa kamu simpan di variable global. Yang pake NbPreferences gitu… Dan biasanya kalo gak pake bantuan Wizard, pake bantuan dari Option Panel.

Tapi berhubung adanya tutorial buat nyimpen dari Option Panel, kita ngikutin ajah yah…

Uhmmm… sebelum ngikutin tutorial ini, pastiin ikutin tutorial sebelumnya yah… Kan nyambung ceritanya.

Pertama, dari NPA sebelumnya, kita buat satu module buat nampung Option Panel. Sebenernya boleh aja kalo mau gabung sama module “LoginModule” sebelumnya, tapi gw pisah… biar mirip sama tutorialnya 😀 Jadi… bikin satu module baru lagi, infonya gini:

1. Identitas Module2. Code Name Base Module

Di module “Pengguna”, buat satu option panel. Klik kanan di module, pilih New →  Other. Muncul 1 window baru, di sebelah kiri pilih “Module Development”, di bagian kanan pilih “Options Panel”.

3. New Option Panel

Bikin Primary Panel ajah kita. Gak usah ada secondary panel-nya… Untuk icon, kalo gak punya, pake ini ajah… User-icon Bukan punya gw jugak c sebenernya… ngambil secara semena-mena dari internet itu… :p

4. Primary Panel

5. Option Panel Name

Klik “Finish”. Perhatikan, ada 3 file kebentuk… Cuma yang kebaca 2 ajah (ekstensi java ajah yang bakal muncul). Yang satu (ManajemenPenggunaOptionsPanelController) buat controller, yang satu lagi (ManajemenPenggunaPanel) buat desain tampilannya.

Di bagian pengaturan tampilan, atur tampilannya jadi kayak gini:

6. Desain Option Panel

Ada 2 label, 1 text field di sebelah “Pengguna” dengan nama variable “username”, 1 text field bernama “password” di sebelah “Kata Sandi”. Dan layoutnya pake Flow Layout.

Kondisi yang kita mau, tiap nutup panel itu, perubahan disimpan, dan tiap dibuka, pengguna ama kata sandi-nya muncul. Artinya, kita bakal kerja dengan method “load” dan “store”. Method ini ada di kelas “ManajemenPenggunaPanel”. Kalo kamu Cuma liat bagian design, coba ubah ke bagian Source. Ntar keliatan tuh yang begituan.

7. Source-Design

8. Method Load-Store

 Kalo load dijalanin pas option panel dibuka, store dijalanin pas ditutup. Sekarang, gw c mau bikin buat “store” dulu. Jadi, kalo mau nyimpen variable, bisa pake kode gini kan yah:

NbPreferences.forModule(REFERENSI_KELAS_YG_DIGUNAKAN).put
     ("NAMA_VAR_YG_DIMAU", "TEXT");

Tinggal diganti nama variable yang diinginkan, terus ganti text sesuai isi yang disimpan. Jadi kalo mau username disimpan di variable bernama “nama” dan isinya “arby”, terus referensi kelasnya itu c option panel tadi, kode di atas bisa diganti jadi:

NbPreferences.forModule(ManajemenPenggunaPanel.class).
     put("nama", "arby");

Dan kode di atas, gak ada hubungannya sama nama variable text field atau apapun yang sebelumnya udah kita buat. Hubungannya, isi dari variable itu kan seharusnya dari text field yang udah kita buat sebelumnya, jadi musti kita ganti pake:

 NbPreferences.forModule(ManajemenPenggunaPanel.class).put
      ("nama", username.getText());

Kalo “nama” di atas, gak usah diganti… itu jadi nama variable global kalo mau ngakses username. Kalo kamu mau ganti yaaa silakan. Tapi kamu musti tau, referensi rujukan variable global-nya jadi berubah. Kalo yang di-store udah selesai diubek2, selanjutnya di method load yang diubah2… Di method ini, kita ubah kode sebelumnya, dari “put” jadi “get”.

NbPreferences.forModule(ManajemenPenggunaPanel.class).get("nama", "")

Kalo kamu liat, isinya jugak ada 2, “nama” dan string kosong. Untuk “nama”, ini merupakan referensi global yang udah kita tentuin tadi. Untuk store ama load, ini harus sesuai. Sedangkan string kosong, itu merupakan default yang dikirimkan kalo si variable global “nama” itu gak ditemuin ama sistem.

Singkat cerita, isi dari method store sama load itu bisa dibikin kayak gini:

    void load() {
        NbPreferences.forModule(ManajemenPenggunaPanel.class).get("nama", "");
        NbPreferences.forModule(ManajemenPenggunaPanel.class).get("sandi", "");
    }

    void store() {
        NbPreferences.forModule(ManajemenPenggunaPanel.class).put("nama", username.getText());
        NbPreferences.forModule(ManajemenPenggunaPanel.class).put("sandi", password.getText());
    }

Dan jangan lupa buat meng-import package terkait:

import org.openide.util.NbPreferences;

Udah?? Coba dijalanin…

Di bagian Tools → Option, ada satu menu “Manajemen Pengguna”. Di sana ada 2 buah text field gini. Dan itu bisa diisi sesukanya…

9. Hasil

Tekan OK, terus tutup aplikasi NPA-nya. Aplikasi lhoh ya… Bukan sekedar Option Panel-nya. Jalanin lagi, lihat di bagian “Manajemen Pengguna”, isi dari “Pengguna” dan “Kata Sandi” bakal tetap ada. Tapi kamu heran… coz yang kamu temuin adalah field kosong… Padahal udah ngikutin langkah2 yang gw tulis dengan baik dan benar.

Oke, kamu gak usah pusing, coz variable itu tetap ada isinya. Cuma emang gak nampil. Itu ajah… Kalo kamu isinya tampil, kamu musti ubah dikit kodingan di method load jadi gini:

    void load() {
        String nama = NbPreferences.forModule(ManajemenPenggunaPanel.class).get("nama", "");
        String sandi = NbPreferences.forModule(ManajemenPenggunaPanel.class).get("sandi", "");
        
        username.setText(nama);
        password.setText(sandi);
    }

Jalanin lagi deh.. Ntar text di sebelah “Pengguna” sama “Kata Sandi” bakal ada isinya…

Oke… Tapi isi yang kesimpen di option panel ini belum ada hubungannya sama modul login. Jadi… kita ubah codingan di modul “LoginModule”. Karena kemarin dibikin bagian pengecekan username sama sandi ada di method “authenticate” dari class Installer, jadi kita liat lagi method tersebut.

    private void authenticate(){
        String uname = lf.getUsername();
        char[] pwd = lf.getPass();
        if(uname.equals("Arby")){
           if(cekPwd(pwd)){
               
           }else{
               exit();
           }
        }else{
            exit();
        }
        
    }
    
    private boolean cekPwd(char[] input){
        boolean benar;
        char[] pass = {'p','e','s','a','n'};
        if(input.length != pass.length){
            benar = false;
        }else{
            benar = Arrays.equals(pass, input);
        }
        Arrays.fill(pass,'0');
        return benar;
    }

Bagian krusial ada di bagian warna merah. Kalo yang warna biru, itu method yang dipanggil sama baris kode warna merah kedua.

Di bagian merah pertama, ada pengecekan username. Dibandingin sama kata “Arby”. Karena kita udah punya pembanding lain, yaitu variable global yang kita simpen di kelas referensi “ManajemenPenggunaPanel” dengan nama “nama”. Sayangnya, “Installer” sama “ManajemenPenggunaPanel” ada di 2 module yang berbeda. Mereka harus dihubungin satu sama lain. Biar terhubung, ada yang nge-publish isinya, ada yang make isi module yang di-publish itu. Dan kalo kita liat lagi, module “Pengguna” yang ada kelas “ManajemenPenggunaPanel” ini lebih bersifat publisher, dan module “LoginModule” yang ada “Installer” cocok buat jadi pengguna sesuatu yang di-publish.

Jadi, klik kanan di module “Pengguna”. Pilih “Properties”, pilih API Versioning, dan centang di bagian “Public Packages”. Tekan OK.

10. Public Package Option Panel

Abis itu, klik kanan di bagian module “LoginModule”, Pilih Bagian “Libraries”. Di tab “Module Dependencies”, pilih “Add Dependency” (Langkah ini bisa kamu lakukan di bagian “Libraries” dari module di window tree project).

11. Module Dependency

Pilih module “Pengguna” dan tekan OK.

12. Dependency Pengguna

12. Dependency Pengguna-2

Kalo udah kayak di atas Module Dependencies dari LoginModule, artinya mereka udah saling mengenal. Yang LoginModule bisa pake module Pengguna. Tapi ada satu masalah lagi… class “ManajemenPenggunaPanel” gak bersifat public. Jadi class itu gak mungkin digunain di luar package terkait. Solusinya, tambahin keyword “public” pas ngedeklarasiin class “ManajemenPenggunaPanel”.

public final class ManajemenPenggunaPanel extends javax.swing.JPanel {

Kalo udah gini…. di method authenticate, bisa diubah jadi:

    private void authenticate(){
        String sNama = NbPreferences.forModule(ManajemenPenggunaPanel.class).get("nama","");
        String uname = lf.getUsername();
        char[] pwd = lf.getPass();
        if(uname.equals(sNama)){
           if(cekPwd(pwd)){
               
           }else{
               exit();
           }
        }else{
            exit();
        }
        
    }

Lihat kan??! Logikanya gampang… Ambil variable global yang udah tersimpan, cek username inputan user sama username dari variable global. Coba jalanin deh… Pasti kalo kamu masukin kayak gambar di bawah, aplikasinya gak bakal jalan.

13. Hasil Akhir

Karena username-nya udah berubah… Jadi “system”… sesuai yang diinput di option panel sebelumnya. Username udah berubah, berikutnya password. Pengecekan password, ada di method “cekPwd”. Jadi oprek2 ajah method itu. Gw ubah method nya jadi kayak gini:

    private boolean cekPwd(char[] input){
        boolean benar;
        String pwd = NbPreferences.forModule(ManajemenPenggunaPanel.class).get("sandi", "");
        char[] pass = pwd.toCharArray();
        if(input.length != pass.length){
            benar = false;
        }else{
            benar = Arrays.equals(pass, input);
        }
        Arrays.fill(pass,'0');
        return benar;
    }

Coba jalanin lagi… Pasti password yang benar udah bukan “pesan” lagi, tapi “arby”. Sesuai yang tersimpan di variable global.

Selesaaaaaiii~~~~

Valid: Hu um….
Kadaluarsa: Cuma dibuktiin buat netbeans 8.0
Sumber: Link di atas + dok. pribadi