<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DEUBQ3g7cCp7ImA9WhRaGU4.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509</id><updated>2012-02-22T19:44:12.608+01:00</updated><category term="mobile" /><category term="oval" /><category term="logging" /><category term="uddi" /><category term="bpel" /><category term="clustering" /><category term="sonar" /><category term="wsi bp" /><category term="tools" /><category term="santuario" /><category term="funny" /><category term="jndi" /><category term="junit" /><category term="web apps" /><category term="selenium" /><category term="camel" /><category term="wtf" /><category term="nunit" /><category term="pmd" /><category term="validation" /><category term="presentation" /><category term="hsql" /><category term="c#" /><category term="objective-c" /><category term="osgi" /><category term="iphone" /><category term="ejb3" /><category term="tiles" /><category term="spring" /><category term="spam" /><category term="richfaces" /><category term="integration testing" /><category term="josso" /><category term=".net" /><category term="performance" /><category term="eclipse" /><category term="wsdl2" /><category term="qpid" /><category term="jax-ws" /><category term="xml" /><category term="virtualbox" /><category term="jsf" /><category term="java" /><category term="cobertura" /><category term="httpd" /><category term="security" /><category term="sticky session" /><category term="djunit" /><category term="jstl" /><category term="best practices" /><category term="jax-rs" /><category term="posts category" /><category term="script engine" /><category term="maven2" /><category term="crucible" /><category term="scdjws" /><category term="woden" /><category term="ac2dm" /><category term="spring web flow" /><category term="rest" /><category term="single sign-on" /><category term="activemq" /><category term="business processes" /><category term="load balancing" /><category term="estimates" /><category term="opinion" /><category term="groovy" /><category term="jpa" /><category term="nuntius" /><category term="asr" /><category term="ibm db2" /><category term="scout" /><category term="soapui" /><category term="quality" /><category term="proguard" /><category term="testing" /><category term="jms" /><category term="virtual machines" /><category term="json" /><category term="nhibernate" /><category term="interceptors" /><category term="servicemix" /><category term="ms test" /><category term="qualitas" /><category term="obfuscation" /><category term="saaj" /><category term="design patterns" /><category term="ode" /><category term="javascript" /><category term="burp" /><category term="debugging" /><category term="dozer" /><category term="glassfish" /><category term="spring mvc" /><category term="cxf" /><category term="tomcat" /><category term="jvm performance" /><category term="wsdl" /><category term="wolfram" /><category term="notifications" /><category term="download" /><category term="transactions" /><category term="ibm" /><category term="xquery" /><category term="ci" /><category term="aspects" /><category term="viewpoint" /><category term="rabbitmq" /><category term="juddi" /><category term="java ee" /><category term="jasper" /><category term="axis2" /><category term="app engine" /><category term="hibernate" /><category term="ant" /><category term="commons-logging" /><category term="soap" /><category term="opensso" /><category term="geronimo" /><category term="wsit" /><category term="gallio" /><category term="human interaction" /><category term="jsp" /><category term="xslt" /><category term="wsi" /><category term="web services" /><category term="jmeter" /><category term="netbeans" /><category term="java se" /><category term="log4j" /><category term="jquery" /><category term="cargo" /><category term="failover" /><category term="enterprise library" /><category term="jaxr" /><category term="garbage collection" /><category term="closure" /><category term="project management" /><category term="clover2" /><category term="spring.net" /><category term="purexml" /><category term="postsharp" /><category term="openjpa" /><category term="apns" /><title>Java EE, Web Services, WS-BPEL, SOA</title><subtitle type="html">Know how blog: Java EE, Web Services, WSIT, WS-BPEL, SOA, Spring, Maven2, best practices and testing</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://jee-bpel-soa.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>193</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/jee-bpel-soa-feed-new" /><feedburner:info uri="jee-bpel-soa-feed-new" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DUIBRn4zfyp7ImA9WhRbEUo.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-6999748900695710986</id><published>2012-02-02T11:07:00.001+01:00</published><updated>2012-02-02T11:12:37.087+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-02T11:12:37.087+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="rabbitmq" /><category scheme="http://www.blogger.com/atom/ns#" term="qpid" /><category scheme="http://www.blogger.com/atom/ns#" term="spring" /><category scheme="http://www.blogger.com/atom/ns#" term="qualitas" /><title>AMQP: RabbitMQ, Spring, Apache Camel, and Apache Qid</title><content type="html">As you know I'm open-sourcing and completely overhauling my PhD system. One of my goals was to replace internal JMS queues with AMQP. Today I'll show you how I did it and why I was forced to change RabbitMQ to Apache Qpid.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;AMQP&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In short. AMQP is an open standard application layer protocol for message-oriented middleware. The most important feature is that AMQP is a wire-level protocol and is interoperable by design. JMS is just an API. Altough JMS brokers can be used in .NET applications (see my post: &lt;a href="http://jee-bpel-soa.blogspot.com/2011/06/activemq-and-net-combined.html" target="_blank"&gt;ActiveMQ and .NET combined!&lt;/a&gt;), but the whole JMS specification does not guarantee interoperability. Also, the AMQP is by design more flexible and powerful (e.g., supports two-way communication by design) - they simply learnt from JMS mistakes :).&lt;br /&gt;
&lt;br /&gt;
Oh, forgot to mention. The AMQP was originally developed by banks :) so I don't have to say that AMQP is secure, fault-tolerant, and so on.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;RabbitMQ&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
RabbitMQ is the most mature AMQP broker. AMQP is written in Erlang so you have to download it first (RabbitMQ Windows installer does it for you). Download it from here: &lt;a href="http://www.rabbitmq.com/" target="_blank"&gt;http://www.rabbitmq.com/&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I also recommend installing the web management console. From Rabbit's &lt;code&gt;sbin&lt;/code&gt; directory execute:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml; gutter:false"&gt;rabbitmq-plugins enable rabbitmq_management&lt;/pre&gt;&lt;br /&gt;
If you're on Windows and you installed Rabbit service you have to restart it.&lt;br /&gt;
&lt;br /&gt;
That's it.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Spring&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Well, it turned out that VMware bought RabbitMQ and SpringSource developers are now developing it. Given this fact, you shouldn't be surprised that Spring - RabbitMQ integration is childishly simple.&lt;br /&gt;
&lt;br /&gt;
Add &lt;code&gt;spring-rabbit&lt;/code&gt; dependency to your Maven project, and then in Spring configuration paste the following:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;rabbit:connection-factory id="connectionFactory" /&amp;gt;
&amp;lt;rabbit:template connection-factory="connectionFactory" id="amqpTemplate" routing-key="myqueue" /&amp;gt;
&amp;lt;rabbit:admin connection-factory="connectionFactory" /&amp;gt;
&amp;lt;rabbit:queue name="myqueue" /&amp;gt;&lt;/pre&gt;&lt;br /&gt;
The default configuration assumes that RabbitMQ is running on a local server using the default port and default credentials (guest/guest). Of course all these settings are configurable.&lt;br /&gt;
&lt;br /&gt;
To sent a message to "myqueue" queue just inject an instance of &lt;code&gt;AmqpTemplate&lt;/code&gt; into your service and send the message. An example would be:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;@Service
public class HomeController {
&amp;nbsp; &amp;nbsp; @Autowired
&amp;nbsp; &amp;nbsp; private AmqpTemplate amqpTemplate;
&amp;nbsp; &amp;nbsp; public void sendMessage(Bundle bundle) throws IOException { &amp;nbsp; &amp;nbsp; &amp;nbsp; 
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; byte[] body = IOUtils.toByteArray(bundle.getInputStream());
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; MessageProperties messageProperties = new MessageProperties();
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; messageProperties.setContentType(bundle.getContentType());
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; messageProperties.setContentLength(bundle.getSize());
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; messageProperties.setTimestamp(new Date());
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; messageProperties.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Message message = new Message(body, messageProperties);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; amqpTemplate.send(message);
&amp;nbsp; &amp;nbsp; }
}&lt;/pre&gt;&lt;br /&gt;
You can open the web console http://localhost:55672/mgmt/ and see 1 message in "myqueue" queue.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Apache Camel&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
To read a message from Apache Camel you first have to add &lt;code&gt;camel-amqp&lt;/code&gt; dependency to your POM. Then just copy and paste the following route definition:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;camelContext xmlns="http://camel.apache.org/schema/spring"&amp;gt;
 &amp;lt;route&amp;gt;
  &amp;lt;from uri="amqp:queue:myqueue" /&amp;gt;
  &amp;lt;to uri="log:Message" /&amp;gt;
 &amp;lt;/route&amp;gt;
&amp;lt;/camelContext&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Run the route by executing &lt;code&gt;mvn:camel-run&lt;/code&gt; and... you'll see an error.&lt;br /&gt;
&lt;br /&gt;
Cutting long story short. Apache Camel 2.9.0 doesn't work with RabbitMQ. This is because &lt;code&gt;camel-amqp&lt;/code&gt; component is using Apache Qpid client under the hood. Current Qpid version is 0.14, but Qpid guys forgot to upload new jars to Maven public repo. Thus &lt;code&gt;camel-amqp&lt;/code&gt; is still using Qpid 0.12 whose client doesn't seem to negotiate protocols. Even if you exclude &lt;code&gt;qpid-commons&lt;/code&gt; and &lt;code&gt;qpid-client&lt;/code&gt; dependencies and explicitly add Qpid 0.14 ones (download them and install in your local repo) there will be an exception thrown from &lt;code&gt;camel-amqp&lt;/code&gt; component as there is no longer a default &lt;code&gt;ConnectionFactory&lt;/code&gt; constructor.&lt;br /&gt;
&lt;br /&gt;
Thus I was forced to install Qpid.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Qpid&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I downloaded the Java server and simply run it. There is no web management console, but that's OK. You can use JConsole for JMX.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Spring AMQP and Qpid&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In order to make Spring AMQP work with Qpid copy and paste the following configuration:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;camelContext xmlns="http://camel.apache.org/schema/spring"&amp;gt;
 &amp;lt;route&amp;gt;
  &amp;lt;from uri="amqp:queue:queue" /&amp;gt;
  &amp;lt;to uri="log:Message" /&amp;gt;
 &amp;lt;/route&amp;gt;
&amp;lt;/camelContext&amp;gt;

&amp;lt;bean id="amqp" class="org.apache.camel.component.amqp.AMQPComponent"&amp;gt;
 &amp;lt;property name="connectionFactory" ref="amqConnectionFactory" /&amp;gt;
&amp;lt;/bean&amp;gt;

&amp;lt;bean id="amqConnectionFactory" class="org.apache.qpid.client.AMQConnectionFactory"&amp;gt;
 &amp;lt;property name="host" value="localhost" /&amp;gt;
 &amp;lt;property name="port" value="5672" /&amp;gt;
 &amp;lt;property name="defaultUsername" value="guest" /&amp;gt;
 &amp;lt;property name="defaultPassword" value="guest" /&amp;gt;
 &amp;lt;property name="virtualPath" value="/development" /&amp;gt;
&amp;lt;/bean&amp;gt;&lt;/pre&gt;&lt;br /&gt;
As you can see in the above snippet I explicitly created &lt;code&gt;AMPQComponent&lt;/code&gt; with &lt;code&gt;connectionFactory&lt;/code&gt; set to Apache Qpid &lt;code&gt;AMQConnectionFactory&lt;/code&gt; object.  &lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Source code and working example&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This solution is a part of the Qualitas project. I use Spring MVC to handle uploads of business processes bundles (e.g., zipped archive of a WS-BPEL process) and send it to AMQP queue. Then Apache Camel consumes the message, does additional processing of the bundle, and installs it on a remote business process execution engine.&lt;br /&gt;
&lt;br /&gt;
The projects you are most interested in are:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;qualitas-webapp (Spring MVC sending message to AMQP)&lt;/li&gt;
&lt;li&gt;qualitas-internall-installation (Apache Camel route consuming messages from AMQP)&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
To check out 0.0.2-SNAPSHOT tag from here: &lt;a href="http://code.google.com/p/qualitas/source/browse/" target="_blank"&gt;http://code.google.com/p/qualitas/source/browse/&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Qualitas&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Read more about Qualitas project here: &lt;a href="http://code.google.com/p/qualitas/" target="_blank"&gt;http://code.google.com/p/qualitas/&lt;/a&gt;. Happy to welcome new developers on board!&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-6999748900695710986?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dM7Ak0Yuc076PpaonpoMEZ-38Rg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dM7Ak0Yuc076PpaonpoMEZ-38Rg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dM7Ak0Yuc076PpaonpoMEZ-38Rg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dM7Ak0Yuc076PpaonpoMEZ-38Rg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/okfxPZarP34" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/6999748900695710986/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=6999748900695710986" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/6999748900695710986?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/6999748900695710986?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/okfxPZarP34/amqp-rabbitmq-spring-apache-camel-and.html" title="AMQP: RabbitMQ, Spring, Apache Camel, and Apache Qid" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2012/02/amqp-rabbitmq-spring-apache-camel-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYGRHY5fSp7ImA9WhRUE00.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-2458906443878834583</id><published>2012-01-23T09:25:00.000+01:00</published><updated>2012-01-23T09:25:25.825+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-23T09:25:25.825+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="qualitas" /><title>Resolutions - 2012 Edition</title><content type="html">Everyone has New Year's resolutions. Here is mine: open-source and completely overhaul my PhD system.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;The original system&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The original system (code name: MS DIES) is written in Java EE 5. The frontent is JSF 1.2 (Facelets, MyFaces, Tomahawk) and the backend is EJB 3.0 (Web Services, SLSB, MDB). The original system runs on Apache Geronimo 2.2 and uses IBM DB2 pureXML as its database.&lt;br /&gt;
&lt;br /&gt;
Here are some screenshots of the original system: &lt;a href="http://code.google.com/p/qualitas/wiki/ScreenshotsOfOldSystem" target="_blank"&gt;http://code.google.com/p/qualitas/wiki/ScreenshotsOfOldSystem&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;The new system&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
New system got a new name: Qualitas. It will be more lightweight (Spring 3.0 and/or Geronimo 3.0 + Aries). I also would like to replace all internal processes (Web Services, EJB, MDB) with Apache Camel routes and use some other sexy technologies (JBoss Drools for computing quality scores, AMPQ instead of JMS, etc.). I already know IBM DB2 pureXML so I'm considering evaluating Oracle and its XML support.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Short term objectives&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I'm especially tempted with using Apache Geronimo 3.0 and Aries! But that's a longer term objective. The very first one would be to create a Little-Q distribution which will contain all core processes and will offer means of embedding it into other products. On top of Little-Q I plan to create the complete system, the fully fledged Qualitas. The front-end would most probably look like the orginal one (screenshots above show MyFaces + Tomahawk and maybe I will use RichFaces or some other JSF + AJAX stuff).&lt;br /&gt;
&lt;br /&gt;
I would like to release Little-Q in 6 months time. The prototype will support gathering, analysing, and computing quality scores for WS-BPEL processes running on Apache ODE engine.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;Project info&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The Qualitas is hosted on Google Code: &lt;a href="https://code.google.com/p/qualitas/" target="_blank"&gt;https://code.google.com/p/qualitas/&lt;/a&gt;. Its license is Apache License 2.0. So you can do what ever you like with it! Follow to get updates on the progress. And yes, you are most welcomed to join the project!&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-2458906443878834583?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vaEyXgZzmbpzjNgFRoihNjwU_PM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vaEyXgZzmbpzjNgFRoihNjwU_PM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vaEyXgZzmbpzjNgFRoihNjwU_PM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vaEyXgZzmbpzjNgFRoihNjwU_PM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/bqNapfjD7Zc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/2458906443878834583/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=2458906443878834583" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/2458906443878834583?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/2458906443878834583?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/bqNapfjD7Zc/resolutions-2012-edition.html" title="Resolutions - 2012 Edition" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2012/01/resolutions-2012-edition.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAAQXc4cCp7ImA9WhRQGUg.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-6010817709716449246</id><published>2011-11-25T09:55:00.001+01:00</published><updated>2011-12-15T13:55:40.938+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-15T13:55:40.938+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="mobile" /><category scheme="http://www.blogger.com/atom/ns#" term="notifications" /><category scheme="http://www.blogger.com/atom/ns#" term="apns" /><category scheme="http://www.blogger.com/atom/ns#" term="ac2dm" /><title>iOS and Android push notifications from Java</title><content type="html">For a couple of past weeks I have been working as a Technical Architect in a mobile application for a large bank (or should I say an insurance department of that bank). The application was written in PhoneGap and Sencha Touch. Two platforms were supported: iOS and Android. I was responsible (apart of many other things) for developing notifications for iOS and Android. The notification simply told the insurance agent how many cases &amp;amp; actions were updated/changed.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Sending notifications to iOS devices&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In order to use Apple Push Notification Service (APNS), apart of standard developer's certificate and a valid provisioning profile, you need one more thing. You need the APNS ceritificate which is used for mutual authorisation. You can generate it from Apple's iOS Provisioning Portal. Once you have it, you're ready to send notifcations.&lt;br /&gt;
&lt;br /&gt;
APNS is using a binary protocol. Of course you don't have to implement it from the scratch. You can use a very good and throughtly tested notnoop java-apns library which is available here: &lt;a href="https://github.com/notnoop/java-apns"&gt;https://github.com/notnoop/java-apns&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Using it is extremelly simple, the following code works fine (&lt;code&gt;Notification&lt;/code&gt; is my internal class):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: java"&gt;@Service
@Qualifier("Apns")
public class ApnsPushNotificationServiceImpl implements PushNotificationService {
 private Resource certResource;
 private String certPassword;
 private boolean useProductionServer;
 private String serverAddress;
 private static final int DEFAULT_APNS_PORT = 2195;
 public void setCertResource(Resource certResource) {
  this.certResource = certResource;
 }
 public void setCertPassword(String certPassword) {
  this.certPassword = certPassword;
 }
 public void setUseProductionServer(boolean useProductionServer) {
  this.useProductionServer = useProductionServer;
 }
 public void setServerAddress(String serverAddress) {
  this.serverAddress = serverAddress;
 }
 public void pushNotification(Notification notification) {
  List&amp;lt;Notification&amp;gt; notList = new ArrayList&amp;lt;Notification&amp;gt;();
  notList.add(notification);
  pushNotifications(notList);
 }
 public void pushNotifications(List&amp;lt;Notification&amp;gt; notifications) {
  ApnsService service = createApnsService();
  service.start();
  for (Notification notification : notifications) {
   doSendNotification(notification, service);
  }
  service.stop();
 }
 private ApnsService createApnsService() {
  ApnsService service = null;
  ApnsServiceBuilder serviceBuilder = APNS.newService()
    .withCert(certResource.getInputStream(), certPassword);
  if (null != serverAddress &amp;amp;&amp;amp; serverAddress.length() &amp;gt; 0) {
   serviceBuilder.withGatewayDestination(serverAddress,
     DEFAULT_APNS_PORT);
  } else if (useProductionServer) {
   serviceBuilder.withProductionDestination();
  } else {
   serviceBuilder.withSandboxDestination();
  }
  service = serviceBuilder.build();
  return service;
 }
 private void doSendNotification(Notification notification,
   ApnsService service) {
  PayloadBuilder payloadBuilder = APNS.newPayload();
  payloadBuilder = payloadBuilder.badge(notification.getBadge());
  payloadBuilder = payloadBuilder.sound(notification.getSound());
  if (notification.getBody() != null) {
   payloadBuilder = payloadBuilder.alertBody(notification.getBody());
  }
  String payload = payloadBuilder.build();
  service.push(notification.getDeviceToken(), payload);
 }
&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Sending notification to Android devices&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In comparison to iOS notifications, implemeting the Android Cloud 2 Device Messaging (AC2DM) was a piece of cake. I didn't need any third part library. Thanks to simple and clear Google's RESTful services, I was able to write a code responsible for pushing notifications to Android devices in less than an hour. &lt;br /&gt;
&lt;br /&gt;
The whole process comprises of 2 steps. The first one is authentication, the second one is the actual pushing of a notification. The source code is as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: java"&gt;@Service
@Qualifier("Ac2dm")
public class Ac2dmPushNotificationServiceImpl implements PushNotificationService {
 private String sendingRoleAccount;
 private String sendingRolePassword;
 public void pushNotification(Notification notification) {
  List&amp;lt;Notification&amp;gt; notList = new ArrayList&amp;lt;Notification&amp;lt;();
  notList.add(notification);
  pushNotifications(notList);
 }
 public void pushNotifications(List&amp;lt;Notification&amp;gt; notifications) {
  try {
   HttpClient client = new HttpClient();
   PostMethod method = new PostMethod(
     "https://www.google.com/accounts/ClientLogin");
   method.addParameter("Email", sendingRoleAccount);
   method.addParameter("Passwd", sendingRolePassword);
   method.addParameter("accountType", "HOSTED_OR_GOOGLE");
   method.addParameter("source", "unit-test");
   method.addParameter("service", "ac2dm");
   client.executeMethod(method);
   byte[] responseBody = method.getResponseBody();
   String response = new String(responseBody);
   String auth = response.split("\n")[2];
   String token = auth.split("=")[1];
   for (Notification notification : notifications) {
    doSendNotification(notification, token, client);
   }
  } catch (Throwable t) {
   throw new RuntimeException(t);
  }
 }
 private void doSendNotification(Notification notification, String token, HttpClient client) throws HttpException, IOException {
  PostMethod method = new PostMethod("https://android.apis.google.com/c2dm/send");
  method.addParameter("registration_id", notification.getDeviceToken());
  method.addParameter("collapse_key", "collapse");
  method.addParameter("data.payload", notification.getBadge().toString());  
  Header header = new Header("Authorization", "GoogleLogin auth="+token);
  method.addRequestHeader(header);
  client.executeMethod(method);  
  byte[] responseBody = method.getResponseBody();  
  String response = new String(responseBody);
 }
 public void setSendingRoleAccount(String sendingRoleAccount) {
  this.sendingRoleAccount = sendingRoleAccount;
 }
 public void setSendingRolePassword(String sendingRolePassword) {
  this.sendingRolePassword = sendingRolePassword;
 }
&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;A Note on WebSphere &amp;amp; IBM's Java 5&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
When the application was deployed to the UAT server and we tried to run integration test responsible for pushing notification to one of our test iPhones, we saw "java.security.InvalidKeyException: Illegal key size" message in the log. After many hours of investigation it turned out that, IBM's Java 5 supports only 512 key sizes. We had to update IBM's Java 5 security jars in order to make it read the APNS certificate.&lt;br /&gt;
&lt;br /&gt;
-1 for IBM!&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
It took me some time, but when you see a notifications coming to your device, then using PhoneGap, you launch a JavaScript application which looks like a native app, it makes you feel good :)&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-6010817709716449246?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/p3NvHGp5PicSRtd2iNlQ_nicOV8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/p3NvHGp5PicSRtd2iNlQ_nicOV8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/p3NvHGp5PicSRtd2iNlQ_nicOV8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/p3NvHGp5PicSRtd2iNlQ_nicOV8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/1lqVlqO6A9Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/6010817709716449246/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=6010817709716449246" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/6010817709716449246?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/6010817709716449246?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/1lqVlqO6A9Q/ios-and-android-push-notifications-from.html" title="iOS and Android push notifications from Java" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/11/ios-and-android-push-notifications-from.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUGQn48eyp7ImA9WhdbE08.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-3323844763273891400</id><published>2011-10-11T10:37:00.000+02:00</published><updated>2011-10-11T10:37:03.073+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-11T10:37:03.073+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="spring" /><category scheme="http://www.blogger.com/atom/ns#" term="security" /><title>Customising Spring Security (for mobile application)</title><content type="html">Last time I used Spring Security it was called Acegi Security. So quite a long time ago.&lt;br /&gt;
&lt;br /&gt;
I'm currently TA in 2 projects and one of them is a mobile application written in Phone Gap. This application communicates with a backend server using RESTful Web Services.&lt;br /&gt;
&lt;br /&gt;
One of my task was to write a security module for our application.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;UserDetailsService&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div class="fullpost"&gt;&lt;br /&gt;
My first task was to write &lt;code&gt;UserDetailsService&lt;/code&gt;. We didn't have and didn't want to have Spring-specific user and role tables. In many Java EE application servers you have to write custom SQL which returns you users and roles. Spring went 1 step farther. You don't have to write any SQL selects, you can implement &lt;code&gt;UserDetailsService&lt;/code&gt; interface and inject your DAOs there. For me this a great and powerful feature! So, all I had to do was to implement this 1 method:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;&lt;/pre&gt;&lt;br /&gt;
It took me a few seconds to implement. I injected &lt;code&gt;@Repository&lt;/code&gt; DAO objects and simply called the find methods. Then I created an instance of Spring-specific &lt;code&gt;UserDetails&lt;/code&gt; object and simply returned it.&lt;br /&gt;
&lt;br /&gt;
Next thing was to define authentication manager in Spring context file with a reference to my &lt;code&gt;mobileUserDetailsService&lt;/code&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;security:authentication-manager&amp;gt;
 &amp;lt;security:authentication-provider user-service-ref="mobileUserDetailsService"&amp;gt;
  &amp;lt;security:password-encoder hash="sha-256" /&amp;gt;
 &amp;lt;/security:authentication-provider&amp;gt;
&amp;lt;/security:authentication-manager&amp;gt;&lt;/pre&gt;&lt;br /&gt;
And I was done.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Method-level security&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The second thing I wanted to do was to secure method calls instead of URL patterns (as you know RESTful URLs have common parts). I decided to use Spring's &lt;code&gt;@Secured("ROLE_XXX")&lt;/code&gt; annotations. To enable method-level security all I had to do was to add the following XML element to Spring configuration file:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;security:global-method-security secured-annotations="enabled"&amp;gt;
&amp;lt;/security:global-method-security&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Nice.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Exposing authentication API over RESTful Web Services&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The very last thing was to use a expose Spring's authentication API over RESTful Web Services. I wrote a &lt;code&gt;MobileAuthenticationManager&lt;/code&gt; which was called by my RESTful Web Service.&lt;br /&gt;
&lt;br /&gt;
I only had one problem with Spring not being able to inject &lt;code&gt;AuthenticationManager&lt;/code&gt; becuase there were 2 instances of it in my project. I decided to implement &lt;code&gt;ApplicationContextAware&lt;/code&gt; interface and inside the &lt;code&gt;setApplicationContext()&lt;/code&gt; method retrieve manually&amp;nbsp;&lt;code&gt;org.springframework.security.authenticationManager&lt;/code&gt; bean. It looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;@Service
public class MobileAuthenticationManagerImpl implements
  MobileAuthenticationManager, ApplicationContextAware {
 protected AuthenticationManager authenticationManager;
 @Autowired
 protected MobDeviceDao mobDeviceDao;
 public Authentication authenticate(String username, String pin) {
  Authentication request = new UsernamePasswordAuthenticationToken(username, pin);
  Authentication result = null;
  try {
   result = authenticationManager.authenticate(request);
  } catch (BadCredentialsException e) {
   // some more code here
  }
  SecurityContextHolder.getContext().setAuthentication(result);
  // some more code removed here
  return result;
 }
 public boolean clearSecurityContext(String deviceId, String pin) {  
  invalidateSecurityContext();  
  return true;
 } 
 public void invalidateSecurityContext() {
  SecurityContextHolder.getContext().setAuthentication(null);
 }
 public void setApplicationContext(ApplicationContext applicationContext)
   throws BeansException {
  authenticationManager = (AuthenticationManager) applicationContext.getBean("org.springframework.security.authenticationManager");
 }
}&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Login and invalid session pages&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The very last thing was to change default &lt;code&gt;login-page&lt;/code&gt; and &lt;code&gt;invalid-session-url&lt;/code&gt; to &lt;code&gt;/logout.json&lt;/code&gt; file which contained a JSON logout response.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;security:http create-session="always" &amp;gt;
 &amp;lt;security:form-login login-page="/logout.json"  /&amp;gt;
 &amp;lt;security:session-management invalid-session-url="/logout.json" /&amp;gt;
&amp;lt;/security:http&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I have to say that Spring (Acegi) Security changed a lot during those nearly 3.5 years when I last used it! It was a piece of cake to write a fully custom security module. Nice work Spring developers! &lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-3323844763273891400?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ktb4RlMGq54-z5mKdb_xq0h7EFs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ktb4RlMGq54-z5mKdb_xq0h7EFs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ktb4RlMGq54-z5mKdb_xq0h7EFs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ktb4RlMGq54-z5mKdb_xq0h7EFs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/H3jMNnDfFHg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/3323844763273891400/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=3323844763273891400" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/3323844763273891400?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/3323844763273891400?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/H3jMNnDfFHg/customising-spring-security-for-mobile.html" title="Customising Spring Security (for mobile application)" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/10/customising-spring-security-for-mobile.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUACRX45fyp7ImA9WhRQGUg.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-5193167326549145890</id><published>2011-08-26T14:03:00.002+02:00</published><updated>2011-12-15T13:56:04.027+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-15T13:56:04.027+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><title>Spring.NET superiority over MS Unity and Ninject - proven</title><content type="html">I'm evaluating .NET-related technologies for the purpose of my latest project (desktop application for processing radiological and pathological images). Today I played with MS Unity and Ninject.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;I was quite surprised that either MS Unity nor Ninject are unable to handle bi-directional references, like these:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: csharp"&gt;class A
{
   B B { get; set; }
}

class B 
{
   A A { get; set; }
}&lt;/pre&gt;&lt;br /&gt;
Both MS Unity and Ninject enter infinite loop (create default constructor and set a break point there).&lt;br /&gt;
&lt;br /&gt;
Spring.NET resolves dependencies without any problems. A huge plus for Spring.NET.&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;br /&gt;
&lt;br /&gt;
p.s.&lt;br /&gt;
In case someone would argue why I use bi-directional references: it's a desktop application where implementing MVC/MVP requires view to have a reference to controller/presenter and controller/presenter to have a reference to view.&lt;br /&gt;
&lt;br /&gt;
p.s.2&lt;br /&gt;
I used latest versions of Unity and Ninject available in NuGet.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-5193167326549145890?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/py1lIAVmJSSDZhIJVYEVvqOvl78/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/py1lIAVmJSSDZhIJVYEVvqOvl78/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/py1lIAVmJSSDZhIJVYEVvqOvl78/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/py1lIAVmJSSDZhIJVYEVvqOvl78/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/DsodwqZDwp0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/5193167326549145890/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=5193167326549145890" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/5193167326549145890?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/5193167326549145890?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/DsodwqZDwp0/springnet-superiority-over-ms-unity-and.html" title="Spring.NET superiority over MS Unity and Ninject - proven" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/08/springnet-superiority-over-ms-unity-and.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMEQX4zfCp7ImA9WhdXEUo.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-1287621490567584673</id><published>2011-08-24T11:00:00.001+02:00</published><updated>2011-08-24T11:00:00.084+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-24T11:00:00.084+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><category scheme="http://www.blogger.com/atom/ns#" term="aspects" /><category scheme="http://www.blogger.com/atom/ns#" term="postsharp" /><title>Aspect Oriented Programming in .NET using PostSharp</title><content type="html">PostSharp is claiming to be the most comprehensive AOP library in the .NET world. I gave it a try and I must to say that their claim is very well founded.&lt;br /&gt;
&lt;br /&gt;
Read more to see PostSharp in action.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;PostSharp&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
PostSharp is not a free tool, but the trail version should be OK to get you started and do some proof of concepts.&lt;br /&gt;
&lt;br /&gt;
The best way to learn AOP and PostSharp itself is to watch PostSharp's podcasts. The usecases shown in those podcasts are well balanced, they are not too easy not too difficult. I suspect that even people without any previous AOP experience will get a pretty solid idea of what AOP is. The podcasts are here: &lt;a href="http://www.sharpcrafters.com/media/tutorials" target="_blank"&gt;http://www.sharpcrafters.com/media/tutorials&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Audit aspect&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I wanted to write a fine-grained audit aspect which could log execution traces. I wanted to be able to do something like this.&lt;br /&gt;
&lt;br /&gt;
1) Add &lt;code&gt;[Audit]&lt;/code&gt; attribute to methods:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;public class GenericDAO&amp;lt;T&amp;gt;
{
    [Audit("DAO")]
    public void Save(T entity)
    {
        /* ... */
    }
}&lt;/pre&gt;&lt;br /&gt;
2) Add &lt;code&gt;[Audit]&lt;/code&gt; attribute to classes, but be able to switch off auditing for some of the methods using &lt;code&gt;[NoAudit]&lt;/code&gt; attribute just like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[Audit("DAO")]
public class GenericDAO&amp;lt;T&amp;gt;
{
    [NoAudit]
    public GenericDAO()
    {
        /* ... */
    }
}&lt;/pre&gt;&lt;br /&gt;
It took me 10 minutes to write the following 2 aspects (note if I were to use them in production, which I'm sure I will in a few weeks, I would make them a slightly more optimised - like reduce reflections etc). Here they are:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[Serializable]
public sealed class AuditAttribute : OnMethodBoundaryAspect
{
    private readonly string _category;
    public AuditAttribute(string category)
    {
        _category = category;
    }
    public override bool CompileTimeValidate(MethodBase method)
    {
        object[] attributes = method.GetCustomAttributes(typeof(NoAuditAttribute), true);
        if (attributes.Length &amp;gt; 0)
        {
            Message.Write(SeverityType.Warning, "Audit", "Skipping auditing on " + method.DeclaringType.ToString() + " method " + method.ToString());
            return false;
        }
        return base.CompileTimeValidate(method);
    }
    public override void OnEntry(MethodExecutionArgs args)
    {
        StringBuilder sb = new StringBuilder();
        ParameterInfo[] parameterInfos = args.Method.GetParameters();
        for (int i = 0; i &amp;lt; parameterInfos.Length; i++)
        {
            ParameterInfo parameterInfo = parameterInfos[i];
            object parameterValue = args.Arguments[i] ?? "null";
            sb.AppendFormat("{0}={1}", parameterInfo.Name, parameterValue);
            if (i &amp;lt; parameterInfos.Length - 1)
            {
                sb.Append(", ");
            }
        }
        Trace.WriteLine(string.Format("Entering {0}.{1} {2}",
            args.Method.DeclaringType.Name, args.Method.Name, sb), _category);
        args.MethodExecutionTag = DateTime.Now;
    }
    public override void OnException(MethodExecutionArgs args)
    {
        Trace.WriteLine(string.Format("Exception " + args.Exception + " thrown in {0}.{1}",
            args.Method.DeclaringType.Name, args.Method.Name), _category);
    }
    public override void OnSuccess(MethodExecutionArgs args)
    {
        DateTime endTime = DateTime.Now;
        TimeSpan executionTime = endTime.Subtract((DateTime)args.MethodExecutionTag);
        bool isVoid = ((MethodInfo)args.Method).ReturnType == typeof(void);
        object returnValue;
        if (isVoid)
        {
            returnValue = "void";
        }
        else
        {
            returnValue = args.ReturnValue ?? "null";    
        }
        Trace.WriteLine(string.Format("Leaving {0}.{1} processing took me {2}ms return value was {3}",
            args.Method.DeclaringType.Name, args.Method.Name, executionTime, returnValue), _category);
    }
}
[Serializable]
public sealed class NoAuditAttribute : Attribute
{
}&lt;/pre&gt;&lt;br /&gt;
When &lt;code&gt;AuditAttribute&lt;/code&gt; is applied to class and a method has &lt;code&gt;NoAuditAttribute&lt;/code&gt; then a warning message "Skipping auditing on ClassABC method MethodXYZ" is displayed in MS VS errors tab (see &lt;code&gt;CompileTimeValidate&lt;/code&gt; method above).&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Applying different aspects to the same method&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Next I wanted to mix my aspects. Apart of auditing aspect I wrote a &lt;code&gt;ValidateAttribute&lt;/code&gt; and wanted to use it this way:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[Serializable]
public sealed class ValidateAttribute : OnMethodBoundaryAspect
{
    /* ... */
}
[Audit("DAO")]
public class GenericDAO&amp;lt;T&amp;gt;
{
    [Validate("Full")]
    public void Save(T entity)
    {
        /* ... */
    }
}&lt;/pre&gt;&lt;br /&gt;
There was one small issue with the above code. It worked, but PostSharp was saying that the order of aspects may have been undeterministic. But this is really not a problem with PostSharp. If I wanted to log the parameters before validation we should have added &lt;code&gt;AspectTypeDependency&lt;/code&gt; attribute to &lt;code&gt;ValidateAttribute&lt;/code&gt; just like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[AspectTypeDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, typeof(AuditAttribute))]&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
As an excercise you can write support for shadowing parameters. For example add a new parameter to the &lt;code&gt;AuditAttribute&lt;/code&gt; which would take an array of parameters' names to shadow (like username, password) and print either null if passed value is null or "*****" otherwise.&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-1287621490567584673?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/L_yiS9RuWe_6OY1eIYV0K0M0n60/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/L_yiS9RuWe_6OY1eIYV0K0M0n60/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/L_yiS9RuWe_6OY1eIYV0K0M0n60/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/L_yiS9RuWe_6OY1eIYV0K0M0n60/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/CriAjhvydJo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/1287621490567584673/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=1287621490567584673" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/1287621490567584673?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/1287621490567584673?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/CriAjhvydJo/aspect-oriented-programming-in-net.html" title="Aspect Oriented Programming in .NET using PostSharp" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/08/aspect-oriented-programming-in-net.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MBRXY8fCp7ImA9WhdQFko.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-5391020741270398517</id><published>2011-08-18T15:50:00.000+02:00</published><updated>2011-08-18T15:50:54.874+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-18T15:50:54.874+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="enterprise library" /><category scheme="http://www.blogger.com/atom/ns#" term="logging" /><title>MS Enterprise Library Logging</title><content type="html">Yesterday I played a little bit with MS Enterprise Library Validation. Today I tried the Logging Application Block. I like it. The number of options is just overwhelming. You can log to files, rolling files, system diagnostics, database, SMTP, MS queues, WMI, WCF, and I probably missed a few more.&lt;br /&gt;
&lt;br /&gt;
Today's post is a simple how-to post.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Project and database setup&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
For the database trace listener I had to create 3 tables and 4 stored procedures. The SQL statements are stored in &lt;code&gt;C:\path\to\your\EntLib50Src\Blocks\Logging\Src\DatabaseTraceListener\Scripts\LoggingDatabase.sql&lt;/code&gt; file. &amp;nbsp;Apart of creating a database&amp;nbsp;I had to create a "Database block" and define a valid connection string. And that was all.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Logging configuration&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I opened the visual editor and added Logging block. It took me 5 minutes to configure the following trace listeners: rolling file, SMTP, and database.&lt;br /&gt;
&lt;br /&gt;
My configuration file looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;configSections&amp;gt;
        &amp;lt;section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging" requirePermission="true" /&amp;gt;
        &amp;lt;section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data" requirePermission="true" /&amp;gt;
    &amp;lt;/configSections&amp;gt;
    &amp;lt;loggingConfiguration name="" tracingEnabled="true" defaultCategory="General"&amp;gt;
        &amp;lt;listeners&amp;gt;
            &amp;lt;add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
                listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
                formatter="Text Formatter" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack" /&amp;gt;
            &amp;lt;add name="Error Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
                listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
                fileName="error-rolling.log" formatter="Text Formatter" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack" /&amp;gt;
            &amp;lt;add name="Email Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.EmailTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
                listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.EmailTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
                toAddress="lukasz@xxx" fromAddress="from@example.com"
                smtpServer="exchange.xxx" formatter="Text Formatter"
                traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack" /&amp;gt;
            &amp;lt;add name="Database Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.Database.FormattedDatabaseTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging.Database"
                listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Database.Configuration.FormattedDatabaseTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging.Database"
                databaseInstanceName="SqlServer" writeLogStoredProcName="WriteLog"
                addCategoryStoredProcName="AddCategory" formatter="" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack" /&amp;gt;
        &amp;lt;/listeners&amp;gt;
        &amp;lt;formatters&amp;gt;
            &amp;lt;add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"
                template="Timestamp: {timestamp}{newline}
Message: {message}{newline}
Category: {category}{newline}
Priority: {priority}{newline}
EventId: {eventid}{newline}
Severity: {severity}{newline}
Title:{title}{newline}
Machine: {localMachine}{newline}
App Domain: {localAppDomain}{newline}
ProcessId: {localProcessId}{newline}
Process Name: {localProcessName}{newline}
Thread Name: {threadName}{newline}
Win32 ThreadId:{win32ThreadId}{newline}
Extended Properties: {dictionary({key} - {value}{newline})}"
                name="Text Formatter" /&amp;gt;
        &amp;lt;/formatters&amp;gt;
        &amp;lt;logFilters&amp;gt;
            &amp;lt;add type="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.CategoryFilter, Microsoft.Practices.EnterpriseLibrary.Logging"
                categoryFilterMode="DenyAllExceptAllowed" name="Category Filter"&amp;gt;
                &amp;lt;categoryFilters&amp;gt;
                    &amp;lt;add name="General" /&amp;gt;
                &amp;lt;/categoryFilters&amp;gt;
            &amp;lt;/add&amp;gt;
        &amp;lt;/logFilters&amp;gt;
        &amp;lt;categorySources&amp;gt;
            &amp;lt;add switchValue="All" name="General"&amp;gt;
                &amp;lt;listeners&amp;gt;
                    &amp;lt;add name="Rolling Flat File Trace Listener" /&amp;gt;
                &amp;lt;/listeners&amp;gt;
            &amp;lt;/add&amp;gt;
        &amp;lt;/categorySources&amp;gt;
        &amp;lt;specialSources&amp;gt;
            &amp;lt;allEvents switchValue="All" name="All Events"&amp;gt;
                &amp;lt;listeners&amp;gt;
                    &amp;lt;add name="Rolling Flat File Trace Listener" /&amp;gt;
                    &amp;lt;add name="Database Trace Listener" /&amp;gt;
                &amp;lt;/listeners&amp;gt;
            &amp;lt;/allEvents&amp;gt;
            &amp;lt;notProcessed switchValue="All" name="Unprocessed Category" /&amp;gt;
            &amp;lt;errors switchValue="All" name="Logging Errors &amp;amp; Warnings"&amp;gt;
                &amp;lt;listeners&amp;gt;
                    &amp;lt;add name="Error Rolling Flat File Trace Listener" /&amp;gt;
                &amp;lt;/listeners&amp;gt;
            &amp;lt;/errors&amp;gt;
        &amp;lt;/specialSources&amp;gt;
    &amp;lt;/loggingConfiguration&amp;gt;
    &amp;lt;dataConfiguration defaultDatabase="SqlServer" /&amp;gt;
    &amp;lt;connectionStrings&amp;gt;
        &amp;lt;add name="SqlServer" connectionString="data source=.\SQLEXPRESS1;Database=Logging;Trusted_Connection=True;MultipleActiveResultSets=True"
            providerName="System.Data.SqlClient" /&amp;gt;
    &amp;lt;/connectionStrings&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Source code&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Then I just used the &lt;code&gt;LogWriter&lt;/code&gt; in my code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;var source = new FileConfigurationSource("ModuleConfiguration.config");

var logWriter = new LogWriterFactory(source).Create();

logWriter.Write("Message 1", "BBB Category");
logWriter.Write("Message 2", "General");
logWriter.Write("Message 3", "AAA Category");&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Simple isn't it? The above code uses an external configuration file. When you use the logging configuration embedded in your &lt;code&gt;App.config&lt;/code&gt; it's even simpler as you don't have to use source objects and log factories - you just log entries using static method &lt;code&gt;Logger.Write()&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
Next thing. Aspect oriented programming and PostSharp!&lt;br /&gt;
&lt;br /&gt;
thanks,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-5391020741270398517?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/qeLZNLofCDzNtrFOu5zVxNojYUs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qeLZNLofCDzNtrFOu5zVxNojYUs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/qeLZNLofCDzNtrFOu5zVxNojYUs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/qeLZNLofCDzNtrFOu5zVxNojYUs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/9h9T8szVYso" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/5391020741270398517/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=5391020741270398517" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/5391020741270398517?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/5391020741270398517?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/9h9T8szVYso/ms-enterprise-library-logging.html" title="MS Enterprise Library Logging" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/08/ms-enterprise-library-logging.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8EQ3czcSp7ImA9WhdQFUo.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-4760062154775460197</id><published>2011-08-17T12:25:00.001+02:00</published><updated>2011-08-17T12:26:42.989+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-17T12:26:42.989+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="enterprise library" /><category scheme="http://www.blogger.com/atom/ns#" term="validation" /><title>MS Enterprise Library Validation</title><content type="html">Last week I played around with &lt;a href="http://jee-bpel-soa.blogspot.com/2011/08/springnet-validation.html" target="_blank"&gt;Spring.NET Validation&lt;/a&gt;. Today I gave MS Enterprise Library a try. In my opinion it's much more powerful than Spring.NET's counterpart. Read below to see why.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Getting Enterprise Library&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Simply download and install &lt;a href="http://msdn.microsoft.com/en-us/library/ff632023.aspx" target="_blank"&gt;Enterprise Library 5.0&lt;/a&gt;. Note: to write code which uses Enterprise Library you can use NuGet packages, but then you won't get things like a visual XML configuration editor (integrated with MS VS of course).&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;XML configuration approach&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Using the visual editor I was able to create validation rules for class &lt;code&gt;Person&lt;/code&gt;. Apart of simple validation rules I was able to create rule sets. Finally, I ended up with defining a "Full" rule set that requires all fields not to be null and &lt;code&gt;EmailAddress&lt;/code&gt; property to be a valid email and a "Partial" rule set which allowed &lt;code&gt;EmailAddress&lt;/code&gt; to be null.&lt;br /&gt;
&lt;br /&gt;
The configuration looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;validation&amp;gt;
    &amp;lt;type name="BusinessModuleTest.Person" defaultRuleset="Full"
        assemblyName="BusinessModuleTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"&amp;gt;
        &amp;lt;ruleset name="Full"&amp;gt;
            &amp;lt;properties&amp;gt;
                &amp;lt;property name="FirstName"&amp;gt;
                    &amp;lt;validator type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.NotNullValidator, Microsoft.Practices.EnterpriseLibrary.Validation"
                        messageTemplate="First name cannot be null" name="FirstName Not Null Validator" /&amp;gt;
                &amp;lt;/property&amp;gt;
                &amp;lt;property name="EmailAddress"&amp;gt;
                    &amp;lt;validator type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.RegexValidator, Microsoft.Practices.EnterpriseLibrary.Validation"
                        pattern="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" options="IgnoreCase"
                        messageTemplate="EmailAddress is not valid" name="Regular Expression Validator" /&amp;gt;
                &amp;lt;/property&amp;gt;
            &amp;lt;/properties&amp;gt;
        &amp;lt;/ruleset&amp;gt;
        &amp;lt;ruleset name="Partial"&amp;gt;
            &amp;lt;add type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.NotNullValidator, Microsoft.Practices.EnterpriseLibrary.Validation"
                messageTemplate="First name cannot be null" name="FirstName Not Null Validator" /&amp;gt;
        &amp;lt;/ruleset&amp;gt;
    &amp;lt;/type&amp;gt;
&amp;lt;/validation&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Then I wrote the following NUnit test:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestFixture]
public class EntLibValidationTest
{
    [Test]
    public void TestValidateTrue()
    {
        var source = new FileConfigurationSource("ModuleConfiguration.config");
        var validator = ValidationFactory.CreateValidatorFromConfiguration&amp;lt;Person&amp;gt;(source);
        var person = new Person() { FirstName = "Łukasz", EmailAddress = "lukasz@server.pl" };
        ValidationResults r = validator.Validate(person);
        Assert.IsTrue(r.IsValid);
    }
    [Test]
    public void TestValidateFalse()
    {
        var source = new FileConfigurationSource("ModuleConfiguration.config");
        var validator = ValidationFactory.CreateValidatorFromConfiguration(typeof(Person), "Full", source);
        var person = new Person() { FirstName = "Łukasz" };
        ValidationResults results = validator.Validate(person);
        Assert.IsFalse(results.IsValid);
        Assert.IsTrue(results.Count == 1);
        foreach (ValidationResult result in results)
        {
            Assert.AreEqual("EmailAddress", result.Key);
        }
    }
    [Test]
    public void TestValidatePartial()
    {
        var source = new FileConfigurationSource("ModuleConfiguration.config");
        var validator = ValidationFactory.CreateValidatorFromConfiguration(typeof(Person), "Partial", source);
        var person = new Person() { FirstName = "Łukasz" };
        ValidationResults results = validator.Validate(person);
        Assert.IsTrue(results.IsValid);
    }
}
public class Person
{
    public string FirstName { get; set; }
    public string EmailAddress { get; set; }
}&lt;/pre&gt;&lt;br /&gt;
All worked as expected.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Attributes approach&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Next I wanted to try the attributes approach. I wrote &lt;code&gt;Person2&lt;/code&gt; class which looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharop"&gt;public class Person2
{
    [NotNullValidator(ErrorMessage = "First name must not be null", Ruleset = "Full")]
    [NotNullValidator(ErrorMessage = "First name must not be null", Ruleset = "Partial")]
    public string FirstName { get; set; }
    [RegexValidator(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", MessageTemplate = "Email address is not valid", Ruleset = "Full")]
    public string EmailAddress { get; set; }
}&lt;/pre&gt;&lt;br /&gt;
A 1:1 mapping of what I defined earlier in XML file.&lt;br /&gt;
&lt;br /&gt;
Next thing was to write the validation test:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestFixture]
public class EntLibValidationAttributeTest
{
    [Test]
    public void TestValidateTrue()
    {
        var validator = ValidationFactory.CreateValidatorFromAttributes&amp;lt;Person2&amp;gt;("Full");
        var person = new Person2() { FirstName = "Łukasz", EmailAddress = "lukasz.budnik@gmail.com" };
        ValidationResults r = validator.Validate(person);
        Assert.IsTrue(r.IsValid);
    }
    [Test]
    public void TestValidateFalse()
    {
        var validator = ValidationFactory.CreateValidatorFromAttributes&amp;lt;Person2&amp;gt;("Full");
        var person = new Person2() { FirstName = "Łukasz" };
        ValidationResults results = validator.Validate(person);
        Assert.IsFalse(results.IsValid);
        Assert.IsTrue(results.Count == 1);
        foreach (ValidationResult result in results)
        {
            Assert.AreEqual("EmailAddress", result.Key);
        }
    }
    [Test]
    public void TestValidatePartial()
    {
        var validator = ValidationFactory.CreateValidatorFromAttributes&amp;lt;Person2&amp;gt;("Partial");
        var person = new Person2() { FirstName = "Łukasz" };
        ValidationResults results = validator.Validate(person);
        Assert.IsTrue(results.IsValid);
    }
}&lt;/pre&gt;&lt;br /&gt;
Again, all worked like a charm.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I must say I like Enterprise Library Validation much more than Spring.NET Validation (which is a surprise for me). Enterprise Library is internationalisation-ready and supports resource messages out of the box (I didn't use them in my simple examples, but I surely will use them in my production application).&lt;br /&gt;
&lt;br /&gt;
My next post will be about Enterprise Library Logging. Then I will move to more interesting parts like AOP with PostSharp and mocking with Moq.&lt;br /&gt;
&lt;br /&gt;
stay tuned,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-4760062154775460197?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4zT3Lp3MWf6RJCb7VfzTuaBbcC4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4zT3Lp3MWf6RJCb7VfzTuaBbcC4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4zT3Lp3MWf6RJCb7VfzTuaBbcC4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4zT3Lp3MWf6RJCb7VfzTuaBbcC4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/qMeUh4XI9NU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/4760062154775460197/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=4760062154775460197" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/4760062154775460197?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/4760062154775460197?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/qMeUh4XI9NU/ms-enterprise-library-validation.html" title="MS Enterprise Library Validation" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/08/ms-enterprise-library-validation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IEQ387eip7ImA9WhdQEUk.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-937782382672435591</id><published>2011-08-12T11:31:00.000+02:00</published><updated>2011-08-12T11:31:42.102+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-12T11:31:42.102+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="spring.net" /><category scheme="http://www.blogger.com/atom/ns#" term="validation" /><title>Spring.NET Validation</title><content type="html">As a part of investigating .NET world I started playing around with Spring.NET. Today I will show you some basics of Spring.NET validation.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Spring.NET Validation Basics&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Validation using Spring.NET is pretty straight forward. I created a &lt;code&gt;User&lt;/code&gt; class which looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;public class User
{
    public string Name { get; set; }
    public string Email { get; set; }
}&lt;/pre&gt;&lt;br /&gt;
Then I created a NUnit test and wrote first test method. I started with a simple &lt;code&gt;RequiredValidator&lt;/code&gt;. As a &lt;code&gt;test&lt;/code&gt; parameter I passed "Name" as I wanted to validate &lt;code&gt;Name&lt;/code&gt; property. The second parameter is null, I used it later on.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestFixture]
public class ValidatorTest
{
    [Test]
    public void TestRequiredValidator()
    {
        User user = new User() { Name = "Łukasz"};
        BaseValidator baseValidator = new RequiredValidator("Name", null);
        IValidationErrors errors = new ValidationErrors();
        bool valid = baseValidator.Validate(user, errors);
        Assert.IsTrue(valid);
    }
}&lt;/pre&gt;&lt;br /&gt;
Test passed.&lt;br /&gt;
&lt;br /&gt;
Maybe something a little bit more complex? Regular expression. Mind my first name is Łukasz and the letter Ł has to be explicitly added to the pattern (otherwise the test fails):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[Test]
public void TestRegexpValidator()
{
    User user = new User() { Name = "Łukasz" };
    BaseValidator baseValidator = new RegularExpressionValidator("Name", null, "[A-Za-zŁł]{2,}");
    IValidationErrors errors = new ValidationErrors();
    bool valid = baseValidator.Validate(user, errors);
    Assert.IsTrue(valid);
}&lt;/pre&gt;&lt;br /&gt;
OK. Nice. &lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Validator groups&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
So maybe we could validate more than one property in a single step? Why not. Spring.NET comes with validator groups. There are 3 different validator groups, here I use simple validator group (more in Spring.NET documentation):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[Test]
public void TestValidatorGroupTrue()
{
    User user = new User() { Name = "Łukasz", Email = "lukasz.budnik@gmail.com"};
    ValidatorGroup validatorGroup = new ValidatorGroup();
    validatorGroup.Validators.Add(new RegularExpressionValidator("Name", null, "[A-Za-zŁł]{2,}"));
    validatorGroup.Validators.Add(new EmailValidator("Email", null));
    IValidationErrors errors = new ValidationErrors();
    bool valid = validatorGroup.Validate(user, errors);
    Assert.IsTrue(valid);
}&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;when parameter&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
That works fine. But will regular expression validator work for the following scenario: name must not be null and must match the given regular expression? &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestValidatorGroupException()
{
    User user = new User() { Name = "Łukasz", Email = "lukasz.budnik@gmail.com" };
    ValidatorGroup validatorGroup = new ValidatorGroup();
    validatorGroup.Validators.Add(new RegularExpressionValidator("Name", null, "[A-Za-zŁł]{2,}"));
    validatorGroup.Validators.Add(new EmailValidator("Email", null));
    IValidationErrors errors = new ValidationErrors();
    bool valid = validatorGroup.Validate(user, errors);
    Assert.Fail("There should be an exception thrown by Validate() method");
}&lt;/pre&gt;&lt;br /&gt;
Actually no. The above test will throw an exception (see &lt;code&gt;ExpectedException&lt;/code&gt; attribute). In the above example when &lt;code&gt;Name&lt;/code&gt; property is null the regular expression validator throws &lt;code&gt;ArgumentException&lt;/code&gt; exception. So now what?&lt;br /&gt;
&lt;br /&gt;
Now is the time for the second parameter - the &lt;code&gt;when&lt;/code&gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;when&lt;/code&gt; defines an expression which tells the validator when the validation should be conducted. If the when expression evaluates to false, no action is taken.&lt;br /&gt;
&lt;br /&gt;
In my case when I wanted to check if name was not null and matched the regular expression I had to add two validators and regular expression validator had the &lt;code&gt;when&lt;/code&gt; parameter set to &lt;code&gt;"Name != null"&lt;/code&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[Test]
public void TestEnhancedValidatorGroup()
{
    User user = new User() { Name = null, Email = null };
    ValidatorGroup validatorGroup = new ValidatorGroup();
    validatorGroup.Validators.Add(new RequiredValidator("Name", null));
    validatorGroup.Validators.Add(new RegularExpressionValidator("Name", "Name != null", "[A-Za-zLl]{2,}"));
    IValidationErrors errors = new ValidationErrors();
    bool valid = validatorGroup.Validate(user, errors);
    Assert.IsFalse(valid);
    user.Name = "L";
    valid = validatorGroup.Validate(user, errors);
    Assert.IsFalse(valid);
    user.Name = "Lukasz";
    valid = validatorGroup.Validate(user, errors);
    Assert.IsTrue(valid);
}&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Quite nice. I just miss a handy profile-based validation, just like it is supported by JSR 303 and frameworks like Oval (I wrote a few posts about Java validation see the &lt;a href="http://jee-bpel-soa.blogspot.com/search/label/validation" target="_blank"&gt;validation&lt;/a&gt; label).&lt;br /&gt;
&lt;br /&gt;
My next post will be about MS Enterprise Library Validation.&lt;br /&gt;
&lt;br /&gt;
stay tuned,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-937782382672435591?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/FmrkO7JdafuLvCpYpgz7trGbE1c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FmrkO7JdafuLvCpYpgz7trGbE1c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/FmrkO7JdafuLvCpYpgz7trGbE1c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FmrkO7JdafuLvCpYpgz7trGbE1c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/FFYPgc2oPGY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/937782382672435591/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=937782382672435591" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/937782382672435591?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/937782382672435591?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/FFYPgc2oPGY/springnet-validation.html" title="Spring.NET Validation" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/08/springnet-validation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ICQXo4eCp7ImA9WhdQEEg.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-4560532001308427632</id><published>2011-08-11T12:46:00.000+02:00</published><updated>2011-08-11T12:46:00.430+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-11T12:46:00.430+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="spring.net" /><category scheme="http://www.blogger.com/atom/ns#" term="nunit" /><title>Spring.NET and NUnit</title><content type="html">As you already know I'm evaluating Spring.NET for a medical desktop software. I did a simple DI, AOP, internationalisation, and logging last week. I wrote about it here: &lt;a href="http://jee-bpel-soa.blogspot.com/2011/08/first-steps-with-springnet.html" target="_blank"&gt;First steps with Spring.NET&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Today I'll focus on testing.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Business logic module&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I wrote &lt;code&gt;IGreeterService&lt;/code&gt; and &lt;code&gt;IWordDictionaryService&lt;/code&gt; interfaces. Then I implemented both interfaces (I don't list dictionary service for brevity):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;public class GreeterService : IGreeterService
{
    public IWordDictionaryService Dictionary { get; set; }
    public string Greet(string name)
    {
    	// yes I know, very intelligent use of dictionary service - anyway it's just a test
        bool result = Dictionary.CheckWord("hello");
        return "Hello " + name + "! How are you?";
    }
}&lt;/pre&gt;&lt;br /&gt;
As you can see greeter service has a reference to dictionary service. I will use Spring.NET to inject it.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Spring.NET configuration file&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
When you are creating a class library project there is no &lt;code&gt;App.config&lt;/code&gt; file. Instead you have to create a &lt;code&gt;Context.xml&lt;/code&gt; file (or whatever name you want). The root element of this file must be &lt;code&gt;&amp;lt;objects /&amp;gt;&lt;/code&gt; element. Also, make sure the &lt;code&gt;Context.xml&lt;/code&gt; is an embedded resource. In my case I wrote something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;objects xmlns="http://www.springframework.net"&amp;gt;
    &amp;lt;object id="GreeterService" type="BusinessModule.Greeter.GreeterService" autowire="byType" /&amp;gt;
    &amp;lt;object id="WordDictionaryService" type="BusinessModule.Dictionary.WordDictionaryService" /&amp;gt;
    &amp;lt;object type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop"&amp;gt;
        &amp;lt;property name="ObjectNames"&amp;gt;
            &amp;lt;list&amp;gt;
                &amp;lt;value&amp;gt;*Service&amp;lt;/value&amp;gt;
            &amp;lt;/list&amp;gt;
        &amp;lt;/property&amp;gt;
        &amp;lt;property name="InterceptorNames"&amp;gt;
            &amp;lt;list&amp;gt;
                &amp;lt;value&amp;gt;SpringLoggingAroundAdvice&amp;lt;/value&amp;gt;
            &amp;lt;/list&amp;gt;
        &amp;lt;/property&amp;gt;
    &amp;lt;/object&amp;gt;
    &amp;lt;object name="SpringLoggingAroundAdvice" type="Spring.Aspects.Logging.SimpleLoggingAdvice, Spring.Aop"&amp;gt;
        &amp;lt;property name="LogUniqueIdentifier" value="false"/&amp;gt;
        &amp;lt;property name="LogExecutionTime"    value="true"/&amp;gt;
        &amp;lt;property name="LogMethodArguments"  value="true"/&amp;gt;
        &amp;lt;property name="LogReturnValue"      value="true"/&amp;gt;
        &amp;lt;property name="Separator"           value=";"/&amp;gt;
        &amp;lt;property name="LogLevel"            value="Info"/&amp;gt;
        &amp;lt;property name="HideProxyTypeNames"  value="true"/&amp;gt;
        &amp;lt;property name="UseDynamicLogger"    value="true"/&amp;gt;
    &amp;lt;/object&amp;gt;
&amp;lt;/objects&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Adding test project&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Once I had the class library ready I wanted to test it. I added test project to my solution. Apart of adding NUnit DLL references, I added &lt;code&gt;Spring.Core&lt;/code&gt;, &lt;code&gt;Spring.Aop&lt;/code&gt;, and &lt;code&gt;Spring.Testing.NUnit&lt;/code&gt; DLL references. Also, I added my business logic module as a project reference.&lt;br /&gt;
&lt;br /&gt;
I created a simple NUnit test as a subclass of Spring.NET's &lt;code&gt;AbstractDependencyInjectionSpringContextTests&lt;/code&gt; class (&lt;code&gt;ConfigLocations&lt;/code&gt; property must be overriden). &lt;br /&gt;
&lt;br /&gt;
My test looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestFixture]
public class DictionaryServiceTest : AbstractDependencyInjectionSpringContextTests
{
public IWordDictionaryService DictionaryService { get; set; }
[Test]
public void TestDictionaryServiceTrue()
{
    bool result = DictionaryService.CheckWord("hello");
    Assert.AreEqual(true, result);
}
[Test]
public void TestDictionaryServiceFalse()
{
    bool result = DictionaryService.CheckWord("qwq");
    Assert.AreEqual(false, result);
}
protected override string[] ConfigLocations
{
    get
    {
        return new string[] { "assembly://BusinessModule/BusinessModule.Config/BusinessModuleContext.xml" };
    }
}
}&lt;/pre&gt;&lt;br /&gt;
As you can see, nowhere in my code I refer to &lt;code&gt;ContextRegistry&lt;/code&gt;. By default Spring.NET tries to inject all matching objects into test's public properties. So &lt;code&gt;DictionaryService&lt;/code&gt; property of type &lt;code&gt;IWordDictionaryService&lt;/code&gt; is injected automatically.  In a matter of fact you can also inject objects into private fields/properties by setting the &lt;code&gt;PopulateProtectedVariables&lt;/code&gt; property to true in test's constructor.&lt;br /&gt;
&lt;br /&gt;
After testing dictionary service I tested greeter service. Everything worked fine. &lt;code&gt;IDictionaryService&lt;/code&gt; was autowired by type.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
That would be all. As I suspected testing Spring.NET applications is extremely easy.&lt;br /&gt;
&lt;br /&gt;
My next step would be to use Spring.NET Validation and compare it with MS Enterprise Library Validation.&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-4560532001308427632?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/eNvAlE4IHG3665d7_-0Z1rcIuVc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/eNvAlE4IHG3665d7_-0Z1rcIuVc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/eNvAlE4IHG3665d7_-0Z1rcIuVc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/eNvAlE4IHG3665d7_-0Z1rcIuVc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/bZPYx-8iWrE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/4560532001308427632/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=4560532001308427632" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/4560532001308427632?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/4560532001308427632?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/bZPYx-8iWrE/springnet-and-nunit.html" title="Spring.NET and NUnit" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/08/springnet-and-nunit.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEHR38-fSp7ImA9WhdRF0Q.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-1481210321896763326</id><published>2011-08-08T10:37:00.000+02:00</published><updated>2011-08-08T10:37:16.155+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-08T10:37:16.155+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="quality" /><category scheme="http://www.blogger.com/atom/ns#" term="gallio" /><category scheme="http://www.blogger.com/atom/ns#" term="testing" /><category scheme="http://www.blogger.com/atom/ns#" term="nunit" /><title>Testing .NET applications with Gallio</title><content type="html">So far I was using MSTest to write and run/debug unit test for my .NET applications. Why? Because MSTest works out of the box in MS VS.&lt;br /&gt;
&lt;br /&gt;
Last week I decided to try out NUnit. The meain reason was a problem with running MSTest tests on a build server. When you want to run MSTests on your build server, the build server complains about missing &lt;code&gt;Microsoft.VisualStudio&lt;/code&gt; namespace. In order to run my MSTests on a build server I had to install MS VS! Which is obviously pretty sick.&lt;br /&gt;
&lt;br /&gt;
The second reason was that once I started learning Spring.NET I decided that I would start writing tests in NUnit (Spring.NET supports both MSTest and NUnit). &lt;br /&gt;
&lt;br /&gt;
The third one was simply to try out something which sounded Java-like :)&lt;br /&gt;
&lt;br /&gt;
But this post is not about NUnit but Gallio.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Gallio&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
NUnit is not supported by MS VS 2010. I started googling in order to find somekind of a plugin for VS. On stackoverflow I found a link with many likes that led me to &lt;a href="http://www.gallio.org/" target="_blank"&gt;Gallio&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Gallio turned out to be test automation platform which supported many .NET testing tools. Gallio is not a test framework it's a test runner (and debugger with a little help of MS VS).&lt;br /&gt;
&lt;br /&gt;
I must say that it integrates surprisingly good with MS VS (or should I say ReSharper's Unit Test Runner). You can run/debug test directly from VS. Apart of running tests from VS, Gallio can run tests from command line (Gallio Echo) and Windows GUI (Gallio Icarus which can attach to VS debugger - works like a charm).&lt;br /&gt;
&lt;br /&gt;
Nice. I like it. For those of you who would like to see it in action a short screenshots-loaded official tutorial is here: &lt;a href="http://www.gallio.org/wiki/doku.php?id=getting_started:my_first_tests" target="_blank"&gt;http://www.gallio.org/wiki/doku.php?id=getting_started:my_first_tests&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Note. I also asked more experienced .NET guys from my company about .NET test platforms. Some of them were using &lt;a href="http://testdriven.net/" target="_blank"&gt;TestDriven.NET&lt;/a&gt;. It's not a free tool, but I heard it integrates with MS VS quite nicely.&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-1481210321896763326?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lKI32BLq89DHlP7_bRh1F_v7p2o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lKI32BLq89DHlP7_bRh1F_v7p2o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lKI32BLq89DHlP7_bRh1F_v7p2o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lKI32BLq89DHlP7_bRh1F_v7p2o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/QahyxfZNtJk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/1481210321896763326/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=1481210321896763326" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/1481210321896763326?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/1481210321896763326?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/QahyxfZNtJk/testing-net-applications-with-gallio.html" title="Testing .NET applications with Gallio" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/08/testing-net-applications-with-gallio.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkENQnc-fCp7ImA9WhdRFEk.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-8328487268937977883</id><published>2011-08-04T08:51:00.000+02:00</published><updated>2011-08-04T08:51:33.954+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-04T08:51:33.954+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="spring.net" /><category scheme="http://www.blogger.com/atom/ns#" term=".net" /><title>First steps with Spring.NET</title><content type="html">I was appointed as Technical Architect for a C++ desktop (medical softoware) project lately. But it turned out that the customer changed his mind and decided to go ahead with C# instead. In our company we have .NET and C# Technical Architects, but the management decided that I will be Technical Architect for this project anyway.&lt;br /&gt;
&lt;br /&gt;
So Java guy architecting a C# application. Nice.&lt;br /&gt;
&lt;br /&gt;
As a part of evaluating .NET technologies I decided to try Spring.NET. No one in my company has used it before.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Installing Spring.NET&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Installation is very straight forward. Download and execute the msi file (or was it exe?).&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;First project&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I created a Console Application. Then I added references to the following DLLs: &lt;code&gt;Spring.Core.dll&lt;/code&gt; and &lt;code&gt;Spring.Aop.dll&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
Then I pointed my browser to Spring.NET documentation web site. I found quite a few quick start articles. I started with the first one.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Dependency Injection&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Dependency injection works without any problems. Because I was already familiar with Spring framework I just scanned the documentation and I did a small mistake. In my case &lt;code&gt;IMovieFinder&lt;/code&gt; has a reference to &lt;code&gt;IMovieListener&lt;/code&gt;. In official documentation it's the oposite. Anyway it's just an exercise. My configuration looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;configSections&amp;gt;
        &amp;lt;sectionGroup name="spring"&amp;gt;
            &amp;lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&amp;gt;
            &amp;lt;section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /&amp;gt;
        &amp;lt;/sectionGroup&amp;gt;
    &amp;lt;/configSections&amp;gt;
    &amp;lt;spring&amp;gt;
        &amp;lt;context&amp;gt;
            &amp;lt;resource uri="config://spring/objects"/&amp;gt;
        &amp;lt;/context&amp;gt;
        &amp;lt;objects xmlns="http://www.springframework.net"&amp;gt;
            &amp;lt;description&amp;gt;An  example that demonstrates simple IoC features.&amp;lt;/description&amp;gt;
            &amp;lt;object id="MyMovieFinder" type="ConsoleApplication1.MovieFinder"&amp;gt;
                &amp;lt;property name="Lister" ref="MyMovieLister" /&amp;gt;
            &amp;lt;/object&amp;gt;
            &amp;lt;object id="MyMovieLister" type="ConsoleApplication1.MovieLister" /&amp;gt;
        &amp;lt;/objects&amp;gt;
    &amp;lt;/spring&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Logging&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Next thing I wanted to add was logging. It turned out that in .NET there is Common.Logging framework (architected after Apache commons-logging) which is a bride/abstraction for different logging frameworks. I tried to bridge it with Log4Net, but failed. Log4Net has a dependency to System.Web (sic!). I had to stay with default simple logger offered by Commmon.Logging.&lt;br /&gt;
&lt;br /&gt;
I added &lt;code&gt;Common.Logging.dll&lt;/code&gt; to my project. Then I added Common.Logging configuration to my App.config:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;configSections&amp;gt;
        &amp;lt;sectionGroup name="spring"&amp;gt;
            &amp;lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&amp;gt;
            &amp;lt;section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /&amp;gt;
        &amp;lt;/sectionGroup&amp;gt;
        &amp;lt;sectionGroup name="common"&amp;gt;
            &amp;lt;section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" /&amp;gt;
        &amp;lt;/sectionGroup&amp;gt;
    &amp;lt;/configSections&amp;gt;
    &amp;lt;spring&amp;gt;
        &amp;lt;context&amp;gt;
            &amp;lt;resource uri="config://spring/objects"/&amp;gt;
        &amp;lt;/context&amp;gt;
        &amp;lt;objects xmlns="http://www.springframework.net"&amp;gt;
            &amp;lt;description&amp;gt;An  example that demonstrates simple IoC features.&amp;lt;/description&amp;gt;
            &amp;lt;object id="MyMovieFinder" type="ConsoleApplication1.MovieFinder"&amp;gt;
                &amp;lt;property name="Lister" ref="MyMovieLister" /&amp;gt;
            &amp;lt;/object&amp;gt;
            &amp;lt;object id="MyMovieLister" type="ConsoleApplication1.MovieLister" /&amp;gt;
        &amp;lt;/objects&amp;gt;
    &amp;lt;/spring&amp;gt;
    &amp;lt;common&amp;gt;
        &amp;lt;logging&amp;gt;
            &amp;lt;factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging"&amp;gt;
                &amp;lt;arg key="level" value="INFO" /&amp;gt;
                &amp;lt;arg key="showLogName" value="true" /&amp;gt;
                &amp;lt;arg key="showDataTime" value="true" /&amp;gt;
                &amp;lt;arg key="dateTimeFormat" value="yyyy/MM/dd HH:mm:ss:fff" /&amp;gt;
            &amp;lt;/factoryAdapter&amp;gt;
        &amp;lt;/logging&amp;gt;
    &amp;lt;/common&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Aspect Oriented Programming&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
My next goal was to create an aspect that would log invocations of my business methods.&lt;br /&gt;
&lt;br /&gt;
Spring.Aop is based on AopAlliance so the concepts and API are almost the same as in Java. I wrote &lt;code&gt;LoggingAroundAdvice&lt;/code&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp;"&gt;using System.Text;
using AopAlliance.Intercept;
using Common.Logging;
namespace ConsoleApplication1
{
    public class LoggingAroundAdvice : IMethodInterceptor
    {
        public object Invoke(IMethodInvocation invocation)
        {
            ILog log = LogManager.GetLogger(invocation.Target.GetType());
            StringBuilder sb = new StringBuilder();
            if (invocation.Arguments != null)
            {
                foreach (object arg in invocation.Arguments)
                {
                    sb.Append(arg + " ");
                }
            }
            log.Info("Invoking " + invocation.Method.Name + " with following args =&amp;gt; " + sb.ToString());
            object result = invocation.Proceed();
            log.Info("Finished invoking " + invocation.Method.Name + " with result ==&amp;gt; " + result);
            return result;
        }
    }
}&lt;/pre&gt;&lt;br /&gt;
OK. Then I had to modify my &lt;code&gt;App.config&lt;/code&gt;. Instead of directly creating my classes I had to create &lt;code&gt;ProxyFactoryObject&lt;/code&gt; whose &lt;code&gt;target&lt;/code&gt; property was set to the original class. The configuration looked like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;configSections&amp;gt;
        &amp;lt;sectionGroup name="spring"&amp;gt;
            &amp;lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&amp;gt;
            &amp;lt;section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /&amp;gt;
        &amp;lt;/sectionGroup&amp;gt;
        &amp;lt;sectionGroup name="common"&amp;gt;
            &amp;lt;section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" /&amp;gt;
        &amp;lt;/sectionGroup&amp;gt;
    &amp;lt;/configSections&amp;gt;
    &amp;lt;spring&amp;gt;
        &amp;lt;context&amp;gt;
            &amp;lt;resource uri="config://spring/objects"/&amp;gt;
        &amp;lt;/context&amp;gt;
        &amp;lt;objects xmlns="http://www.springframework.net"&amp;gt;
            &amp;lt;description&amp;gt;An  example that demonstrates simple IoC features.&amp;lt;/description&amp;gt;
            &amp;lt;object id="MyMovieLister" type="Spring.Aop.Framework.ProxyFactoryObject"&amp;gt;
                &amp;lt;property name="target"&amp;gt;
                    &amp;lt;object id="MyMovieListerTarget" type="ConsoleApplication1.MovieLister, ConsoleApplication1"/&amp;gt;
                &amp;lt;/property&amp;gt;
                &amp;lt;property name="interceptorNames"&amp;gt;
                    &amp;lt;list&amp;gt;
                        &amp;lt;value&amp;gt;LoggingAroundAdvice&amp;lt;/value&amp;gt;
                    &amp;lt;/list&amp;gt;
                &amp;lt;/property&amp;gt;
            &amp;lt;/object&amp;gt;
            &amp;lt;object id="MyMovieFinder" type="Spring.Aop.Framework.ProxyFactoryObject"&amp;gt;
                &amp;lt;property name="target"&amp;gt;
                    &amp;lt;object id="MyMovieFinderTarget" type="ConsoleApplication1.MovieFinder, ConsoleApplication1"&amp;gt;
                        &amp;lt;property name="Lister" ref="MyMovieLister"/&amp;gt;
                    &amp;lt;/object&amp;gt;
                &amp;lt;/property&amp;gt;
                &amp;lt;property name="interceptorNames"&amp;gt;
                    &amp;lt;list&amp;gt;
                        &amp;lt;value&amp;gt;LoggingAroundAdvice&amp;lt;/value&amp;gt;
                    &amp;lt;/list&amp;gt;
                &amp;lt;/property&amp;gt;
            &amp;lt;/object&amp;gt;
            &amp;lt;object id="LoggingAroundAdvice" type="ConsoleApplication1.LoggingAroundAdvice, ConsoleApplication1"/&amp;gt;
        &amp;lt;/objects&amp;gt;
    &amp;lt;/spring&amp;gt;
    &amp;lt;common&amp;gt;
        &amp;lt;logging&amp;gt;
            &amp;lt;factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging"&amp;gt;
                &amp;lt;arg key="level" value="INFO" /&amp;gt;
                &amp;lt;arg key="showLogName" value="true" /&amp;gt;
                &amp;lt;arg key="showDataTime" value="true" /&amp;gt;
                &amp;lt;arg key="dateTimeFormat" value="yyyy/MM/dd HH:mm:ss:fff" /&amp;gt;
            &amp;lt;/factoryAdapter&amp;gt;
        &amp;lt;/logging&amp;gt;
    &amp;lt;/common&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;&lt;br /&gt;
But there was one problem with it. The XML configuration was blown out. Number of lines increased and the config was less human readable. I googled for a few seconds and found a better solution: &lt;code&gt;ObjectNameAutoProxyCreator&lt;/code&gt;. I updated my &lt;code&gt;App.config&lt;/code&gt; one more time: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;configSections&amp;gt;
        &amp;lt;sectionGroup name="spring"&amp;gt;
            &amp;lt;section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/&amp;gt;
            &amp;lt;section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" /&amp;gt;
        &amp;lt;/sectionGroup&amp;gt;
        &amp;lt;sectionGroup name="common"&amp;gt;
            &amp;lt;section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" /&amp;gt;
        &amp;lt;/sectionGroup&amp;gt;
    &amp;lt;/configSections&amp;gt;
    &amp;lt;spring&amp;gt;
        &amp;lt;context&amp;gt;
            &amp;lt;resource uri="config://spring/objects"/&amp;gt;
        &amp;lt;/context&amp;gt;
        &amp;lt;objects xmlns="http://www.springframework.net"&amp;gt;
            &amp;lt;description&amp;gt;An  example that demonstrates simple IoC features.&amp;lt;/description&amp;gt;
            &amp;lt;object id="MyMovieFinder" type="ConsoleApplication1.MovieFinder"&amp;gt;
                &amp;lt;property name="Lister" ref="MyMovieLister" /&amp;gt;
            &amp;lt;/object&amp;gt;
            &amp;lt;object id="MyMovieLister" type="ConsoleApplication1.MovieLister" /&amp;gt;
            &amp;lt;object id="LoggingAroundAdvice" type="ConsoleApplication1.LoggingAroundAdvice, ConsoleApplication1"/&amp;gt;
            &amp;lt;object type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop"&amp;gt;
                &amp;lt;property name="ObjectNames"&amp;gt;
                    &amp;lt;list&amp;gt;
                        &amp;lt;value&amp;gt;*Movie*&amp;lt;/value&amp;gt;
                    &amp;lt;/list&amp;gt;
                &amp;lt;/property&amp;gt;
                &amp;lt;property name="InterceptorNames"&amp;gt;
                    &amp;lt;list&amp;gt;
                        &amp;lt;value&amp;gt;LoggingAroundAdvice&amp;lt;/value&amp;gt;
                    &amp;lt;/list&amp;gt;
                &amp;lt;/property&amp;gt;
            &amp;lt;/object&amp;gt;
        &amp;lt;/objects&amp;gt;
    &amp;lt;/spring&amp;gt;
    &amp;lt;common&amp;gt;
        &amp;lt;logging&amp;gt;
            &amp;lt;factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging"&amp;gt;
                &amp;lt;arg key="level" value="INFO" /&amp;gt;
                &amp;lt;arg key="showLogName" value="true" /&amp;gt;
                &amp;lt;arg key="showDataTime" value="true" /&amp;gt;
                &amp;lt;arg key="dateTimeFormat" value="yyyy/MM/dd HH:mm:ss:fff" /&amp;gt;
            &amp;lt;/factoryAdapter&amp;gt;
        &amp;lt;/logging&amp;gt;
    &amp;lt;/common&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Much, much better. While googing I found out that there is already a logging aspect (which was not a surprise for me). To use it I just added the following object configuration:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml;"&gt;&amp;lt;object name="SpringLoggingAroundAdvice" type="Spring.Aspects.Logging.SimpleLoggingAdvice, Spring.Aop"&amp;gt;
    &amp;lt;property name="LogUniqueIdentifier" value="false"/&amp;gt;
    &amp;lt;property name="LogExecutionTime"    value="true"/&amp;gt;
    &amp;lt;property name="LogMethodArguments"  value="true"/&amp;gt;
    &amp;lt;property name="LogReturnValue"      value="true"/&amp;gt;
    &amp;lt;property name="Separator"           value=";"/&amp;gt;
    &amp;lt;property name="LogLevel"            value="Info"/&amp;gt;
    &amp;lt;property name="HideProxyTypeNames"  value="true"/&amp;gt;
    &amp;lt;property name="UseDynamicLogger"    value="true"/&amp;gt;
&amp;lt;/object&amp;gt;&lt;/pre&gt;&lt;br /&gt;
And changed &lt;code&gt;InterceptorNames&lt;/code&gt; property of the &lt;code&gt;ObjectNameAutoProxyCreator&lt;/code&gt; object to &lt;code&gt;SpringLoggingAroundAdvice&lt;/code&gt;. Worked like a charm.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Internationalisation&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
OK. Medical software has to support internationalisation. Spring.NET supports resx files. I created &lt;code&gt;Common.resx&lt;/code&gt; and &lt;code&gt;Common.pl-PL.resx&lt;/code&gt; files. I added definition for "Yes" word. Next I had to add two more objects to my &lt;code&gt;App.config&lt;/code&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml;"&gt;&amp;lt;object name="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core"&amp;gt;
    &amp;lt;property name="resourceManagers"&amp;gt;
        &amp;lt;list&amp;gt;
            &amp;lt;ref object="myResourceManager"/&amp;gt;
        &amp;lt;/list&amp;gt;
    &amp;lt;/property&amp;gt;
&amp;lt;/object&amp;gt;
&amp;lt;object name="myResourceManager" type="Spring.Objects.Factory.Config.ResourceManagerFactoryObject, Spring.Core"&amp;gt;
    &amp;lt;property name="baseName"&amp;gt;
        &amp;lt;value&amp;gt;ConsoleApplication1.Resources.Common&amp;lt;/value&amp;gt;
    &amp;lt;/property&amp;gt;
    &amp;lt;property name="assemblyName"&amp;gt;
        &amp;lt;value&amp;gt;ConsoleApplication1&amp;lt;/value&amp;gt;
    &amp;lt;/property&amp;gt;
&amp;lt;/object&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Too much lines of code! I found out much shorter solution (in a matter of fact you can mix both approaches):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml;"&gt;&amp;lt;object name="messageSource" type="Spring.Context.Support.ResourceSetMessageSource, Spring.Core"&amp;gt;
    &amp;lt;property name="resourceManagers"&amp;gt;
        &amp;lt;list&amp;gt;
            &amp;lt;value&amp;gt;ConsoleApplication1.Resources.Common, ConsoleApplication1&amp;lt;/value&amp;gt;
        &amp;lt;/list&amp;gt;
    &amp;lt;/property&amp;gt;
&amp;lt;/object&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Much better.&lt;br /&gt;
&lt;br /&gt;
In my application's code I wrote:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp;"&gt;string msg = ctx.GetMessage(Resources.Common.Yes, CultureInfo.CurrentCulture);
string msgPl = ctx.GetMessage(Resources.Common.Yes, new CultureInfo("pl-PL"));&lt;/pre&gt;&lt;br /&gt;
Ran the application and it worked.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Not too bad. Not too bad at all for a .NET application :)&lt;br /&gt;
&lt;br /&gt;
Stay tuned, I plan to write some NUnit tests for my Spring.NET project.&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-8328487268937977883?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kR9jfCOcceYfOHP3SKEUsRsvp1U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kR9jfCOcceYfOHP3SKEUsRsvp1U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kR9jfCOcceYfOHP3SKEUsRsvp1U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kR9jfCOcceYfOHP3SKEUsRsvp1U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/yFB2K_MdTWo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/8328487268937977883/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=8328487268937977883" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/8328487268937977883?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/8328487268937977883?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/yFB2K_MdTWo/first-steps-with-springnet.html" title="First steps with Spring.NET" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/08/first-steps-with-springnet.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cHRn06cSp7ImA9WhdSGU8.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-3629316295914788300</id><published>2011-07-29T10:43:00.000+02:00</published><updated>2011-07-29T10:43:57.319+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-29T10:43:57.319+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="quality" /><category scheme="http://www.blogger.com/atom/ns#" term="ci" /><category scheme="http://www.blogger.com/atom/ns#" term="project management" /><title>TeamCity - my first impressions</title><content type="html">So far I have been using CruiseControl as my CI server for both Java and .NET projects. This week I decided to give TeamCity a try.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Installation&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The installation is straight forward. For the Windows version you just download the installer and it takes care of everything else (except for pressing Next buttons).&lt;br /&gt;
&lt;br /&gt;
Once the installation is complete, TeamCity service starts and you can log in into TeamCity console.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Setting up project&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I have to say that for first 5 minutes I was a little bit muddled. I thought I would make it without reading the documentation.&amp;nbsp;I haven't used it before, but within 15 minutes I was able to find all information I needed from TeamCity web site which is a great plus.&amp;nbsp;Now that I have configured 3 projects in TeamCity I can say that the configuration is intuitive.&lt;br /&gt;
&lt;br /&gt;
In total (excluding time required to install SQL Server, SQL Server SP 2, SQL Server Management Studio, and VS 2010 - unfortunatelly we write tests in MSTest which use &lt;code&gt;Microsoft.VisualStudio&lt;/code&gt; namespace) it took me 15 minutes to configure the following things:&lt;br /&gt;
&lt;br /&gt;
1) Build project - 1st build step&lt;br /&gt;
2) Run MSTest tests - 2nd build step&lt;br /&gt;
3) Run code coverage analysis (TeamCity 6.x is shipped with dotCover) - part of 2nd build step&lt;br /&gt;
&lt;br /&gt;
While I was configuring my 2nd project it took me even less, aprox 5 minutes to configure:&lt;br /&gt;
&lt;br /&gt;
1) Build project&lt;br /&gt;
2) Run MSTest tests&lt;br /&gt;
3) Run code coverage analysis&lt;br /&gt;
4) Update email notification settings&lt;br /&gt;
&lt;br /&gt;
Nice.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;TeamCity for C++ developers&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;Yes. As a part of preparation to my next project I started playing around with C++ and it's support in VS. TeamCity can build C++ projects as Visual Studio Solutions. C++ unit tests are executed by MSTest tool. Source code coverage... works like a charm! I still have to find some kind of StyleCop for C++ and hook it into TeamCity.&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;TeamCity IDE plugins&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
TeamCity has many IDE plugins. They can be found on your TeamCity server. In my case I installed VS 2010 plugin (/update/vsAddinInstallerv4.msi) and universal tray notifier app (/update/TrayNotifierInstaller.msi). No problems at all. VS 2010 required restart.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
TeamCity looks like a really professional and powerful tool.&lt;br /&gt;
&lt;br /&gt;
Cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-3629316295914788300?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/mwrjTtNtTYttrLyf5ss-DNQ0xHY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mwrjTtNtTYttrLyf5ss-DNQ0xHY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/mwrjTtNtTYttrLyf5ss-DNQ0xHY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/mwrjTtNtTYttrLyf5ss-DNQ0xHY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/3qRgdptkRMk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/3629316295914788300/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=3629316295914788300" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/3629316295914788300?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/3629316295914788300?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/3qRgdptkRMk/teamcity-my-first-impressions.html" title="TeamCity - my first impressions" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/07/teamcity-my-first-impressions.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQGQH4-fyp7ImA9WhZaF0o.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-6128973914898801713</id><published>2011-07-04T10:49:00.001+02:00</published><updated>2011-07-04T12:12:01.057+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-04T12:12:01.057+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="jms" /><title>Two way communication in JMS</title><content type="html">Today I will debuke quite a popular myth about one-way only communication in JMS. There is no classic request-response&amp;nbsp;equivalent&amp;nbsp;of course (just like there is in AMQP), but a message may convey a reply to header containing a reference to a temporary queue. This way we can achieve two way communication in JMS.&lt;br /&gt;
&lt;br /&gt;
Below I give you a simple JUnit test which illustrates the idea.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Example&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In the following example I use a temporary queue and set it as JMS reply to header. The temporary queue exists as long as its creator's session is active. The code is pretty simple and self commenting. In &lt;code&gt;testA&lt;/code&gt; I create a message and a temporary queue which I expect to recieve a response from the consumer. Comsumer in &lt;code&gt;testB&lt;/code&gt; consumes the message, retrieves the reply to destination and sends a text message to it. &lt;code&gt;testC&lt;/code&gt; consumes the message from temporary queue. Once the session is closed, temporary queue is disposed and removed.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;public class AppTest {
 private static Connection connection;
 private static Session session;
 private static Destination destination;
 private static Destination replyToDestination;
 @BeforeClass
 public static void setup() throws JMSException {
  ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
    "tcp://localhost:62626");
  connection = connectionFactory.createConnection();
  connection.start();
  session = connection.createSession(true, Session.SESSION_TRANSACTED);
  destination = session.createQueue("Java.ActiveMQ.Test.Queue");
  replyToDestination = session.createTemporaryQueue();
 }
 @AfterClass
 public static void cleanup() throws JMSException {
  session.close();
  connection.stop();
  connection.close();
 }
 @Test
 public void testA() throws JMSException {
  MessageProducer producer = session.createProducer(destination);
  Person person = new Person();
  person.setFirstName("Lukasz");
  person.setLastName("Budnik");
  Message message = session.createObjectMessage(person);
  message.setJMSReplyTo(replyToDestination);
  producer.send(message);
  session.commit();
 }
 @Test
 public void testB() throws JMSException, InterruptedException {
  Person person = null;
  MessageConsumer consumer = session.createConsumer(destination);
  Message message;
  while ((message = consumer.receive(2000l)) != null) {
   if (message instanceof ObjectMessage) {
    ObjectMessage objectMessage = (ObjectMessage) message;
    Object object = objectMessage.getObject();
    if (object instanceof Person) {
     person = (Person) object;
     Assert.assertEquals("Lukasz", person.getFirstName());
     Assert.assertEquals("Budnik", person.getLastName());
     Destination replyToDestination = message.getJMSReplyTo();     
     MessageProducer replyToMessageProducer = session.createProducer(replyToDestination);
     Message replyMessage = session.createTextMessage("OK");
     replyToMessageProducer.send(replyMessage);     
     session.commit();
    }
   }
  }
  if (person == null) {
   Assert.fail("Person is null");
  }
 }
 @Test
 public void testC() throws JMSException, InterruptedException {
  String text = null;
  MessageConsumer consumer = session.createConsumer(replyToDestination);
  Message message;
  while ((message = consumer.receive(2000l)) != null) {
   if (message instanceof TextMessage) {
    TextMessage textMessage = (TextMessage) message;
    text = textMessage.getText();
    Assert.assertEquals("OK", text);     
    session.commit();
   }
  }
  if (text == null) {
   Assert.fail("Text is null");
  }
 }
}&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Simple, isn't it? This mechanism is used heavily in Apache Camel and WS frameworks which use transacted JMS under the hood for WS-RM implementations. Using those frameworks, temporary queues and reply to headers are being taken care of transparently so I may even not know that you use them :)&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-6128973914898801713?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nBlRKpPQiUT7Mk5oQ9_q71GDuwo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nBlRKpPQiUT7Mk5oQ9_q71GDuwo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nBlRKpPQiUT7Mk5oQ9_q71GDuwo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nBlRKpPQiUT7Mk5oQ9_q71GDuwo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/pfzQoYTY5_0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/6128973914898801713/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=6128973914898801713" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/6128973914898801713?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/6128973914898801713?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/pfzQoYTY5_0/two-way-communication-in-jms.html" title="Two way communication in JMS" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/07/two-way-communication-in-jms.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MMQXYycSp7ImA9WhZaEkg.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-1493339482275469548</id><published>2011-06-28T10:58:00.004+02:00</published><updated>2011-06-28T10:58:00.899+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-28T10:58:00.899+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="activemq" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>ActiveMQ and .NET combined!</title><content type="html">ActiveMQ is one of the most popular messaging frameworks. For sure the most popular open source framework. Many people think that ActiveMQ works only with Java and this is not true at all. ActiveMQ can work with almost every popular language (including JavaScript!) through numerous protocols which it supports.&lt;br /&gt;
&lt;br /&gt;
Today I will show you how to use ActiveMQ in .NET-based solutions.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Project setup&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Using VS 2010's Extension Manger I installed NuGet Package Manager. After installation and VS 2010 restart, I created a project called ActiveMQNMS. I right-clicked it and selected "Manage NuGet packages...". In the search field I typed: "ActiveMQ". There was a package called Apache.NMS.ActiveMQ. I installed it. (Note: ActiveMQ has one dependency - Apache.NMS package. The NMS package provides a unified API for working with different messaging frameworks and providers.)&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Starting ActiveMQ&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I already had ActiveMQ installed on my machine. If you don't have one, download it from &lt;a href="http://activemq.apache.org/" target="_blank"&gt;http://activemq.apache.org&lt;/a&gt;. The default instance listens on 61616 port. However, mine is listening on 62626. If you want to run my code, please remember to change the port.&lt;br /&gt;
&lt;br /&gt;
To start ActiveMQ I executed:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml;gutter:false"&gt;activemq-5.5.0\bin\activemq&lt;/pre&gt;&lt;br /&gt;
Depending on configured ports, you can use ActiveMQ web console to manage your queues, topics, subscribers, connections, embedded Apache Camel, etc. I'm using 8282 port, and the console URL is: http://localhost:8282/admin.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Test stub&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In general the .NET API is almost a copy of the Java API. So if you're familiar with JMS and/or ActiveMQ you don't need any documentation. Please note &lt;code&gt;TestIntialize&lt;/code&gt; and &lt;code&gt;TestCleanup&lt;/code&gt; methods.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;using System;
using Apache.NMS;
using Apache.NMS.ActiveMQ;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ActiveMQNMS
{
    [Serializable]
    public class Person
    {
        public string FirstName
        {
            get;
            set;
        }
        public string LastName
        {
            get; set;
        }
    }
    [TestClass]
    public class ActiveMqTest
    {
        private IConnection _connection;
        private ISession _session;
        private const String QUEUE_DESTINATION = "DotNet.ActiveMQ.Test.Queue";
        [TestInitialize]
        public void TestInitialize()
        {
            IConnectionFactory factory = new ConnectionFactory("tcp://localhost:62626");
            _connection = factory.CreateConnection();
            _connection.Start();
            _session = _connection.CreateSession();
        }
        [TestCleanup]
        public void TestCleanup()
        {
            _session.Close();
            _connection.Close();
        }
    }
}&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Writing Producer&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Here is the producer:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestMethod]
public void TestA()
{
    IDestination dest = _session.GetQueue(QUEUE_DESTINATION);
    using (IMessageProducer producer = _session.CreateProducer(dest))
    {
        var person = new Person
        {
            FirstName = "Łukasz",
            LastName = "Budnik"
        };
        var objectMessage = producer.CreateObjectMessage(person);
        producer.Send(objectMessage);
    }
}
&lt;/pre&gt;&lt;br /&gt;
Run the test and refresh "Queues" list in ActiveMQ web console. You should see &lt;code&gt;DotNet.ActiveMQ.Test.Queue&lt;/code&gt; queue with 1 enqueued and pending message. Purge the queue by hitting the purge link or you simply delete it.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Writing Consumer&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Now we have to consume the message. Here is the code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestMethod]
public void TestB()
{
    Person person = null;
    IDestination dest = _session.GetQueue(QUEUE_DESTINATION);
    using (IMessageConsumer consumer = _session.CreateConsumer(dest))
    {
        IMessage message;
        while ((message = consumer.Receive(TimeSpan.FromMilliseconds(2000))) != null)
        {
            var objectMessage = message as IObjectMessage;
            if (objectMessage != null)
            {
                person = objectMessage.Body as Person;
                if (person != null)
                {
                    Assert.AreEqual("Łukasz", person.FirstName);
                    Assert.AreEqual("Budnik", person.LastName);
                }
            }
            else
            {
                Assert.Fail("Object Message is null");
            }
        }
    }
    if (person == null)
    {
        Assert.Fail("Person object is null");
    }
}&lt;/pre&gt;&lt;br /&gt;
Run tests. Refresh "Queues" tab in ActiveMQ web console. You should see 1 message enqueued and 1 message dequeued. As expected.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
That's all. Simple, isn't it? ActiveMQ works very, very nicely with .NET.&lt;br /&gt;
&lt;br /&gt;
I have to find some performance comparison for ActiveMQ and MS or pure .C#/NET messaging frameworks. Or maybe you have it? Please share.&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-1493339482275469548?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Jq4kD6aH_T2LsdNHkznIdsxR1TQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jq4kD6aH_T2LsdNHkznIdsxR1TQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Jq4kD6aH_T2LsdNHkznIdsxR1TQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jq4kD6aH_T2LsdNHkznIdsxR1TQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/W8Cp8OUV84c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/1493339482275469548/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=1493339482275469548" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/1493339482275469548?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/1493339482275469548?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/W8Cp8OUV84c/activemq-and-net-combined.html" title="ActiveMQ and .NET combined!" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>8</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/06/activemq-and-net-combined.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUMQHw9fCp7ImA9WhZbFUg.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-8795390478342750154</id><published>2011-06-20T10:24:00.000+02:00</published><updated>2011-06-20T10:24:41.264+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-20T10:24:41.264+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><title>Passing backend data to JavaScript</title><content type="html">When you create your front-ends dynamically using JavaScript frameworks you have to work with the backend data: constants, URLs, labels, or localised labels.&lt;br /&gt;
&lt;br /&gt;
Properties files are made for this. The problem is when you use frameworks like SenchTouch and your HTML body looks like this: &amp;lt;body /&amp;gt;. The other problem is when some of the data is actually stored in database.&lt;br /&gt;
&lt;br /&gt;
A very bad idea is to hard code copies of these values in JavaScripts. The presentation layer should not store any of these.&lt;br /&gt;
&lt;br /&gt;
In general there are 3 ways of handling such situations. Here they are.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;1. Generating JavaScripts directly in views&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Here is an example of what I'm talking about:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:javascript"&gt;&amp;lt;script type="text/javascript"&amp;gt;
var App.Resources.OKButtonLabel = 'Depending on technology of your choice read the properties here';
&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Advantages:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;JavaScript is generated when web page is rendered&lt;/li&gt;
&lt;li&gt;it's fast&lt;/li&gt;
&lt;/ul&gt;Disadvantages:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;not the most elegant way&lt;/li&gt;
&lt;li&gt;static - generated only during the render phase&lt;/li&gt;
&lt;li&gt;uses only properties files&lt;/li&gt;
&lt;/ul&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;2. Generating JavaScripts on the fly&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
A sample:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:javascript"&gt;&amp;lt;script type="text/javascript" src="/dynamic/messages.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;br /&gt;
And the contents of given URL are generated dynamically.&lt;br /&gt;
&lt;br /&gt;
Advantages:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;more elegant than generating JavaScripts directly in views&lt;/li&gt;
&lt;li&gt;more flexible: can return data stored in properties files as well as data stored in database&lt;/li&gt;
&lt;/ul&gt;Disadvantages:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;browser has to download additional JavaScripts&lt;/li&gt;
&lt;li&gt;static - contents of external JavaScripts are loaded only onced&lt;/li&gt;
&lt;/ul&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;3. Using AJAX&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Advantages:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;fully dynamic behaviour&lt;/li&gt;
&lt;li&gt;data can be reloaded at any time&lt;/li&gt;
&lt;li&gt;supports dynamic localisation and language change&lt;/li&gt;
&lt;li&gt;can return data stored in properties files as well as data stored in database&lt;/li&gt;
&lt;/ul&gt;Disadvantages:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;asynchronous calls are slower by nature&lt;/li&gt;
&lt;li&gt;additional JavaScript logic is required&lt;/li&gt;
&lt;/ul&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
All 3 of the above approaches work, but when designing your application you have to balance all pros and cons and choose the one that suits your needs.&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-8795390478342750154?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xHXK7DTn_Q_9IAI6YcdLlmDxthY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xHXK7DTn_Q_9IAI6YcdLlmDxthY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xHXK7DTn_Q_9IAI6YcdLlmDxthY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xHXK7DTn_Q_9IAI6YcdLlmDxthY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/VBuIYgULQD0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/8795390478342750154/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=8795390478342750154" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/8795390478342750154?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/8795390478342750154?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/VBuIYgULQD0/passing-backend-data-to-javascript.html" title="Passing backend data to JavaScript" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/06/passing-backend-data-to-javascript.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcDR389fyp7ImA9WhZUEEw.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-2305094609876119942</id><published>2011-06-02T11:53:00.001+02:00</published><updated>2011-06-02T14:17:56.167+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-02T14:17:56.167+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="transactions" /><category scheme="http://www.blogger.com/atom/ns#" term="nhibernate" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><title>Transactions and Isolation Levels explained once and for all (nHibernate examples)</title><content type="html">A question about transactions and isolation levels is one of my favourites when interviewing software engineers. Some of them heard about it, some of them know what they are, some of them can list them, some of them can describe them in detail. But there are also developers that don't have the slightest idea what are isolation levels.&lt;br /&gt;
&lt;br /&gt;
Today, as a part of my nHibernate series I'll show you a unit test which shows you the behaviour of 4 isolation levels: read uncommitted, read committed, repeatable read, and serialisable.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;The project&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
For this excercise I used nHibernate project I wrote last time. The post is here: &lt;a href="http://jee-bpel-soa.blogspot.com/2011/05/playing-around-with-nhibernate-basics.html" target="_blank"&gt;Playing around with nHibernate: the basics&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Test structure&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
OK. To test concurent accesses I had to create 2 independent sessions and 2 independent transactions. I create sessions and transactions in &lt;code&gt;[TestInitialize]&lt;/code&gt; and dispose them in &lt;code&gt;[TestCleanup]&lt;/code&gt;. Just in case something goes wrong I delete all records from app_country in &lt;code&gt;[ClassCleanup]&lt;/code&gt; method.&lt;br /&gt;
&lt;br /&gt;
The structure looks like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestClass]
public class TransactionsTest
{

    private ISession SessionA { get; set; }
    private ISession SessionB { get; set; }
    private ITransaction TransactionA { get; set; }
    private ITransaction TransactionB { get; set; }

    [TestInitialize]
    public void Startup()
    {
        SessionA = OpenSession();
        SessionB = OpenSession();
        TransactionA = SessionA.BeginTransaction();
        TransactionB = SessionB.BeginTransaction();
    }

    [TestCleanup]
    public void Cleanup()
    {
        TransactionA.Dispose();
        TransactionB.Dispose();
        SessionA.Dispose();
        SessionB.Dispose();
    }

    [ClassCleanup]
    public static void ClassCleanup()
    {
        using (ISession session = OpenSession())
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                IQuery query = session.CreateSQLQuery("delete from app_country");
                query.ExecuteUpdate();
                transaction.Commit();
            }
        }
    }

    private static ISessionFactory _sessionFactory;
    private static ISession OpenSession()
    {
        if (_sessionFactory == null)
        {
            Configuration configuration = new Configuration();
            configuration.AddAssembly(Assembly.GetCallingAssembly());
            _sessionFactory = configuration.BuildSessionFactory();
        }
        return _sessionFactory.OpenSession();
    }
}&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Rolling back transactions&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Before I show you the isolation levels I'd like to show you how to rollback a transaction. The code is very simple and self commenting:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestMethod]
public void TestRollback()
{
    Country country = new Country()
    {
        Description = "Poland",
        ContinentId = 1
    };

    try
    {
        SessionA.Save(country);
        Assert.IsTrue(country.Id &amp;gt; 0);
        TransactionA.Rollback();
        Assert.IsTrue(TransactionA.WasRolledBack);
        IQuery query = SessionA.CreateQuery("FROM Country WHERE Id = :id");
        query.SetInt32("id", country.Id);
        Country nonExistingRolledBackCountry = query.UniqueResult&amp;lt;Country&amp;gt;();
        Assert.IsNull(nonExistingRolledBackCountry);
    }
    catch (Exception e)
    {
        Assert.Fail("Test failed " + e.Message);
    }
}&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Default Isolation Level&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
OK. When you create a transaction using just &lt;code&gt;BeginTransaction()&lt;/code&gt; (without the isolation level parameter) it starts the transaction in default isolcation level. If you don't know what is the default isolation level you will know it after reading this post :)&lt;br /&gt;
&lt;br /&gt;
This and all next tests use &lt;code&gt;SessionA&lt;/code&gt; and &lt;code&gt;SessionB&lt;/code&gt; objects to simulate 2 concurent clients.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;public void TestDefaultIsolationLevel()
{
    Country countryA = new Country()
    {
        Description = "Poland",
        ContinentId = 1
    };

    try
    {
        // save an object in session A
        SessionA.Save(countryA);
        Assert.IsTrue(countryA.Id &amp;gt; 0);

        // try to retrieve newly inserted object from session B
        IQuery query = SessionB.CreateQuery("FROM Country WHERE Id = :id");
        query.SetInt32("id", countryA.Id);
        Country countryB = query.UniqueResult&amp;lt;Country&amp;gt;();
    }
    catch (GenericADOException ex)
    {
        // this is the expected behaviour!
        Assert.AreSame(typeof(GenericADOException), ex.GetType());
    }
    catch (Exception ex)
    {
        Assert.Fail("Unexpected exception " + ex.Message);
    }
    finally
    {
        TransactionA.Rollback();
    }
}&lt;/pre&gt;&lt;br /&gt;
Result: Session B client is not able to retrieve the country because it's not yet committed. The root cause is timeout exception.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Read Uncommitted Isolation Level&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This is the lowest isolation level. In this isolation level you can retrieve uncommitted records:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestMethod]
public void TestReadUncommittedIsolationLevel()
{
    Country countryA = new Country()
    {
        Description = "Poland",
        ContinentId = 1
    };

    // close session B transaction
    TransactionB.Dispose();
    // create a new one with ReadUncommitted isolation level
    TransactionB = SessionB.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);

    try
    {
        // save an object in session A
        SessionA.Save(countryA);
        Assert.IsTrue(countryA.Id &amp;gt; 0);

        // try to retrieve newly inserted object from session B
        IQuery query = SessionB.CreateQuery("FROM Country WHERE Id = :id");
        query.SetInt32("id", countryA.Id);
        Country countryB = query.UniqueResult&amp;lt;Country&amp;gt;();
        Assert.IsNotNull(countryB);

        // rollback transaction A
        TransactionA.Rollback();
        // session B stays with dirty record countryB
    }
    catch (Exception ex)
    {
        Assert.Fail("Unexpected exception " + ex.Message);
    }
}&lt;/pre&gt;&lt;br /&gt;
Result: Session B reads dirty (uncommitted) record, session A rolls back the transaction, Session B stays with dirty record.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Read Committed Isolation Level&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This isolation level guarantees no dirty records.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestMethod]
public void TestReadCommittedIsolationLevel()
{
    Country countryA = new Country()
    {
        Description = "Poland",
        ContinentId = 1
    };

    TransactionB.Dispose();
    // create new transaction
    TransactionB = SessionB.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);

    try
    {
        // save an object in session A
        SessionA.Save(countryA);
        Assert.IsTrue(countryA.Id &amp;gt; 0);

        // try to retrieve newly inserted object from session B
        IQuery query = SessionB.CreateQuery("FROM Country WHERE Id = :id");
        query.SetInt32("id", countryA.Id);
        Country countryB = query.UniqueResult&amp;lt;Country&amp;gt;();
    }
    catch (GenericADOException ex)
    {
        // this is expected behaviour!
        Assert.AreSame(typeof(GenericADOException), ex.GetType());
    }
    catch (Exception ex)
    {
        Assert.Fail("Unexpected exception " + ex.Message);
    }
    finally
    {
        TransactionA.Rollback();
    }
}&lt;/pre&gt;&lt;br /&gt;
Result: Session B cannot read uncommitted record.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;Repeatable Read Isolation Level&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This isolation level guarantees repeatable reads. If a repeatable read isolation level is used, a read lock is acquired on fetched records.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestMethod]
public void TestRepeatableReadIsolationLevel()
{
    Country countryA = new Country()
    {
        Description = "Poland",
        ContinentId = 1
    };
    Country countryB = null;

    // close current session B transaction
    TransactionB.Dispose();
    // open new transaction with RepeatableRead isolation level
    TransactionB = SessionB.BeginTransaction(System.Data.IsolationLevel.RepeatableRead);

    try
    {
        // save an object in session A
        SessionA.Save(countryA);
        Assert.IsTrue(countryA.Id &amp;gt; 0);

        TransactionA.Commit();
        // open new transaction
        TransactionA.Dispose();
        TransactionA = SessionA.BeginTransaction();
        // retrieve from session A
        IQuery queryA = SessionA.CreateQuery("FROM Country WHERE Id = :id");
        queryA.SetInt32("id", countryA.Id);
        countryA = queryA.UniqueResult&amp;lt;Country&amp;gt;();

        // retrieve from session B
        IQuery queryB = SessionB.CreateQuery("FROM Country WHERE Id = :id");
        queryB.SetInt32("id", countryA.Id);
        countryB = queryB.UniqueResult&amp;lt;Country&amp;gt;();

        SessionA.Delete(countryA);
        TransactionA.Commit();
    }
    catch (GenericADOException ex)
    {
        // this is the expected behaviour!
        Assert.AreSame(typeof(GenericADOException), ex.GetType());
    }
    catch (Exception ex)
    {
        Assert.Fail("Unexpected exception " + ex.Message);
    }
    finally
    {
        SessionB.Delete(countryB);
        TransactionB.Commit();
    }
}&lt;/pre&gt;&lt;br /&gt;
Result: Session A cannot update/delete country, because session B acquired a read lock thanks to using a transaction with a repeatable read isolation level.&lt;br /&gt;
&lt;br /&gt;
Some databases don't acquire read locks (called range-locks) when fetching large data sets like where Id between (0, 1000000). Thus phantom records can occur.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Serialisable Isolation Level&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This is the most resource-consuming (and thus slowest) transaction level. But it guarantees a complete transaction isolation. All transactions are serialisable. No phantom records occur.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;[TestMethod]
public void TestSerialisable()
{
    Country countryA = new Country()
    {
        Description = "Poland",
        ContinentId = 1
    };

    // close current session B transaction
    TransactionB.Dispose();
    // open new transaction with Serializable isolation level
    TransactionB = SessionB.BeginTransaction(System.Data.IsolationLevel.Serializable);

    try
    {
        // save an object in session A
        SessionA.Save(countryA);
        Assert.IsTrue(countryA.Id &amp;gt; 0);

        TransactionA.Commit();
        // open new transaction
        TransactionA.Dispose();
        TransactionA = SessionA.BeginTransaction();
        // retrieve in 1 session
        IQuery queryA = SessionA.CreateQuery("FROM Country WHERE Id = :id");
        queryA.SetInt32("id", countryA.Id);
        countryA = queryA.UniqueResult&amp;lt;Country&amp;gt;();

        // if I would like to delete a record there would be a timeout exception see TestRepeatableReadIsolationLevel()
        // alghought I haven't used any INSERT/UPDATE/DELETE statements I have to release read locks
        // if I close the transaction B, transaction A will work
        TransactionB.Rollback();

        SessionA.Delete(countryA);
        TransactionA.Commit();
    }
    catch (GenericADOException ex)
    {
        // this is expected behaviour!
        Assert.AreSame(typeof(GenericADOException), ex.GetType());
    }
    catch (Exception ex)
    {
        Assert.Fail("Unexpected exception " + ex.Message);
    }
}&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
So, what is the default transaction isolation level?&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-2305094609876119942?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/83HrVJyyMbNEIWiEmI61I7301Rk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/83HrVJyyMbNEIWiEmI61I7301Rk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/83HrVJyyMbNEIWiEmI61I7301Rk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/83HrVJyyMbNEIWiEmI61I7301Rk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/KSGphVUWz54" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/2305094609876119942/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=2305094609876119942" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/2305094609876119942?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/2305094609876119942?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/KSGphVUWz54/transactions-and-isolation-levels.html" title="Transactions and Isolation Levels explained once and for all (nHibernate examples)" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/06/transactions-and-isolation-levels.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIHSX09fyp7ImA9WhZVF0k.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-2703122026811218941</id><published>2011-05-30T11:08:00.000+02:00</published><updated>2011-05-30T11:08:58.367+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-30T11:08:58.367+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="nhibernate" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="ms test" /><title>Playing around with nHibernate: the basics</title><content type="html">I used Hibernate in a quite a few Java projects. Last week I was asked by my .NET colleagues to show them nHibernate.&lt;br /&gt;
&lt;br /&gt;
I created a series of simple tests showing them some of nHibernate features. Today I publish the first one. &lt;br /&gt;
&lt;br /&gt;
The basics of Hibernate: Session, CRUD operations, and Criteria API.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Database&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
OK. For a start just 1 table. &lt;br /&gt;
&lt;br /&gt;
I opened my SQL Express Management Studio and created a database &lt;code&gt;tech_clash_test_db&lt;/code&gt;. Then I created &lt;code&gt;app_country&lt;/code&gt; table:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: sql"&gt;CREATE TABLE [dbo].[app_country](
 [countryId] [int] IDENTITY(1,1) NOT NULL,
 [description] [nvarchar](50) NOT NULL,
 [continentId] [int] NOT NULL
);&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Setting up the project&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
First, I had to download &lt;a href="http://www.hibernate.org/" target="_blank"&gt;Hibernate&lt;/a&gt; and add NHibernate and Iesi.Collections (shipped with nHibernate) references to my project.&lt;br /&gt;
&lt;br /&gt;
Just like in Java, you can configure nHibernate in two ways. By using XML descriptors or by using attributes (Java annotations). Today I will show you the first one.&lt;br /&gt;
&lt;br /&gt;
For the given &lt;code&gt;app_country&lt;/code&gt; table I created &lt;code&gt;Country.hbm.xml&lt;/code&gt; file (Embedded Resource) and wrote:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true"&amp;gt;
    &amp;lt;class name="nHibernateTest.Model.Country, nHibernateTest" table="app_country"&amp;gt;
        &amp;lt;id name="Id" column="countryId"&amp;gt;
            &amp;lt;generator class="native" /&amp;gt;
        &amp;lt;/id&amp;gt;
        &amp;lt;property name="Description" column="description"/&amp;gt;
        &amp;lt;property name="ContinentId" column="continentId"/&amp;gt;
    &amp;lt;/class&amp;gt;
&amp;lt;/hibernate-mapping&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Having a table and its nHibernate mapping I only had to create a model class (yes, properties are virtual):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;public class Country
{
    public virtual int Id { get; set; }

    public virtual string Description { get; set; }

    public virtual int ContinentId { get; set; }
}&lt;/pre&gt;&lt;br /&gt;
Also, I had to tell my application that I used Hibernate. I created &lt;code&gt;App.config&lt;/code&gt; file and copied and pasted the following configuration:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;configSections&amp;gt;
        &amp;lt;section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" /&amp;gt;
        &amp;lt;section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /&amp;gt;
    &amp;lt;/configSections&amp;gt;
    &amp;lt;hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"&amp;gt;
        &amp;lt;session-factory&amp;gt;
            &amp;lt;property name="connection.provider"&amp;gt;
                NHibernate.Connection.DriverConnectionProvider
            &amp;lt;/property&amp;gt;
            &amp;lt;property name="connection.driver_class"&amp;gt;
                NHibernate.Driver.SqlClientDriver
            &amp;lt;/property&amp;gt;
            &amp;lt;property name="connection.connection_string"&amp;gt;
                Server=.\SQLEXPRESS1;Database=tech_clash_test_db;Trusted_Connection=True;MultipleActiveResultSets=True
            &amp;lt;/property&amp;gt;
            &amp;lt;property name="dialect"&amp;gt;
                NHibernate.Dialect.MsSql2000Dialect
            &amp;lt;/property&amp;gt;
            &amp;lt;property name="show_sql"&amp;gt;
                true
            &amp;lt;/property&amp;gt;
        &amp;lt;/session-factory&amp;gt;
    &amp;lt;/hibernate-configuration&amp;gt;
    &amp;lt;log4net&amp;gt;
        &amp;lt;appender name="ConsoleAppender"
        type="log4net.Appender.ConsoleAppender, log4net"&amp;gt;
            &amp;lt;layout type="log4net.Layout.PatternLayout, log4net"&amp;gt;
                &amp;lt;param name="ConversionPattern" value="%m" /&amp;gt;
            &amp;lt;/layout&amp;gt;
        &amp;lt;/appender&amp;gt;
        &amp;lt;root&amp;gt;
            &amp;lt;priority value="WARN" /&amp;gt;
            &amp;lt;appender-ref ref="ConsoleAppender" /&amp;gt;
        &amp;lt;/root&amp;gt;
    &amp;lt;/log4net&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;&lt;br /&gt;
That's it.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Writing unit test&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Using VS 2010 I created a Test Project. I changed &lt;code&gt;UnitTest1.cs&lt;/code&gt; to &lt;code&gt;CRUDTest.cs&lt;/code&gt; and wrote:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;using System;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;
using nHibernateTest.Model;

namespace nHibernateTest
{
    [TestClass]
    public class CRUDTest
    {
        public static int CountryId { set; get; }

        public TestContext TestContext { set; get; }

        [ClassCleanup()]
        public static void ClassCleanup()
        {
            using (ISession session = OpenSession())
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    IQuery query = session.CreateSQLQuery("delete from app_country");
                    query.ExecuteUpdate();
                    transaction.Commit();
                }
            }   
        }

        [TestMethod]
        public void TestCreate()
        {
            Country country = new Country()
            {
                Description = "Poland",
                ContinentId = 1
            };

            try
            {
                using (ISession session = OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        session.Save(country);
                        transaction.Commit();
                        Assert.IsTrue(country.Id &amp;gt; 0);
                        CountryId = country.Id;
                    }
                }
            }
            catch (Exception e)
            {
                Assert.Fail("Test failed " + e.Message);
            }
        }

        [TestMethod]
        public void TestRetrieveAll()
        {
            try
            {
                using (ISession session = OpenSession())
                {
                    IQuery query = session.CreateQuery("SELECT c FROM Country c");
                    IList&amp;lt;Country&amp;gt; countries = query.List&amp;lt;Country&amp;gt;();
                    Assert.IsNotNull(countries);
                    Assert.IsTrue(countries.Count &amp;gt; 0);
                }
            } catch (Exception e)
            {
                Assert.Fail("Test failed " + e.Message);
            }
        }

        [TestMethod]
        public void TestRetrieveSingleRecord()
        {
            try
            {
                using (ISession session = OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        IQuery query = session.CreateQuery("FROM Country WHERE Id = :id and Description = :description ORDER BY Description ASC");
                        query.SetInt32("id", CountryId);
                        query.SetString("description", "Poland");
                        Country country = query.UniqueResult&amp;lt;Country&amp;gt;();
                        Assert.AreEqual("Poland", country.Description);
                    }
                }
            }
            catch (Exception e)
            {
                Assert.Fail("Test failed " + e.Message);
            }
        }

        [TestMethod]
        public void TestUpdate()
        {
            try
            {
                using (ISession session = OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        IQuery query = session.CreateQuery("FROM Country WHERE Id = :id");
                        query.SetInt32("id", CountryId);
                        Country country = query.UniqueResult&amp;lt;Country&amp;gt;();
                        country.Description = "Poland 2";
                        transaction.Commit();
                        Country country2 = query.UniqueResult&amp;lt;Country&amp;gt;();
                        Assert.AreEqual("Poland 2", country2.Description);
                    }
                }
            }
            catch (Exception e)
            {
                Assert.Fail("Test failed " + e.Message);
            }
        }

        [TestMethod]
        public void TestDelete()
        {
            try
            {
                using (ISession session = OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        IQuery query = session.CreateQuery("FROM Country WHERE Id = :id");
                        query.SetInt32("id", CountryId);
                        Country country = query.UniqueResult&amp;lt;Country&amp;gt;();
                        session.Delete(country);
                        transaction.Commit();
                        Country country2 = query.UniqueResult&amp;lt;Country&amp;gt;();
                        Assert.IsNull(country2);
                    }
                }
            }
            catch (Exception e)
            {
                Assert.Fail("Test failed " + e.Message);
            }
        }

        [TestMethod]
        public void TestCriteriaAPI()
        {
            try
            {
                using (ISession session = OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        ICriteria criteria = session.CreateCriteria(typeof(Country));
                        criteria.Add(Restrictions.Eq("Description", "Poland"));
                        criteria.Add(Restrictions.Eq("Id", CountryId));
                        criteria.AddOrder(Order.Asc("Description"));

                        Country country = criteria.UniqueResult&amp;lt;Country&amp;gt;();

                        Assert.IsNotNull(country);
                    }
                }
            }
            catch (Exception e)
            {
                Assert.Fail("Test failed " + e.Message);
            }
        }

        private static ISessionFactory _sessionFactory;
        private static ISession OpenSession()
        {
            if (_sessionFactory == null)
            {
                Configuration configuration = new Configuration();
                configuration.AddAssembly(Assembly.GetCallingAssembly());
                _sessionFactory = configuration.BuildSessionFactory();
            }
            return _sessionFactory.OpenSession();
        }
    }
}&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
OK. I don't think comments are needed here. &lt;br /&gt;
&lt;br /&gt;
As you can see, the core component is the Session component. Session component represents a connection to a database and it allows you to create transactions, queries, criteria, and of course perform CRUD operations.&lt;br /&gt;
&lt;br /&gt;
One more thing. The above test fails. The order of execution is relevant. But that's not a problem. Using VS 2010 I created ordered test. The most important thing is to place &lt;code&gt;TestCreate()&lt;/code&gt; method as a first method and &lt;code&gt;TestDelete()&lt;/code&gt; as the last one. In my case I ordered them in the following way (the output of ordered test results):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;Passed Unit Test TestCreate  00:00:00.0033537
Passed Unit Test TestRetrieveAll  00:00:00.0023378
Passed Unit Test TestRetrieveSingleRecord  00:00:00.0031339
Passed Unit Test TestCriteriaAPI  00:00:00.0037914
Passed Unit Test TestUpdate  00:00:00.0046633
Passed Unit Test TestDelete  00:00:00.0203877&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Next time I will show you either transactions with different isolation levels or I will show you 1:1, 1:n, and n:m mappings with lazy and eager loading.&lt;br /&gt;
&lt;br /&gt;
Stay tuned,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-2703122026811218941?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/KLzyZDWe9HvTRtGBT04RPT9KqWo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/KLzyZDWe9HvTRtGBT04RPT9KqWo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/KLzyZDWe9HvTRtGBT04RPT9KqWo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/KLzyZDWe9HvTRtGBT04RPT9KqWo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/AkdR_xcd5KY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/2703122026811218941/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=2703122026811218941" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/2703122026811218941?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/2703122026811218941?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/AkdR_xcd5KY/playing-around-with-nhibernate-basics.html" title="Playing around with nHibernate: the basics" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/05/playing-around-with-nhibernate-basics.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUHQHY_cCp7ImA9WhZVEk4.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-8593123261491393581</id><published>2011-05-24T12:17:00.000+02:00</published><updated>2011-05-24T12:17:11.848+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-24T12:17:11.848+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="performance" /><category scheme="http://www.blogger.com/atom/ns#" term="activemq" /><category scheme="http://www.blogger.com/atom/ns#" term="geronimo" /><category scheme="http://www.blogger.com/atom/ns#" term="jms" /><category scheme="http://www.blogger.com/atom/ns#" term="java ee" /><title>True power of Java EE and JMS: distributed computations!</title><content type="html">As you already know I'm writing a PhD about evaluating and measuring quality of Web Services compositions. In my system I focus on evaluating WS-BPEL processes (but the framework I designed is extremely flexible and supports any business scenario technology).&lt;br /&gt;
&lt;br /&gt;
The system (called Measurement System DIES) is a Java EE application. It is designed in a distributed manner which makes scaling out and distributing computations very easy. &lt;br /&gt;
&lt;br /&gt;
Last week, out of pure curiosity, I decided to do stress tests. Apache Geronimo did not survive this nor did the embedded ActiveMQ. After I killed Geronimo and started it again all queues stopped working... I had to install brand new instance of Geronimo.&lt;br /&gt;
&lt;br /&gt;
But thanks to Java EE capabilities and the distributed nature of my system I was able to overcome this problem. See how I did it with JMS and distributed computations!&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;The EJB module of my application&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div class="fullpost"&gt;&lt;br /&gt;
Most of the work performed by my system is done, of course, in EJB module.&amp;nbsp;The EJB module of my application consists of the following (among many other things of course):&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Queue for execution orders - each execution of a WS-BPEL process instance may last minutes (I have a 10 minutes timeout set up),&lt;/li&gt;
&lt;li&gt;Queue for asynchronous computing of quality and performance score of&amp;nbsp;each activity trace&amp;nbsp;- this task usually takes up to 4 seconds to complete (most of the time spent here is to query external services like geolocation services),&lt;/li&gt;
&lt;li&gt;Timer for computing statistics - every 10 seconds I retrieve all completed instances which are not yet analysed and conduct some statistical computations.&lt;/li&gt;
&lt;/ul&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;The development environment&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
While developing my system I used 1 box &amp;nbsp;for everything:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Apache Geronimo with my Java EE application and&amp;nbsp;embedded ActiveMQ server&lt;/li&gt;
&lt;li&gt;Apache ODE as an WS-BPEL execution engine&lt;/li&gt;
&lt;li&gt;IBM DB2 pureXML&lt;/li&gt;
&lt;/ol&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;New Machine(s)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I managed to get a second machine. Based on that I decided to distribute my components this way:&lt;br /&gt;
&lt;br /&gt;
1st computer:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Apache Geronimo with my Java EE application with Timer but without Queue components&lt;/li&gt;
&lt;li&gt;IBM DB2 pureXML&lt;/li&gt;
&lt;li&gt;Apache ODE as an execution engine&lt;/li&gt;
&lt;/ol&gt;2nd computer:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Apache Geronimo with EJB module with Queue components&lt;/li&gt;
&lt;li&gt;Standalone ActiveMQ&lt;/li&gt;
&lt;/ol&gt;Ideally I would need 2 more machines:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;3rd for IBM DB2 pureXML database&lt;/li&gt;
&lt;li&gt;4th for Apache ODE&lt;/li&gt;
&lt;/ul&gt;But having 2 machines was enough.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Distributing components&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Here is what I did:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;I split my EJB components. I moved my two queues into a separate project and deployed them to Apache Geronimo installed on the second machine. I decided to leave the Timer component in the original EJB project.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;I downloaded a standalone ActiveMQ server and installed it on the second machine.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Finally I configured connection factories for both Apache Geronimos. I used the wizard offered by Geronimo's Admin Console - it was childishly simple! I use application-wide JMS resources and just compared the generated deployment plans with the ones I already had. It turned out that I had to add  1 line to my deployment plans - the external server url. NICE! This is how the enterprise configuration should look like!&lt;/li&gt;
&lt;/ol&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Rerunning the stress test again&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I re-ran my stress test. Both Geronimos and ActiveMQ survived :)&lt;br /&gt;
&lt;br /&gt;
What was the improvement rate? Hard to say... In Java when you add, subtract, multiply or divide NaN by any other number you still get NaN. I know one thing for sure, the first configuration did not survive the stress test :)&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Always keep in mind that some day your system will have to be distributed or scaled out. At the design stage it's far more easier to introduce basic enterprise architectural patterns and concepts than to introduce them during the maintenance phase (when, for example, task distribution would have a huge impact on the whole system).&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-8593123261491393581?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/prmq_drBYdS2ORv24ckA1zx8pJU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/prmq_drBYdS2ORv24ckA1zx8pJU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/prmq_drBYdS2ORv24ckA1zx8pJU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/prmq_drBYdS2ORv24ckA1zx8pJU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/K_ZhZow38W8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/8593123261491393581/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=8593123261491393581" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/8593123261491393581?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/8593123261491393581?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/K_ZhZow38W8/true-power-of-java-ee-and-jms.html" title="True power of Java EE and JMS: distributed computations!" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/05/true-power-of-java-ee-and-jms.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMMQnszfSp7ImA9WhZWFU4.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-6694984381158682575</id><published>2011-05-16T11:00:00.003+02:00</published><updated>2011-05-16T11:01:23.585+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-16T11:01:23.585+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="c#" /><category scheme="http://www.blogger.com/atom/ns#" term="groovy" /><title>Java sucks, Groovy and C# rock!</title><content type="html">When I was a student a few years ago one of my lecturers told us that Java and C# can be described by an adjective starting with the "M" letter: Java is Mature and C# is Modern.&lt;br /&gt;
&lt;br /&gt;
To be completely frank with you I think that Java should be described by two adjectives starting with "O": old and obsolete.&lt;br /&gt;
&lt;br /&gt;
Note that I have over 6 years of experience in Java. I'm Sun Certified Java Programmer, Sun Certified Developer for Java Web Services and also Java EE and Spring are still my technologies of choice. I'm just talking about the language here...&lt;br /&gt;
&lt;br /&gt;
Despite that Java as a language sucks very much there is one good thing about it. It's the JVM. JVM is efficient, stable, and above all portable. Atop JVM new dynamic languages are developed. Like for example Groovy and Scala. Last year I wrote a post about 21 things I like and don't like about Groovy (compared to vanilla Java) - you may find it here:&amp;nbsp;&lt;a href="http://jee-bpel-soa.blogspot.com/2010/03/21-things-i-like-and-dont-like-about.html" target="_blank"&gt;21 things I like and don't like about Groovy&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
It would be a low blow if I compared Java to C# (it's like comparing a BMW to a Fiat).&lt;br /&gt;
&lt;br /&gt;
Let's try Groovy with C#.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;1. No primitives&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In Groovy everything is an object. In C# int, double, and so on, are structs with methods.&lt;br /&gt;
&lt;br /&gt;
Groovy:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;def i = 148;&lt;/pre&gt;def test = Integer.class == i.class&lt;br /&gt;
&lt;br /&gt;
C#:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;int i = 12;
int j = 12;
bool test = i.Equals(j);
int hash = 148.GetHashCode();&lt;/pre&gt;&lt;br /&gt;
Result: draw&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;2. Named parameters&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Groovy:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;def person = new Person(name: "Łukasz Budnik", age: 27);&lt;/pre&gt;&lt;br /&gt;
C#:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;Person person = new Person()
{
name = "Łukasz Budnik",
age = 27
};&lt;/pre&gt;&lt;br /&gt;
Result: draw&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;2. Default parameters&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Groovy:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;def s = printStars()
assertEquals('***', s)
s = printStars(2)
assertEquals('**', s)

String printStars(count = 3) {
def sb = new StringBuilder()
while(count--) {
sb.append ('*')
}
return sb
}&lt;/pre&gt;&lt;br /&gt;
C#:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;string stars1 = PrintStars();
string stars2 = PrintStars(13);

public static string PrintStars(int count = 3)
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;StringBuilder sb = new StringBuilder();

&amp;nbsp;&amp;nbsp; &amp;nbsp;while (count-- &amp;gt; 0)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sb.Append("*");
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;return sb.ToString();
}&lt;/pre&gt;&lt;br /&gt;
Result: draw&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;3. Handling arrays, lists, maps&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Groovy:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;def array = [1, 2, 3, 4, 4, 3, 2, 1]
def set = [1, 2, 3, 4, 4, 3, 2, 1] as Set&lt;/pre&gt;&lt;br /&gt;
C#:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;int[] array = {12,12,12,12};
IEnumerable&amp;lt;int&amp;gt; enumerable = new List&amp;lt;int&amp;gt; { 12, 12, 12, 12 };
IEnumerable&amp;lt;int&amp;gt; set = new HashSet&amp;lt;int&amp;gt; { 12, 12, 12, 12 };
IDictionary&amp;lt;string, string&amp;gt; dict = new Dictionary&amp;lt;string, string&amp;gt; { {"key1", "value1"}, { "key2", "value2"} };&lt;/pre&gt;&lt;br /&gt;
Result: draw (slightly Groovy)&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;4. Operator overloading&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Groovy:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;class Box {
&amp;nbsp;&amp;nbsp; def w;
&amp;nbsp;&amp;nbsp; def h; 
&amp;nbsp;&amp;nbsp; Box plus(Box other) {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;return new Box(w: this.w + other.w, h: this.h + other.h)
&amp;nbsp;&amp;nbsp; }
}


def box1 = new Box(w: 100, h: 100)
def box2 = new Box(w: 40, h: 40);
def box3 = box1 + box2;&lt;/pre&gt;&lt;br /&gt;
C#:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;class Box
{
&amp;nbsp;&amp;nbsp; public int W { get; set; }
&amp;nbsp;&amp;nbsp; public int H { get; set; }

&amp;nbsp;&amp;nbsp; public static Box operator +(Box b1, Box b2)
&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;   return new Box { W = b1.W + b2.W, H = b1.H + b2.H};
&amp;nbsp;&amp;nbsp; }
}

var box1 = new Box { W = 100, H = 100 };
var box2 = new Box { W = 40, H = 40 };
var box3 = box1 + box2;&lt;/pre&gt;&lt;br /&gt;
Result: draw&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;5. Multi-line strings and parsing strings&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Multi-line string and parsing ${variable} ${closure(param1)} in string literals in Groovy:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;def variable1 = 'I\'m a string'
def variable2 = 123
def label = "${variable1} and my length is not ${variable2}"&lt;/pre&gt;&lt;br /&gt;
and in C#:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;var variable1 = @"I'm a
multi-line string";
var variable2 = 123;
var label = String.Format("{0} and my length is not {1}", variable1, variable2);&lt;/pre&gt;&lt;br /&gt;
Result: draw (slightly Groovy)&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;6. Closoures&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
A closure in C# takes the form of an in-line delegate method and is strongly typed.&lt;br /&gt;
&lt;br /&gt;
Groovy:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;def square = { num -&amp;gt; num * num }
def x = square(10)&lt;/pre&gt;&lt;br /&gt;
C#:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;delegate int square(int x);
square s = delegate(int x) { return x * x; };
int squareInt = s(10);&lt;/pre&gt;&lt;br /&gt;
Apart of this in C# you have also &lt;code&gt;Delegate&lt;/code&gt; and &lt;code&gt;Func&lt;/code&gt; mechanisms. Groovy has also pointers to methods, which is uber cool (see point 10 in this post).&lt;br /&gt;
&lt;br /&gt;
Result: draw&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;7. Operations on collections&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Operations on collections... C# rocks with its LINQ technology (See this for a small sample of what can be done with LINQ: &lt;a href="http://msdn.microsoft.com/en-us/vcsharp/aa336746" target="_blank"&gt;http://msdn.microsoft.com/en-us/vcsharp/aa336746&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
If you want to invoke a method on all objects in a collection, in Groovy you would use *. operator:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;def x = [ ' aaa ', 'b', ' c &amp;nbsp;']
x = x*.trim()&lt;/pre&gt;&lt;br /&gt;
in C# you would use the following LINQ construct:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;IEnumerable&amp;lt;string&amp;gt; strings = new List&amp;lt;string&amp;gt; { " asas ", "sdas &amp;nbsp; ", " &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; asds &amp;nbsp;" };
IEnumerable&amp;lt;string&amp;gt; trimmedStrings = strings.Select(it =&amp;gt; it.Trim());&lt;/pre&gt;&lt;br /&gt;
Result: C# wins with its LINQ technology (actually C# gets +2 points here)&lt;br /&gt;
&lt;br /&gt;
See the link above to have a full picture of LINQ, another example may be grouping countries list by continents:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;def countriesGroupedByContinents = from country in countries
&amp;nbsp;&amp;nbsp; &amp;nbsp;group country by country.ContinentId into g
&amp;nbsp;&amp;nbsp; &amp;nbsp;orderby g.Key
&amp;nbsp;&amp;nbsp; &amp;nbsp;select g;
&lt;/pre&gt;&lt;br /&gt;
The SQL-like tree syntax embedded directly into a programming language, what a beauty and a fantastic idea!&lt;br /&gt;
(hold on, I, obdurate Java programmer, just wrote that M$ technology is fantastic? Something wrong is happening to me or is it C#...)&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;8. ?. operator - null-safe invocation, null coalescing operator&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Groovy - much more powerful:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;def person = new Person(name: 'Łukasz Budnik')
def street = person?.address?.street&lt;/pre&gt;&lt;br /&gt;
C# - only a poor substitute&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;int? x = null;
int y = x ?? -1;&lt;/pre&gt;&lt;br /&gt;
Result: Groovy wins (back on track, tenacious Java programmer)&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;9. == operator&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Both languages == is more logical/intuitive than in Java, doesn't compare the identities, compares objects.&lt;br /&gt;
&lt;br /&gt;
Groovy:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;def name1 = 'Łukasz Budnik'
def name2 = new StringBuilder().append('Łukasz').append(' ')
name2 += 'Budnik'
assertTrue(name1 == name2)
// identity comparison, old Java == behaviour
assertFalse(name1.is(name2))&lt;/pre&gt;&lt;br /&gt;
C#:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;var name1 = "Łukasz Budnik";
var name2 = new StringBuilder().Append("Łukasz").Append(" ").Append("Budnik").ToString();

bool test1 = name1 == name2;
// identity comparison
bool test2 = Object.ReferenceEquals(name1, name2);&lt;/pre&gt;&lt;br /&gt;
Result: draw&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;10. Expando and extensions mechanism&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Groovy:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;String stringAsStars(def length) {
&amp;nbsp;&amp;nbsp; def sb = new StringBuilder();
&amp;nbsp;&amp;nbsp; while (length--) {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;sb.append '*'
&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp; return sb;
}

String.metaClass.addQuestionMark = {-&amp;gt;
&amp;nbsp;&amp;nbsp; return delegate + '?'
}
String.metaClass.addExclamationMark = {-&amp;gt;
&amp;nbsp;&amp;nbsp; return delegate + '!'
}
// ex-C programmer? pointers to functions here? rings any bells?
def method = this.&amp;amp;stringAsStars
String.metaClass.asStars = {-&amp;gt;
&amp;nbsp;&amp;nbsp; return method (delegate.length())
}
String question = 'Are you Groovy programmer'.addQuestionMark()
String answer = 'Yes'.addExclamationMark()
println question
println answer
println answer.asStars()&lt;/pre&gt;&lt;br /&gt;
C#:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;StringExtension.AsStarsDelegateFunction = Program.AsStarsImplementation;
string question = "Are you C# programmer".AddQuestionMark();
string answer = "Yes".AddExclamationMark();
string stars = answer.AsStars();

public static string AsStarsImplementation(int length)
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;StringBuilder sb = new StringBuilder();
&amp;nbsp;&amp;nbsp; &amp;nbsp;while (length-- &amp;gt; 0)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sb.Append("*");
&amp;nbsp;&amp;nbsp; &amp;nbsp;}
&amp;nbsp;&amp;nbsp; &amp;nbsp;return sb.ToString();
}

public static class StringExtension
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;public delegate string AsStarsDelegate(int length);

&amp;nbsp;&amp;nbsp; &amp;nbsp;public static AsStarsDelegate AsStarsDelegateFunction;

&amp;nbsp;&amp;nbsp; &amp;nbsp;public static string AddQuestionMark(this string s)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return s + "?";
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;public static string AddExclamationMark(this string s)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return s + "?";
&amp;nbsp;&amp;nbsp; &amp;nbsp;}
&amp;nbsp;&amp;nbsp; &amp;nbsp;public static string AsStars(this string s)
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return AsStarsDelegateFunction(s.Length);
&amp;nbsp;&amp;nbsp; &amp;nbsp;}
}&lt;/pre&gt;&lt;br /&gt;
Result: draw&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;11. XML/JSON markups&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Groovy (More in &lt;a href="http://jee-bpel-soa.blogspot.com/2009/09/first-steps-with-groovy-and-its-xml.html" target="_blank"&gt;First steps with Groovy and its XML support&lt;/a&gt; post):&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.people() {
&amp;nbsp;&amp;nbsp; person(id:123) {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;name ('Lukasz Budnik')
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;age(27)
&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp; person(id:321) {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;name ('Budnik Lukasz')
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;age(72)
&amp;nbsp;&amp;nbsp; }
}
def source = writer.toString()
println source&lt;/pre&gt;&lt;br /&gt;
In C# there are anonymous types, but there is no direct XML or JSON builders:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;var json = new
{
&amp;nbsp;&amp;nbsp; &amp;nbsp;name = "Łukasz Budnik",
&amp;nbsp;&amp;nbsp; &amp;nbsp;id = 123,
&amp;nbsp;&amp;nbsp; &amp;nbsp;address = new
&amp;nbsp;&amp;nbsp; &amp;nbsp;{
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;city = "Gdansk",
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;country = "Poland"
&amp;nbsp;&amp;nbsp; &amp;nbsp;}
};&lt;/pre&gt;&lt;br /&gt;
But using &lt;code&gt;ExpandoObjects&lt;/code&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:csharp"&gt;dynamic contact = new ExpandoObject();
contact.Name = "Łukasz Budnik";
contact.Address = new ExpandoObject();
contact.Address.City = "Gdansk";
contact.Address.Country = "Poland";&lt;/pre&gt;&lt;br /&gt;
you can write your own wrappers and dynamically format dynamic objects as XML documents:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://blogs.msdn.com/b/csharpfaq/archive/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject.aspx" target="_blank"&gt;http://blogs.msdn.com/b/csharpfaq/archive/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject.aspx&lt;/a&gt;&amp;nbsp;:)&lt;br /&gt;
&lt;br /&gt;
Result: draw (dynamic objects C#, markup builders Groovy)&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;13. Unchecked exceptions&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
In Groovy and C# all exceptions are unchecked. I personally don't like it. It would be nice to have syntax support, like in Java throws in method declaration, so that developer will know what exceptions might be thrown by given method.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;14. Output parameters&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Only available in C#.&lt;br /&gt;
&lt;br /&gt;
Result: C# wins&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;&lt;b&gt;15. Partial classes&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Count me in! The second best C# feature (after LINQ). Why/When is it important? Suppose you are generating some of the classes dynamically (base on DB schema) apart of ordinary properties and &lt;code&gt;Equals&lt;/code&gt;/&lt;code&gt;HashCode&lt;/code&gt; methods you may want to add convenient methods as well - these could be placed in a partial class.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style="font-size: large;"&gt;Summary&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Do you remember that when Oracle refused to certify Apache Harmony as a Java implementation, there were some voices in Apache Foundation calling for abandoning Java and moving to a different language? Can you imagine Apache CXF, Apache Tomcat, Apache Geronimo, Apache ServiceMix, Apache Camel or Apache Hadoop written in C#? I do!&lt;br /&gt;
&lt;br /&gt;
And what about you? What do you like and don't like about Java and C#?&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-6694984381158682575?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/a58pt3p-DMzw5DENQwJVRoMBuKM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/a58pt3p-DMzw5DENQwJVRoMBuKM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/a58pt3p-DMzw5DENQwJVRoMBuKM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/a58pt3p-DMzw5DENQwJVRoMBuKM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/4x1GkoYccfg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/6694984381158682575/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=6694984381158682575" title="25 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/6694984381158682575?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/6694984381158682575?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/4x1GkoYccfg/java-sucks-groovy-and-c-rock.html" title="Java sucks, Groovy and C# rock!" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>25</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/05/java-sucks-groovy-and-c-rock.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck8FSHc7fCp7ImA9WhZQEkw.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-1945507292972143276</id><published>2011-04-19T12:59:00.001+02:00</published><updated>2011-04-19T13:00:19.904+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-19T13:00:19.904+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="bpel" /><title>Array Operations in WS-BPEL</title><content type="html">Almost 3 years ago I wrote a short article about handling complex types in WS-BPEL. Today I will show you how to handle arrays.&lt;br /&gt;
&lt;br /&gt;
I used Eclipse BPEL Designer, Apache ODE as a WS-BPEL engine, and soapUI as a Web Services testing tool.&lt;br /&gt;
&lt;br /&gt;
Let's start.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Simple process&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
First, I created a synchronous process using Eclipse BPEL Designer wizard. I didn't modify the WSDL file I just added the following assign activity to the WS-BPEL stub:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;bpel:assign validate="no" name="Assign"&amp;gt;
  &amp;lt;bpel:copy&amp;gt;
   &amp;lt;bpel:from&amp;gt;
    &amp;lt;bpel:literal xml:space="preserve"&amp;gt;&amp;lt;tns:ArrayOperationsBusinessProcessResponse
     xmlns:tns="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;
  &amp;lt;tns:result&amp;gt;&amp;lt;/tns:result&amp;gt;
&amp;lt;/tns:ArrayOperationsBusinessProcessResponse&amp;gt;
&amp;lt;/bpel:literal&amp;gt;
   &amp;lt;/bpel:from&amp;gt;
   &amp;lt;bpel:to variable="output" part="payload"&amp;gt;&amp;lt;/bpel:to&amp;gt;
  &amp;lt;/bpel:copy&amp;gt;
  &amp;lt;bpel:copy&amp;gt;
   &amp;lt;bpel:from&amp;gt;
                    &amp;lt;![CDATA[concat('Hello ', $input.payload/tns:input, '! How are you?')]]&amp;gt;
  &amp;lt;/bpel:from&amp;gt;
  &amp;lt;bpel:to part="payload" variable="output"&amp;gt;
   &amp;lt;bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"&amp;gt;&amp;lt;![CDATA[tns:result]]&amp;gt;&amp;lt;/bpel:query&amp;gt;
  &amp;lt;/bpel:to&amp;gt;
 &amp;lt;/bpel:copy&amp;gt;
&amp;lt;/bpel:assign&amp;gt;&lt;/pre&gt;&lt;br /&gt;
To invoke it, I used soapUI and the following input message:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:arr="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;
   &amp;lt;soapenv:Header/&amp;gt;
   &amp;lt;soapenv:Body&amp;gt;
      &amp;lt;arr:ArrayOperationsBusinessProcessRequest&amp;gt;
         &amp;lt;arr:input&amp;gt;Łukasz&amp;lt;/arr:input&amp;gt;
      &amp;lt;/arr:ArrayOperationsBusinessProcessRequest&amp;gt;
   &amp;lt;/soapenv:Body&amp;gt;
&amp;lt;/soapenv:Envelope&amp;gt;&lt;/pre&gt;&lt;br /&gt;
The result was:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"&amp;gt;
   &amp;lt;soapenv:Body&amp;gt;
      &amp;lt;ArrayOperationsBusinessProcessResponse xmlns="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;
         &amp;lt;tns:result xmlns:tns="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;Hello Łukasz! How are you?&amp;lt;/tns:result&amp;gt;
      &amp;lt;/ArrayOperationsBusinessProcessResponse&amp;gt;
   &amp;lt;/soapenv:Body&amp;gt;
&amp;lt;/soapenv:Envelope&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Adding multiple input elements&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
OK, I had it working, now it was time to introduce the input array.&lt;br /&gt;
&lt;br /&gt;
All what was required was to add &lt;code&gt;maxOccurs="unbounded"&lt;/code&gt; to the WSDL file just like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;element name="input" maxOccurs="unbounded" type="string"/&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Now, I was able to invoke it this way:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:arr="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;
   &amp;lt;soapenv:Header/&amp;gt;
   &amp;lt;soapenv:Body&amp;gt;
      &amp;lt;arr:ArrayOperationsBusinessProcessRequest&amp;gt;
         &amp;lt;arr:input&amp;gt;Łukasz&amp;lt;/arr:input&amp;gt;
         &amp;lt;arr:input&amp;gt;Jerzy&amp;lt;/arr:input&amp;gt;
         &amp;lt;arr:input&amp;gt;Izydor&amp;lt;/arr:input&amp;gt;
         &amp;lt;arr:input&amp;gt;Budnik&amp;lt;/arr:input&amp;gt;
      &amp;lt;/arr:ArrayOperationsBusinessProcessRequest&amp;gt;
   &amp;lt;/soapenv:Body&amp;gt;
&amp;lt;/soapenv:Envelope&amp;gt;&lt;/pre&gt;&lt;br /&gt;
But for the above input, the WS-BPEL returned the first &lt;code&gt;input&lt;/code&gt; value (Łukasz).&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Iterating over an array&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
When you iterate over an array in WS-BPEL keep in mind the following:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;indexes start with 1!!&lt;/li&gt;
&lt;li&gt;as a consequence to the above, the end condition is &amp;lt;= (less or equal)&lt;/li&gt;
&lt;li&gt;when you index an element in an array, cast the counter value to number using number() function&lt;/li&gt;
&lt;li&gt;don't forget to increment the counter otherwise you will end up in infinite loop :)&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
The updated code was:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;bpel:while name="While"&amp;gt;
 &amp;lt;bpel:condition&amp;gt;&amp;lt;![CDATA[$counter &amp;lt;= count($input.payload/tns:input)]]&amp;gt;&amp;lt;/bpel:condition&amp;gt;
 &amp;lt;bpel:sequence&amp;gt;
  &amp;lt;bpel:assign validate="no" name="Assign Output"&amp;gt;
   &amp;lt;bpel:copy&amp;gt;
    &amp;lt;bpel:from&amp;gt;
                &amp;lt;![CDATA[concat($output.payload/tns:result, ' ', $input.payload/tns:input[number($counter)])]]&amp;gt;
    &amp;lt;/bpel:from&amp;gt;
    &amp;lt;bpel:to part="payload" variable="output"&amp;gt;
     &amp;lt;bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"&amp;gt;&amp;lt;![CDATA[tns:result]]&amp;gt;&amp;lt;/bpel:query&amp;gt;
    &amp;lt;/bpel:to&amp;gt;
   &amp;lt;/bpel:copy&amp;gt;
  &amp;lt;/bpel:assign&amp;gt;
 &amp;lt;/bpel:sequence&amp;gt;
&amp;lt;/bpel:while&amp;gt;
&amp;lt;bpel:assign validate="no" name="Assign"&amp;gt;
 &amp;lt;bpel:copy&amp;gt;
  &amp;lt;bpel:from&amp;gt;&amp;lt;![CDATA[concat('Hello', $output.payload/tns:result, '! How are you?')]]&amp;gt;&amp;lt;/bpel:from&amp;gt;
  &amp;lt;bpel:to part="payload" variable="output"&amp;gt;
   &amp;lt;bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"&amp;gt;&amp;lt;![CDATA[tns:result]]&amp;gt;&amp;lt;/bpel:query&amp;gt;
  &amp;lt;/bpel:to&amp;gt;
 &amp;lt;/bpel:copy&amp;gt;
&amp;lt;/bpel:assign&amp;gt;M&lt;/pre&gt;&lt;br /&gt;
After deployment, for the above SOAP input all names were returned.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Creating arrays&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
OK. So here comes a really difficult part. Iterating over an array is a piece of cake. Creating arrays is much harder. Why? Because WS-BPEL spec does not say anything about instantiating arrays.&lt;br /&gt;
&lt;br /&gt;
There are two things that can be done in order to create arrays:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;use XSLT transformations&lt;/li&gt;
&lt;li&gt;use vendor-specific&amp;nbsp;extensions&amp;nbsp;and XSLT functions&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
I will show you both.&lt;br /&gt;
&lt;br /&gt;
Before I started creating arrays I added two new elements to my response for storing odd and even input words:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;element name="oddInput" maxOccurs="unbounded" type="string"/&amp;gt;
&amp;lt;element name="evenInput" maxOccurs="unbounded" type="string"/&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Manipulating arrays using XSLT transformations&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
For this task I used WS-BPEL function called &lt;code&gt;bpel:doXslTransform&lt;/code&gt;. As a first argument in takes an XSTL stylesheet file, the second on is the XML input, the following arguments are XSLT params in name-value pairs.&lt;br /&gt;
&lt;br /&gt;
So first, the XSLT:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"&amp;gt;
 &amp;lt;xsl:output method="xml"/&amp;gt;
 &amp;lt;xsl:template match="/"&amp;gt;
  &amp;lt;!-- &amp;lt;root /&amp;gt; element prevents org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR --&amp;gt;
  &amp;lt;root&amp;gt;&amp;lt;xsl:apply-templates /&amp;gt;&amp;lt;/root&amp;gt;
 &amp;lt;/xsl:template&amp;gt;
 &amp;lt;xsl:template
  match="*[local-name() = 'ArrayOperationsBusinessProcessRequest' and namespace-uri() = 'http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations']"&amp;gt;
   &amp;lt;xsl:apply-templates select="*[local-name() = 'input' and namespace-uri() = 'http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations' and position() mod 2 = 0]" /&amp;gt;
 &amp;lt;/xsl:template&amp;gt;

 &amp;lt;xsl:template match="@*|node()"&amp;gt;
  &amp;lt;xsl:copy&amp;gt;
   &amp;lt;xsl:apply-templates select="@*|node()"/&amp;gt;
  &amp;lt;/xsl:copy&amp;gt;
 &amp;lt;/xsl:template&amp;gt;
&amp;lt;/xsl:stylesheet&amp;gt;&lt;/pre&gt;&lt;br /&gt;
And the WS-BPEL invoking the XSLT:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;bpel:assign validate="no" name="Do XSLT Transform"&amp;gt;
 &amp;lt;bpel:copy&amp;gt;
  &amp;lt;bpel:from&amp;gt;bpel:doXslTransform("ArrayCopy.xslt", $input.payload)
  &amp;lt;/bpel:from&amp;gt;
  &amp;lt;bpel:to part="payload" variable="output"&amp;gt;
   &amp;lt;bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"&amp;gt;
                &amp;lt;![CDATA[tns:evenInput]]&amp;gt;
   &amp;lt;/bpel:query&amp;gt;
  &amp;lt;/bpel:to&amp;gt;
 &amp;lt;/bpel:copy&amp;gt;
&amp;lt;/bpel:assign&amp;gt;&lt;/pre&gt;&lt;br /&gt;
No that bad. I mean, the XSLT is no that complicated, but it's not what you would like to do every time you need to create an array :)&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Manipulating arrays using Apache ODE specific functions&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
OK. So Apache ODE provides &lt;code&gt;ode&lt;/code&gt; namespace which contains many, many useful functions (I encourage you to check it out). Among those functions is function called: ode:insert-as-last-into. It expects two arguments, the first one is a destination array, the second one is an element to be inserted.&lt;br /&gt;
&lt;br /&gt;
The usage of this function is straig forward. Using XSLT I copied even words, below I copy odd words:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;bpel:while name="While"&amp;gt;
 &amp;lt;bpel:condition&amp;gt;&amp;lt;![CDATA[$counter &amp;lt;= count($input.payload/tns:input)]]&amp;gt;&amp;lt;/bpel:condition&amp;gt;
 &amp;lt;bpel:sequence&amp;gt;
  &amp;lt;bpel:assign validate="no" name="Assign Output"&amp;gt;
   &amp;lt;bpel:copy&amp;gt;
    &amp;lt;bpel:from&amp;gt;
                &amp;lt;![CDATA[concat($output.payload/tns:result, ' ', $input.payload/tns:input[number($counter)])]]&amp;gt;
    &amp;lt;/bpel:from&amp;gt;
    &amp;lt;bpel:to part="payload" variable="output"&amp;gt;
     &amp;lt;bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"&amp;gt;&amp;lt;![CDATA[tns:result]]&amp;gt;&amp;lt;/bpel:query&amp;gt;
    &amp;lt;/bpel:to&amp;gt;
   &amp;lt;/bpel:copy&amp;gt;

  &amp;lt;/bpel:assign&amp;gt;
  &amp;lt;bpel:if name="If"&amp;gt;
   &amp;lt;bpel:condition&amp;gt;&amp;lt;![CDATA[number($counter) mod 2 = 1]]&amp;gt;&amp;lt;/bpel:condition&amp;gt;
   &amp;lt;bpel:assign validate="no" name="Assign Odd"&amp;gt;
    &amp;lt;bpel:copy&amp;gt;
     &amp;lt;bpel:from&amp;gt;
                        &amp;lt;![CDATA[ode:insert-as-last-into($output.payload/tns:oddInput, $input.payload/tns:input[number($counter)])]]&amp;gt;
     &amp;lt;/bpel:from&amp;gt;
     &amp;lt;bpel:to part="payload" variable="output"&amp;gt;
      &amp;lt;bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0"&amp;gt;
                            &amp;lt;![CDATA[tns:oddInput]]&amp;gt;
      &amp;lt;/bpel:query&amp;gt;
     &amp;lt;/bpel:to&amp;gt;
    &amp;lt;/bpel:copy&amp;gt;
   &amp;lt;/bpel:assign&amp;gt;
  &amp;lt;/bpel:if&amp;gt;
 &amp;lt;/bpel:sequence&amp;gt;
&amp;lt;/bpel:while&amp;gt;&lt;/pre&gt;&lt;br /&gt;
And that's all.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Using the soapUI, for the given input request:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:arr="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;
   &amp;lt;soapenv:Header/&amp;gt;
   &amp;lt;soapenv:Body&amp;gt;
      &amp;lt;arr:ArrayOperationsBusinessProcessRequest&amp;gt;
         &amp;lt;arr:input&amp;gt;Łukasz&amp;lt;/arr:input&amp;gt;
         &amp;lt;arr:input&amp;gt;Jerzy&amp;lt;/arr:input&amp;gt;
         &amp;lt;arr:input&amp;gt;Izydor&amp;lt;/arr:input&amp;gt;
         &amp;lt;arr:input&amp;gt;Budnik&amp;lt;/arr:input&amp;gt;
      &amp;lt;/arr:ArrayOperationsBusinessProcessRequest&amp;gt;
   &amp;lt;/soapenv:Body&amp;gt;
&amp;lt;/soapenv:Envelope&amp;gt;&lt;/pre&gt;&lt;br /&gt;
the WS-BPEL response was:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"&amp;gt;
   &amp;lt;soapenv:Body&amp;gt;
      &amp;lt;ArrayOperationsBusinessProcessResponse xmlns="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;
         &amp;lt;tns:result xmlns:tns="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;Hello Łukasz Jerzy Izydor Budnik! How are you?&amp;lt;/tns:result&amp;gt;
         &amp;lt;tns:oddInput xmlns:tns="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;
            &amp;lt;input&amp;gt;Łukasz&amp;lt;/input&amp;gt;
            &amp;lt;input&amp;gt;Izydor&amp;lt;/input&amp;gt;
         &amp;lt;/tns:oddInput&amp;gt;
         &amp;lt;tns:evenInput xmlns:tns="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;
            &amp;lt;input xmlns:arr="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;Jerzy&amp;lt;/input&amp;gt;
            &amp;lt;input xmlns:arr="http://jee-bpel-soa.blogspot.com/ws-bpel/array-operations"&amp;gt;Budnik&amp;lt;/input&amp;gt;
         &amp;lt;/tns:evenInput&amp;gt;
      &amp;lt;/ArrayOperationsBusinessProcessResponse&amp;gt;
   &amp;lt;/soapenv:Body&amp;gt;
&amp;lt;/soapenv:Envelope&amp;gt;&lt;/pre&gt;&lt;br /&gt;
So it worked!&lt;br /&gt;
&lt;br /&gt;
Cheers!&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-1945507292972143276?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/n4gnQHZEeC-bxFEpAXFh8ETybIM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/n4gnQHZEeC-bxFEpAXFh8ETybIM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/n4gnQHZEeC-bxFEpAXFh8ETybIM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/n4gnQHZEeC-bxFEpAXFh8ETybIM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/-5zhfQMaX3A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/1945507292972143276/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=1945507292972143276" title="8 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/1945507292972143276?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/1945507292972143276?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/-5zhfQMaX3A/array-operations-in-ws-bpel.html" title="Array Operations in WS-BPEL" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>8</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/04/array-operations-in-ws-bpel.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEEQH0-eip7ImA9WhZREEw.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-3240061435976379808</id><published>2011-04-04T10:23:00.003+02:00</published><updated>2011-04-05T17:33:21.352+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-05T17:33:21.352+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java ee" /><title>Automatically starting up Java EE 5 Timers</title><content type="html">When you're developing a Java EE application and need a simple scheduler you may decide to use Java EE Timer Service API.&lt;br /&gt;
&lt;br /&gt;
Of course Java EE Timer Service is not as powerful as Quartz, but it's provided out of the box :)&lt;br /&gt;
&lt;br /&gt;
Last week I needed to implement a simple scheduler in my Java EE 5 app. I encountered a small problem - I wanted to start it automatically just after the application start up.&lt;br /&gt;
&lt;br /&gt;
Here is how I did it.&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;1st approach: create timer inside @PostConstruct method&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I tried this at first:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;@Local
public interface PeriodicWorker {
 void callback(Timer timer);
}&lt;/pre&gt;&lt;pre class="brush:java"&gt;@Stateless
public class PeriodicWorkerImpl implements PeriodicWorker {
 private static final Log log = LogFactory.getLog(PeriodicWorkerImpl.class);
 @Resource
 private TimerService timerService;
 @PostConstruct
 void init() {
  log.debug("Timer Service injected " + (timerService != null));
  timerService.createTimer(new Date(), 10000, PeriodicWorkerImpl.class);
 }
 @Timeout
 @Override
 public void callback(Timer timer) {
  log.debug("Got timeout from timer " + timer.getInfo());  
 }
}&lt;/pre&gt;&lt;br /&gt;
Of course it didn't work. Java EE container does not instantiate all SLSB when the app is started those components are started when they are needed (lazy loading).&lt;br /&gt;
&lt;br /&gt;
So my problem was, where to inject it... &lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;2nd approach: injecting worker SLSB it into another EJB component&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Injecting into another EJB? Might be tempting, but again, that EJB component had to be first called in order to be instantiated and all its &lt;code&gt;@Resource&lt;/code&gt; fields populated.&lt;br /&gt;
&lt;br /&gt;
But then it struck me, the reference to my SLSB can be injected into web container-managed &lt;code&gt;ServletContextListener&lt;/code&gt; object.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;3rd approach: injecting worker SLSB into ServletContextListener&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;ServletContextListener&lt;/code&gt; defines lifecycle methods which are called after the servlet context is initialised/destroyed.&lt;br /&gt;
&lt;br /&gt;
I was almost done, but this time I got an exception saying that it is illegal to create a timer within SLSB's &lt;code&gt;@PostConstruct&lt;/code&gt; method.&lt;br /&gt;
&lt;br /&gt;
This time it was simple to fix.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;4th and final solution&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I added&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: monospace;"&gt;createTimer&amp;nbsp;&lt;/span&gt;method to my &lt;code&gt;PeriodicWorker&lt;/code&gt; and moved creation of timer there:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;@Stateless
public class PeriodicWorkerImpl implements PeriodicWorker {
 private static final Log log = LogFactory.getLog(PeriodicWorkerImpl.class);
 @Resource
 private TimerService timerService;
 @PostConstruct
 void init() {
  log.debug("Timer Service injected " + (timerService != null));
 }
 @Override
 public void createTimer() {
  timerService.createTimer(new Date(), 10000, PeriodicWorkerImpl.class);
 }
 @Timeout
 @Override
 public void callback(Timer timer) {
  log.debug("Got timeout from timer " + timer.getInfo());  
 }
}&lt;/pre&gt;&lt;br /&gt;
And then I simply call &lt;code&gt;createTimer()&lt;/code&gt; method from my &lt;code&gt;ServletContextListener&lt;/code&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;public class TimerInitialiserContextListener implements ServletContextListener { 
 private static final Log log = LogFactory.getLog(TimerInitialiserContextListener.class);
 @EJB
 private PeriodicWorker worker;
 public void contextDestroyed(ServletContextEvent ctx) {
 }
 public void contextInitialized(ServletContextEvent ctx) {
  worker.createTimer();
 }
}&lt;/pre&gt;&lt;br /&gt;
I deployed the app and it worked like a charm.&lt;br /&gt;
&lt;br /&gt;
It turned out not to be that simple (took me 15 minutes including deploying on application server!), but it works out of the box. I pity there is no EJB-specific component which is started when the EJB module is started. Wouldn't it be nice?&lt;br /&gt;
&lt;br /&gt;
Note: Yes it would, and it's possible in Java EE 6. See this post's comments below :)&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-3240061435976379808?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BHNd_rRq4B6FbkwTSJzHr75HM0w/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BHNd_rRq4B6FbkwTSJzHr75HM0w/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BHNd_rRq4B6FbkwTSJzHr75HM0w/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BHNd_rRq4B6FbkwTSJzHr75HM0w/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/4An2p8Vy574" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/3240061435976379808/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=3240061435976379808" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/3240061435976379808?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/3240061435976379808?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/4An2p8Vy574/automatically-starting-up-java-ee.html" title="Automatically starting up Java EE 5 Timers" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/04/automatically-starting-up-java-ee.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUDSX08eip7ImA9WhZTFkQ.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-545314546562468648</id><published>2011-03-21T07:50:00.001+01:00</published><updated>2011-03-21T07:51:18.372+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-21T07:51:18.372+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="bpel" /><title>Manipulating WS-BPEL partnerLink</title><content type="html">Last week I was trying to copy partner link's endpoint reference to a variable. It's simple to override, but how to get it?&lt;br /&gt;
&lt;br /&gt;
Section 3.4.5 of &lt;a href="http://docs.oasis-open.org/wsbpel/2.0/Primer/wsbpel-v2.0-Primer.htm" target="_blank"&gt;Web Services Business Process Execution Language Version 2.0 Primer&lt;/a&gt; states, that:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;from partnerLink="Supplier"/&amp;gt;&lt;/pre&gt;&lt;br /&gt;
is sufficient.&lt;br /&gt;
&lt;br /&gt;
Well, not in case of Apache ODE...&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Running on Apache ODE&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
When you run the following code on Apache ODE:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;bpws:copy&amp;gt;
  &amp;lt;bpws:from partnerLink="abcPartnerLink"/&amp;gt;
  &amp;lt;bpws:to part="parameters" variable="variable"&amp;gt;
   &amp;lt;bpws:query&amp;gt;namespace:EPR&amp;lt;/bpws:query&amp;gt;
  &amp;lt;/bpws:to&amp;gt;
&amp;lt;/bpws:copy&amp;gt;&lt;/pre&gt;&lt;br /&gt;
you will get:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;java org.apache.ode.tools.bpelc.cline.BpelC: error: [CopyFromUndeclaredPartnerRole] Copy from partner link
abcPartnerLink with enpoint reference myRole requires the corresponding role to be defined on partner link.&lt;/pre&gt;&lt;br /&gt;
Well, OK I understand the message, but how to fix it?&lt;br /&gt;
&lt;br /&gt;
I tried google, but with no luck. Finally I found a solution for this. You have to add &lt;code&gt;endpointReference&lt;/code&gt; attribute to &lt;code&gt;&amp;lt;bpws:from /&amp;gt;&lt;/code&gt; element, just like this:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;bpws:from partnerLink="abcPartnerLink" endpointReference="partnerRole" /&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Works like a charm.&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Unexpected help&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
But guess who helped me with finding the answer to this question?&lt;br /&gt;
&lt;br /&gt;
My "beloved" Eclipse BPEL designer. Remember my &lt;a href="http://jee-bpel-soa.blogspot.com/2010/08/dynamic-web-services-invocations-in-ws.html" target="_blank"&gt;Dynamic Web Services invocations in WS-BPEL&lt;/a&gt; post where I cut Eclipse BPEL to the ribbons?&lt;br /&gt;
&lt;br /&gt;
Well, there is a newer version of Eclipse BPEL designer and I must say that things improved greatly. During last month I created 3 complex WS-BPEL processes and I hardly had to modify anything by hand! I also liked the feature of asking whether I want to generate initializers for variables - cool. Good job Eclipse BPEL developers!&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-545314546562468648?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/odJa6eF_ceVXGSQspuHda2phd74/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/odJa6eF_ceVXGSQspuHda2phd74/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/odJa6eF_ceVXGSQspuHda2phd74/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/odJa6eF_ceVXGSQspuHda2phd74/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/SQwkL6-FXys" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/545314546562468648/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=545314546562468648" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/545314546562468648?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/545314546562468648?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/SQwkL6-FXys/manipulating-ws-bpel-partnerlink.html" title="Manipulating WS-BPEL partnerLink" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/03/manipulating-ws-bpel-partnerlink.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QFQHczcSp7ImA9Wx9UFEw.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-250650257366259228</id><published>2011-02-11T10:08:00.000+01:00</published><updated>2011-02-11T10:08:31.989+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-11T10:08:31.989+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="opinion" /><title>Google Chrome is a piece of ...</title><content type="html">I switched from Firefox to Chrome some time ago, but there is one thing I really hate about Chrome. It's its complete infirmity when it comes to handling XML content.&lt;br /&gt;
&lt;br /&gt;
To view and download WSDL files I have to use Internet Explorer. Why?&lt;br /&gt;
&lt;br /&gt;
First, when you view WSDL in Chrome it displays an empty page, not XML tree, like for example FF or IE. And second, most terifying thing in handling XML content, Chrome is changing camel case elements' names to lowecase when you save/download XML documents. Here are examples of such elements:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;xs:complextype name="cancelBookingResponse"&amp;gt;
    &amp;lt;xs:sequence&amp;gt;
      &amp;lt;xs:element name="result" type="xs:boolean" /&amp;gt;
    &amp;lt;/xs:sequence&amp;gt;
&amp;lt;/xs:complextype&amp;gt;
 
&amp;lt;wsdl:porttype name="Warehouse"&amp;gt;
     &amp;lt;wsdl:operation name="cancelBooking"&amp;gt;
       &amp;lt;wsdl:input message="tns:cancelBooking" name="cancelBooking"&amp;gt;
     &amp;lt;/wsdl:input&amp;gt;
       &amp;lt;wsdl:output message="tns:cancelBookingResponse" name="cancelBookingResponse"&amp;gt;
     &amp;lt;/wsdl:output&amp;gt;
    &amp;lt;/wsdl:operation&amp;gt;
&amp;lt;/wsdl:porttype&amp;gt;&lt;/pre&gt;&lt;br /&gt;
What a disgrace!&lt;br /&gt;
&lt;br /&gt;
Long live IE! :)&lt;br /&gt;
&lt;br /&gt;
Łukasz&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-250650257366259228?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/azUvVLX57MjM_nX3VuBIwO3_Kus/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/azUvVLX57MjM_nX3VuBIwO3_Kus/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/azUvVLX57MjM_nX3VuBIwO3_Kus/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/azUvVLX57MjM_nX3VuBIwO3_Kus/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/uC9E7zEB-b8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/250650257366259228/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=250650257366259228" title="20 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/250650257366259228?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/250650257366259228?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/uC9E7zEB-b8/google-chrome-is-piece-of.html" title="Google Chrome is a piece of ..." /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>20</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/02/google-chrome-is-piece-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMCSHo_fSp7ImA9Wx9UEUg.&quot;"><id>tag:blogger.com,1999:blog-9000325999416544509.post-2994929405272748062</id><published>2011-02-08T10:08:00.001+01:00</published><updated>2011-02-08T10:14:29.445+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-08T10:14:29.445+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="uddi" /><category scheme="http://www.blogger.com/atom/ns#" term="web services" /><category scheme="http://www.blogger.com/atom/ns#" term="cxf" /><title>Implementing simple Web Services Registry using CXF</title><content type="html">UDDI is an enterprise-grade solution for Web Services Directory. Most of Java EE application servers are shipped with UDDI applications. I wrote about UDDI and JAXR previously: &lt;a href="http://jee-bpel-soa.blogspot.com/2009/11/preparing-for-scdjws-part-8-uddi.html" target="_blank"&gt;Preparing for SCDJWS Part 8: UDDI&lt;/a&gt;, &lt;a href="http://jee-bpel-soa.blogspot.com/2009/12/juddi-09rc4-and-scout-12-bugs.html" target="_blank"&gt;Fixing jUDDI 0.9rc4 and Scout 1.2 bugs&lt;/a&gt;, and &lt;a href="http://jee-bpel-soa.blogspot.com/2010/01/preparing-to-scdjws-part-15-jaxr-and.html" target="_blank"&gt;Preparing for SCDJWS Part 15: JAXR and Web Services Registries&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
Today I will show you a more flyweight approach to Web Services Registry. I will use Apache CXF for it.&lt;br /&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;div class="fullpost"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Bean configuration&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Let's start with beans.xml configuration:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:xml"&gt;&amp;lt;bean id="RegistryServiceBean" class="pl.gda.pg.eti.nuntius.testcases.orders_local_business_process_services.registry.RegistryServiceImpl " /&amp;gt;
&amp;lt;jaxws:endpoint 
   id="RegistryService" 
   implementor="#RegistryServiceBean" 
   address="/Registry" /&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
:) Simple isn't it?&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;The implementation&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Assume our registry service expects &lt;code&gt;namespace&lt;/code&gt; and &lt;code&gt;portType&lt;/code&gt; arguments, and returns a list of &lt;code&gt;W3CEndpointReference&lt;/code&gt; (WS-Addressing) endpoints:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush:java"&gt;@WebService(name = "Registry", serviceName = "RegistryService")
public class RegistryServiceImpl implements ApplicationContextAware {

 private ServletTransportFactory servletTransportFactory;

 public List&amp;lt;W3CEndpointReference&amp;gt; findWebServices(
   @WebParam(name = "namespace") String namespace,
   @WebParam(name = "portType") String portType) {

  QName portTypeQName = new QName(namespace, portType);

  List&amp;lt;W3CEndpointReference&amp;gt; endpointReferences = new ArrayList&amp;lt;W3CEndpointReference&amp;gt;();

  for (ServletDestination servletDestination : servletTransportFactory
    .getDestinations()) {
   EndpointInfo endpointInfo = servletDestination.getEndpointInfo();
   if (portTypeQName.equals(endpointInfo.getInterface().getName())) {
    String address = endpointInfo.getAddress();
    W3CEndpointReference endpointReference = new W3CEndpointReferenceBuilder()
      .address(address).build();
    endpointReferences.add(endpointReference);
   }
  }

  return endpointReferences;
 }

 @Override
 @WebMethod(exclude = true)
 public void setApplicationContext(ApplicationContext applicationContext)
   throws BeansException {
  servletTransportFactory = (ServletTransportFactory) applicationContext
    .getBean(ServletTransportFactory.class.getCanonicalName());
 }

}&lt;/pre&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
I think no comments are required, but if you have any questions give me a shout.&lt;br /&gt;
&lt;br /&gt;
cheers,&lt;br /&gt;
Łukasz&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9000325999416544509-2994929405272748062?l=jee-bpel-soa.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/EkbX43sHteGVQ_2WBF58orwXhuQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/EkbX43sHteGVQ_2WBF58orwXhuQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/EkbX43sHteGVQ_2WBF58orwXhuQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/EkbX43sHteGVQ_2WBF58orwXhuQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/jee-bpel-soa-feed-new/~4/is1RgWXAKP4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://jee-bpel-soa.blogspot.com/feeds/2994929405272748062/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9000325999416544509&amp;postID=2994929405272748062" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/2994929405272748062?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9000325999416544509/posts/default/2994929405272748062?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/jee-bpel-soa-feed-new/~3/is1RgWXAKP4/implementing-simple-web-services.html" title="Implementing simple Web Services Registry using CXF" /><author><name>Łukasz Budnik</name><uri>http://www.blogger.com/profile/14390183710558627143</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://3.bp.blogspot.com/_DutjqqRLzpg/SLJc4ZYBFSI/AAAAAAAAB6M/ZI7Szj9p45U/S220/profil.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://jee-bpel-soa.blogspot.com/2011/02/implementing-simple-web-services.html</feedburner:origLink></entry></feed>

