Listing 1: OrderServiceBean

@Stateless
@Interceptor("net.jcg.event.interceptor.EventInterceptor")
public class OrderServiceBean implements OrderService {

   @Inject
   private EntityManager manager;

   public Order submit(Order order) {
	order.setDate(new Date());
	manager.persist(order);
	return order;
   }

   public Order provision(Order order) {
      ...
   }

   public Order complete(Order order) {
	manager.merge(order);

	for (LineItem item : order.getLineItems()) {
		double qty = item.getQuantity();
		Product p = item.getProduct();
		p.setQuantity( p.getQuantity() - qty );
		manager.merge(p);
	}
	return order;
   }
}

Listing 2 - EventInterceptor

public class EventInterceptor {

   @AroundInvoke
   public Object invoke(InvocationContext ctx) throws Exception {
	Event event = null;
	try {
		event = new Event();
		event.setSource(ctx.getBean().getClass().getName());
		event.setName(ctx.getMethod().getName());
		event.setArguments(ctx.getParameters());
		event.setUserId(getUserId(ctx));

		Object output = ctx.proceed();
		event.setOutput(output);
		return output;
	} catch (Exception e) {
		event.setName(event.getName() + "Fault");
		event.setException(e);
		throw e;
	} finally {
		PublisherUtil.publish(event);
	}
   }
   ...
}


Listing 3 - RulesMDB

@MessageDriven(activateConfig = {
   @ActivationConfigProperty(
      propertyName = "destinationType", 
      propertyValue = "javax.jms.Topic"),
   @ActivationConfigProperty(
      propertyName = "destination",
      propertyValue = "topic/net.jcg.EventTopic")})
   @ActivationConfigProperty(
      propertyName = "subscription-durability",
      propertyValue = "Durable")})

public class RulesMDB
implements MessageListener {
   ...
   @Inject(jndiName = "net.jcg.RuleRuntime")
   private RuleRuntime rt;

   public void onMessage(Message message) {
	try {
		Event event = getEvent(message);
		onEvent(event);
	} catch (RuntimeException e) {
		throw e;
	} catch (Throwable t) {
		context.setRollbackOnly();
		throw new RuntimeException(t);
	} finally {
	}
   }

   protected void onEvent(Event event)
throws Exception {
	List input = new ArrayList();
	input.add(event);

      StatelessRuleSession srs = 
	  (StatelessRuleSession)
		rt.createRuleSession("OrderProcess", null,
		   RuleRuntime.STATELESS_SESSION_TYPE);
	srs.executeRules(input);
   }
   ...
}

Listing 4 - Rules

<rule-set name="OrderProcess">
 ...
 <rule name="onSubmitOrder">
  <parameter identifier="event">
    <class>net.jcg.event.entity.Event</class>
  </parameter>

  <java:condition>
     event.getSource().equals(OrderServiceBean.class.getName())
  </java:condition>
  <java:condition>
      event.getName().equals("submit")
  </java:condition>

  <java:consequence>
      Order o = (Order) event.getOutput();
      getOrderService().provision(o);
  </java:consequence>
 </rule>

 <rule name="onProvisionOrder">
  <parameter identifier="event">
    <class>net.jcg.event.entity.Event</class>
  </parameter>

  <java:condition>
     event.getSource().equals(OrderServiceBean.class.getName())
  </java:condition>
  <java:condition>
     event.getName().equals("provision")
  </java:condition>

  <java:consequence>
      Order o = (Order) event.getOutput();
      Task task = new Task();
      task.setTarget(o);
      task.setDescription("Ship Order: " + o.getId());
      task.setRole("Shipper");
      getTaskService().initiate(task);
   </java:consequence>
  </rule>
 ...
</rule-set>

Additional Source Code - Zip file 927KB