<?xml version="1.0"?>
<rss version="2.0">
<channel>
  <title>The Kitchen in the Zoo</title>
  <link>http://blog.maxant.co.uk:80/pebble/</link>
  <description>&lt;small&gt;A blog where Ant writes about anything he finds interesting! &lt;a href=&#039;http://www.linkedin.com/in/maxant&#039;&gt;&lt;font color=&#039;white&#039;&gt;Who is Ant?&lt;/font&gt;&lt;/a&gt;      &lt;a href=&#039;/pebble/pages/copyright.html&#039;&gt;&lt;font color=&#039;white&#039;&gt;Copyright 2005-2013 Ant Kutschera&lt;/font&gt;&lt;/a&gt;&lt;/small&gt;</description>
  <language>en</language>
  <copyright>Ant Kutschera</copyright>
  <lastBuildDate>Wed, 03 Oct 2012 22:16:00 GMT</lastBuildDate>
  <generator>Pebble (http://pebble.sourceforge.net)</generator>
  <docs>http://backend.userland.com/rss</docs>
  
  
  <item>
    <title>Play 2.0 framework and XA transactions</title>
    <link>http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html</link>
    
      
        <description>
          &lt;p&gt;XA&amp;nbsp;transactions are useful and out of the box, Play 2.0 today does not have support for them.&amp;nbsp; Here I&amp;nbsp;show how to add that support:&lt;/p&gt;
&lt;p&gt;First off, some examples when XA is useful:&lt;br /&gt;
&lt;br /&gt;
- JPA uses two physical  connections if you use entities from two different persistence.xml -  those two connections might need to be committed in one transaction, so  XA is your only option&lt;br /&gt;
- Committing a change in a database and at the  same time committing a message to JMS.&amp;nbsp; E.g. you want to guarantee that  an email is sent after you successfully commit an order to the  database, asynchronously.&amp;nbsp; There are other ways, but JMS provides a  transactional way to do this with little overhead in having to think  about failure.&lt;br /&gt;
- Writing to a physically different database because  of any of several political reasons (legacy system, different department  responsible for different database server / different budgets).&lt;br /&gt;
- See &lt;a href=&#034;http://docs.codehaus.org/display/BTM/FAQ#FAQ-WhywouldIneedatransactionmanager&#034; target=&#034;_blank&#034;&gt;http://docs.codehaus.org/&lt;wbr&gt;&lt;/wbr&gt;display/BTM/FAQ#FAQ-&lt;wbr&gt;&lt;/wbr&gt;WhywouldIneedatransactionmanag&lt;wbr&gt;&lt;/wbr&gt;er&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
So the way I see it, XA is something Play needs to &amp;quot;support&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Adding  support is very easy.&amp;nbsp; I have created a play plugin which is based on  Bitronix.&amp;nbsp; Resources are configured in the Bitronix JNDI tree (why on  earth does Play use a config file rather than JNDI?! anyway...)&amp;nbsp; You  start the transaction like this, &amp;quot;withXaTransaction&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def someControllerMethod = Action {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; withXaTransaction { ctx =&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;TicketRepository.&lt;/em&gt;&lt;/p&gt;
&lt;div&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;addValidation(user.get, bookingRef, ctx)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;ValidationRepository.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;addValidation(bookingRef, user.get, ctx)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; val tickets = TicketRepository.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;getByEventUid(eventUid)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Ok(views.html.ticketsInEvent(&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;eventUid, getTickets(eventUid), user, eventValidationForm))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&lt;/em&gt;The  ctx object is an XAContext (my own class) which lets you look up  resources like a datasource, or set rollback in case of a failure.&amp;nbsp; So  the validation repo does this, using ScalaQuery (I used &amp;quot;withSession&amp;quot;  rather than &amp;quot;withTransaction!&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def addValidation(bookingRef: String, validator: User, ctx: XAContext) = {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val ds = ctx.lookupDS(&amp;quot;jdbc/maxant/&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;scalabook_admin&amp;quot;)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Database.forDataSource(ds) withSession { implicit db: Session =&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Validations.insert(Validation(&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;bookingRef, validator.email, new java.sql.Timestamp(now)))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&lt;/em&gt;&lt;br /&gt;
And the ticket repo does the following with JMS:&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def addValidation(user: User, bookingRef: String, ctx: XAContext) = {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; val xml = &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ticketValidation&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;bookingReference&amp;gt;{bookingRef}&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;&amp;lt;/bookingReference&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;validatorId&amp;gt;{user.email}&amp;lt;/&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;validatorId&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/ticketValidation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val qcf = ctx.lookupCF(&amp;quot;jms/maxant/&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;scalabook/ticketvalidations&amp;quot;)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val qc = qcf.createConnection(&amp;quot;&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;ticketValidation&amp;quot;,&amp;quot;password&amp;quot;)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val qs = qc.createSession(false, Session.AUTO_ACKNOWLEDGE)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val q = qs.createQueue(&amp;quot;&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;ticketValidationQueue&amp;quot;) //val q = ctx.lookup(QUEUE).&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;asInstanceOf[Queue]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val sender = qs.createProducer(q)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val m = qs.createTextMessage(xml.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;toString)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; sender.send(m)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; sender.close&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; qs.close&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; qc.close&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&lt;/em&gt;&lt;br /&gt;
I&#039;ve  tested it with writing to MySQL and sending a JMS message to JBoss  (HornetQ) and it seems to work well (except getting hornetQ to play with Bitronix was a bitch - see here: &lt;a href=&#034;https://community.jboss.org/thread/206180?tstart=0&#034; target=&#034;_blank&#034;&gt;https://community.jboss.org/&lt;wbr&gt;&lt;/wbr&gt;thread/206180?tstart=0&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
The scala code for the XA support is:&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;package ch.maxant.scalabook.play20.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;plugins.xasupport&lt;br /&gt;
&lt;br /&gt;
import play.api.mvc.RequestHeader&lt;br /&gt;
import play.api.mvc.Results&lt;br /&gt;
import play.api.mvc.Request&lt;br /&gt;
import play.api.mvc.AnyContent&lt;br /&gt;
import play.api.mvc.Result&lt;br /&gt;
import play.api.mvc.Action&lt;br /&gt;
import play.api.mvc.Security&lt;br /&gt;
import play.api._&lt;br /&gt;
import play.api.mvc._&lt;br /&gt;
import play.api.data._&lt;br /&gt;
import play.api.data.Forms._&lt;br /&gt;
import ch.maxant.scalabook.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;persistence.UserRepository&lt;br /&gt;
import bitronix.tm.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;TransactionManagerServices&lt;br /&gt;
import java.util.Hashtable&lt;br /&gt;
import javax.naming.Context._&lt;br /&gt;
import javax.naming.InitialContext&lt;br /&gt;
import javax.sql.DataSource&lt;br /&gt;
import bitronix.tm.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;BitronixTransaction&lt;br /&gt;
import java.io.File&lt;br /&gt;
import org.scalaquery.session.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;Database&lt;br /&gt;
import org.scalaquery.SQueryException&lt;br /&gt;
import scala.collection.mutable.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;ListBuffer&lt;br /&gt;
import java.sql.Connection&lt;br /&gt;
import java.sql.SQLException&lt;br /&gt;
import org.scalaquery.session.Session&lt;br /&gt;
import bitronix.tm.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;BitronixTransactionManager&lt;br /&gt;
import javax.jms.ConnectionFactory&lt;br /&gt;
&lt;br /&gt;
class XAContext {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private val env = new Hashtable[String, String]()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; env.put(INITIAL_CONTEXT_&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;FACTORY, &amp;quot;bitronix.tm.jndi.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;BitronixInitialContextFactory&amp;quot;&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private val namingCtx = new InitialContext(env);&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; var rollbackOnly = false&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; def lookup(name: String) = {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; namingCtx.lookup(name)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; def lookupDS(name: String) = {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; lookup(name).asInstanceOf[&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;DataSource]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; def lookupCF(name: String) = {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; lookup(name).asInstanceOf[&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;ConnectionFactory]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
trait XASupport { self: Controller =&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private lazy val tm = play.api.Play.current.plugin[&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;XASupportPlugin] match {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case Some(plugin) =&amp;gt; &lt;/em&gt;&lt;a href=&#034;http://plugin.tm&#034; target=&#034;_blank&#034;&gt;&lt;em&gt;plugin.tm&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  case None =&amp;gt; throw new Exception(&amp;quot;There is no XASupport plugin  registered. Make sure it is enabled. See play documentation. (Hint: add  it to play.plugins)&amp;quot;)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; /**&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Use this flow control to make resources used inside `f` commit with the XA protocol.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Conditions: get resources like drivers or connection factories out of the context passed to f.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Connections are opened and closed as normal, for example by the withSession flow control offered &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * by ScalaQuery / SLICK.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; def withXaTransaction[T](f: XAContext =&amp;gt; T): T = {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; tm.begin&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;  &amp;nbsp;&amp;nbsp;&amp;nbsp; //get a ref to the transaction, in case when we want to commit we  are no longer on the same thread and TLS has lost the TX.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //we have no idea what happens inside f!&amp;nbsp; they might spawn new threads or send work to akka asyncly&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val t = tm.getCurrentTransaction&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Logger(&amp;quot;XASupport&amp;quot;).info(&amp;quot;&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;Started XA transaction &amp;quot; + t.getGtrid())&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val ctx = new XAContext()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; var completed = false&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; try{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val result = f(ctx)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; completed = true&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!ctx.rollbackOnly){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Logger(&amp;quot;XASupport&amp;quot;).info(&amp;quot;&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;committing &amp;quot; + t.getGtrid() + &amp;quot;...&amp;quot;)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; t.commit&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Logger(&amp;quot;XASupport&amp;quot;).info(&amp;quot;&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;committed &amp;quot; + t.getGtrid())&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; result&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }finally{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; if(!completed || ctx.rollbackOnly){&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //in case of exception, or in case of set rollbackOnly = true&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Logger(&amp;quot;XASupport&amp;quot;).warn(&amp;quot;&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;rolling back (completed=&amp;quot; + completed + &amp;quot;/ctx.rollbackOnly=&amp;quot; + ctx.rollbackOnly)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; t.rollback&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class XASupportPlugin(app: play.Application) extends Plugin {&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; protected[plugins] var tm: BitronixTransactionManager = null&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; override def onStart {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //TODO how about getting config out of jar!&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val file = new File(&amp;quot;.&amp;quot;, &amp;quot;app/bitronix-default-config.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;properties&amp;quot;).getAbsolutePath&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Logger(&amp;quot;XASupport&amp;quot;).info(&amp;quot;&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;Using Bitronix config at &amp;quot; + file)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; val prop = System.getProperty(&amp;quot;bitronix.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;tm.configuration&amp;quot;, file) //default&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; System.setProperty(&amp;quot;bitronix.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;tm.configuration&amp;quot;, prop) //override with default, if not set&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //start the TM&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; tm = TransactionManagerServices.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;getTransactionManager&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Logger(&amp;quot;XASupport&amp;quot;).info(&amp;quot;&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;Started TM with resource config &amp;quot; + TransactionManagerServices.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;getConfiguration.&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;getResourceConfigurationFilena&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;me)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; override def onStop {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; //on graceful shutdown, we want to shutdown the TM too&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Logger(&amp;quot;XASupport&amp;quot;).info(&amp;quot;&lt;/em&gt;&lt;wbr&gt;&lt;/wbr&gt;&lt;em&gt;Shutting down TM&amp;quot;)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; tm.shutdown&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Logger(&amp;quot;XASupport&amp;quot;).info(&amp;quot;TM shut down&amp;quot;)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&lt;br /&gt;
}&lt;/em&gt;&lt;br /&gt;
&lt;br /&gt;
Use the code as you like, I&#039;m giving it away for free :-)&amp;nbsp; Just don&#039;t complain if it don&#039;t work ;-)&lt;br /&gt;
&lt;br /&gt;
It  would be nice to see this plugin extended and turned into something a  little more production ready.&amp;nbsp; Even nicer would be for Play to support a  transaction manager natively, including fetching resources out of JNDI.&lt;br /&gt;
&lt;br /&gt;
Have fun!&lt;/div&gt;
&lt;p&gt;(copyright Ant Kutschera 2012)&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&amp;amp;title=Play+2.0+framework+and+XA+transactions&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&amp;amp;title=Play+2.0+framework+and+XA+transactions&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&amp;amp;title=Play+2.0+framework+and+XA+transactions&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&amp;amp;title=Play+2.0+framework+and+XA+transactions&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&amp;amp;title=Play+2.0+framework+and+XA+transactions&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&amp;amp;title=Play+2.0+framework+and+XA+transactions&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&amp;amp;t=Play+2.0+framework+and+XA+transactions&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&amp;amp;title=Play+2.0+framework+and+XA+transactions&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html&amp;amp;t=Play+2.0+framework+and+XA+transactions&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2012/10/04/1349302560000.html</guid>
    <pubDate>Wed, 03 Oct 2012 22:16:00 GMT</pubDate>
  </item>
  
  <item>
    <title>Hacking Maven</title>
    <link>http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html</link>
    
      
        <description>
          &lt;p&gt;We don&#039;t use M2Eclipse to integrate Maven and Eclipse, partly because we had some bad experiences a couple of years ago when we were still using Eclipse 3.4 and partly because some of our developers use IBMs RAD to develop, and it doesn&#039;t  (or at least wasn&#039;t) compatible.  Our process is to update our local sources from SVN and then to run  Maven&#039;s eclipse:eclipse locally with the relevant workspace setting so that our .project and .classpath files are generated, based on the dependencies and other information in the POMs.  It works well enough, but the plan is indeed to move to M2Eclipse at some stage soon. &lt;br /&gt;
&lt;br /&gt;
We have parent POMs for each sub-system (each of which is made of several Eclipse projects).   Some of us pull multiple sub-systems into our workspaces which is useful when you refactor  interfaces between sub-systems, because Eclipse can refactor the code which calls the   interfaces at the same time as you refactor the interfaces, saving lots of work.  Maven generates  .classpath files for Eclipse which reference everything in the workspace as a source projet rather than a  JAR out of the local Maven repo.  That is important because if Maven created JAR references and not project references, Eclipse&#039;s refactoring wouldn&#039;t adjust the code calling the refactored code. &lt;br /&gt;
&lt;br /&gt;
10 days ago we switched from a build process based on continuum and archiva to jenkins and nexus.  All of a sudden we lost some of the source references which were replaced with JAR references.  If a project was referred to in a parent POM then it was referenced as a project in Eclipse, but if it was a sub-system built using a second parent POM, then Eclipse was referring to the project as a JAR from the local Maven repo.  That was bad news for our refactoring!  Here is an example of what used to happen:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;subsystem-a-project-1&lt;/code&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;subsystem-a-project-2&lt;/code&gt; references subsystem-a-project-1 as a project&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;subsystem-b-project-1&lt;/code&gt; references subsystem-a-project-1 as a &lt;b&gt;project&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is what was happening when we used Jenkins and Nexus:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;subsystem-a-project-1&lt;/code&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;subsystem-a-project-2&lt;/code&gt; references subsystem-a-project-1 as a project&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;subsystem-b-project-1&lt;/code&gt; references subsystem-a-project-1 as a &lt;b&gt;JAR!!!&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
At the same time as moving to Jenkins and Nexus, we upgraded a few libraries and our organisational POM.  We also moved our parent POMs from the root directory of the sub-system into a project for the parent (in preparation for using M2Eclipse which prefers having the parent POM in the workspace).&lt;br /&gt;
&lt;br /&gt;
The question was, where do we start looking?  Some people suggested it was because we&#039;d moved the parent POM, others thought it was because we&#039;d updated a version of a library on which eclipse:eclipse might have a dependency and others were of the opinion we had to return to Continuum and Archiva.&lt;br /&gt;
&lt;br /&gt;
One of our sharp eyed developers noticed that we were getting the following output on the command line during the local Maven build:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;Artifact subsystem-a-project-1 already available as a workspace project, but with different version...&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
That was the single find which led to us solving the problem quickly.  I downloaded the source of eclipse:eclipse from Maven central, under org/apache/maven/plugins/maven-eclipse-plugin.  I created a dummy Java project in Eclipse.  Next, I added the following environment variable to my command line from where I run Maven:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;set MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=28000&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
That tells the JRE to open a debug port and wait until a debugger is connected before running the app.  Running a Java program with those args makes it output &amp;quot;&lt;code&gt;Listening for transport dt_socket at address: 28000&lt;/code&gt;&amp;quot;.  In Eclipse I went to the debug run configurations and added a remote connection at localhost on port 28000.  It needs a project, so I added the dummy project I&#039;d just created.  I connected and Maven continued to run now that I was connected.  The next step was to add the Maven Plugin source code which I&#039;d downloaded from Maven Central. By right clicking on the debug view in the debug perspective (click on the tree), it is possible to add/update source attachments, and I added the sources JAR that I&#039;d downloaded.  The last bit was to find a suitable breakpoint.  I extracted the sources from the downloaded ZIP and searched the files for the text which was being output by Maven which was hinting at the problem (&amp;quot;already available as a workspace project&amp;quot;).  &lt;code&gt;EclipsePlugin&lt;/code&gt; was the suspect class!&lt;br /&gt;
&lt;br /&gt;
I added the eclipse:eclipse JAR to my dummy project so that I could open the class in Eclipse using ctrl+shift+t.  Eclipse opened the class, but hadn&#039;t worked out that the source from the source attachment belongs to that class.  There is a button in the editor to attach the source by locating the JAR downloaded from Maven Central and Eclipse then showed the source code and I was able to add a breakpoint.  By this time Maven had finished, so I restarted it and this time I hit the breakpoint, and the problem became quite clear.  For some reason, rather than the version being a simple SNAPSHOT version, it contained a timestamp.  The eclipse:eclipse plugin was of the opinion that I didn&#039;t have the correct code in the workspace, and so rather than create a project reference, it created a JAR reference based on the JAR in the local Maven repo.&lt;br /&gt;
&lt;br /&gt;
The internet is full of information about how Maven3 now uses unqiue timestamps for each build artefact deployed to the repo.  There were some references saying you could disable it for Maven2 (which we still use), but when you move to Maven3 you can&#039;t disable it.  I thought about submitting a bug report to Codehaus (who supplies the eclipe:eclipse plugin), but it occurred to me that we were still referencing version 2.8 in our organisational POM and I&#039;d spotted a 2.9 version when I was at Maven Central.  So I updated the organisational POM to use version 2.9 of eclipse:eclipse and gave that a shot.&lt;br /&gt;
&lt;br /&gt;
Hooray!  23:17 and I&#039;d fixed our problem.  Shame I had a 06:30 start the next day for a meeting :-/&lt;br /&gt;
&lt;br /&gt;
This isn&#039;t the first time that we&#039;ve made the mistake of doing too much in a migration.  We could have stuck with Continuum and Archiva when we updated our org-POM, and then step for step migrated to Nexus (still using Archiva) and then finally moved over to Nexus.  Had we done that, we might not have had the problems we did; but the effort of a slow migration might also have been larger.&lt;br /&gt;
&lt;br /&gt;
For me, the point to take away is that it easier to debug maven and go straight to the source of the problem, than it is to attempt to fix the problem by trail and error, as we were doing before I debugged Maven.  Debugging Maven might sound like it&#039;s advanced or complicated, but it&#039;s damn fun - it&#039;s real hacking and the feeling of solving a puzzle in this way makes the effort worth it.  I fully recommend it if for no other reason that you get exposed to reading other peoples (open source) code.&lt;br /&gt;
&lt;br /&gt;
Copyright &amp;copy; 2012, Ant Kutschera &lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&amp;amp;title=Hacking+Maven&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&amp;amp;title=Hacking+Maven&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&amp;amp;title=Hacking+Maven&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&amp;amp;title=Hacking+Maven&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&amp;amp;title=Hacking+Maven&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&amp;amp;title=Hacking+Maven&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&amp;amp;t=Hacking+Maven&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&amp;amp;title=Hacking+Maven&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html&amp;amp;t=Hacking+Maven&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2012/05/10/1336680420000.html</guid>
    <pubDate>Thu, 10 May 2012 20:07:00 GMT</pubDate>
  </item>
  
  <item>
    <title>100% code coverage, Hibernate Validator and Design by Contract</title>
    <link>http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html</link>
    
      
        <description>
          Code coverage in unit testing was one of the first things I learned in my software engineering career.  The company I worked at taught me that you should have 100% coverage as a goal, but achieving it does not mean there are no bugs in the system.  At that time, I worked at a company whose big thing was that they delivered &lt;i&gt;very reliable&lt;/i&gt; billing software to telecomms operators.  We used to invest as much time writing unit tests as we did writing the code.  If you included unit tests, integration tests, system tests and acceptance tests, more time was spent testing than designing and implementing the code which ran in production.  It was impressive and I have never worked with or for a company with that kind of model since, although I am sure there are many companies which operate like that.&lt;br&gt;
&lt;br&gt;
The other day I was thinking back to those days and reading up about unit testing to refresh myself in preparation for a unit testing course I&#039;m attending soon (don&#039;t want the instructor to know more than me!) and I started to wonder about what kind of code could be fully covered during unit testing, but which could still contain a bug.  While I learned that 100% coverage should be the goal, in over 10 years I have never worked on a project which achieved that.  So I have never surprised to find a bug in code which I thought was &#034;fully&#034; tested.&lt;br&gt;
&lt;br&gt;
It&#039;s fun write whacky code - you don&#039;t normally try and write bugs :-)  I started with the specification:&lt;br&gt;
&lt;br&gt;
&lt;tt&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* @return String &#034;a&#034; or &#034;b&#034; depending upon the values&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* passed to the init method. If variable &#034;a&#034; is true,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* then string &#034;a&#034; is returned. If variable &#034;b&#034; is true,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* then &#034;b&#034; is returned. If neither is true, then &#034;&#034; is&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* returned. Variable &#034;b&#034; is important than &#034;a&#034;, so if&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* both are true then return &#034;b&#034;.&lt;br&gt; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br&gt;
&lt;/tt&gt;
&lt;br&gt;
Now, the tricky part was to write code which contained a bug yet was easy to cover with incomplete tests.  I came up with the following. The specification above is for the &#034;getResult()&#034; method.&lt;br&gt;
&lt;br&gt;
&lt;tt&gt;
public class SomeClass {&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private boolean a;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private boolean b;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public SomeClass init(boolean a, boolean b) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.a = a;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.b = b;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return this;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public String getResult() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String s = &#034;&#034;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(a) {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;s = &#034;a&#034;;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(b){&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;s += &#034;b&#034;; // &lt;-- oops!&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return s;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;br&gt;
&lt;/tt&gt;
&lt;br&gt;
The &#034;bug&#034; is in the method &#034;getResult&#034; and the problem is that instead of just an assignment, the &#034;plus equals&#034; operator has been used.  An &#034;else&#034; would probably make the code a little safer too.  But I think code like this is quite typical of the buggy code that finds its way into productive systems.  Even the best programmers have lapses of concentration where they write typos like this (especially in open plan offices!).&lt;br&gt;
&lt;br&gt;
The unit test which a programmer trying to achieve 100% coverage, would look something like this:&lt;br&gt;
&lt;br&gt;
&lt;tt&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Test&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void test() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertEquals(&#034;a&#034;, new SomeClass().init(true, false).getResult());&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertEquals(&#034;b&#034;, new SomeClass().init(false, true).getResult());&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;/tt&gt;
&lt;br&gt;
Using &lt;a href=&#039;http://www.eclemma.org/&#039; target=&#039;_blank&#039;&gt;Emma for Eclipse&lt;/a&gt; I measured complete coverage.  But wait!  There is still a bug.  The code does not do what it says in the Javadoc spec.  If I initialise the object with &#034;true, true&#034;, then the result will be &#034;ab&#034;, because of the &#034;plus equals&#034; operator.  &lt;i&gt;So even though I have 100% coverage, I still have a bug.&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
I asked myself what that means to me as a programmer.  What do I need to look out for, when writing tests.  Imagine the code above was tucked away among hundereds of other lines of code, then the chances of seeing it are really quite small.  The test wouldn&#039;t be just two lines long and the problem wouldn&#039;t be jumping out of the page.&lt;br&gt;
&lt;br&gt;
One way to look at the problem is to say that there is a bug because the code isn&#039;t fulfilling its contract.  OK, I use &#034;contract&#034; in the loose sense of the word, but the Javadoc is basically a contract.  It tells anyone calling that method what to expect, yet the codes is not doing what the user expects.&lt;br&gt;
&lt;br&gt;
So perhaps one solution is to not only entirely exercise the code, but entirely exercise the contract?  Is there a way to translate the Javadoc contract into something more concrete which the testing tools can help me check?  Yes, namely my using some kind of Design (or Program) by Contract (DBC or PBC) framework.  &lt;a href=&#039;http://jcp.org/en/jsr/detail?id=303&#039; target=&#039;_blank&#039;&gt;JSR-303&lt;/a&gt; isn&#039;t strictly DBC, but close.  It lets you use annotations to state your expectations about parameters passed to methods, as well as your expectation about the result being returned.  You can &lt;a href=&#039;http://docs.jboss.org/hibernate/validator/4.0.1/reference/en/html/validator-customconstraints.html&#039; target=&#039;_blank&#039;&gt;create your own complex constraints&lt;/a&gt; quite easily.  I added the following annotations to my code to help in my quest for bug free code:&lt;br&gt;
&lt;br&gt;
&lt;tt&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;b&gt;@Valid &lt;/b&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;b&gt;@NotNull&lt;/b&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;b&gt;@Size(min=0, max=1)&lt;/b&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public String getResult() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br&gt;
&lt;/tt&gt;
&lt;br&gt;
Now, method validation (validating method calls, rather than validating the bean itself) is something which comes as an extra in Hibernate Validator, and which really isn&#039;t part of JSR-303 - it&#039;s only described in Appendix C as optional.  To test this, I used Google Guice to add an AOP interceptor to any methods marked with the &lt;code&gt;@Valid&lt;/code&gt; annotation, and in that interceptor, I call the Hibernate Method Validator.  I end up with something like this:&lt;br&gt;
&lt;br&gt;
&lt;tt&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Injector injector = Guice.createInjector(new AbstractModule(){&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected void configure() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bindInterceptor(Matchers.any(),&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Matchers.annotatedWith(Valid.class),&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;new MethodValidatorInterceptor&lt;SomeClass&gt;());&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SomeClass someClass = injector.getInstance(SomeClass.class);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;someClass.init(true, false);&lt;br&gt;   
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertEquals(&#034;a&#034;, someClass.getResult());&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;someClass = injector.getInstance(SomeClass.class);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;someClass.init(false, true);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertEquals(&#034;b&#034;, someClass.getResult());&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
public class MethodValidatorInterceptor&amp;lt;T&amp;gt; implements MethodInterceptor {&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public Object invoke(MethodInvocation invocation) throws Throwable {&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//validate all inputs&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Set&amp;lt;MethodConstraintViolation&amp;lt;T&amp;gt;&amp;gt; mcvs =&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;methodValidator.validateAllParameters((T)invocation.getThis(),&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invocation.getMethod(), invocation.getArguments());&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(mcvs.size() != 0){&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw new IllegalArgumentException(String.valueOf(mcvs));&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//call through to the actual method being called&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Object ret = invocation.proceed();&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//validate result&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mcvs = methodValidator.validateReturnValue((T)invocation.getThis(),&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;invocation.getMethod(), ret);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(mcvs.size() != 0){&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw new IllegalArgumentException(String.valueOf(mcvs));&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return ret;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
.&lt;br&gt;
&lt;/tt&gt;
&lt;br&gt;
The above is something which a (Java EE) container should do for me - I was just messing around with simple classes in a simple Java Project.
Now, it isn&#039;t quite complete, because I still have 100% coverage, and I still have that bug, because the new annotations haven&#039;t really done anything useful.  Well that isn&#039;t entirely true - the reader of the code knows that the contract is a little stricter than it was when it was simple Javadoc. The reader may assume that the system will check these constraints when the method is called.  But while there is still a bug, I&#039;ve laid the path for adding some full pre- or post-conditions.  The next step was to add a new annotation, an interface and make use of them in the interceptor.&lt;br&gt;
&lt;br&gt;
&lt;tt&gt;
@Target( { ElementType.METHOD })&lt;br&gt;
@Retention(RetentionPolicy.RUNTIME)&lt;br&gt;
@Documented&lt;br&gt;
public @interface PreCondition {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Class&amp;lt;? extends ConditionChecker&amp;gt; implementation();&lt;br&gt;
}&lt;br&gt;
&lt;br&gt;
/** Any pre- or post-condition is written in &lt;br&gt;
&amp;nbsp;&amp;nbsp;* an implementation of this interface &lt;br&gt;
&amp;nbsp;&amp;nbsp;*/&lt;br&gt;
public interface ConditionChecker {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void checkCondition() &lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throws ConstraintViolationException;&lt;br&gt;
}&lt;br&gt;
&lt;/tt&gt;
&lt;br&gt;
The annotation can be added to the business code, in this case to add a pre-condition.  I created a similar annotation for post-conditions.  When I add the pre-condition to a method, I also state which class contains the code for checking that pre-condition:&lt;br&gt;
&lt;br&gt;
&lt;tt&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Valid&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@NotNull&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Size(min=0, max=1)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;b&gt;@PreCondition(implementation=MyPreAndPostCondition.class)&lt;/b&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public String getResult() {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br&gt;
&lt;/tt&gt;
&lt;br&gt;
The interceptor can check for the presence of such a pre-condition annotation before calling through to the method being called.  If the annotation is found, the interceptor attempts to create an instance of the implementation class, and calls it&#039;s &#034;checkCondition&#034; method.&lt;br&gt;
&lt;br&gt;
So the final part of this puzzle is to write a pre-condition which will help me to &lt;i&gt;fail&lt;/i&gt; to get 100% coverage when I test with the test shown near the top of this post. Here it is, implemented as a static final inner class inside the &lt;code&gt;SomeClass&lt;/code&gt; class, so that it has access to the fields &#034;a&#034; and &#034;b&#034;:&lt;br&gt;
&lt;br&gt;
&lt;tt&gt;
public class MyPreAndPostCondition implements ConditionChecker {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void checkCondition() &lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throws ConstraintViolationException {&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//im going to list all combinations of &lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//a and b which I support&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(!a &amp;&amp; b) return;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(!b &amp;&amp; a) return;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(!b &amp;&amp; !a) return;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(a &amp;&amp; b) return;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br&gt;
}&lt;br&gt;
&lt;/tt&gt;
&lt;br&gt;
When I now test my code, I no longer get 100% coverage, because the last two lines in the pre-condition are not covered. Hooray!  The tools can now tell me what I still need to test...&lt;br&gt;
&lt;br&gt;
Now, while this technical solution works, I think it is &lt;i&gt;&lt;b&gt;really ugly&lt;/b&gt;&lt;/i&gt;.  Like I said, if the code which is causing the problem were to be found within one or two hundred other lines of code, and were reliant on local variables rather than fields in my class, I would have no chance of using a pre-condition like this to help me locate the problem.&lt;br&gt;
&lt;br&gt;
So to sum up, DBC isn&#039;t going to help me solve the problem that 100% code coverage can still contain errors.  I think DBC frameworks (and there are a lot out there, some which do exactly what I have done here using the &lt;code&gt;@PreCondition&lt;/code&gt; annotation) help to make contracts more concrete.  If you use method validation from Hibernate Validator, you don&#039;t have to write as much Javadoc, because the reader knows that the container will give up before calling the method if anything fails to validate.  To me as a programmer, that is much more satisfying than praying that some Javadoc reflects what I have really implemented.&lt;br&gt;
&lt;br&gt;
I have known programmers who don&#039;t write tests because a DBC framework is in place and that makes them feel safe.  But just because you declare a contract, does not mean the code actually works.  Whether the code fails hard with a validation exception or at some time later because your code is buggy, makes no difference - both are inacceptable!  From that perspective, DBC contracts are simply hints to the tester what could be useful tests, and they ensure that the code fails hard, early.&lt;br&gt;
&lt;br&gt;
While I was refreshing my testing skills, I also learned the difference between mocks and stubs.  For years I had always thought they were the same thing, but it turns out that stubs return  pre-fed answers, whereby mocks check the sequence of calls to them too.  On a different thread at DZone, someone made a point that unit testing was pointless because it never helped them find bugs, and it caused lots of work when refactoring, because all that does is break their tests.  I&#039;d say that this is simply a question of black box versus white box testing.  Black box unit testing should never break if you refactor your code - the tests are simply clients to the code which you are refactoring, and tools like Eclipse will modify the calling code if you modify the interfaces being called, including tests.  You can get pretty good testing results by just using black box tests - the large majority of the tests I write are black box tests and when I write such tests, I tend to have bug free code.  &lt;br&gt;
&lt;br&gt;
I&#039;ve talked about writing contracts to help the reader determine what they should expect when they use your code.  Unit tests themselves work similarly, because they show the reader examples of how to call your code and what to expect when your code changes system state.  They hint to the reader how the writer intended the code to be used.  While I don&#039;t advocate TDD (perhaps only because I have never been on a project which used it or at a company which valued quality enough to warrant TDD), I do encourage writing tests and using validation and pre-/post-conditions because they help document the code with the added bonus of finding the occassional bug.  At the same time, I am an architect and we need to keep things like budgets in mind.  You have an influence on your budget when you estimate, assuming you are allowed to do that.  Your customer might push you to reduce your estimates, and that is an indication about their commitment to quality, because they won&#039;t budge on scope or delivery dates!  So write as many tests as you can, within your budget and start with the code which is most complex and which gets called most often.  and remember, 100% coverage is not really your best friend because bugs may still lurk.  
&lt;br&gt;
&lt;br&gt;
&amp;copy; 2011, Ant Kutschera
&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&amp;amp;title=100%25+code+coverage%2C+Hibernate+Validator+and+Design+by+Contract&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&amp;amp;title=100%25+code+coverage%2C+Hibernate+Validator+and+Design+by+Contract&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&amp;amp;title=100%25+code+coverage%2C+Hibernate+Validator+and+Design+by+Contract&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&amp;amp;title=100%25+code+coverage%2C+Hibernate+Validator+and+Design+by+Contract&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&amp;amp;title=100%25+code+coverage%2C+Hibernate+Validator+and+Design+by+Contract&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&amp;amp;title=100%25+code+coverage%2C+Hibernate+Validator+and+Design+by+Contract&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&amp;amp;t=100%25+code+coverage%2C+Hibernate+Validator+and+Design+by+Contract&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&amp;amp;title=100%25+code+coverage%2C+Hibernate+Validator+and+Design+by+Contract&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html&amp;amp;t=100%25+code+coverage%2C+Hibernate+Validator+and+Design+by+Contract&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2011/11/28/1322465377854.html</guid>
    <pubDate>Mon, 28 Nov 2011 07:29:37 GMT</pubDate>
  </item>
  
  <item>
    <title>A really simple but powerful rule engine</title>
    <link>http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html</link>
    
      
        <description>
          &lt;p&gt;UPDATE: Version 2.0 of the library now exists which supports Scala.  It is a breaking change in that &amp;quot;Action&amp;quot; instances as shown below are now &amp;quot;AbstractAction&amp;quot;, and the &amp;quot;Action&amp;quot; class is only supported in Scala, where functions can be passed to the action constructor instead of having to override the AbstractAction.  Scala collections are also supported in the engine.&lt;/p&gt;
&lt;p&gt;I have the requirement to use a rule engine.  I want something light weight and fairly simple, yet powerful.  While there are products out there which are super good, I don&#039;t want something with the big learning overhead.  And, I fancied writing my own!&lt;br /&gt;
&lt;br /&gt;
Here are my few basic requirements:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Use some kind of expression language to write the rules,&lt;/li&gt;
    &lt;li&gt;It should be possible to store rules in a database,&lt;/li&gt;
    &lt;li&gt;Rules need a priority, so that only the best can be fired,&lt;/li&gt;
    &lt;li&gt;It should also be possible to fire all matching rules,&lt;/li&gt;
    &lt;li&gt;Rules should evaluate against one input which can be an object like a tree, containing all the information which rules need to evaluate against&lt;/li&gt;
    &lt;li&gt;Predefined actions which are programmed in the system should be executed when certains rules fire.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So to help clarify those requirements, imagine the following examples:&lt;br /&gt;
&lt;br /&gt;
1) &lt;i&gt;In some forum system, the administrator needs to be able to configure when emails are sent.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Here, I would write some rules like &amp;quot;when the config flag called sendUserEmail is set to true, send an email to the user&amp;quot; and &amp;quot;when the config flag called sendAdministratorEmail is true and the user has posted less than 5 postings, send an email to the administrator&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
2) &lt;i&gt;A tarif system needs to be configurable, so that the best tarif can be offered to customers.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
For that, I could write rules like these: &amp;quot;when the person is younger than 26 the Youth tarif is applicable&amp;quot;, &amp;quot;when the person is older than 59, the Senior tarif is applicable&amp;quot;, and &amp;quot;when the person is neither a youth, nor a senior, then they should be given the Default tarif, unless they have had an account for more than 24 months, in which case they should be offered the Loyalty tarif&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
3) &lt;i&gt;A train ticket can be considered to be a product.  Depending upon the travel request, different products are suitable.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
A rule here, could be something like: &amp;quot;if the travel distance is more than 100km and first class is desired, then product A is to be sold.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Finally, a more complex example, involving some iteration of the input, rather than just property evaluation:&lt;br /&gt;
&lt;br /&gt;
4) &lt;i&gt;Timetable software needs to deterimine when students can leave school.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
A rule for that might read: &amp;quot;If a class contains any student under age 10, the entire class gets to leave early.  Otherwise, they leave at the normal time.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
So, with those requirements in mind, I went to look for an expression language.  I started with the unified expression language specified in JSP 2.1.  Using the jasper jar used in Tomcat and Apache Commons EL jar, I got something up and running very quickly.  Then I discovered the &lt;a target=&#034;_blank&#034; href=&#034;http://mvel.codehaus.org&#034;&gt;MVEL library from Codehaus.org&lt;/a&gt;, which incidentally is used in Drools (the leading Java rule engine?) and it worked even better.  It offers far more functionality as far as I can tell.&lt;br /&gt;
&lt;br /&gt;
So, I designed my rule engine to work like this:&lt;br /&gt;
&lt;br /&gt;
1) An engine is configured with some rules.&lt;br /&gt;
&lt;br /&gt;
2) A rule has these attributes:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- namespace: an engine may contain many rules, but only some may be relevant to a particular call and this namespace can be used for filtering&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- name: a unique name within a namespace&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- expression: an MVEL expression for the rule&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- outcome: a string which the engine might use if this rules expression evaluates to true&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- priority: an integer.  The bigger the value, the higher the priority.&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- description: a useful description to aid the management of rules.&lt;br /&gt;
&lt;br /&gt;
3) The engine is given an input object and evaluates all rules (optionally within a namespace) and either:&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a) returns all rules which evaluate to true,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b) returns the outcome (string) from the rule with the highest priority, out of all rules evaluating to true,&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;c) execute an action (defined within the application) which is associated with the outcome of the rule with the highest priority, out of all rules evaluating to true.&lt;br /&gt;
&lt;br /&gt;
4) &amp;quot;Action&amp;quot;s are instances of classes which the application programmer can supply.  An action is given a name.  When the engine is asked to execute an action based on the rules, the name of the action matching the &amp;quot;winning&amp;quot; rule&#039;s outcome is executed.&lt;br /&gt;
&lt;br /&gt;
5) A rule can be built up of &amp;quot;sub-rules&amp;quot;.  A subrule is only ever used as a building block on which to base more complex rules.  When evaluating rules, the engine will never select a subrule to be the best (highest priority) &amp;quot;winning&amp;quot; rule, i.e. one evaluating to true.  Subrules make it easier to build complex rules, as I shall show shortly.&lt;br /&gt;
&lt;br /&gt;
So, time for some code!&lt;br /&gt;
&lt;br /&gt;
First, let&#039;s look at the code for the tarif system:&lt;/p&gt;
&lt;div style=&#034;border: thin none; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
Rule r1 = new Rule(&amp;quot;YouthTarif&amp;quot;, &amp;quot;input.person.age &amp;lt; 26&amp;quot;, &amp;quot;YT2011&amp;quot;, 3, &amp;quot;ch.maxant.someapp.tarifs&amp;quot;, null);
Rule r2 = new Rule(&amp;quot;SeniorTarif&amp;quot;, &amp;quot;input.person.age &amp;gt; 59&amp;quot;, &amp;quot;ST2011&amp;quot;, 3, &amp;quot;ch.maxant.someapp.tarifs&amp;quot;, null);
Rule r3 = new Rule(&amp;quot;DefaultTarif&amp;quot;, &amp;quot;!#YouthTarif &amp;amp;&amp;amp; !#SeniorTarif&amp;quot;, &amp;quot;DT2011&amp;quot;, 3, &amp;quot;ch.maxant.someapp.tarifs&amp;quot;, null);
Rule r4 = new Rule(&amp;quot;LoyaltyTarif&amp;quot;, &amp;quot;#DefaultTarif &amp;amp;&amp;amp; input.account.ageInMonths &amp;gt; 24&amp;quot;, &amp;quot;LT2011&amp;quot;, 4, &amp;quot;ch.maxant.someapp.tarifs&amp;quot;, null);
List&amp;lt;Rule&amp;gt; rules = Arrays.asList(r1, r2, r3, r4);

Engine engine = new Engine(rules, true);

TarifRequest request = new TarifRequest();
request.setPerson(new Person(&amp;quot;p&amp;quot;));
request.setAccount(new Account());

request.getPerson().setAge(24);
request.getAccount().setAgeInMonths(5);
String tarif = engine.getBestOutcome(request);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
So, in the above code, I have added 4 rules to the engine, and told the engine to throw an exception if any rule cannot be pre-compiled.  Then, I created a TarifRequest, which is the input object.  That object is passed into the engine, when I ask the engine to give me the best outcome.  In this case, the best outcome is the string &amp;quot;YT2011&amp;quot;, the name of the most suitable tarif for the customer I added to the tarif request.&lt;br /&gt;
&lt;br /&gt;
How does it all work?  When the engine is given the rules, it does some validation on them, and pre-compiles the rules (to improve overall performance).  Notice how the first two rules refer to an object called &amp;quot;input&amp;quot;?  That is the object passed into the &amp;quot;getBestOutcome&amp;quot; method on the engine.  The engine passes the input object to the MVEL class together with each rules expression.  Anytime an expression evaluates to &amp;quot;true&amp;quot;, the rule is put to the side as a candidate to be the winner.  At the end, the candidates are sorted in order of priority, and the outcome field of the rule with the highest priority is returned by the engine.&lt;br /&gt;
&lt;br /&gt;
Notice how the third and fourth rules contain the &#039;#&#039; character.  That is not standard MVEL expression language.  The engine examines all rules when they are passed to it, and it replaces any token starting with a hash symbol, with the expression found in the rule named the same as the token.  It wraps the expression in brackets.  The logger outputs the full rule after reference rules have been resolved and replaced, just in case you want to check the rule.&lt;br /&gt;
&lt;br /&gt;
In the above business case, we were only interested in the best tarif for the customer.  Equally, we might have been interested in a list of possible tarifs, so that we could offer the customer a choice.  In that case, we could have called the &amp;quot;getMatchingRules&amp;quot; method on the engine, which would have returned all rules, sorted by priority.  The tarif names are (in this case) the &amp;quot;outcome&amp;quot; field of the rules.&lt;br /&gt;
&lt;br /&gt;
In the above example, I wanted to receive any of the four outcomes, from the four rules.  Sometimes however, you might want to build complex rules based on building blocks, but you might never want those building blocks to be a winning outcome.  The train trip example from above can be used to show what I mean here:&lt;/p&gt;
&lt;div style=&#034;border: thin none; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
Rule rule1 = new SubRule(&amp;quot;longdistance&amp;quot;, &amp;quot;input.distance &amp;gt; 100&amp;quot;, &amp;quot;ch.maxant.produkte&amp;quot;, null);
Rule rule2 = new SubRule(&amp;quot;firstclass&amp;quot;, &amp;quot;input.map[\&amp;quot;travelClass\&amp;quot;] == 1&amp;quot;, &amp;quot;ch.maxant.produkte&amp;quot;, null);
Rule rule3 = new Rule(&amp;quot;productA&amp;quot;, &amp;quot;#longdistance &amp;amp;&amp;amp; #firstclass&amp;quot;, &amp;quot;productA&amp;quot;, 3, &amp;quot;ch.maxant.produkte&amp;quot;, null);
List&amp;lt;Rule&amp;gt; rules = Arrays.asList(rule1, rule2, rule3);

Engine e = new Engine(rules, true);

TravelRequest request = new TravelRequest(150);
request.put(&amp;quot;travelClass&amp;quot;, 1);
List&lt;rule&gt; rs = e.getMatchingRules(request); &lt;/rule&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
In the above code, I build rule3 from two subrules.  But I never want the outcomes of those building blocks to be output from the engine.  So I create them as SubRules.  SubRules don&#039;t have an outcome field or priority.  They are simply used to build up more complex rules.  After the engine has used the sub-rules to replace all tokens beginning in a hash during initialisation, it discards the SubRules - they are not evaluated.&lt;br /&gt;
&lt;br /&gt;
The TravelRequest above takes a distance in the constructor, and contains a map of additional parameters.  MVEL let&#039;s you easily access map values using the syntax shown in rule 2.&lt;br /&gt;
&lt;br /&gt;
Next, consider the business case of wanting to configure an forum system.  The code below introduces actions.  Actions are created by the application programmer and supplied to the engine.  The engine takes the outcomes (as described in the first example), and searches for actions with the same names as those outcomes, and calls the &amp;quot;execute&amp;quot; method on those actions (they all implement the IAction interface).  This functionality is useful when a system must be capable of predefined things, but the choice of what to do needs to be highly configurable and independent of deployment.&lt;/p&gt;
&lt;div style=&#034;border: thin none; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
Rule r1 = new Rule(&amp;quot;SendEmailToUser&amp;quot;, &amp;quot;input.config.sendUserEmail == true&amp;quot;, &amp;quot;SendEmailToUser&amp;quot;, 1, &amp;quot;ch.maxant.someapp.config&amp;quot;, null);
Rule r2 = new Rule(&amp;quot;SendEmailToModerator&amp;quot;, &amp;quot;input.config.sendAdministratorEmail == true and input.user.numberOfPostings &amp;lt; 5&amp;quot;, &amp;quot;SendEmailToModerator&amp;quot;, 2, &amp;quot;ch.maxant.someapp.config&amp;quot;, null);
List&amp;lt;Rule&amp;gt; rules = Arrays.asList(r1, r2);
		
final List&amp;lt;String&amp;gt; log = new ArrayList&amp;lt;String&amp;gt;();
		
Action&amp;lt;ForumSetup, Void&amp;gt; a1 = new Action&amp;lt;ForumSetup, Void&amp;gt;(&amp;quot;SendEmailToUser&amp;quot;) {
&amp;nbsp;&amp;nbsp;@Override
&amp;nbsp;&amp;nbsp;public Void execute(ForumSetup input) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;log.add(&amp;quot;Sending email to user!&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return null;
&amp;nbsp;&amp;nbsp;}
};
Action&amp;lt;ForumSetup, Void&amp;gt; a2 = new Action&amp;lt;ForumSetup, Void&amp;gt;(&amp;quot;SendEmailToModerator&amp;quot;) {
&amp;nbsp;&amp;nbsp;@Override
&amp;nbsp;&amp;nbsp;public Void execute(ForumSetup input) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;log.add(&amp;quot;Sending email to moderator!&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return null;
&amp;nbsp;&amp;nbsp;}
};

Engine engine = new Engine(rules, true);

ForumSetup setup = new ForumSetup();
setup.getConfig().setSendUserEmail(true);
setup.getConfig().setSendAdministratorEmail(true);
setup.getUser().setNumberOfPostings(2);
			
engine.executeAllActions(setup, Arrays.asList(a1, a2));
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
In the code above, the actions are passed to the engine when we call the &amp;quot;executeAllActions&amp;quot; method.  In this case, both actions are executed, because the setup object causes both rules to evaluate to true.  Note that the actions are executed in the order of highest priority rule first.  Each action is only ever executed once - it&#039;s name is noted after execution and it will not be executed again, until the engines &amp;quot;execute*Action*&amp;quot; method is called again.  Also, if you only want the action associated with the best outcome to be executed, call the &amp;quot;executeBestAction&amp;quot; method instead of &amp;quot;executeAllActions&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Finally, let&#039;s consider the classroom example.&lt;/p&gt;
&lt;div style=&#034;border: thin none; overflow: auto; width: 525px; height: 300px; background-color: rgb(255, 255, 255);&#034;&gt;
&lt;pre&gt;
String expression = 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;for(student : input.students){&amp;quot; +
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;	if(student.age &amp;lt; 10) return true;&amp;quot; +
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;}&amp;quot; +
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;return false;&amp;quot;;

Rule r1 = new Rule(&amp;quot;containsStudentUnder10&amp;quot;, expression , &amp;quot;leaveEarly&amp;quot;, 1, &amp;quot;ch.maxant.rules&amp;quot;, &amp;quot;If a class contains a student under 10 years of age, then the class may go home early&amp;quot;);
		
Rule r2 = new Rule(&amp;quot;default&amp;quot;, &amp;quot;true&amp;quot; , &amp;quot;leaveOnTime&amp;quot;, 0, &amp;quot;ch.maxant.rules&amp;quot;, &amp;quot;this is the default&amp;quot;);
		
Classroom classroom = new Classroom();
classroom.getStudents().add(new Person(12));
classroom.getStudents().add(new Person(10));
classroom.getStudents().add(new Person(8));

Engine e = new Engine(Arrays.asList(r1, r2), true);
		
String outcome = e.getBestOutcome(classroom);
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;
The outcome above is &amp;quot;leaveEarly&amp;quot;, because the classroom contains one student whose age is less than 10.  MVEL let&#039;s you write some pretty comprehensive expressions, and is really a programming language in it&#039;s own right.  The engine simply requires a rule to return true, if the rule is to be considered a candidate for firing.&lt;br /&gt;
&lt;br /&gt;
There are more examples in the JUnit tests contained in the source code.&lt;br /&gt;
&lt;br /&gt;
So, the requirements are fulfiled, except for &amp;quot;It should be possible to store rules in a database&amp;quot;.  While this library doesn&#039;t support reading and writing rules to / from a database, rules are String based.  So it wouldn&#039;t be hard to create some JDBC or JPA code which reads rules out of a database and populates Rule objects and passes them to the Engine.  I haven&#039;t added this to the library, because normally these things as well as the management of rules is something quite project specific.  And because my library will never be as cool or popular as Drools, I&#039;m not sure it would be worth my while to add such functionality.&lt;br /&gt;
&lt;br /&gt;
I&#039;ve put the rule engine into an OSGi library with the LGPL licence and it can be downloaded from &lt;a target=&#034;_blank&#034; href=&#034;http://www.maxant.co.uk/tools.jsp&#034;&gt;my tools site&lt;/a&gt;.  This library depends on &lt;a href=&#034;http://mvel.codehaus.org/Downloading+MVEL&#034; target=&#034;_blank&#034;&gt;MVEL, which can be downloaded here&lt;/a&gt; (I used version 2.0.19).  If you like it, let me know! &lt;br /&gt;
&lt;br /&gt;
&amp;copy; 2011, Ant Kutschera&lt;/p&gt;&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&amp;amp;title=A+really+simple+but+powerful+rule+engine&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&amp;amp;title=A+really+simple+but+powerful+rule+engine&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&amp;amp;title=A+really+simple+but+powerful+rule+engine&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&amp;amp;title=A+really+simple+but+powerful+rule+engine&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&amp;amp;title=A+really+simple+but+powerful+rule+engine&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&amp;amp;title=A+really+simple+but+powerful+rule+engine&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&amp;amp;t=A+really+simple+but+powerful+rule+engine&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&amp;amp;title=A+really+simple+but+powerful+rule+engine&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html&amp;amp;t=A+really+simple+but+powerful+rule+engine&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2011/11/12/1321129560000.html</guid>
    <pubDate>Sat, 12 Nov 2011 20:26:00 GMT</pubDate>
  </item>
  
  <item>
    <title>JSR-299 &amp; @Produces</title>
    <link>http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html</link>
    
      
        <description>
          I&#039;ve been reading &lt;a href=&#039;http://www.jcp.org/en/jsr/detail?id=299&#039; target=&#039;_blank&#039;&gt;JSR-299&lt;/a&gt; and I have a few thoughts.&lt;br&gt;
&lt;br&gt;
First, a quote from chapter 1:&lt;br&gt;
&lt;br&gt;
&lt;i&gt;&#034;The use of these services significantly simplifies the task of creating Java EE applications by integrating the Java EE web
tier with Java EE enterprise services. In particular, EJB components may be used as JSF managed beans, thus integrating
the programming models of EJB and JSF.&#034;&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
The second sentence made my ears prick up.  Do I really want EJBs to be the backing beans of web pages?  To me that sounds like one is mixing up responsibilities in MVC.  Sure, there are people out there who say that an MVC Controller should be skinny and the model should be fat (&lt;a href=&#039;http://www.youtube.com/watch?v=91C7ax0UAAc&#039; target=&#039;_blank&#039;&gt;youtube ad&lt;/a&gt;).  Perhaps I&#039;m old school, but I prefer my JSF page to have a backing bean which is my view model and deals with presentation specific logic, and when it needs transaction and security support, it can call through to an EJB which deals with more businessy things.&lt;br&gt;
&lt;br&gt;
The JSR then goes on to introduce the &lt;code&gt;@Produces&lt;/code&gt; annotation.  I don&#039;t like that annotation and the rest of this blog posting is about why.&lt;br&gt;
&lt;br&gt;
When I need an object, like a service or a resource, I can get the container to inject it for me.  Typically, I use the &lt;code&gt;@Inject&lt;/code&gt;, &lt;code&gt;@EJB&lt;/code&gt;, &lt;code&gt;@Resource&lt;/code&gt; or &lt;code&gt;@PersistenceContext&lt;/code&gt; annotations.  In the object which has such things injected, I can write code which uses those objects.  I let the container compose my object using those pieces and other beans.  There are many advantages, like having code which is easily testable because I can compose the object out of mocks if required, or like being able to configure its composition rather than hard coding it.  And we are all used to composing objects like this, from the earliest days of Spring, if not before.&lt;br&gt;
&lt;br&gt;
Now, with &lt;code&gt;@Produces&lt;/code&gt;, we have a new way to declare where things come from.  Take the example in the JSR, where a &lt;code&gt;Login&lt;/code&gt; bean is shown (chapter 1). 
The Login bean &#034;produces&#034; the current user (page 4).  Well, let&#039;s start with some code:&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;@Produces @LoggedIn User getCurrentUser()&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
If I read that code out loud, I say something with a similar meaning to: &lt;i&gt;&#034;The bean called Login produces the currently logged in user&#034;.&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
Well, that doesn&#039;t make too much sense to me, because coming at the design from a pure OO point of view, starting with use-cases, there is no Login bean mentioned in the use case, and even if there were, it does not &#034;produce&#034; the user!  The user exists before they login to the software.  They are simply authenticated and perhaps authorised after login.  The login component of the software (which could be represented by the Login bean) can provide the details of the currently logged in user.  The syntax used in that code above has a poor semantic meaning, in my view.&lt;br&gt;
&lt;br&gt;
So if this is the modern trendy way of passing information around in a JSF app, I have to ask myself whether we were not able to do such things in the past?  Or was it really hard to program before we had the &lt;code&gt;@Produces&lt;/code&gt; annotation?  Let&#039;s look at one solution; some code in a bean which needs to know the logged in user.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;@Inject Login loginBean;&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
To use that, the Login bean would need to be declared as being &lt;code&gt;@SessionScoped&lt;/code&gt;, and guess what - it is already marked so in the JSR example.&lt;br&gt;
&lt;br&gt;
To access the current user, I would simply write code like this:&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;loginBean.getCurrentUser().getName() blah blah&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
Simple huh?&lt;br&gt;
&lt;br&gt;
If you don&#039;t like the idea of injecting the Login bean, then why not simply create a session scoped bean called &#034;&lt;code&gt;CurrentUser&lt;/code&gt;&#034; and during login, set the authenticated user attributes into that session scoped bean?  Why go to the lengths of adding yet another way of injecting objects, namely the &lt;code&gt;@Produces&lt;/code&gt; annotation?  Because there is a different way of doing injection, the whole mechanism has become more complex.  I believe it is these types of complexity which cause newbies to give up Java EE before fully understanding it, and which cause existing Java advocates to give up and move to Grails, etc.&lt;br&gt;
&lt;br&gt;
To go with the &lt;code&gt;@Produces&lt;/code&gt; annotation, we are given qualifiers.  Qualifiers are effectively type safe names used for filtering, and as such, potentially better than String constants in an interface somewhere used in conjunction with an &lt;code&gt;@Named&lt;/code&gt; annotation.  Here is why I don&#039;t think Qualifiers should be used as the norm, but rather as the exception.  The class of object being injected should have a suitable name to tell the reader what is going on.  Consider this code, which injects the current user which the login bean produces:&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;@Inject @LoggedIn User currentUser;&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
There is unnecessary triplication going on in that line.  &#034;LoggedIn&#034;, &#034;User&#034; and &#034;currentUser&#034;.  In the ideal world, I don&#039;t want three names here, I want one.  Java forces me to declare the type, which is actually not really that necessary, because the compiler could, using conventions, infer the type from the name.  But let&#039;s not go there, and instead accept that we have to declare a type.  Why on earth then, do I want to additionally declare a qualifier?  I don&#039;t, it&#039;s a waste of finger energy.  Only when there is ambiguity would I be required to use a qualifier.  But if I have a session scoped model, which contained the user, I could spare myself the energy of using a qualifier.  I would simply inject the model bean and pull the current user out of it.  That is what I have been doing for years without a problem.  My Mum always told me not to fix something which isn&#039;t broken.&lt;br&gt;
&lt;br&gt;
At this &lt;a target=&#039;_blank&#039; href=&#039;https://docs.jboss.org/author/display/AS7/Getting+Started+Developing+Applications+Guide&#039;&gt;JBoss getting started guide&lt;/a&gt;, they give an example of producing a random number, with code like this (in the producer):&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;@Produces @Random int next() {&lt;/code&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;return getRandom().nextInt(maxNumber - 1) + 1;&lt;/code&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;}&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
and this code in the consumer:&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;@Inject @Random int someRandomNumber;&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
Sure, it&#039;s a toy example.  But what is wrong with injecting the &lt;code&gt;Generator&lt;/code&gt; bean (which contains that producer method), and calling the method on it which generates the random number?  I could even work with &lt;code&gt;@Alternative&lt;/code&gt; if I wanted to decide on the actual implementation at deployment time.&lt;br&gt;
&lt;br&gt;
For me, injecting the bean, rather than the value is very important for readability.  It gives the reader (maintainer) contextual information about where that value is coming from.  In my mind, the following code is much better.  It is quicker to write, because I don&#039;t need to create a qualifier annotation.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;@Inject Generator generator;&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
And then in that class, some code to use the generator:&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;generator.nextRandomInt();&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
Section 1.3.3 of the JSR gives an example of setting up the entity managers for injection into beans:&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;@Produces @PersistenceContext(unitName=&#034;UserData&#034;) @Users&lt;/code&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;EntityManager userDatabaseEntityManager;&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
And then here, the code which uses that entity manager:&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;@Inject @Users EntityManager userDatabaseEntityManager;&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
Oh, and don&#039;t forget the code for the &lt;code&gt;@Users&lt;/code&gt; annotation...  I end up with two extra files (the annotation and the producer).  Is all that code really better than the following, which is simply put into a bean requiring the entity manager:&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;@PersistenceContext(unitName=Units.UserData)&lt;/code&gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;code&gt;EntityManager userDatabaseEntityManager;&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
I&#039;m just not convinced that the &#034;modern&#034; &amp;amp; trendy, yet complex JSR-299 way of doing it is better.&lt;br&gt;
&lt;br&gt;
Section 3.3 then goes on to tell us a bit more about why producers exist and in which circumstances we might want to use them:&lt;br&gt;
&lt;br&gt;
&lt;i&gt; - the objects to be injected are not required to be instances of beans&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
Since almost every class is now a bean, I am hard pushed to think of a case where I could not create a bean if I wanted something injected.&lt;br&gt;
&lt;br&gt;
&lt;i&gt; - the concrete type of the objects to be injected may vary at runtime&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
This is exactly what &lt;code&gt;@Alternative&lt;/code&gt; and &lt;code&gt;@Specialize&lt;/code&gt; annotations are for, and I do not need to use a producer to vary the concrete runtime implementation.&lt;br&gt;
&lt;br&gt;
&lt;i&gt; - the objects require some custom initialization that is not performed by the bean constructor&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
Adding the &lt;code&gt;@Inject&lt;/code&gt; annotation to a constructor tells the container which constructor to call when special construction is required.  How can a producer produce something which a bean couldn&#039;t?&lt;br&gt;
&lt;br&gt;
Section 3.4.2 then talks about declaring producer fields.  The example they give shows the field having default (package) visibility, yet as far as I can tell, any bean in the deployment bundle, even one outside the producers package, can use the &#034;product&#034;.  This is a little like indecently assaulting Java.&lt;br&gt;
&lt;br&gt;
So to summarise, I guess I just want to put out a plea to future spec authors.  If you can&#039;t work out a way to do things simply, especially if we already have that mechanism, please don&#039;t go and make things more complicated than they need to be.  I don&#039;t want to learn 92 pages of JSR just to be good at using beans, when I already have to learn thousands of other pages of JSR just to get working with Java EE.&lt;br&gt;
&lt;br&gt;
&amp;copy; 2011, Ant Kutschera
&lt;br&gt;
&lt;br&gt;
&lt;div class=&#034;tags&#034;&gt;&lt;span&gt;Social Bookmarks : &lt;/span&gt;&amp;nbsp;&lt;a href=&#034;http://slashdot.org/bookmark.pl?url=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&amp;amp;title=JSR-299+%26+%40Produces&#034; target=&#034;_blank&#034; title=&#034;Add this post to Slash Dot&#034;&gt;&lt;img src=&#034;common/images/slashdot.png&#034; alt=&#034;Add this post to Slashdot&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://digg.com/submit?url=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&amp;amp;title=JSR-299+%26+%40Produces&#034; target=&#034;_blank&#034; title=&#034;Digg this post&#034;&gt;&lt;img src=&#034;common/images/digg.png&#034; alt=&#034;Add this post to Digg&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://reddit.com/submit?url=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&amp;amp;title=JSR-299+%26+%40Produces&#034; target=&#034;_blank&#034; title=&#034;Add this post to Reddit&#034;&gt;&lt;img src=&#034;common/images/reddit.png&#034; alt=&#034;Add this post to Reddit&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://del.icio.us/post?url=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&amp;amp;title=JSR-299+%26+%40Produces&#034; target=&#034;_blank&#034; title=&#034;Save this post to Del.icio.us&#034;&gt;&lt;img src=&#034;common/images/delicious.png&#034; alt=&#034;Add this post to Delicious&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.stumbleupon.com/submit?url=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&amp;amp;title=JSR-299+%26+%40Produces&#034; target=&#034;_blank&#034; title=&#034;Stumble this post&#034;&gt;&lt;img src=&#034;common/images/stumbleupon.png&#034; alt=&#034;Add this post to Stumble it&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.google.com/bookmarks/mark?op=edit&amp;amp;bkmk=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&amp;amp;title=JSR-299+%26+%40Produces&#034; target=&#034;_blank&#034; title=&#034;Add this post to Google&#034;&gt;&lt;img src=&#034;common/images/google.png&#034; alt=&#034;Add this post to Google&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://technorati.com/faves?add=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Technorati&#034;&gt;&lt;img src=&#034;common/images/technorati.png&#034; alt=&#034;Add this post to Technorati&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.bloglines.com/sub/http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Bloglines&#034;&gt;&lt;img src=&#034;common/images/bloglines.png&#034; alt=&#034;Add this post to Bloglines&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.facebook.com/share.php?u=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&#034; target=&#034;_blank&#034; title=&#034;Add this post to Facebook&#034;&gt;&lt;img src=&#034;common/images/facebook.png&#034; alt=&#034;Add this post to Facebook&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://www.furl.net/storeIt.jsp?u=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&amp;amp;t=JSR-299+%26+%40Produces&#034; target=&#034;_blank&#034; title=&#034;Add this post to Furl&#034;&gt;&lt;img src=&#034;common/images/furl.png&#034; alt=&#034;Add this post to Furl&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;https://favorites.live.com/quickadd.aspx?mkt=en-us&amp;amp;url=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&amp;amp;title=JSR-299+%26+%40Produces&#034; target=&#034;_blank&#034; title=&#034;Add this post to Windows Live&#034;&gt;&lt;img src=&#034;common/images/windowslive.png&#034; alt=&#034;Add this post to Windows Live&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href=&#034;http://bookmarks.yahoo.com/toolbar/savebm?opener=tb&amp;amp;u=http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html&amp;amp;t=JSR-299+%26+%40Produces&#034; target=&#034;_blank&#034; title=&#034;Add this post to Yahoo!&#034;&gt;&lt;img src=&#034;common/images/yahoo.png&#034; alt=&#034;Add this post to Yahoo!&#034; border=&#034;0&#034; /&gt;&lt;/a&gt;&lt;/div&gt;
        </description>
      
      
    
    
    
    <comments>http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html#comments</comments>
    <guid isPermaLink="true">http://blog.maxant.co.uk:80/pebble/2011/11/07/1320702240000.html</guid>
    <pubDate>Mon, 07 Nov 2011 21:44:00 GMT</pubDate>
  </item>
  
  </channel>
</rss>
