Beberapa catatan penting tentang JSP


Mungkin ini hanya sekelumit sharing tentang pengalaman saya menggunakan J2EE, terutama jsp. Walaupun sederhana, namun saya ingin menuliskan di sini sekaligus sebagai dokumentasi saya. Pertama, jsp sepertinya sangat sensitif dengan karakter whitespace. Jika kita mengembalikan dokumen teks (html, json, dsb.) mungkin tidak menimbulkan masalah. Namun ketika kita mengembalikan objek biner, seperti gambar, maka sebelum pengiriman array byte ke browser, kita perlu memastikan bahwa dalam satu file jsp kita tidak ada whitespace yang muncul sebelum pengiriman tersebut. Untuk memastikan ini, maka kita dapat menambahkan elemen jsp-config pada file web.xml kita. Berikut contohnya:


<jsp-config>
 <jsp-property-group>
 <url-pattern>*.jsp</url-pattern>
 <trim-directive-whitespaces>true</trim-directive-whitespaces>
 </jsp-property-group>
 </jsp-config>

Kedua, sebaiknya kita sediakan halaman khusus yang menampilkan pesan kesalahan HTTP maupun Exception yang terjadi dari aplikasi jsp/servlet. Untuk menyediakan ini, maka pada file web.xml perlu ditambahkan elemen berikut:

    <error-page>
        <error-code>404</error-code>
        <location>/pagenotfound.jsp</location>
    </error-page>
    <error-page>
        <exception-type>java.lang.Exception</exception-type>
        <location>/error.jsp</location>
    </error-page>

Pada contoh di atas, untuk kesalahan 404, maka akan ditampilkan halaman bernama pagenotfound.jsp. Sedangkan jika terjadi Exception dari Java Runtime, maka akan dibukan file error.jsp.

Iklan

java.lang.IllegalStateException: getOutputStream() has already been called for t his response


Kesalahan atau exception tersebut selalu saya peroleh ketika dari servlet yang saya buat mengembalikan sebuah dokumen SWF. Potongan program servlet yang saya gunakan untuk mengembalikan dokumen SWF adalah sebagai berikut :

response.setContentType("application/x-shockwave-flash");
response.setContentLength(baos.size());
response.setHeader("Content-Disposition", "inline; filename=\"test.swf\"");

ServletOutputStream outs = response.getOutputStream();
baos.writeTo(outs);
outs.flush();

baos adalah objek bertipe ByteArrayOutputStream.

Sayapun akhirnya menjelajah ke forum-forum yang ada, sampai akhirnya saya menemukan sedikit pencerahan untuk mengubah urutan baris programnya sebagai berikut :

ServletOutputStream outs = response.getOutputStream();
response.reset();
response.setContentType("application/x-shockwave-flash");
response.setContentLength(baos.size());
response.setHeader("Content-Disposition", "inline; filename=\"test.swf\"");

baos.writeTo(outs);
outs.flush();
outs.close();

Jadi ternyata, pemanggilan getOutputStream() sebaiknya dilakukan sebelum pengiriman header HTTP dan isi dari file yang akan kita kirim ke client. Metode reset() kita panggil untuk memastikan servlet membersihkan buffer sekaligus kondisi buffer saat ini. Jika saat reset() di jalankan, dan ternyata buffer response sudah dalam keadaan ter-commit, maka J2EE akan mengembalikan kesalahan IllegalStateException. Agak membingungkan memang. Dan semoga dengan perubahan ini tidak sesering mengembalikan kesalahan seperti pada judul saya di atas.