Menyimpan Template simple-escp Di Database


Ada beberapa pengguna aplikasi yang sering kali ingin mengubah hasil percetakan di printer dari waktu ke waktu. Bila kode program percetakan disimpan di dalam aplikasi, ini berarti saya harus mengubah kode program setiap kali ada perubahan layout. Hal ini lama-lama bisa merepotkan! Oleh sebab itu, pada artikel Memakai simple-escp Di Griffon, saya mendefinisikan template percetakan dalam bentuk file JSON. Setiap kali ada yang ingin merubah layout percetakan, mereka bisa meng-edit file JSON ini sendiri tanpa harus menunggu saya.

Solusi di atas bekerja dengan baik bila template laporan terletak di server yang dipakai bersama (misalnya aplikasi web). Bagaimana dengan aplikasi desktop yang dikembangkan dengan menggunakan Griffon dan simple-jpa? Saya dapat menyimpan template JSON untuk simple-escp ke dalam database. Dengan demikian, perubahan template yang dibuat oleh satu pengguna tetap dapat dilihat dan dipakai oleh pengguna lainnya.

Sebagai contoh, saya bisa membuat sebuah entity untuk mewakili template simple-escp seperti berikut ini:

@DomainClass @Entity @Canonical
class TemplateFaktur {

    @NotBlank
    String nama

    @Lob
    String isi

}

Saya memakai annotation @Lob pada field isi untuk menandakan bahwa kolom tersebut dapat di-isi dengan banyak karaketer (large object type). Pada Hibernate JPA dan database MySQL Server, kombinasi ini akan menghasilkan field dengan tipe longtext yang dapat menampung hingga maksimum 4 GB karakter (bandingkan dengan VARCHAR yang menampung maksimal 255 karakter).

Untuk mencetak template simple-escp berdasarkan TemplateFaktur yang sudah disimpan di database, saya dapat menggunakan kode program seperti berikut ini:

TemplateFaktur template = findTemplateFakturByNama(model.nama)
JsonTemplate template = new JsonTemplate(template.isi)
PrintPreviewPane printPreviewPane = view.printPreviewPane
printPreviewPane.display(template, DataSources.from(model.dataSource, model.options))

Sekarang, saya perlu membuat sebuah MVC untuk mengedit template yang ada. Agar pengguna bisa lebih nyaman dalam meng-edit template, saya akan menggunakan groovy.ui.ConsoleTextEditor bawaan Groovy. ConsoleTextEditor mengandung sebuah JTextPane yang dilengkapi dengan syntax highlighting sehingga sangat berguna untuk menampilkan dokumen teks yang memiliki syntax seperti bahasa pemograman. Sebagai contoh, saya bisa mendefinisikan view seperti berikut ini:

actions {
    action(id: 'cari', name: 'Cari', closure: controller.cari)
    action(id: 'simpan', name: 'Simpan', closure: controller.simpan)
    action(id: 'reset', name: 'Reset', closure: controller.reset)
}

panel(id: 'mainPanel') {
    borderLayout()

    panel(constraints:PAGE_START) {
        flowLayout(alignment: FlowLayout.LEFT)
        comboBox(id: 'namaTemplateFaktur', model: model.namaTemplateFaktur)
        button(action: cari)
    }

    widget(new ConsoleTextEditor(), id: 'inputEditor', constraints: CENTER)

    panel(constraints: PAGE_END) {
        flowLayout(alignment: FlowLayout.LEFT)
        button(action: simpan)
        button(action: reset)
    }
}

Untuk menampilkan template dari database untuk di-edit, saya dapat menggunakan kode program seperti berikut ini di controller:

def cari = {
    execInsideUISync {
        String namaTemplateFaktur = model.namaTemplateFaktur.selectedItem
        if (namaTemplateFaktur) {
            String isi = findTemplateFakturBy(namaTemplateFaktur)?.isi
            TextEditor textEditor = view.inputEditor.textEditor
            DefaultStyledDocument doc = new DefaultStyledDocument()
            doc.setDocumentFilter(new SimpleEscpFilter(doc))
            doc.insertString(0, isi?: '', null)
            textEditor.setDocument(doc)
            textEditor.caretPosition = 0
        }
    }
}

Secara default, ConsoleTextEditor akan melakukan syntax highlighting berdasarkan format Groovy. Karena simple-escp memakai format yang berbeda, saya akan mendefinisikan sebuah DocumentFilter baru yang saya sebut sebagai SimpleEscpFilter yang isinya seperti berikut ini:

class SimpleEscpFilter extends StructuredSyntaxDocumentFilter {

    public static final String VARIABLES = /(?ms:${.*?})/
    public static final String FUNCTIONS = /(?ms:%{.*?})/
    public static final String CODE = /(?ms:{{.*?}})/

    SimpleEscpFilter(DefaultStyledDocument document) {
        super(document)

        StyleContext styleContext = StyleContext.getDefaultStyleContext()
        Style defaultStyle = styleContext.getStyle(StyleContext.DEFAULT_STYLE)

        Style variables = styleContext.addStyle(VARIABLES, defaultStyle)
        StyleConstants.setForeground(variables, Color.GREEN.darker().darker())
        getRootNode().putStyle(VARIABLES, variables)

        Style functions = styleContext.addStyle(FUNCTIONS, defaultStyle)
        StyleConstants.setForeground(functions, Color.BLUE.darker().darker())
        getRootNode().putStyle(FUNCTIONS, functions)

        Style code = styleContext.addStyle(CODE, defaultStyle)
        StyleConstants.setForeground(code, Color.MAGENTA.darker().darker())
        getRootNode().putStyle(CODE, code)
    }

}

StructuredSyntaxDocumentFilter adalah DocumentFilter bawaan Groovy yang melakukan syntax highlighting berdasarkan ekspresi Regex. Pada implementasi di atas, saya memberikan pewarnaan yang berbeda untuk setiap komponen dalam template simple-escp. Bila saya menjalankan program, saya akan memperoleh hasil seperti pada gambar berikut ini:

Tampilan editor

Tampilan editor

Bila pengguna men-klik tombol simpan, saya dapat menyimpan perubahan dengan kode program seperti berikut ini:

def simpan = {
    TemplateFaktur templateFaktur = findTemplateFakturByNama(namaTemplateFaktur)
    if (!templateFaktur) {
       templateFaktur = new TemplateFaktur(nama: model.namaTemplateFaktur.selectedItem)
       persist(templateFaktur)
    }
    templateFaktur.isi = view.inputEditor.textEditor.text
}

Sekarang, saya tidak perlu khawatir lagi harus men-deploy ulang aplikasi hanya karena perubahan kecil di layout percetakan. Bila pengguna tidak memiliki tim IT yang memahami syntax simple-escp, setidaknya saya masih bisa mengirim email berisi template yang sudah dimodifikasi untuk di-copy paste oleh mereka. Ini masih jauh lebih baik daripada harus men-deploy ulang aplikasi😀

Perihal Solid Snake
I'm nothing...

4 Responses to Menyimpan Template simple-escp Di Database

  1. SF© mengatakan:

    Gan, boleh nanya
    saya menggunakan simple Escp untuk mengeprint di printer epson, semua berjalan normal tetapi ketika coba memakai template jadi ada errornya :

    JsonTemplate jsonTemplate = new JsonTemplate(getClass().getResource(“/template.json”).toURI());

    dan exceptionnya :
    java.lang.NullPointerException
    at jampok.ui.IfCetalJournalToExcel.btCetakActionPerformed(IfCetalJournalToExcel.java:199)
    at jampok.ui.IfCetalJournalToExcel.access$100(IfCetalJournalToExcel.java:44)
    at jampok.ui.IfCetalJournalToExcel$2.actionPerformed(IfCetalJournalToExcel.java:81)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at com.jtattoo.plaf.BaseButtonListener.mouseReleased(BaseButtonListener.java:60)
    at java.awt.Component.processMouseEvent(Component.java:6516)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6281)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4872)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4698)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4698)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:740)
    at java.awt.EventQueue.access$300(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:699)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:713)
    at java.awt.EventQueue$4.run(EventQueue.java:711)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:710)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

    terima kasih atas bantuannya

    • Solid Snake mengatakan:

      Coba pastikan file bernama template.json sudah dibuat dan terletak di posisi root package. Coba pastikan getClass().getResource("/template.json") tidak mengembalikan nilai null, misalnya dengan mencoba melalui debugger.

      • SF© mengatakan:

        saya sudah membuat file template.json pada root package, gimana cara mendapatkan file tersebut, kenapa selalu null ya

        ini contoh codenya
        Template template = new JsonTemplate(Main.class.getResourceAsStream(“/template.json”));
        String hasil = new FillJob(template.parse()).fill();

        apakah ada yang salah di kode saya, mohon bantuannya

        • Solid Snake mengatakan:

          Ada beberapa kemungkinan.. Bila memakai NetBeans, semua file bukan *.java di folder src tidak akan disertakan di JAR yang dihasilkan. Oleh sebab itu, bila memakai NetBeans, file template harus diletakkan di folder resources (NetBeans tetap akan menyatukannya ke dalam 1 jar dengan hierarki yang sama walaupun folder-nya terpisah di proyek). Selain itu, bila masih belum berhasil, coba ganti /template.json menjadi template.json.

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: