Ouertani Slim was born in Tunisia in 1981. Now he is a software engineer since 2004 and he is Java 6 and Spring certified with 100% and 94% respectively. He is very interested in Java technology, Scala and open source projects. He believes that programming is one of the hardest jobs and most beautiful in the world. Slim has posted 32 posts at DZone. You can read more from them at their website. View Full User Profile

Basic MDB with Scala, Sbt and JEE 6

09.11.2011
| 5707 views |
  • submit to reddit
While I am an Akka fan, and a Typesafe follower, in this post I will continue presenting scala on the JEE 6 environment and introduce basic message driven beans (MDB ) using scala language.

As an example let’s take a simple MDB that will consome operation commands like add and substract and my be asked to replay by the result

I- Exchange API
sealed trait TOperation
case class Add(x:Int) extends  TOperation
case class Sub(x:Int) extends TOperation
case class Sum extends TOperation
case class Count(x:Int) extends TOperation
II- The listener

The object

object MDbListener {
  var count = 0
  val L = Logger.getLogger(classOf[MDbListener])
}

 

The class 
@MessageDriven(
  messageListenerInterface=classOf[MessageListener],
  mappedName = "jms/toMdb",
  activationConfig = Array(
    new ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    new ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")))
class MDbListener extends MessageListener {

  import MDbListener._

  override def onMessage(message: Message) {
    L.debug("Message Received")

    message match {
      case o: ObjectMessage => {
          try {
            val obj = o.getObject()
            obj match {
              case action: TOperation => handle(action)
              case _ => L.warn("Unkownen msg")
            }
          } catch {
            case ex: Exception => L.error(">>> Exception", ex)
          }

        }
      case _ => L.warn("unknown msg")
    }
  }

  def handle(op: TOperation ) = op match {/* TODO */
  }
}
 

Nothing special here but be careful to not forget adding messageListenerInterface=classOf[MessageListener] on MessageDriven annotation.  This is because of ScalaObject super class and that’s all for the listener.

III- The sender

The handle method will do mathematical operations and can be requested to send the sum to another JMS Queue.

def handle(op: TOperation ) = op match {
    case   Add(x) => count +=x
    case   Sub(x) => count -=x
    case   s:Sum =>  sendJMSMessageToTt( Count (count))
    case   c:Count => L.warn ("Wrong message destination!")
  }

Very easy with pattern matching!

The sendJmsMessageToIt method can be done like the following

 

 @Resource(mappedName = "jms/Rep")
  var  queue :Queue=_
  @Resource(mappedName = "jms/RepFactory")
  var  factory:ConnectionFactory=_

  private [ws ] def sendJMSMessageToTt( messageData:Count)  {
    def  createJMSMessageForjmsTt( session:Session,  messageData:Count):Message={
      val om = session.createObjectMessage()
      om.setObject(messageData)
      om
    }

    def tryWith[A<%{ def close()}](ac :A)(f: A=> Unit)
    {
      try {f} finally { ac.close }
    }

    tryWith(factory.createConnection()){
      connection => tryWith(connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
        	session =>  tryWith( session createProducer queue ){
          		messageProducer => messageProducer.send(createJMSMessageForjmsTt(session, messageData))
        }
      }
    }
  }

Here we used an old trick to manage resources : http://ouertani.com/2010/12/scala-try-with-resources/

Published at DZone with permission of its author, Slim Ouertani.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)