Sunday, April 19, 2009

Message-Driven Bean

Message-Driven Bean (MDB) adalah komponen EJB yang digunakan untuk berhubungan dengan asynchronous message sebagai consumer. MDB dikelola menggunakan pooling. Segera setelah message tiba di destination, container mengambil sebuah MDB dari pool untuk meng-handle-nya. Tidak seperti session bean, MDB tidak memiliki remote atau local business interface. MDB bisa digunakan untuk berbagai macam messaging teknologi seperti JMS dan JCA. MDB yang digunakan bersama JMS harus implements interface MessageListener (ingat interface yang punya method onMessage pada JMS?). Sama seperti stateless session bean, MDB memiliki dua callback method yaitu PostConstruct yang dipanggil setelah MDB dibuat, dan PreDestroy yang dipanggil sebelum MDB dihapus dari pool untuk didestroy. Pada MDB, kita biasanya tidak secara eksplisit menangani transaksi, melainkan kita menyerahkan urusan tersebut kepada container. Secara default, container memulai transaksi sebelum method onMessage dipanggil dan mengakhiri transaksi saat onMessage berakhir atau terjadi rollback melalui MessageDrivenContext.

Perhatikan contoh MDB berikut :

public class MessageReceiverMDB implements MessageListener {
@Resource
private MessageDrivenContext context;

public void onMessage(Message message) {
try {
ObjectMessage objectMessage = (ObjectMessage)message;
ShippingRequest shippingRequest = (ShippingRequest)objectMessage.getObject();
System.out.println(shippingRequest);
} catch (Exception e) {
e.printStackTrace();
context.setRollbackOnly();
}
}
}

Bagaimana jadinya jika message yg dikirim bukan bertipe ObjectMessage? Code di atas akan gagal dan melakukan rollback. Rollback berarti message yang sudah diambil akan dikembalikan ke destination (queue/topic). Dan selanjutnya MDB akan berusaha mengambil message tersebut lagi, kemudian gagal lagi. Maka terjadi looping yang terus menerus mengalami kegagalan yang sama. Karena itu sebaiknya pada onMessage tidak dilakukan rollback message sehingga method di atas sebaiknya menjadi :

public class MessageReceiverMDB implements MessageListener {
public void onMessage(Message message) {
try {
ObjectMessage objectMessage = (ObjectMessage)message;
ShippingRequest shippingRequest = (ShippingRequest)objectMessage.getObject();
System.out.println(shippingRequest);
} catch (Exception e) {
e.printStackTrace();
}
}
}

Hal yang sama juga bisa terjadi jika kita tidak mendesain exception-handling dengan baik. Perhatikan code berikut :

public class MessageReceiverMDB implements MessageListener {
public void onMessage(Message message) {
try {
ObjectMessage objectMessage = (ObjectMessage)message;
ShippingRequest shippingRequest = (ShippingRequest)objectMessage.getObject();
System.out.println(shippingRequest);
} catch (JMSException e) {
e.printStackTrace();
}
}
}

Bagaimana jika terjadi exception selain JMSException? Misalnya RuntimeException, RemoteException, atau EJBException. Method onMessage di atas akan melempar exception yang tidak di-handling. Dan exception yang tidak di-handling menyebabkan transaction rollback. Jika transaction rollback, maka looping yang terus menerus mengalami kegagalan akan terus terjadi. Karena itu sebaiknya onMessage tidak melempar exception, sehingga kode di atas sebaiknya kembali menjadi :

public class MessageReceiverMDB implements MessageListener {
public void onMessage(Message message) {
try {
ObjectMessage objectMessage = (ObjectMessage)message;
ShippingRequest shippingRequest = (ShippingRequest)objectMessage.getObject();
System.out.println(shippingRequest);
} catch (Exception e) {
e.printStackTrace();
}
}
}

0 comments:

 

©2009 Stay the Same | by TNB