<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>bogdan@j3e</title>
	<atom:link href="http://www.bserban.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bserban.org</link>
	<description>Web, Java, J2EE, SaaS, Tips&#38;Tricks</description>
	<lastBuildDate>Thu, 08 Jul 2010 11:53:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Key takeaways from my TDD training sessions</title>
		<link>http://www.bserban.org/2010/02/key-takeaways-from-my-tdd-training-sessions/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=key-takeaways-from-my-tdd-training-sessions</link>
		<comments>http://www.bserban.org/2010/02/key-takeaways-from-my-tdd-training-sessions/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 11:38:33 +0000</pubDate>
		<dc:creator>bserban</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[Test Driven Development]]></category>
		<category><![CDATA[Test First Programming]]></category>

		<guid isPermaLink="false">http://www.bserban.org/?p=307</guid>
		<description><![CDATA[Recently I had the chance to participate to a Test Driven Development session. Until now I never tried TDD I just simply used the TFP (Test First Programming), so let&#8217;s see what are the differences between Waterfall model, TDD and TFP. After that I&#8217;ll list some key points about doing TDD. Programmers&#8217; headache started in [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2010%2F02%2Fkey-takeaways-from-my-tdd-training-sessions%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2010%2F02%2Fkey-takeaways-from-my-tdd-training-sessions%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=TDD,Test+Driven+Development,Test+First+Programming" height="61" width="50" /><br />
			</a>
		</div>
<p align="justify">Recently I had the chance to participate to a Test Driven Development session. Until now I never tried TDD I just simply used the TFP (Test First Programming), so let&#8217;s see what are the differences between Waterfall model, TDD and TFP. After that I&#8217;ll list some key points about doing TDD.</p>
<p style="clear: both" align="justify"><img style="margin: 0px 0px 10px 10px; display: inline; float: right" alt="Waterfall process" align="right" src="http://www.bserban.org/wp-content/uploads/2010/02/Waterfall2-e1266745293226.png" />Programmers&#8217; headache started in 1970 when Winston Royce published the <strong>Waterfall</strong> model. This model was based on a set of sequential steps: Analysis, Design, Code, Test, Maintain. The big assumption made was that the design precedes the coding phase and the testing phase comes after the coding. A very structured approach. This is a description of a well defined process which works great on other industries but the practice proved that software development is an empiric process rather than a very well defined one and for such process you need a short feedback loop. This assumption is the foundation of the agile methodologies which are surfacing the project problems since the beginning.</p>
<p style="clear: both" align="justify"><img style="margin: 0px 0px 10px 10px; display: inline; float: right" alt="Test first model" align="right" src="http://www.bserban.org/wp-content/uploads/2010/02/tfp-13.png" />Test Driven Development and <strong>Test First Programming</strong> are reducing the gap between testing and design allowing you to adapt your design as you go. The Test First Programming assumes that you have a design upfront and you start your coding by writing tests to validate your design. The loop is only between code and tests but no for design. This is in fact a longer development cycle because the design is corrected at the later time.</p>
<p style="clear: both" align="justify"><img style="margin: 0px 0px 10px 10px; display: inline; float: right" alt="Test Driven Development Cycle" align="right" src="http://www.bserban.org/wp-content/uploads/2010/02/tdd-13.png" width="150" /><strong>TDD</strong> assumes that you don&#8217;t have design upfront, your design emerges with the code and you have a loop between all three key elements: Test, Design, Code. Now you can incorporate testing feedback into design and code as you go. Such a cycle should take around 30 minutes.</p>
<p style="clear: both">The four golden rules of TDD:</p>
<p style="clear: both;"><span id="more-307"></span></p>
<blockquote><ul>
<li>Add code on red </li>
<li>Delete code on green </li>
<li>Remove duplications </li>
<li>Fix bad names </li>
</ul>
</blockquote>
<p>The development cycle look likes this:</p>
<div><img style="margin: 0px 10px 10px 0px; display: inline; float: left" alt="TDD cycle" align="left" src="http://www.bserban.org/wp-content/uploads/2010/02/cycle1.png" /> </div>
<p><br style="clear: both" />
<p style="clear: both">Key takeaways:</p>
<ul style="clear: both">
<li>With TDD you take the design decision as late as you can. </li>
<li>TDD maximize code clarity </li>
<li>With TDD you go steady, you will get speed on the way </li>
<li>Your code is more changeable and you are able to accommodate the changes with less effort </li>
<li>Run your tests very often, try every 5 minutes </li>
<li>If you have a long build time then TDD will surface these problems. Probably you have dependencies problems. </li>
<li>Try to reduce the compile time of your work to 30s </li>
<li>There is no such thing as large modular system. If it is modular then your module should compile and build fast. </li>
<li>Name the methods correctly </li>
<li>Name methods after what they do and look after &#8220;Or&#8221; &#8220;And&#8221; method names, something is wrong there. </li>
<li>Look for multiple responsibilities and remove them </li>
<li>If the data is not where you need it then something is wrong. </li>
<li>Follow the <em>open close</em> principle </li>
<li>The link between inputs and outputs should be clear for the tests </li>
<li>When you have design disputes you can branch and meet after 1h </li>
<li>Stop when no new feature or new defect force you to refactor </li>
<li>Refactoring depends on the personal appetite </li>
<li>If you go back after 1 week you should understand the code completely </li>
<li>Write the test for single threaded, if your code runs in multithreading environment then apply the rules of multithreading programming. </li>
<li>Small code don&#8217;t need TDD. If the cost of TDD is higher than throwing your code away and rewrite it then you don&#8217;t need TDD. </li>
</ul>
<blockquote><p style="clear: both">TDD and junior teams myth:      <br />Junior programmers have always less to forget and fewer bad habits. Junior teams benefit most from TDD while experience programmers have to forget some of their bad habits.</p>
</blockquote>
<h1>A TDD example</h1>
<p style="clear: both" align="justify">Let’s code and design a simple stack using TDD. I’ll present couple of steps of the process but not the final implementation. First we have to answer to the most mind boggling question of a programmer: </p>
<p style="clear: both" align="center"><em>Who was first the test or the code?</em></p>
<p style="clear: both" align="justify">Of course the answer is <strong>THE TEST!</strong> Remember the first step of the TDD cycle, write the simplest test that fails.</p>
<p style="clear: both" align="justify">So our test class is <em>StackTest</em> and our first method is <em>testEmptyStack:</em></p>
<pre class="brush: java">import static junit.framework.Assert.assertEquals;
import org.junit.Test;

public class StackTest {
    @Test
    public void testEmptyStack() {
        assertEquals(0, stack.size());
    }
}</pre>
<p align="justify">Now we have to make the test pass writing only the code required for that. I am going to use junit for the assert methods. Our stack will be named <em>MStack</em> to avoid the name collision with the <em>java.util.Stack</em>. My IDE is insisting in using that class. </p>
<pre class="brush: java">    public void testEmptyStack() {
        MStack stack = new MStack();
        assertEquals(0, stack.size());
    }</pre>
<p align="justify">Now let&#8217;s create the MStack, for the sake of simplicity I am going to use inner classes and in the end when the design is complete I&#8217;ll pull the code out: </p>
<pre class="brush: java">public class StackTest {
    @Test
    public void testEmptyStack() {
        MStack stack = new MStack();
        assertEquals(0, stack.size());
    }
}
class MStack {
    public int size() {
        return 0;
    }
}</pre>
<p align="justify">So we have written the code that make the test pass, looking of the code i see no duplicates or function names that have to rename to a better name. Let’s write the simple test that make the code fail. I say let’s test the “<em>push</em>”.</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="runtests-1" border="0" alt="runtests-1" src="http://www.bserban.org/wp-content/uploads/2010/02/runtests1.gif" /></p>
<pre class="brush: java">   @Test
    public void testPushElement() {
        MStack stack = new MStack();
        stack.push(&quot;First element&quot;);
        assertEquals(1, stack.size());
    }</pre>
<p align="justify">Add the <em>push</em> method and run the test to see them fail: </p>
<pre class="brush: java">junit.framework.AssertionFailedError: expected:&lt;1&gt; but was:&lt;0&gt;
	at org.bserban.tdd.StackTest.testPushElement(StackTest.java:16)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)</pre>
<p align="justify">&#160;</p>
<p align="justify">Now write the simplest code that make the code pass the tests, remember the rules! </p>
<blockquote><p>Add code on red, delete code on green! </p></blockquote>
<pre class="brush: java">class MStack {
    private boolean elementAdded;
    public int size() {
        if (elementAdded) {
            return 1;
        }
        return 0;
    }
    public void push(String element) {
        elementAdded = true;
    }
}
Run the tests:
Process finished with exit code 0
</pre>
<p align="justify">The code above could look stupid but this is the essence of the test driven design, remember experience programmers have a lot to forget <img src='http://www.bserban.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> , they are not willing to code in such manner until the see the true benefit of such approach. The problem we choose is trivial and for people with experience this way to code sounds silly. I&#8217;ll add two new asserts that make the code fail the tests. </p>
<pre class="brush: java">    @Test
    public void testPushElement() {
        MStack stack = new MStack();
        stack.push(&quot;First element&quot;);
        assertEquals(1, stack.size());
        stack.push(&quot;Second element&quot;);
        assertEquals(2, stack.size());
        stack.push(&quot;Third element&quot;);
        assertEquals(3, stack.size());
    }

Process finished with exit code -1

junit.framework.AssertionFailedError: expected:&lt;2&gt; but was:&lt;1&gt;
	at org.bserban.tdd.StackTest.testPushElement(StackTest.java:19)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)</pre>
<p align="justify">Remember, don&#8217;t delete the existing code on red: </p>
<pre class="brush: java">class MStack {
    private boolean elementAdded;
    private boolean secondElementAdded;
    private boolean thirdElementAdded;

    public int size() {
        if (thirdElementAdded) {
            return 3;
        }else if (secondElementAdded) {
            return 2;
        } else if(elementAdded){
                return 1;
        }
        return 0;
    }
    public void push(String element) {
        if (elementAdded) {
            if (secondElementAdded) {
                thirdElementAdded = true;
            } else {
                secondElementAdded = true;
            }
        } else {
            elementAdded = true;
        }
    }
}

Run the tests:
Process finished with exit code 0</pre>
<p align="justify">Now we are on green and we are ready to refactor, the rules are: &#8220;Remove duplication and fix bad wording&#8221;. Studying the code above we see that <em>elementAdded</em>, <em>secondElementAdded</em> and <em>thirdElementAdded</em> is in fact a duplication, also from the size method we see that the last element added gives us the size. </p>
<p align="justify">So I say to refactor like this, let’s add a size variable and every time we push an element you increment this variable. Evrika! The code becomes cleaner and compact <img src='http://www.bserban.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . I must confess that these are lines that I would be writing from the start, what a bad habit <img src='http://www.bserban.org/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<pre class="brush: java">class MStack {
    private int size = 0;
    public int size() {
        return size;
    }
    public void push(String element) {
        size++;
    }
}
Run the tests:
Process finished with exit code 0
</pre>
<p align="justify">Now we proceed with method pop in the similar mater. Write the simplest test that fails:</p>
<pre class="brush: java">    @Test
    public void testPopElement() {
        MStack stack = new MStack();
        stack.push(&quot;First element&quot;);
        assertEquals(1, stack.size());
        stack.pop();
        assertEquals(0, stack.size());
    }
Run the tests:
junit.framework.AssertionFailedError: expected:&lt;0&gt; but was:&lt;1&gt;
	at org.bserban.tdd.StackTest.testPopElement(StackTest.java:29)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
</pre>
<p align="justify">We are on red, we add code, we create variable popOnce:</p>
<pre class="brush: java">private boolean popOnce=false;
    public int size() {
        if (popOnce) {
            return size - 1;
        }
        return size;
    }
    public void pop() {
        popOnce = true;
    }
Run the tests:
Process finished with exit code 0
</pre>
<p align="justify">Now we add the simple test that fails, three <em>pushes</em> and two <em>pops</em>. And so on, in the end we end up with the following <em>pop</em> code</p>
<pre class="brush: java">public class StackTest {
    @Test
    public void testEmptyStack() {
        MStack stack = new MStack();
        assertEquals(0, stack.size());
    }
    @Test
    public void testPushElement() {
        MStack stack = new MStack();
        stack.push(&quot;First element&quot;);
        assertEquals(1, stack.size());
        stack.push(&quot;Second element&quot;);
        assertEquals(2, stack.size());
        stack.push(&quot;Third element&quot;);
        assertEquals(3, stack.size());
    }
    @Test
    public void testPopElement() {
        MStack stack = new MStack();
        stack.push(&quot;First element&quot;);
        assertEquals(1, stack.size());
        stack.pop();
        assertEquals(0, stack.size());
        stack.push(&quot;First element&quot;);
        stack.push(&quot;Second element&quot;);
        stack.push(&quot;Third element&quot;);
        stack.pop();
        stack.pop();
        assertEquals(1, stack.size());
    }
}
class MStack {
    private int size = 0;
    public int size() {
        return size;
    }
    public void push(String element) {
        size++;
    }
    public void pop() {
        if (size &gt; 0) {
            size--;
        }
    }
}
Run the tests:
Process finished with exit code 0
</pre>
<p>I think you&#8217;ve got the idea. I let you finish this implementation, I&#8217;ll just remind you the golden rules:</p>
<ul>
<li>Add code on red</li>
<li>Delete code on green </li>
<li>Remove duplications </li>
<li>Fix bad names</li>
</ul>
<p>Cheers,</p>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2010%2F02%2Fkey-takeaways-from-my-tdd-training-sessions%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2010%2F02%2Fkey-takeaways-from-my-tdd-training-sessions%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=TDD,Test+Driven+Development,Test+First+Programming" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bserban.org/2010/02/key-takeaways-from-my-tdd-training-sessions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How a DNS problem can put your Mysql server down</title>
		<link>http://www.bserban.org/2010/01/how-a-dns-problem-can-put-your-mysql-server-down/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-a-dns-problem-can-put-your-mysql-server-down</link>
		<comments>http://www.bserban.org/2010/01/how-a-dns-problem-can-put-your-mysql-server-down/#comments</comments>
		<pubDate>Sat, 16 Jan 2010 15:10:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Infrastructure]]></category>
		<category><![CDATA[MySql]]></category>
		<category><![CDATA[clustering]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[Mysql client]]></category>

		<guid isPermaLink="false">http://www.bserban.org/?p=288</guid>
		<description><![CDATA[Last week i was waked up from bed by the monitoring team from my company. There was a problem with my system, there was a DNS problem undergoing but as a side effect my app was down. Since it has a lot of traffic it had to be solved immediately. I jumped to the computer [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2010%2F01%2Fhow-a-dns-problem-can-put-your-mysql-server-down%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2010%2F01%2Fhow-a-dns-problem-can-put-your-mysql-server-down%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=DNS,MySql,Mysql+client" height="61" width="50" /><br />
			</a>
		</div>
<p>Last week i was waked up from bed by the monitoring team from my company. There was a problem with my system, there was a DNS problem undergoing but as a side effect my app was down. Since it has a lot of traffic it had to be solved immediately.</p>
<p>I jumped to the computer and I quickly diagnosed the system. Everything was fine except the Mysql connection pool which was exhausted. The first thing that crossed my mind is that it was just a coincidence and I quickly ran <em>show processlist</em> to see a list of MySQL processes. The output was an infinite list of load balancer&#8217;s ip address having &#8220;login&#8221; text as status. In order to achieve high availability i am using Mysql by having a balanced ip address between two Mysql servers. The balancer runs a quick check every 5 seconds by connecting to Mysql and does a simple select on a table.</p>
<p>So for a particular reason the &#8220;load balancer&#8221; was not able to finish its login attempts and it was overloading my Mysql servers. While I was in the middle of the investigation  the problem suddenly stopped. I was happy but somehow scared, i had no idea what the hell happened.</p>
<p>A quick search into Mysql documentation reveals that Mysql is doing a reverse DNS lookup which was the cause of my problems. Since the DNS server had a problem,  the operation of reverse DNS was taking far more that 5 seconds to time out. This resulted in overloading the database servers. Check this explanation in the official documentation, <a href="http://dev.mysql.com/doc/refman/5.0/en/dns.html">How MySQL Uses DNS</a></p>
<p>After reading tha page I think that mysql needs this reverse DNS lookup only for its permission module and if you don&#8217;t use host names with the grant option then you are safe to disable this option. I quote here the parameter which does this:</p>
<blockquote><p>&#8211;skip-name-resolve</p>
<p>Do not resolve host names when checking client connections. Use only IP numbers. If you use this option, all Host column values in the grant tables must be IP numbers or localhost. See Section 7.5.11, “How MySQL Uses DNS”.</p></blockquote>
<p>I have been able to avoid this? Perhaps, but considering that I used MySQL in production for the first time, it is unlikely to think so.</p>
<p>Long live the reverse DNS, cheers!
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2010%2F01%2Fhow-a-dns-problem-can-put-your-mysql-server-down%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2010%2F01%2Fhow-a-dns-problem-can-put-your-mysql-server-down%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=DNS,MySql,Mysql+client" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bserban.org/2010/01/how-a-dns-problem-can-put-your-mysql-server-down/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating a secure JMX Agent in JDK 1.5</title>
		<link>http://www.bserban.org/2009/10/creating-a-secure-jmx-agent-in-jdk-1-5/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=creating-a-secure-jmx-agent-in-jdk-1-5</link>
		<comments>http://www.bserban.org/2009/10/creating-a-secure-jmx-agent-in-jdk-1-5/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 17:03:39 +0000</pubDate>
		<dc:creator>bserban</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[JMX]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[Agent]]></category>
		<category><![CDATA[JMX Architecture]]></category>
		<category><![CDATA[JMX JDK 1.5]]></category>
		<category><![CDATA[JMXConnectorServer]]></category>
		<category><![CDATA[MBeanServer]]></category>
		<category><![CDATA[SSL JMX]]></category>

		<guid isPermaLink="false">http://www.bserban.org/?p=254</guid>
		<description><![CDATA[What is JMX? Java Management Extension is an open technology for management, and monitoring that can be deployed wherever management and monitoring are needed. The most common use in a web application is for application management. This is very often an afterthought which results in many unmanaged application deployments. You can monitor you application for [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F10%2Fcreating-a-secure-jmx-agent-in-jdk-1-5%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F10%2Fcreating-a-secure-jmx-agent-in-jdk-1-5%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=Agent,JMX,JMX+Architecture,JMX+JDK+1.5,JMXConnectorServer,MBeanServer,SSL+JMX" height="61" width="50" /><br />
			</a>
		</div>
<h2>What is JMX?</h2>
<p>Java Management Extension is an open technology for management, and monitoring that can be deployed wherever management and monitoring are needed. The most common use in a web application is for application management. This is very often an afterthought which results in many unmanaged application deployments.</p>
<p>You can monitor you application for availability and performance but in the same time you can use the JMX to manage and monitor you application from business perspective. Application&#8217;s runtime metrics can be expose through JMX, or in a service oriented architecture you could use JMX to control your services.</p>
<p>All good but when you start to work with <strong>JMX and JDK 1.5</strong> soon you will discover one big limitation that was fixed in jdk 1.6 update 16 if i recall correctly:</p>
<blockquote><p>Default RMI JMX agent for remote access opens 2 ports, one which is set by the -Dcom.sun.management.jmxremote.port=XXXX <strong>and one randomly assigned port.</strong>. What about firewalls?</p></blockquote>
<h2>JMX service url</h2>
<p>service:jmx:rmi://hostname:<strong>port1</strong>/jndi/rmi//hostname:<strong>port2</strong>/jmxrmi</p>
<p>Where:</p>
<ul>
<li><strong>port1 </strong>is the port number on which the <strong>RMIServer </strong>and <strong>RMIConnection </strong>remote objects are exported</li>
<li><strong>port2 </strong>is the port number of the <strong>RMI Registry</strong></li>
</ul>
<p><span id="more-254"></span><br />
To access the RMIAgent you only need to know were the RMI registry is located from which to obtain the connection objects. I guess this was the reason to randomly assign the port1, but you have pretty high chances to have a firewall problem.</p>
<p>The solution is to replace the default agent and to create your own version of JMX Agent to provide access to RMI connection on a specific port.</p>
<h2>JMX Architecture</h2>
<p>There are three main components that makes the JMX possible:</p>
<ul>
<li>Instrumentation<strong> </strong>layer, the managed beans and their resources. What you want to manage</li>
<li>JMX Agent, standard management agent that directly controls resources and makes them available to remote management applications. It is a mean to expose the managed beans, mbean server, monitoring, timing, relation, and class-loading services.</li>
<li>Remote management, permits the interaction between remote clients and the JMX Agent. There are a couple of default adapters that are built in, these are: HTTP Adapter (for viewing management data), RMI Adapter, SOAP Adapter, and SNMP Adapter.</li>
</ul>
<h2>Creating the Agent</h2>
<p>To overcome the problems in JDK 1.5 explained above we need to create an java agent to export the RMI Registry and the RMIServer on specific ports.</p>
<p>This is pretty straight forward, we just need to export the RMIRegistry o a specific port, to get the MBeanServer and to create a JMXConnectorServer between those two. Then we just need to start the connector server and it is done</p>
<pre class="brush: java">....................
LocateRegistry.createRegistry(port);
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
final String hostname = InetAddress.getLocalHost().getHostName();
JMXServiceURL url = new JMXServiceURL(&quot;service:jmx:rmi://&quot;+hostname+&quot;:&quot;+port+&quot;/jndi/rmi://&quot;+hostname+&quot;:&quot;+port+&quot;/jmxrmi&quot;);
JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
cs.start();
</pre>
<p>Simple as it gets, but right now we don;t have any security in place. If we want to add SSL and authorization things will complicate a little.</p>
<h2>Securing the Agent</h2>
<p>To make the access secure we have to expose the RMIRegisty over the SSL. For this we need to make the following modification:</p>
<pre class="brush: java">
..............
SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory();
SslRMIServerSocketFactory ssf = new SslRMIServerSocketFactory();
Registry registry = LocateRegistry.createRegistry(port, csf, ssf);
................

// Now specify the SSL Socket Factories:
//
// For the client side (remote)
//
env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf);
// For the server side (local)
//
env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf);
// For binding the JMX RMI Connector Server with the registry
// created above:
//
env.put(&quot;com.sun.jndi.rmi.factory.socket&quot;, csf);

final RMIServerImpl stub = new RMIJRMPServerImpl(port, csf, ssf, env);

final JMXConnectorServer cs =
new RMIConnectorServer(new JMXServiceURL(&quot;rmi&quot;, hostname, port),
env, stub, mbs) {
@Override
public JMXServiceURL getAddress() {
return url;
}
@Override
public synchronized void start() throws IOException {
try {
registry.bind(&quot;jmxrmi&quot;, stub);
} catch (AlreadyBoundException x) {
final IOException io = new IOException(x.getMessage());
io.initCause(x);
throw io;
}
super.start();
}
};
cs.start();</pre>
<p>As you see we had to secure also the connection between ConnectorServer and JMX agent and for RMI server and client. Not that simple as the unsecure version. To add the authorization we just need to provide the credentials. Usually these are store in files and passed to the jmx connector server using environment variables:</p>
<pre class="brush: java">env.put(&quot;jmx.remote.x.password.file&quot;, pasword);
env.put(&quot;jmx.remote.x.access.file&quot;, access);
</pre>
<p>And their content:</p>
<pre class="brush: java">admin password1
monitor password2
..................
admin readwrite
monitor readonly
</pre>
<p>In order that SSL connections to work we need to create a keystore. This is done using keytool and can be create like this:</p>
<pre class="brush: java">
keytool -genkey -keyalg RSA -keysize 1024 -dname &quot;CN=org.bserban.www&quot; -keystore ./jmx-demo.jks -storepass bserban
</pre>
<h3>Running the Agent</h3>
<pre class="brush: java">
java -javaagent:jmx-agent.jar -Djavax.net.ssl.trustStore=./jmx-demo.jks -Djavax.net.ssl.trustPassword=bserban -Djavax.net.ssl.keyStore=./jmx-demo.jks -Djavax.net.ssl.keyStorePassword=bserban org.abserban.jmx.agent.StartAgentStandalone
</pre>
<h3>Running the Client</h3>
<pre class="brush: java">
java -Djavax.net.ssl.trustStore=./jmx-demo.jks -Djavax.net.ssl.trustPassword=bserban -Djavax.net.ssl.keyStore=./jmx-demo.jks -Djavax.net.ssl.keyStorePassword=bserban org.abserban.jmx.client.StartClient -host:localhost -port:8787 -status:on
</pre>
<p>See the comple code from Resources section. It includes the complete java code, ant file and the keystore.</p>
<h3>Resources</h3>
<ul>
<li><a href="http://www.bserban.org/wp-content/uploads/2009/10/jmx-agent.zip">Comple source code</a></li>
<li><a href="http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/best-practices.jsp">JMX Best practices</a></li>
<li><a href="http://java.sun.com/javase/technologies/core/mntr-mgmt/javamanagement/articles.jsp">JMX Articles</a></li>
</ul>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F10%2Fcreating-a-secure-jmx-agent-in-jdk-1-5%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F10%2Fcreating-a-secure-jmx-agent-in-jdk-1-5%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=Agent,JMX,JMX+Architecture,JMX+JDK+1.5,JMXConnectorServer,MBeanServer,SSL+JMX" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bserban.org/2009/10/creating-a-secure-jmx-agent-in-jdk-1-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Configure Apache and Tomcat severs together</title>
		<link>http://www.bserban.org/2009/08/configure-apache-and-tomcat-severs-together/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=configure-apache-and-tomcat-severs-together</link>
		<comments>http://www.bserban.org/2009/08/configure-apache-and-tomcat-severs-together/#comments</comments>
		<pubDate>Sat, 08 Aug 2009 08:12:00 +0000</pubDate>
		<dc:creator>bserban</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Tomcat]]></category>
		<category><![CDATA[clustering]]></category>
		<category><![CDATA[mod_proxy_ajp]]></category>
		<category><![CDATA[AJP]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Apache Benchmark]]></category>
		<category><![CDATA[mod_proxy]]></category>

		<guid isPermaLink="false">http://www.bserban.org/?p=209</guid>
		<description><![CDATA[The most common way to deploy your application in the production environment is to hide the Tomcat behind Apache. This has good and bad parts but it gives you a lot of flexibility and support from Apache. There are a couple of alternatives to put these two severs together: mod_jk, this is the old connector [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F08%2Fconfigure-apache-and-tomcat-severs-together%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F08%2Fconfigure-apache-and-tomcat-severs-together%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=AJP,Apache,Apache+Benchmark,mod_proxy,mod_proxy_ajp,Tomcat" height="61" width="50" /><br />
			</a>
		</div>
<p>The most common way to deploy your application in the production environment is to hide the Tomcat behind Apache. This has good and bad parts but it gives you a lot of flexibility and support from Apache. There are a couple of alternatives to put these two severs together:</p>
<ul>
<li><em>mod_jk</em>, this is the old connector developed under the Tomcat project and it is using the Tomcat&#8217;s AJP protocol. It is expected to be faster than the HTTP protocol which is text based.</li>
<li><em>mod_proxy</em>, is the support module for HTTP protocol. It is TCP based and uses the HTTP which is plain text. When a web client makes a request to Apache, the Apache will make the same call to the Tomcat and then the Tomcat&#8217;s response is passed back to the web client. This connector is part of the Apache for a very long time and it is available also for older versions of Apache. This is the simplest way to put the Apache in front of a Tomcat but also the slowest way to do it.</li>
<li><em>mod_proxy_ajp</em>, is new and is part of the Apache 2.2. It is working like <em>mod_proxy</em>, but as the name says it is using the AJP connector for sending and getting data from Tomcat. It is using also TCP and it is expected to be faster than plain <em>mod_proxy</em></li>
</ul>
<p><span id="more-209"></span></p>
<h1>Using mod_proxy</h1>
<p>Create your own tomcat-httpd.conf file and configure the proxy:</p>
<p><code>#<br />
# Server will not close the connection after each request allowing the browser to use the same connection<br />
#<br />
KeepAlive On<br />
MaxKeepAliveRequests 100<br />
KeepAliveTimeout 5</code></p>
<p>#<br />
# Load mod_proxy modules<br />
#<br />
&lt;IfModule !proxy_module&gt;<br />
LoadModule proxy_module modules/mod_proxy.so<br />
&lt;/IfModule&gt;</p>
<p>&lt;IfModule !proxy_http_module&gt;<br />
LoadModule proxy_http_module modules/mod_proxy_http.so<br />
&lt;/IfModule&gt;</p>
<p>ProxyRequests Off<br />
ProxyPreserveHost On<br />
ProxyTimeout 1000<br />
TimeOut 1000</p>
<p>#<br />
# Configure the mod_proxy<br />
#<br />
ProxyPass / http://127.0.0.1:8080/<br />
ProxyPassReverse / http://127.0.0.1:8080/</p>
<p>Include your configuration into Apache <em>httpd.conf</em> using Include directive:</p>
<p><code>#load Tomcat proxy configuration<br />
Include /usr/local/tomcat6/conf/tomcat-httpd.conf</code></p>
<h1>Using mod_proxy_ajp</h1>
<p>The only difference between mod_proxy and mod_proxy_ajp is that you have to load mod_proxy_ajp and proxy the request to Tomcat using the ajp protocol.</p>
<p><code>#<br />
# Load mod_proxy modules<br />
#<br />
&lt;IfModule !proxy_module&gt;<br />
LoadModule proxy_module modules/mod_proxy.so<br />
&lt;/IfModule&gt;</code></p>
<p>&lt;IfModule !proxy_http_module&gt;<br />
LoadModule proxy_http_module modules/mod_proxy_http.so<br />
&lt;/IfModule&gt;</p>
<p>&lt;IfModule !proxy_ajp_module&gt;<br />
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so<br />
&lt;/IfModule&gt;</p>
<p>ProxyRequests Off<br />
ProxyPreserveHost On<br />
ProxyTimeout 1000<br />
TimeOut 1000<br />
#<br />
# Enable the AJP proxy<br />
#<br />
ProxyPass / ajp://localhost:8009/<br />
ProxyPassReverse / ajp://localhost:8009/</p>
<p>Include your configuration into Apache <em>httpd.conf</em> using Include directive:</p>
<p><code>#load Tomcat proxy configuration<br />
Include /usr/local/tomcat6/conf/tomcat-httpd.conf</code></p>
<h1>Using mod_jk</h1>
<p>Edit your <em>tomcat-httpd.conf</em> file and add mod_jk configuration:<br />
<code><br />
#<br />
# Load mod_jk is is not loaded already<br />
#<br />
&lt;IfModule !jk_module&gt;<br />
LoadModule jk_module modules/mod_jk.so<br />
&lt;/IfModule&gt;<br />
#<br />
#<br />
#<br />
JkWorkersFile /etc/httpd/conf/workers.properties<br />
JkLogFile /var/logs/httpd/mod_jk.log<br />
JkLogLevel info<br />
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "<br />
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories<br />
JkRequestLogFormat "%w %V %T"<br />
JkMount /test/* worker1</code></p>
<p>Include your configuration into Apache httpd.conf using Include directive:</p>
<p><code>#load mod_jk configuration configuration<br />
Include /usr/local/tomcat6/conf/tomcat-httpd.conf<br />
</code><br />
Now edit the workers.properties and configure your worker:<br />
<code><br />
worker.list=worker1<br />
worker.worker1.type=ajp13<br />
worker.worker1.host=localhost<br />
worker.worker1.port=8009<br />
worker.worker1.connection_pool_size=150<br />
worker.worker1.connection_pool_timeout=600<br />
worker.worker1.socket_keepalive=1</code></p>
<h1>Test each configuration using Apache Benchmark tool</h1>
<p>Apache benchmark it is a great tool for testing the above configurations. All you need is to create a typical application page that should be hit with the ab tool. This tool takes a single url and makes requests repeatedly in separates threads. The number of threads is controlled by command line arguments. It also supports keep alive connections.</p>
<p>For more details about Apache Benchmark check this page <a href="http://httpd.apache.org/docs/2.0/programs/ab.html">Apache Benchmark</a></p>
<p>For testing purposes i have created a test war which has a test.jsp page. Because what we test does not influence the processing time overall we don’t need a complete test which includes a database call or working with certain frameworks. In the end all we need is the output of an application and to test how this output reach the browser using one of the three modes explained in the section above.</p>
<p>The test page will include a previous post of mine which is medium size: http://www.bserban.org/2009/05/put-together-struts2-jpa-hibernate-and-spring/. I have right-clicked in the browser, chosen the view source and copy and paste the content into test.jsp. The file has 112Kb in size.</p>
<p><em><br />
bserban-mac:~ bserban$ ls -la ~/bin/srv/apache-tomcat-5.5.27/webapps/test/test.jsp<br />
-rw-r&#8211;r&#8211;  1 bserban  staff  113698 Aug  7 09:39 /Users/bserban/bin/srv/apache-tomcat-5.5.27/webapps/test/test.jsp<br />
</em></p>
<p>I am going to hit the Tomcat and the Apache with 10,000 request using 50 threads. The ab command looks like this:</p>
<p><em><br />
ab -k -n 10000 -c 50 http://localhost/test/test.jsp<br />
</em></p>
<p>To access directly the Tomcat i am going to hit the 8080 port. To preserve the similar enviroment and test conditions I will restart the Apache and Tomcat after each test.</p>
<h2>Test results</h2>
<p>The table below summarize the results obtained.</p>
<table class="design5" border="0">
<thead>
<tr>
<th></th>
<th>Direct</th>
<th>mode_proxy</th>
<th>mode_proxy_ajp</th>
</tr>
</thead>
<tbody>
<tr>
<td>Throughput</td>
<td>992 reg/s</td>
<td>667 req/s</td>
<td>702 req/s</td>
</tr>
<tr>
<td>Average Response Time</td>
<td>50 ms</td>
<td>75 ms</td>
<td>71 ms</td>
</tr>
<tr>
<td>90% Response line</td>
<td>75 ms</td>
<td>90 ms</td>
<td>71 ms</td>
</tr>
<tr>
<td>100% Response line</td>
<td>207 ms</td>
<td>980 ms</td>
<td>972 ms</td>
</tr>
</tbody>
</table>
<p>As you see, the fastest connecting mode is to connect directly to tomcat using HTTP. Direct HTTP connect will server more request per second that the other modes. The second choice is mode_proxy_ajp followed very closely by the mod_proxy. However the overhead added the the Apache will leverage for real life applications because the application processing time will minimize the impact of using Apache in front of Tomcat. Probably in real world the differences between direct HTTP connect and mod_proxy_ajp will not exceed 5-10% percents in terms of throughput and average time per request. This is the price to pay for the flexibility brought by Apache, because having the Apache in front of the Tomcat will give access to the whole Apache functionality and support.</p>
<p>For those who want to see test results in detail, I included in the post the tests logs.</p>
<h2>Test result trace for Tomcat HTTP</h2>
<p><code>bserban-mac:~ bserban$ ab -k -n 10000 -c 50 http://localhost:8080/test/test.jsp<br />
This is ApacheBench, Version 2.3 &lt;$Revision: 655654 $&gt;<br />
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br />
Licensed to The Apache Software Foundation, http://www.apache.org/</code></p>
<p>Benchmarking localhost (be patient)<br />
Completed 1000 requests<br />
Completed 2000 requests<br />
Completed 3000 requests<br />
Completed 4000 requests<br />
Completed 5000 requests<br />
Completed 6000 requests<br />
Completed 7000 requests<br />
Completed 8000 requests<br />
Completed 9000 requests<br />
Completed 10000 requests<br />
Finished 10000 requests</p>
<p>Server Software:        Apache-Coyote/1.1<br />
Server Hostname:        localhost<br />
Server Port:            8080</p>
<p>Document Path:          /test/test.jsp<br />
Document Length:        113678 bytes</p>
<p>Concurrency Level:      50<br />
Time taken for tests:   10.079 seconds<br />
Complete requests:      10000<br />
Failed requests:        0<br />
Write errors:           0<br />
Keep-Alive requests:    0<br />
Total transferred:      1139157786 bytes<br />
HTML transferred:       1137007356 bytes<br />
Requests per second:    992.18 [#/sec] (mean)<br />
Time per request:       50.394 [ms] (mean)<br />
Time per request:       1.008 [ms] (mean, across all concurrent requests)<br />
Transfer rate:          110376.03 [Kbytes/sec] received</p>
<p>Connection Times (ms)<br />
min  mean[+/-sd] median   max<br />
Connect:        0    7   7.3      5      67<br />
Processing:     5   43  22.4     37     182<br />
Waiting:        0   16  19.9     11     161<br />
Total:          7   50  22.4     45     207</p>
<p>Percentage of the requests served within a certain time (ms)<br />
50%     45<br />
66%     52<br />
75%     57<br />
80%     61<br />
90%     75<br />
95%     91<br />
98%    119<br />
99%    147<br />
100%    207 (longest request)</p>
<h2>Test result trace for mod_proxy_ajp</h2>
<p><code>bserban-mac:~ bserban$ ab -k -n 10000 -c 50 http://localhost/test/test.jsp<br />
This is ApacheBench, Version 2.3 &lt;$Revision: 655654 $&gt;<br />
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br />
Licensed to The Apache Software Foundation, http://www.apache.org/</code></p>
<p>Benchmarking localhost (be patient)<br />
Completed 1000 requests<br />
Completed 2000 requests<br />
Completed 3000 requests<br />
Completed 4000 requests<br />
Completed 5000 requests<br />
Completed 6000 requests<br />
Completed 7000 requests<br />
Completed 8000 requests<br />
Completed 9000 requests<br />
Completed 10000 requests<br />
Finished 10000 requests</p>
<p>Server Software:<br />
Server Hostname:        localhost<br />
Server Port:            80</p>
<p>Document Path:          /test/test.jsp<br />
Document Length:        113678 bytes</p>
<p>Concurrency Level:      50<br />
Time taken for tests:   14.251 seconds<br />
Complete requests:      10000<br />
Failed requests:        0<br />
Write errors:           0<br />
Keep-Alive requests:    0<br />
Total transferred:      1140884936 bytes<br />
HTML transferred:       1139000800 bytes<br />
Requests per second:    701.70 [#/sec] (mean)<br />
Time per request:       71.256 [ms] (mean)<br />
Time per request:       1.425 [ms] (mean, across all concurrent requests)<br />
Transfer rate:          78179.54 [Kbytes/sec] received</p>
<p>Connection Times (ms)<br />
min  mean[+/-sd] median   max<br />
Connect:        0    7   8.3      5      87<br />
Processing:     6   64  89.8     47     967<br />
Waiting:        0   38  86.9     21     920<br />
Total:          6   71  89.4     52     972</p>
<p>Percentage of the requests served within a certain time (ms)<br />
50%     52<br />
66%     58<br />
75%     64<br />
80%     69<br />
90%     83<br />
95%    115<br />
98%    507<br />
99%    689<br />
100%    972 (longest request)</p>
<h2>Test result trace for mod_proxy</h2>
<p><code>bserban-mac:~ bserban$ ab -k -n 10000 -c 50 http://localhost/test/test.jsp<br />
This is ApacheBench, Version 2.3 &lt;$Revision: 655654 $&gt;<br />
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/<br />
Licensed to The Apache Software Foundation, http://www.apache.org/</code></p>
<p>Benchmarking localhost (be patient)<br />
Completed 1000 requests<br />
Completed 2000 requests<br />
Completed 3000 requests<br />
Completed 4000 requests<br />
Completed 5000 requests<br />
Completed 6000 requests<br />
Completed 7000 requests<br />
Completed 8000 requests<br />
Completed 9000 requests<br />
Completed 10000 requests<br />
Finished 10000 requests</p>
<p>Server Software:        Apache-Coyote/1.1<br />
Server Hostname:        localhost<br />
Server Port:            80</p>
<p>Document Path:          /test/test.jsp<br />
Document Length:        113678 bytes</p>
<p>Concurrency Level:      50<br />
Time taken for tests:   14.985 seconds<br />
Complete requests:      10000<br />
Failed requests:        0<br />
Write errors:           0<br />
Keep-Alive requests:    0<br />
Total transferred:      1140715856 bytes<br />
HTML transferred:       1138561771 bytes<br />
Requests per second:    667.34 [#/sec] (mean)<br />
Time per request:       74.925 [ms] (mean)<br />
Time per request:       1.498 [ms] (mean, across all concurrent requests)<br />
Transfer rate:          74339.90 [Kbytes/sec] received</p>
<p>Connection Times (ms)<br />
min  mean[+/-sd] median   max<br />
Connect:        0    9  10.1      5     123<br />
Processing:     9   66  83.2     52     975<br />
Waiting:        0   41  83.7     27     949<br />
Total:          9   74  82.6     59     980</p>
<p>Percentage of the requests served within a certain time (ms)<br />
50%     59<br />
66%     66<br />
75%     72<br />
80%     76<br />
90%     98<br />
95%    123<br />
98%    192<br />
99%    675<br />
100%    980 (longest request)
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F08%2Fconfigure-apache-and-tomcat-severs-together%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F08%2Fconfigure-apache-and-tomcat-severs-together%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=AJP,Apache,Apache+Benchmark,mod_proxy,mod_proxy_ajp,Tomcat" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bserban.org/2009/08/configure-apache-and-tomcat-severs-together/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tomcat Clustering &amp; Java Servlet Specification</title>
		<link>http://www.bserban.org/2009/08/tomcat-clustering-java-servlet-specification/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=tomcat-clustering-java-servlet-specification</link>
		<comments>http://www.bserban.org/2009/08/tomcat-clustering-java-servlet-specification/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 11:34:51 +0000</pubDate>
		<dc:creator>bserban</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Tomcat]]></category>
		<category><![CDATA[clustering]]></category>
		<category><![CDATA[Distributable]]></category>
		<category><![CDATA[Servlet Specification]]></category>
		<category><![CDATA[Sticky Sessions]]></category>
		<category><![CDATA[Tomcat clustering]]></category>

		<guid isPermaLink="false">http://www.bserban.org/2009/08/tomcat-clustering-java-servlet-specification/</guid>
		<description><![CDATA[After I read more about Tomcat Clustering I realized that the main purpose of Tomcat clustering is to offer fault tolerance, failover  and high availability support. I read a lot about load balancing but when it comes to Java Servlets I found out that the only choice you have in terms of balancing is to [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F08%2Ftomcat-clustering-java-servlet-specification%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F08%2Ftomcat-clustering-java-servlet-specification%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=Distributable,Servlet+Specification,Sticky+Sessions,Tomcat+clustering" height="61" width="50" /><br />
			</a>
		</div>
<p>After I read more about Tomcat Clustering I realized that the main purpose of Tomcat clustering is to offer fault tolerance, failover  and high availability support. I read a lot about load balancing but when it comes to Java Servlets I found out that the only choice you have in terms of balancing is to use sticky sessions. This is more a limitation that comes from Java Servlet Specification and not from Tomcat, but it make sense.</p>
<p>For an application to be &#8220;distributed&#8221; you have to mark  it as &#8220;distributable&#8221; by add the &lt;distributable/&gt; tag in web.xml.</p>
<p>&lt;web-app&gt;<br />
&lt;distributable /&gt;<br />
&lt;/web-app&gt;</p>
<p>There are multiple ways to balance the client request to your server pool but when it comes to Java Servlet Specification you have only one choice, as the specs say:</p>
<p>&#8220;<em>Within an application that is marked as distributable, all requests that are part of a session can only be handled on a single JVM at any one time.</em>&#8221;</p>
<p>&#8220;<em>You may have multiple JVMs, each handling requests from different clients concurrently for any given distributable web application</em>&#8221;</p>
<p>So, I guess you can kiss goodbye the round robin and all other load balancing options, but at least Tomcat will provide you  failover, scalability  and high availability.
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F08%2Ftomcat-clustering-java-servlet-specification%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F08%2Ftomcat-clustering-java-servlet-specification%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=Distributable,Servlet+Specification,Sticky+Sessions,Tomcat+clustering" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bserban.org/2009/08/tomcat-clustering-java-servlet-specification/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Tomcat clustering configuration</title>
		<link>http://www.bserban.org/2009/06/tomcat-clustering-configuration/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=tomcat-clustering-configuration</link>
		<comments>http://www.bserban.org/2009/06/tomcat-clustering-configuration/#comments</comments>
		<pubDate>Tue, 09 Jun 2009 08:33:36 +0000</pubDate>
		<dc:creator>bserban</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Tomcat]]></category>
		<category><![CDATA[clustering]]></category>
		<category><![CDATA[deltamanager]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[Tomcat clustering]]></category>
		<category><![CDATA[tomcat session replication]]></category>

		<guid isPermaLink="false">http://www.bserban.org/?p=180</guid>
		<description><![CDATA[The following steps assume that you have installed a Tomcat 5.5.x bundle or latest, i only tested on 5.5.27 but is should work for other configuration as well. The network configuration apply to Linux and may vary with the distribution. It should work as is for distributions based on Red Hat. For Tomcat clustering we [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F06%2Ftomcat-clustering-configuration%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F06%2Ftomcat-clustering-configuration%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=clustering,deltamanager,replication,Tomcat+clustering,tomcat+session+replication" height="61" width="50" /><br />
			</a>
		</div>
<p align="justify">The following steps assume that you have installed a Tomcat 5.5.x bundle or latest, i only tested on 5.5.27 but is should work for other configuration as well. The network configuration apply to Linux and may vary with the distribution. It should work as is for distributions based on Red Hat.</p>
<p>For Tomcat clustering we have two main things to configure:</p>
<ul>
<li>Configure the network environment for clustering (open ports, add multicast route),</li>
<li>Configure Tomcat clustering support.</li>
</ul>
<h2>Configure the network support for cluster</h2>
<h3>Opening Specific HTTP Ports (e.g. Port 45564, 4001)</h3>
<p align="justify">The cluster class will start up a membership service (multicast) and a replication service (tcp unicast). See also http://www.cyberciti.biz/faq/howto-rhel-linux-open-port-using-iptables/ for a brief article on this. You will need to have root access as noted above to complete this.</p>
<p>Your server may or may not already have this entry. Open iptables:</p>
<pre class="xml:nogutter:nocontrols">&gt; vi /etc/sysconfig/iptables</pre>
<p>Add the following entries:</p>
<pre class="xml:nogutter:nocontrols">-A RH-Firewall-1-INPUT -p udp -m udp --dport 45564 -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp -m tcp --dport 45564 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 4001 -j ACCEPT</pre>
<p>Save and close the above file and after restart the iptables</p>
<pre class="xml:nogutter:nocontrols">  &gt; /etc/init.d/iptables restart</pre>
<h3>Configure the multicast address and routes.</h3>
<p align="justify">Clustering membership is established using very simple multicast pings. Each Tomcat instance will periodically send out a multicast ping, in the ping message the instance will broad cast its IP and TCP listen port for replication. If an instance has not received such a ping within a given timeframe, the member is considered dead.</p>
<p>Add route  (the server&#8217;s ip address)</p>
<pre class="xml:nogutter:nocontrols">sudo /sbin/route add 228.0.0.4 gw 10.72.10.1 dev bond0</pre>
<p>Edit rc.local to make the change persistent through restarts.</p>
<pre class="xml:nogutter:nocontrols">sudo vim /etc/rc.d/rc.local</pre>
<p>Add this line at the end (the server&#8217;s ip address)</p>
<pre class="xml:nogutter:nocontrols">/sbin/route add 228.0.0.4 gw 10.72.10.1 dev bond0</pre>
<h2>Configure Tomcat to support clustering.</h2>
<p>Application clustering with Tomcat has two steps:</p>
<ul>
<li>Enable clustering support,</li>
<li>Make you application clusterizable.</li>
</ul>
<h3>Enable Tomcat clustering support</h3>
<p>You need to enable the cluster support in Tomcat by editing the server.xml file. Open server.xml</p>
<pre class="xml:nogutter:nocontrols">sudo vim /usr/local/tomcat-5.5.27/conf/server.xml</pre>
<p>Enable clustering configuration in the configuration file, notice that the default configuration is using the DeltaManager which will replicate only the session&#8217;s changes and not the entire object:</p>
<pre class="xml:nogutter:nocontrols">&lt;Cluster className="org.apache.catalina.cluster.tcp.SimpleTcpCluster"
managerClassName="org.apache.catalina.cluster.session.DeltaManager"
	expireSessionsOnShutdown="false"
	useDirtyFlag="true"
	notifyListenersOnReplication="true"&gt;
&lt;Membership className="org.apache.catalina.cluster.mcast.McastService"
	mcastAddr="228.0.0.4"
	mcastPort="45564"
	mcastFrequency="500"
	mcastDropTime="3000"/&gt;
&lt;Receiver className="org.apache.catalina.cluster.tcp.ReplicationListener"
	tcpListenAddress="10.72.10.1"
	tcpListenPort="4001"
	tcpSelectorTimeout="100"
	tcpThreadCount="6"/&gt;
&lt;Sender className="org.apache.catalina.cluster.tcp.ReplicationTransmitter"
	replicationMode="pooled"
	ackTimeout="15000"
	waitForAck="true"/&gt;
&lt;Valve className="org.apache.catalina.cluster.tcp.ReplicationValve"
  filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/&gt;
&lt;Deployer className="org.apache.catalina.cluster.deploy.FarmWarDeployer"
	tempDir="/tmp/war-temp/"
	deployDir="/tmp/war-deploy/"
	watchDir="/tmp/war-listen/"
	watchEnabled="false"/&gt;
&lt;ClusterListener className="org.apache.catalina.cluster.session.ClusterSessionListener"/&gt;
  &lt;/Cluster&gt;</pre>
<p>One main condition for replication to work is that your session content is serializable. Add a _jvmRoute_ to your Tomcat Engine section From</p>
<pre class="xml:nogutter:nocontrols">  &lt;Engine name="Catalina" defaultHost="localhost"&gt;</pre>
<p>To</p>
<pre class="xml:nogutter:nocontrols">  &lt;Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1"&gt;</pre>
<p><em>jvmRoute</em> identifies unique a Tomcat instance in a cluster. If multiple servers are used I recommend you to use descriptive names.</p>
<h3>Make your application clusterizable</h3>
<p>Configuring Tomcat clustering is not enough to cluster your application. For that you need to tell Tomcat which application you want to be clusterizable. This is achieved in two ways:</p>
<ul>
<li>by modifying the ROOT.xml (the context configuration file&#8221;</li>
<li>by modifying the web.xml</li>
</ul>
<h4>Enable application clustering by ROOT.xml</h4>
<p>Edit ROOT.xml file</p>
<pre class="xml:nogutter:nocontrols"> sudo vim /usr/local/tomcat-5.5.27/conf/Catalina/localhost/ROOT.xml</pre>
<p>Look for</p>
<pre class="xml:nogutter:nocontrols"> &lt;Context path="" cookies="true" distributable="true" crossContext="true"&gt;</pre>
<p>Change it to</p>
<pre class="xml:nogutter:nocontrols"> &lt;Context path="" debug="0" reloadable="true"
cookies="true" crossContext="false" privileged="false" &gt;</pre>
<h4>Enable application clustering by editing the web.xml</h4>
<p>Edit the web.xml file</p>
<pre class="xml:nogutter:nocontrols"> sudo vim /usr/local/tomcat-5.5.27/webapps/ROOT/WEB-INF/web.xml</pre>
<p>Look for:</p>
<pre class="xml:nogutter:nocontrols"> &lt;web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"&gt;
	&lt;context-param&gt;
	&lt;param-name&gt;contextClass&lt;/param-name&gt;
	.............</pre>
<p>Change it to:</p>
<pre class="xml:nogutter:nocontrols"> &lt;web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"&gt;
	&lt;distributable/&gt;
	&lt;context-param&gt;
	&lt;param-name&gt;contextClass&lt;/param-name&gt;
	.............</pre>
<p>Restart Tomcat</p>
<pre class="xml:nogutter:nocontrols"> cd /usr/local/tomcat-5.5.27/bin/
sudo ./shutdown.sh
sudo ./startup.sh
or if you have a init script
sudo /etc/init.d/tomcat5 restart</pre>
<p>You need to configure all the nodes in the cluster as detailed above. Every node should have unique name provided by &#8220;jvmRoute&#8221; attribute.</p>
<h2>Further reading</h2>
<p>Cluster-howto | http://tomcat.apache.org/tomcat-5.5-doc/cluster-howto.html
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F06%2Ftomcat-clustering-configuration%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F06%2Ftomcat-clustering-configuration%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=clustering,deltamanager,replication,Tomcat+clustering,tomcat+session+replication" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bserban.org/2009/06/tomcat-clustering-configuration/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Put together Struts2, JPA, Hibernate and Spring</title>
		<link>http://www.bserban.org/2009/05/put-together-struts2-jpa-hibernate-and-spring/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=put-together-struts2-jpa-hibernate-and-spring</link>
		<comments>http://www.bserban.org/2009/05/put-together-struts2-jpa-hibernate-and-spring/#comments</comments>
		<pubDate>Sun, 31 May 2009 11:02:44 +0000</pubDate>
		<dc:creator>bserban</dc:creator>
				<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Struts2]]></category>
		<category><![CDATA[Freemarker]]></category>

		<guid isPermaLink="false">http://www.bserban.org/?p=158</guid>
		<description><![CDATA[This weekend I played a bit with Struts2. Obviously my first thought was to put together &#8220;fellowship of the ring&#8221; ie Struts, Spring and Hibernate. Now, we have two ways for integrating Hibernate and I’ve chosen the Java Persistence Architecture approach, because is the latest trend in terms of persistence in the J2EE landscape. Create [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F05%2Fput-together-struts2-jpa-hibernate-and-spring%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F05%2Fput-together-struts2-jpa-hibernate-and-spring%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=Freemarker,Hibernate,JPA,MVC,Spring,Struts2" height="61" width="50" /><br />
			</a>
		</div>
<p align="justify">This weekend I played a bit with Struts2. Obviously my first thought was to put together <em>&#8220;fellowship of the ring&#8221;</em> ie Struts, Spring and Hibernate. Now, we have two ways for integrating Hibernate and I’ve chosen the Java Persistence Architecture approach, because is the latest trend in terms of persistence in the J2EE landscape.</p>
<h1>Create your domain model</h1>
<p align="justify">For the sake of simplicity I&#8217;ll take  a simple example that contains <em>Books</em> and <em>Authors</em>. A book has one or more authors while one author wrote one or more books. This looks like a many to many relationship and we want to be able to get, from one shoot, the book and its authors and for an author his entire list of books.</p>
<p>Book.java</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">package org.bserban.shs.model;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">import javax.persistence.*;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">import java.util.List;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">@Entity</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">@Table(name = "book")</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">public class Book {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    @Id</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    @GeneratedValue</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    private Integer id;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    private String title;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    private String publisher;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    private String keywords;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    private String ISBN13;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    private String ISBN10;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    @ManyToMany(fetch = FetchType.EAGER)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    private List<span style="color: #0000ff">&lt;</span><span style="color: #800000">Author</span><span style="color: #0000ff">&gt;</span> authors;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">........................................</pre>
</div>
</div>
<p>Author. java</p>
<div>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">package org.bserban.shs.model;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">import javax.persistence.*;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">import java.util.List;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">@Entity</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">@Table(name = "author")</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">public class Author {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    @Id</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    @GeneratedValue</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    private Integer id;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    private String firstName;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    private String lastName;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    private String blog;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    @ManyToMany(mappedBy="authors",fetch = FetchType.EAGER)</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    private List<span style="color: #0000ff">&lt;</span><span style="color: #800000">Book</span><span style="color: #0000ff">&gt;</span> books;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">.......................................</pre>
</div>
</div>
</div>
<p align="justify">As you see in the code snippets above, the many to many relationship was marked with <em>@ManyToMany</em> annotation. We specified that the many to many relationship is mapped by <em>Author </em>entity too. No need to create a <em>persistence.xml</em> or <em>hibernate.cfg.xml</em> files at this moment because the whole configuration will take place in the Spring files.</p>
<h1>Create a DAOs</h1>
<p align="justify">First of all create a generic DAO object to keep the reference to the EntityManager and avoid duplicate code in other DAOs.</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">package org.bserban.shs.dao;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">import javax.persistence.EntityManager;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">import javax.persistence.PersistenceContext;</pre>
<p>public abstract class GenericJPADAO&lt;T, ID extends Serializable&gt; {</p>
<p>private Class&lt;T&gt; persistentClass;</p>
<p>protected EntityManager em;</p>
<p>@PersistenceContext<br />
public void setEntityManager(EntityManager em) {<br />
this.em = em;<br />
}</p>
<p>public EntityManager getEntityManager() {<br />
return em;<br />
}</p>
<p>public void save(T entity) {<br />
getEntityManager().persist(entity);<br />
}</p>
<p>public void delete(T entity) {<br />
getEntityManager().remove(entity);<br />
}<br />
public T getById(Object id) {<br />
return getEntityManager().find(persistentClass, id);<br />
}</p></div>
</div>
<p>By making a generic DAO class using java generics we are avoiding casting and using the Object class as parameter, in this way our methods will always have the proper type for their operation. While this is very easy with simple application it can become more complicated, but don’t forget that now we are building bricks that will help us to build our house, for more complicated logic we just simply create a <em>facade</em> class that will use our bricks.<br />
<em>BookDAO.java</em> and <em>AuthorDAO.java</em></p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">package org.bserban.shs.dao;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">import org.bserban.shs.model.Author;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">public class AuthorDAO extends GenericJPADAO<span style="color: #0000ff">&lt;</span><span style="color: #800000">Author</span>,<span style="color: #ff0000">Integer</span><span style="color: #0000ff">&gt;</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">}</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">package org.bserban.shs.dao;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">import org.bserban.shs.model.Book;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">public class BookDAO extends GenericJPADAO<span style="color: #0000ff">&lt;</span><span style="color: #800000">Book</span>,<span style="color: #ff0000">Integer</span><span style="color: #0000ff">&gt;</span>{</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">}</pre>
</div>
</div>
<p>These classes are empty so far but specific methods will probably be added.</p>
<h1>Create your service layer</h1>
<p align="justify">I am going to build also a generic service similar with the generic DAO class. For this example I only need basic operations that can be easily made generic. All I need is to create a generic interface called <em>GenericService</em> and ask for a type. Note that while <em>GenericService</em> is an interface for the DAOs I&#8217;ve done an abstract class because I wanted to add code to methods.</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">package org.bserban.shs.service;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">import java.util.List;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">public interface GenericService<span style="color: #0000ff">&lt;</span><span style="color: #800000">T</span><span style="color: #0000ff">&gt;</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    T create(T entity);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    void delete(T entity);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    T update(T entity);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    List<span style="color: #0000ff">&lt;</span><span style="color: #800000">T</span><span style="color: #0000ff">&gt;</span> list(int page, int size);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">}</pre>
</div>
</div>
<p align="justify">Now, in the <em>Service</em>s<em> </em> classes we need to have also a reference to the specific DAO object for that type of service. I am going to create a <em>dao</em> field in each class and I am going to assume that somebody will set the <em>dao </em>to the correct value when the service will be used.</p>
<p>BookService.java and AuthorService.java, their structure is identically so i will list only one here:</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">package org.bserban.shs.service;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">import org.bserban.shs.dao.AuthorDAO;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">import org.bserban.shs.model.Author;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">import java.util.List;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">public class AuthorService implements GenericService<span style="color: #0000ff">&lt;</span><span style="color: #800000">Author</span><span style="color: #0000ff">&gt;</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    private AuthorDAO dao;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    public Author create(Author entity) {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        dao.save(entity);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        return entity;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    public void delete(Author entity) {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        dao.delete(entity);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    public Author update(Author entity) {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        dao.save(entity);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        return entity;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    public List<span style="color: #0000ff">&lt;</span><span style="color: #800000">Author</span><span style="color: #0000ff">&gt;</span> list(int page, int size) {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        return dao.list(page,size);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    public AuthorDAO getDao() {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        return dao;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    public void setDao(AuthorDAO dao) {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        this.dao = dao;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">}</pre>
</div>
</div>
<p align="justify">For the listing feature I simply added a new method in the DAOs for list, and it looks like this:</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">................</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">public List<span style="color: #0000ff">&lt;</span><span style="color: #800000">Author</span><span style="color: #0000ff">&gt;</span> list(int page, int size) {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    Query query = this.em.createQuery("from Author order by lastName,firstName");</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    query.setFirstResult((page - 1) * size);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    query.setMaxResults(size);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    return query.getResultList();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">}</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">.................</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">public List<span style="color: #0000ff">&lt;</span><span style="color: #800000">Book</span><span style="color: #0000ff">&gt;</span> list(int page, int size) {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    Query query = this.em.createQuery("from Book order by title");</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    query.setFirstResult((page - 1) * size);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    query.setMaxResults(size);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    return query.getResultList();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">}</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">..................</pre>
</div>
</div>
<h1>Create the Actions</h1>
<p align="justify">The actions are part of the controller and they need to validate data and to provide error handling before calling the service layer. One characteristic of putting together the Spring and Struts2 is that the dependency injection is done via a constructor argument. You could do it also with setters and getters but this would expose your service class to the exterior. One could call your action via HTTP by providing a parameter with the same name of your service class which will result into an unpredictable behavior, most probably an error.</p>
<p align="justify">In the actions I am going to have three fields, the first is the <em>Service</em> reference, the second is the list of model object and the third is a solo entity used for create, update, delete.</p>
<p align="justify">I will only list one <em>Action</em> class because they are pretty similar:</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">public class AuthorAction extends FrontendAction {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    private GenericService<span style="color: #0000ff">&lt;</span><span style="color: #800000">Author</span><span style="color: #0000ff">&gt;</span> service;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    private List<span style="color: #0000ff">&lt;</span><span style="color: #800000">Author</span><span style="color: #0000ff">&gt;</span> authors;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    private Author author;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    public AuthorAction(GenericService&lt;Author&gt; service) {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        this.service = service;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    public String list() {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        authors=service.list(page, size);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        return SUCCESS;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    public String update() {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        service.update(author);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        return SUCCESS;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    public String create() {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        service.create(author);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        return SUCCESS;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    public String delete() {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        service.delete(author);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        return SUCCESS;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">......................................</pre>
</div>
</div>
<p align="justify">
<p align="justify">I have created a <em>FrontendAction</em> to put the page and size parameters, since they are a common feature of both actions.  Similar, you can put here other attributes that are common for the all actions.</p>
<p align="justify">Now lets add our actions into <em>struts.xml</em> file and start to configure the Spring support. I have chosen the extension of our actions to be *.html. I also want to set the Struts2 into dev mode to debug the application if necessary. For IOC Struts2 has a property called <em>objectFactory</em> which let’s you to specify what is your IOC container, i set this to &#8220;spring&#8221; values. The views will be written as Freemarker templates which I consider to be a powerful template engine.</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">constant</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="struts.devMode"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="true"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">constant</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="struts.action.extension"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="html"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">constant</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="struts.objectFactory"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="spring"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">constant</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="struts.ui.theme"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="simple"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">constant</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="struts.ui.templateSuffix"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="ftl"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">constant</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="struts.configuration.xml.reload"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="true"</span><span style="color: #0000ff">/&gt;</span></pre>
</div>
</div>
<p>Now we need to declare our actions, I’ve decided to create different name space for each action which means that the http calls will look like this: <em>/books/</em>&#8230;..  <em> /authors/&#8230;..</em></p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">package</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="books"</span> <span style="color: #ff0000">namespace</span><span style="color: #0000ff">="/books"</span> <span style="color: #ff0000">extends</span><span style="color: #0000ff">="struts-default"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    <span style="color: #0000ff">&lt;</span><span style="color: #800000">action</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="list"</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="bookAction"</span> <span style="color: #ff0000">method</span><span style="color: #0000ff">="list"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        <span style="color: #0000ff">&lt;</span><span style="color: #800000">result</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="success"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="freemarker"</span><span style="color: #0000ff">&gt;</span>/WEB-INF/pages/books/list.ftl<span style="color: #0000ff">&lt;/</span><span style="color: #800000">result</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">action</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">package</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">package</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="authors"</span> <span style="color: #ff0000">namespace</span><span style="color: #0000ff">="/authors"</span> <span style="color: #ff0000">extends</span><span style="color: #0000ff">="struts-default"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    <span style="color: #0000ff">&lt;</span><span style="color: #800000">action</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="list"</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="authorAction"</span> <span style="color: #ff0000">method</span><span style="color: #0000ff">="list"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        <span style="color: #0000ff">&lt;</span><span style="color: #800000">result</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="success"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="freemarker"</span><span style="color: #0000ff">&gt;</span>/WEB-INF/pages/authors/list.ftl<span style="color: #0000ff">&lt;/</span><span style="color: #800000">result</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">action</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">package</span><span style="color: #0000ff">&gt;</span></pre>
</div>
</div>
<p>For the purpose of demonstration I am providing only the listing capability, I let you code the rest. So I need to create two templates to list the entities, they are done in the same way so i am pasting only the author&#8217;s list page:</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">[#ftl]</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">&lt;link media="screen" type="text/css" href="${base}/resources/css/style.css" rel="stylesheet"&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">&lt;div&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">&lt;<span style="color: #0000ff">table</span> <span style="color: #0000ff">class</span>="listing"&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    &lt;tr&gt;&lt;td <span style="color: #0000ff">class</span>="hed" colspan="3"&gt;List <span style="color: #0000ff">of</span> authors&lt;/td&gt;&lt;/tr&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    &lt;tr&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        &lt;th&gt;<span style="color: #0000ff">First</span> Name&lt;/th&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        &lt;th&gt;<span style="color: #0000ff">Last</span> Name&lt;/th&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        &lt;th&gt;Books&lt;/th&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    &lt;/tr&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    [#list authors <span style="color: #0000ff">as</span> author]</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    &lt;tr [#<span style="color: #0000ff">if</span> author_index%2 = 0]<span style="color: #0000ff">class</span>="bg"[/#<span style="color: #0000ff">if</span>]&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        &lt;td&gt;${author.firstName!<span style="color: #006080">''</span>}&lt;/td&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">        &lt;td&gt;${author.lastName!<span style="color: #006080">''</span>}&lt;/td&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        &lt;td&gt;[#<span style="color: #0000ff">if</span> author.books??][#list author.books <span style="color: #0000ff">as</span> book] ${book.title}[#<span style="color: #0000ff">if</span> book_has_next],[/#<span style="color: #0000ff">if</span>][/#list][/#<span style="color: #0000ff">if</span>]&lt;/td&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    &lt;/tr&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    [/#list]</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">&lt;/<span style="color: #0000ff">table</span>&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">&lt;/div&gt;</pre>
</div>
</div>
<h1>Glue the code with Spring</h1>
<p align="justify">This example uses Spring 2.5.5 version. I am going to separate the configuration files in two, one is for generic configuration for JPA and transactions and the second will contain our classes glued together.</p>
<p align="justify">My applicationContext.xml</p>
<p align="justify">Declare the JPA support</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"</span> <span style="color: #0000ff">/&gt;</span></pre>
</div>
</div>
<p>Now declare the EntityManager bean</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="entityManagerFactory"</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="dataSource"</span> <span style="color: #ff0000">ref</span><span style="color: #0000ff">="dataSource"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="jpaVendorAdapter"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        <span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">            <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">            <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="database"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="MYSQL"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">            <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="showSql"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="true"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        <span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">property</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></pre>
</div>
</div>
<p>The data source used by EntityManager bean</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="dataSource"</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.springframework.jdbc.datasource.DriverManagerDataSource"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="driverClassName"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="com.mysql.jdbc.Driver"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="url"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="jdbc:mysql://localhost/example"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="username"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="example"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="password"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="example"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></pre>
</div>
</div>
<p align="justify">Now I need to configure the transaction manager for my classes and obviously I am going to use the one that supports annotations. The era for declarative transaction configuration has long gone.</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="transactionManager"</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.springframework.orm.jpa.JpaTransactionManager"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">        <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="entityManagerFactory"</span> <span style="color: #ff0000">ref</span><span style="color: #0000ff">="entityManagerFactory"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    <span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">tx:annotation-driven</span> <span style="color: #ff0000">transaction-manager</span><span style="color: #0000ff">="transactionManager"</span> <span style="color: #0000ff">/&gt;</span></pre>
</div>
</div>
<p>Let’s not forgot our objects, let’s tell Spring where is our application specific configuration file</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">&lt;</span><span style="color: #800000">import</span> <span style="color: #ff0000">resource</span><span style="color: #0000ff">="exampleContext.xml"</span><span style="color: #0000ff">/&gt;</span></pre>
</div>
</div>
<div>Now, all I need is to glue my classes together, basically our <em>DAOs</em> need the <em>JPA</em> beans, the <em>Services</em> need our <em>DAOs</em> and Struts <em>Actions</em> need our <em>Services. </em></div>
<div><em></em></div>
<div><em>exampleContext.xml</em> will contain the followings:</div>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #008000">&lt;!-- daos --&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"> <span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="authorDao"</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.bserban.shs.dao.AuthorDAO"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"> <span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="bookDAO"</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.bserban.shs.dao.BookDAO"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"> <span style="color: #008000">&lt;!-- services --&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"> <span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="authorService"</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.bserban.shs.service.AuthorService"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">     <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="dao"</span> <span style="color: #ff0000">ref</span><span style="color: #0000ff">="authorDao"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"> <span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="bookService"</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.bserban.shs.service.BookService"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">     <span style="color: #0000ff">&lt;</span><span style="color: #800000">property</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="dao"</span> <span style="color: #ff0000">ref</span><span style="color: #0000ff">="bookDAO"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"> <span style="color: #008000">&lt;!-- action --&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"> <span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="authorAction"</span> <span style="color: #ff0000">scope</span><span style="color: #0000ff">="prototype"</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.bserban.shs.action.AuthorAction"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">     <span style="color: #0000ff">&lt;</span><span style="color: #800000">constructor-arg</span> <span style="color: #ff0000">ref</span><span style="color: #0000ff">="authorService"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"> <span style="color: #0000ff">&lt;</span><span style="color: #800000">bean</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="bookAction"</span> <span style="color: #ff0000">scope</span><span style="color: #0000ff">="prototype"</span> <span style="color: #ff0000">class</span><span style="color: #0000ff">="org.bserban.shs.action.BookAction"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">     <span style="color: #0000ff">&lt;</span><span style="color: #800000">constructor-arg</span> <span style="color: #ff0000">ref</span><span style="color: #0000ff">="bookService"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></pre>
</div>
</div>
<p align="justify">Now add the transaction support to our service classes. I simply need to put the <em>@Transactional</em> annotation at class level which means that all method from that class support transactions.</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">import org.springframework.transaction.annotation.Transactional;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">@Transactional</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">public class BookService implements GenericService<span style="color: #0000ff">&lt;</span><span style="color: #800000">Book</span><span style="color: #0000ff">&gt;</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">.........................</pre>
</div>
</div>
<p>I am going to configure also the <strong>web.xml</strong> file, where I’ll put the configuration for Struts and for Spring.</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">&lt;context-param&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    &lt;param-<span style="color: #0000ff">value</span>&gt;/WEB-INF/applicationContext.xml&lt;/param-<span style="color: #0000ff">value</span>&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">&lt;/context-param&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">&lt;filter&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    &lt;filter-name&gt;struts2&lt;/filter-name&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    &lt;filter-<span style="color: #0000ff">class</span>&gt;org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    &lt;/filter-<span style="color: #0000ff">class</span>&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">&lt;/filter&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">&lt;filter-mapping&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    &lt;filter-name&gt;struts2&lt;/filter-name&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    &lt;url-pattern&gt;/*&lt;/url-pattern&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">&lt;/filter-mapping&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">&lt;listener&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    &lt;listener-<span style="color: #0000ff">class</span>&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-<span style="color: #0000ff">class</span>&gt;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">&lt;/listener&gt;</pre>
</div>
</div>
<p>Now all we need is to hit run and see if it is working. Also we are going to need some testing data.</p>
<h1>Database tables</h1>
<p>Putting this line <em>&lt;property name=&#8221;generateDdl&#8221; value=&#8221;true&#8221; /&gt;</em> into EntintyManagerFactory bean configuration will cause the generation of our database tables.</p>
<p><a href="http://www.bserban.org/wp-content/uploads/2009/05/tables.gif"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="tables" src="http://www.bserban.org/wp-content/uploads/2009/05/tables-thumb.gif" border="0" alt="tables" width="200" height="116" /></a></p>
<p>I just need to insert manually some sample data to be able to list them in the “list” pages.</p>
<p>Sample data:</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">INSERT <span style="color: #0000ff">INTO</span> `author` (`id`,`firstName`,`lastName`,`blog`) <span style="color: #0000ff">VALUES</span>  (1,<span style="color: #006080">'John'</span>,<span style="color: #006080">'Doe'</span>,<span style="color: #006080">'no blog'</span>), (2,<span style="color: #006080">'Sam'</span>,<span style="color: #006080">'Dune'</span>,<span style="color: #006080">'no blog'</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">INSERT <span style="color: #0000ff">INTO</span> `book` (`id`,`title`,`publisher`,`keywords`,`ISBN13`,`ISBN10`) <span style="color: #0000ff">VALUES</span>  (1,<span style="color: #006080">'Some Random Title'</span>,<span style="color: #006080">'The plublisher'</span>,<span style="color: #006080">'random'</span>,<span style="color: #006080">'0596517726'</span>,<span style="color: #006080">'978-0596517724'</span>);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">INSERT <span style="color: #0000ff">INTO</span> `book_author` (`books_id`,`authors_id`) <span style="color: #0000ff">VALUES</span>  (1,1);</pre>
</div>
</div>
<h1>Html Views</h1>
<p>Let’s add a simple css file to give a decent look to our pages, all we need is to customize the table look&amp;feel.</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #0000ff">table</span>.listing {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    text-align: center;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    font-weight: normal;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    font-<span style="color: #0000ff">size</span>: 11px;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    color: #fff;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    width: 280px;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    background-color: #666;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    border: 0px;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    border-collapse: collapse;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    border-spacing: 0px;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">}</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #0000ff">table</span>.listing td {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    background-color: #CCC;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    color: #000;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    padding: 4px;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    text-align: <span style="color: #0000ff">left</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    border: 1px #fff solid;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">}</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #0000ff">table</span>.listing td.hed {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    background-color: #666;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    color: #fff;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    padding: 4px;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    text-align: <span style="color: #0000ff">left</span>;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    border-bottom: 2px #fff solid;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">    font-<span style="color: #0000ff">size</span>: 12px;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">    font-weight: bold;</pre>
</div>
</div>
<p>End the result:</p>
<p><a title="http://localhost:8080/books/list.html" href="http://localhost:8080/books/list.html">http://localhost:8080/books/list.html</a></p>
<p><a href="http://www.bserban.org/wp-content/uploads/2009/05/listbooks1.gif"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="listBooks" src="http://www.bserban.org/wp-content/uploads/2009/05/listbooks-thumb1.gif" border="0" alt="listBooks" width="363" height="96" /></a></p>
<p><a title="http://localhost:8080/authors/list.html" href="http://localhost:8080/authors/list.html">http://localhost:8080/authors/list.html</a></p>
<p><a href="http://www.bserban.org/wp-content/uploads/2009/05/listauthors1.gif"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="listAuthors" src="http://www.bserban.org/wp-content/uploads/2009/05/listauthors-thumb1.gif" border="0" alt="listAuthors" width="285" height="90" /></a></p>
<p>I hope I’ll have the time to continue this apps and introduce jQuery for simple actions like add/edit/delete/filter books and authors.</p>
<p>Cheers,</p>
<h1>Resources</h1>
<p>I’ll list here all the needed jars/frameworks for this sample application:</p>
<ul>
<li>Hibernate 3.2.1 (+ deps)</li>
<li>archive-browsing-1.0.jar, this was needed by hibernate to work with JPA</li>
<li>hibernate-entity-manager-3.2.1.jar</li>
<li>mysql-connector-java-5.0.4.jar</li>
<li>jta-1.0.B.jar</li>
<li>persistence-api-1.0.jar</li>
<li>Spring 2.5.5 jar file</li>
<li>Struts 2.1.6 (+ deps)</li>
<li>struts2-spring-plugin.jar</li>
</ul>
<p>Source code sample, you can downloaded from here <a href="http://www.bserban.org/wp-content/uploads/2009/05/struts2springjpahibernate.zip">Struts2, Spring, JPA, Hibernate</a>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F05%2Fput-together-struts2-jpa-hibernate-and-spring%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F05%2Fput-together-struts2-jpa-hibernate-and-spring%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=Freemarker,Hibernate,JPA,MVC,Spring,Struts2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bserban.org/2009/05/put-together-struts2-jpa-hibernate-and-spring/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Key-Value Storage using MemcacheDB</title>
		<link>http://www.bserban.org/2009/03/key-value-storage-using-memcachedb/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=key-value-storage-using-memcachedb</link>
		<comments>http://www.bserban.org/2009/03/key-value-storage-using-memcachedb/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 21:08:37 +0000</pubDate>
		<dc:creator>bserban</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Memcachedb]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[distributed storage]]></category>
		<category><![CDATA[Entity Attribute value]]></category>
		<category><![CDATA[high performance]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://www.bserban.org/?p=146</guid>
		<description><![CDATA[What is Entity-Attribute-Value model (aka key-value storage) This is also know as Entity-Attribute-Value model, and it is used in circumstances where the number of attributes (properties) that can be used to describe an entity  is very vast but the number of attributes that will actually be used is modest. Let’s think in terms of a [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F03%2Fkey-value-storage-using-memcachedb%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F03%2Fkey-value-storage-using-memcachedb%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=Architecture,distributed+storage,Entity+Attribute+value,high+performance,Memcachedb,Scalability" height="61" width="50" /><br />
			</a>
		</div>
<h2>What is Entity-Attribute-Value model (aka key-value storage)</h2>
<p>This is also know as Entity-Attribute-Value model, and it is used in circumstances where the number of attributes (properties) that can be used to describe an entity  is very vast but the number of attributes that will actually be used is modest.</p>
<p>Let’s think in terms of a database how an Entity-Attribute-Value model would look like for storing an user profile.</p>
<table border="0" cellspacing="0" cellpadding="2" width="400">
<tbody>
<tr>
<td width="100" valign="top">id</td>
<td width="100" valign="top">user_id</td>
<td width="100" valign="top">key</td>
<td width="100" valign="top">value</td>
</tr>
<tr>
<td width="100" valign="top">1</td>
<td width="100" valign="top">101</td>
<td width="100" valign="top">screen_name</td>
<td width="100" valign="top">john</td>
</tr>
<tr>
<td width="100" valign="top">2</td>
<td width="100" valign="top">101</td>
<td width="100" valign="top">first_name</td>
<td width="100" valign="top">John</td>
</tr>
<tr>
<td width="100" valign="top">3</td>
<td width="100" valign="top">101</td>
<td width="100" valign="top">last_name</td>
<td width="100" valign="top">Smith</td>
</tr>
</tbody>
</table>
<p align="justify">The table has one row for each Attribute-Value pair. In practice, we prefer to separate values based on data type to let the database to perform type validation checks and to support proper indexing. So programmers tend to create separate EAV tables for strings, real and integer numbers, dates, long text and BLOBS.</p>
<p align="justify">The benefits of such structure are:</p>
<ol>
<li>Flexibility, there is no limit on attributes used to describe an entity. No schema redesign.</li>
<li>The storage is efficient on sparse data.</li>
<li>Easy to put the data into an XML format for interchange.</li>
</ol>
<p align="justify">There are also some important drawbacks:</p>
<ol>
<li>No real use of data types</li>
<li>Awkward use of database constraints</li>
<li>There are several problems in querying such a structure.</li>
</ol>
<h2>What is MemcacheDB</h2>
<p align="justify">Memcachedb is a <strong>distributed key-value storage</strong> system designed for persistence. It is a very <strong>fast an reliable</strong> distributed storage. It includes transaction and replication. It is using Berkeley DB as persistence storage.</p>
<p>Why is better than a database?</p>
<ol>
<li>Faster, no SQL engine on top of MemcacheDB</li>
<li>Designed for concurrency, design for millions of requests</li>
<li>Optimized for small data</li>
</ol>
<p align="justify">Memcachedb is suitable for Messaging, metadata storage, Identity Management (Accounts, Profiles, Preferences, etc), index, counters, flags, etc.</p>
<p>The main features for Memcachedb are:</p>
<ul>
<li>
<div>High performance read/write for a key-value based object<br />
Rapid set/get for a key-value based object, not relational. Benchmark<br />
will tell you the true later.</div>
</li>
<li>
<div>High reliable persistent storage with transaction Transaction is used to make your data more reliable</div>
</li>
<li>
<div>High availability data storage with replication Replication rocks! Achieve your HA, spread your read, make your transaction durable</div>
</li>
<li>
<div>Memcache protocol compatibility Lots of Memcached Client APIs can be used for Memcachedb, almost in any language, Perl, C, Python, Java</div>
</li>
</ul>
<h3>Storage, replication and recovery</h3>
<p align="justify">Berkeley DB stores data quickly and easily without the overhead found in other databases. Read more about Berkeley DB <a href="http://www.oracle.com/technology/products/berkeley-db/db/index.html">here</a></p>
<p><img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://oracleimg.com/technology/products/berkeley-db/images/berkeley-db-stack.gif" alt="" /></p>
<p align="justify">MemcacheDB supports replication using Masters and Slaves nodes. The exact deployment design must chosen according with your application needs. A MemcacheDB environment consists intro three things:</p>
<ul>
<li>Database files, files that store your data</li>
<li>Log files, all your transaction commit first into logs</li>
<li>Region files, back the share memory region</li>
</ul>
<p align="justify">One problem could be spot in Log files, that record you transaction, over time they will contain a lot of data making the recovery a pain moment. For this Memcache DB has a <em>Checkpoint</em>. The checkpoint empties the in-memory cache, writes a checkpoint record, flushes the logs and writes a list of open database files.</p>
<p align="justify">Berkeley DB also allows hot backups and uses gzip and tar to compress the backup.</p>
<h3>Monitoring</h3>
<p align="justify">
<p align="justify">Memcache DB has a lot of built in commands for monitoring, such as:</p>
<ul>
<li>
<div>Current status: <em>stats</em></div>
</li>
<li>
<div>Database engine status: <em>stats db</em></div>
</li>
<li>
<div>Replication status: <em>stats rep </em></div>
</li>
</ul>
<p align="justify">What i liked most at Memcached is that you can use telnet to log on the running process and issue commands from command prompt. The same thing is valid also for MemcacheDB.</p>
<p>Besides memcached built function the Berkeley DB engine comes with his own stats command:</p>
<p>db_stats, –c locking statistics, –l logging statistics, –m cache statistics, –r replication statistics, –t transaction statistics.</p>
<p align="justify">Overall i liked what i saw about this alternative and i think that this is the most suitable solution for storing user profiles and user data that don’t need to be queried. When you need to scale this is for sure a very reliable solution. Have fun!</p>
<h2>Further reading</h2>
<p>Homepage: <a href="http://memcachedb.org">http://memcachedb.org</a></p>
<p>Mailing list: <a href="http://groups.google.com/group/memcachedb">http://groups.google.com/group/memcachedb</a>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F03%2Fkey-value-storage-using-memcachedb%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F03%2Fkey-value-storage-using-memcachedb%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=Architecture,distributed+storage,Entity+Attribute+value,high+performance,Memcachedb,Scalability" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bserban.org/2009/03/key-value-storage-using-memcachedb/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Facebook temporarily lost data.</title>
		<link>http://www.bserban.org/2009/03/facebook-temporarily-lost-data/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=facebook-temporarily-lost-data</link>
		<comments>http://www.bserban.org/2009/03/facebook-temporarily-lost-data/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 22:51:20 +0000</pubDate>
		<dc:creator>bserban</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[data loss]]></category>
		<category><![CDATA[distributed storage]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[heavy load]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[storage]]></category>

		<guid isPermaLink="false">http://www.bserban.org/?p=134</guid>
		<description><![CDATA[Last Sunday Facebook reported a data loss. We are talking about approximately 15% of users&#8217; photos. Loosing your client’s data is the worst thing that could happen to you and reminded me what a guy said once in a tech talk: “The main rules in running an online community service are: Never lose data and [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F03%2Ffacebook-temporarily-lost-data%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F03%2Ffacebook-temporarily-lost-data%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=data+loss,distributed+storage,facebook,heavy+load,memcached,storage" height="61" width="50" /><br />
			</a>
		</div>
<p>Last Sunday <a href="http://blog.facebook.com/blog.php?post=58637767130">Facebook reported</a> a data loss. We are talking about approximately 15% of users&#8217; photos. Loosing your client’s data is the worst thing that could happen to you and reminded me what a guy said once in a tech talk: “The main rules in running an online community service are: Never lose data and never go to jail.”</p>
<p>Facebook has not yet made public the details of what happened but only assured users that their photos will be restored using a backup. The official report states that we are talking about a hardware failure at storage level.</p>
<p>First of some key facts about Facebook</p>
<ul>
<li><a href="http://www.alexa.com/data/details/main/facebook.com">Facebook is the number 5</a> site in the world, which means it has a huge traffic (source Alexa.com),</li>
<li>They have 10,000 servers including 1,800 MySQL servers (administrated only by two guys, they say),</li>
<li>Last October the users uploaded <a href="http://www.facebook.com/note.php?note_id=30695603919">10 billion pictures on Facebook</a> and considering that they keep 4 back-up copies it means that they have to store 40 billion pictures,</li>
<li>2-3 Terabytes of photos are uploaded every day,</li>
<li>They serve 15 billion photo images per day,</li>
<li>Daily uploads are around 100 million photos,</li>
<li>The peak is about 450,000 images per second.</li>
</ul>
<p>Based on the above numbers it means that they lost approximately <strong>1.5 billion</strong> of pictures. Waw!</p>
<p>How is Facebook handling user’s images? Last year Jason Sobel, Manager of the Facebook Infrastructure Group, presented some insights about the current Facebook storage solution and the future one. We don’t know right now whether the new storage solution failed or the old one is to blame.</p>
<h2>Writing files using the old way</h2>
<p>They were using upload servers and stored images via NFS into a NetApp storage (last year they were planning to replace it). Each image is stored 4 times. This solution experienced heavy workload when processing metadata.</p>
<h2>Reading files using the old way</h2>
<p>Here all resumes to speed.</p>
<ul>
<li>First level of Cache is done using CDN, which has a hit rate of 99.8% for profiles and 92% for the rest.</li>
<li>Second Level of Cache is done using Cachr for profiles which is a modified evhttpd with memcached as storage,  and a File Handle Cache (lighttpd and memcached) for the rest of it to reduce metadata workload on NetApp.</li>
<li>NetApp storage via NFS. They tried to optimize it and to reduce the number of I/O access because of the the metadata heavy workload.</li>
</ul>
<p>The main concerns with the above architecture are:  Netapp storage is overwhelmed, they rely too much on CDNs.</p>
<p>Obviously when your app grows like hell, you start to think that is better to make your own toys, fully customized and optimized for your particular problem. So did Amazon back in 2001 and  Google too.  This is how the Facebook storage was born: <strong>Haystack</strong></p>
<h2>Haystack</h2>
<p>The answer was to develop in house a distributed file system like GFS (Google File System). Haystack should run on inexpensive commodity hardware, and it should deliver high aggregate performance to a large number of clients.</p>
<p>Haystack is file based and stores arbitrary data in files. For 1Gb disk data file they create 1M in memory index. In this way they have one disk seek which is much better than NetApp which had 3.</p>
<p>The Haystack format is rather simple and efficient, Version number, Magic number (supplied by the client to prevent brute force attack), length, data, checksum.  The index simply stores the Version, Photo key, Photo size, start, length.</p>
<p>Using a Haystack server</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">To write uses POST</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">/write/[pvid]_[key]_[magic]_[size].jpg</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">- writes data on disk haystack</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">- writes data on in memory index</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">To read uses GET</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">/[pvid]_[key]_[magic]_[size].jpg</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;">- uses the in memory index to retrieve the offset</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">- reads data from the on-disk file</pre>
</div>
</div>
<p>This simple approach allows Facebook to easily balance the reads and writes using Haystack clusters but to speed up the reads they still plan to use CDNs in areas where they don’t have datacenters and Cachr for profiles. This is their first step to create their own CDN network.</p>
<h2>Additional readings</h2>
<p><a href="http://www.flowgram.com/p/2qi3k8eicrfgkv/">Needle in a haystack: efficient storage of billions of photos</a></p>
<p><a href="http://www.facebook.com/note.php?note_id=30695603919">Engineering[at]Facebook’s Notes</a>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F03%2Ffacebook-temporarily-lost-data%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F03%2Ffacebook-temporarily-lost-data%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=data+loss,distributed+storage,facebook,heavy+load,memcached,storage" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bserban.org/2009/03/facebook-temporarily-lost-data/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Simple MVC for Flex and AIR</title>
		<link>http://www.bserban.org/2009/02/simple-mvc-for-flex-and-air/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=simple-mvc-for-flex-and-air</link>
		<comments>http://www.bserban.org/2009/02/simple-mvc-for-flex-and-air/#comments</comments>
		<pubDate>Sat, 21 Feb 2009 20:29:44 +0000</pubDate>
		<dc:creator>bserban</dc:creator>
				<category><![CDATA[AIR]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[flex mvc]]></category>
		<category><![CDATA[simple flex mvc]]></category>

		<guid isPermaLink="false">http://www.bserban.org/?p=119</guid>
		<description><![CDATA[This weekend I tried to make an &#8220;Air&#8221; client for search using &#8220;Adobe Community Help. I had no prior experience with Flex and AIR. My first attempt ended as a simple project for college, a spaghetti code. All examples found on the web or official documentation are based on massive use mxml code. I ended [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F02%2Fsimple-mvc-for-flex-and-air%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F02%2Fsimple-mvc-for-flex-and-air%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=AIR,Flex,flex+mvc,simple+flex+mvc" height="61" width="50" /><br />
			</a>
		</div>
<p align="justify">This weekend I tried to make an &#8220;Air&#8221; client for search using &#8220;Adobe Community Help. I had no prior experience with Flex and AIR. My first attempt ended as a simple project for college, a spaghetti code. All examples found on the web or official documentation are based on massive use mxml code. I ended up having a glorious mxml file. Huge <img src='http://www.bserban.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
<p>Some smart guys are telling you to split your mxml using an ActionScript file but is like putting the trash under the carpet. It is still spaghetti code but in two dishes.</p>
<p align="justify">I tried to remember how I would have programmed it in Java Swing.  9 years have passed since then but I remembered. <em>TableModel</em>, <em>DefaultListModel</em>, <em>ButtonModel </em>etc. they all came out from a dark corner of my memory. Yes ! I remembered, Swing MVC.</p>
<p>A typical sample from documentation…..</p>
<div style="border: 1px solid gray; margin: 20px 0px 10px; padding: 4px; overflow: auto; font-size: 8pt; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">&lt;?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">="1.0"</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">="utf-8"</span>?<span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:Application</span> <span style="color: #ff0000">xmlns:mx</span><span style="color: #0000ff">="http://www.adobe.com/2006/mxml"</span> <span style="color: #ff0000">layout</span><span style="color: #0000ff">="absolute"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   3:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:Panel</span> <span style="color: #ff0000">x</span><span style="color: #0000ff">="10"</span> <span style="color: #ff0000">y</span><span style="color: #0000ff">="10"</span> <span style="color: #ff0000">width</span><span style="color: #0000ff">="350"</span> <span style="color: #ff0000">height</span><span style="color: #0000ff">="200"</span> <span style="color: #ff0000">title</span><span style="color: #0000ff">="Rate Customer Service"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   4:</span>         <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:ComboBox</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="cbxRating"</span> <span style="color: #ff0000">x</span><span style="color: #0000ff">="20"</span> <span style="color: #ff0000">y</span><span style="color: #0000ff">="20"</span> <span style="color: #ff0000">width</span><span style="color: #0000ff">="100"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   5:</span>             <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:dataProvider</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   6:</span>                 <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:Array</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   7:</span>                     <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:String</span><span style="color: #0000ff">&gt;</span>Satisfied<span style="color: #0000ff">&lt;/</span><span style="color: #800000">mx:String</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   8:</span>                     <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:String</span><span style="color: #0000ff">&gt;</span>Neutral<span style="color: #0000ff">&lt;/</span><span style="color: #800000">mx:String</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   9:</span>                     <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:String</span><span style="color: #0000ff">&gt;</span>Dissatisfied<span style="color: #0000ff">&lt;/</span><span style="color: #800000">mx:String</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  10:</span>                 <span style="color: #0000ff">&lt;/</span><span style="color: #800000">mx:Array</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  11:</span>             <span style="color: #0000ff">&lt;/</span><span style="color: #800000">mx:dataProvider</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  12:</span>         <span style="color: #0000ff">&lt;/</span><span style="color: #800000">mx:ComboBox</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  13:</span>         <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:Button</span> <span style="color: #ff0000">x</span><span style="color: #0000ff">="140"</span> <span style="color: #ff0000">y</span><span style="color: #0000ff">="20"</span> <span style="color: #ff0000">label</span><span style="color: #0000ff">="Send"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  14:</span>     <span style="color: #0000ff">&lt;/</span><span style="color: #800000">mx:Panel</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  15:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">mx:Application</span><span style="color: #0000ff">&gt;</span></pre>
</div>
</div>
<p align="justify">Who hard-codes his application in this way? In a typical application you get this stuff from files or database. But let’s see the good part, at least is giving you a hint, a <em>ComboBox</em> and <em>List </em>are accepting an <em>Array </em>as input.</p>
<h1>MVC applied to Flex</h1>
<p>First of all a briefing about MVC</p>
<ol>
<li><strong>Model</strong>, is the data. Manipulates the internal state and fire events when the internal state changed.</li>
<li><strong>View</strong>, the visual representation for the Model’s data (controls on the screen)</li>
<li><strong>Controller</strong>, is responsible for interpreting the user actions on the view and make changes to the model. (usually an event handler in flex)</li>
</ol>
<p align="justify">In reality there is no 100% demarcation between these three layers. Is not that easy to make them completely decoupled and usually we end up making some tradeoffs.</p>
<p align="justify">The controller will always know about the view and the view about the controller. Controller also knows about the model. In the end I could say that the model is the only piece of the MVC that can be “100% decoupled”.</p>
<p align="justify">Let’s try to put a simple screen like this into MVC.</p>
<p align="justify"><a href="http://www.bserban.org/wp-content/uploads/2009/02/image.png"><img style="border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; border-left: 0px; margin-right: auto; border-bottom: 0px" title="image" src="http://www.bserban.org/wp-content/uploads/2009/02/image-thumb.png" border="0" alt="image" width="228" height="244" /></a></p>
<p align="justify">We fill in some text and then press Add. After we press add the text box is cleared and the text is added into de the list. In the end wee look into it and try to make a reusable component.</p>
<h2>Model</h2>
<p align="justify">The model contains the actual data, and for our example it should a class that hold list values. As I pointed out earlier we could use an ArrayCollection to store the list. For this we make an actionscript class named <strong>ListModel</strong></p>
<p align="justify">The view should display model’s changes and for this we mark the model class as <strong>[Bindable]</strong>. This is nice feature of ActionScript, no such thing in Java Swing.</p>
<p align="justify">Now, to add a new item in the list we simply nee an <strong><em>addElement</em></strong> function. In this example we make the model a singleton. This means that if we make more than one list they will share the same data.</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   1:</span> package org.bserban.flex.simplemvc.model</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   3:</span>     import mx.collections.ArrayCollection;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   4:</span>     /**</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   5:</span>     * Model class used to store list data and to</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   6:</span>     * provide access to the list content.</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   7:</span>     *</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   8:</span>     * For demo purposes, we have only addElement.</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   9:</span>      */</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  10:</span>     [Bindable]</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  11:</span>     public class ListModel</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  12:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  13:</span>         public var items :ArrayCollection = new ArrayCollection();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  14:</span>         private static var instance:ListModel;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  15:</span>         public function ListModel()</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  16:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  17:</span>             instance=this;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  18:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  19:</span>         /**</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  20:</span>          * For this demo we treat this class as singletone.</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  21:</span>          * If list is reused the component that reuse it</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  22:</span>          * must keep reference to model and controler.</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  23:</span>          */</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  24:</span>         public static function getInstance():ListModel{</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  25:</span>             if(instance == null){</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  26:</span>                 instance = new ListModel();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  27:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  28:</span>             return instance;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  29:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  30:</span>         /**</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  31:</span>          * Add a new element to the list, the model is bindable,</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  32:</span>          * no further actions are required, the view</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  33:</span>          * is notified automatically.</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  34:</span>          */</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  35:</span>         public function addElement(itm:String): void{</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  36:</span>             items.addItem(itm);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  37:</span>             trace(" item added, now we have:"+items.length);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  38:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  39:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  40:</span> }</pre>
</div>
</div>
<h2>Controller</h2>
<p>The controller is responsible for the interaction between view and model. In our case will make the validation of the text, it doesn’t allow the view to add empty text into the list. Let’s make a new class named <strong>Controller</strong>. As an exercise add also a sort function.</p>
<p>The controller holds a reference to the model and provides functions to the view. In a more advanced implementation the Controller would listen for events from the view and the decides what action should do.</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   1:</span> package org.bserban.flex.simplemvc.controller</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   2:</span> {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   3:</span>     import org.bserban.flex.simplemvc.model.ListModel</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   4:</span>     import mx.utils.StringUtil;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   5:</span>     public class Controller</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   6:</span>     {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   7:</span>        private var model:ListModel = ListModel.getInstance();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   8:</span>         /**</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   9:</span>          * Glue the interaction between view and model.</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  10:</span>          */</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  11:</span>         public function Controller(){</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  12:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  13:</span>         /**</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  14:</span>          * add a new item into the list model.</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  15:</span>          */</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  16:</span>         public function addPerson(name:String):void</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  17:</span>         {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  18:</span>             if(name==null || StringUtil.trim(name).length==0){</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  19:</span>                 trace("empty name");</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  20:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  21:</span>             else{</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  22:</span>                 model.addElement(name);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  23:</span>            }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  24:</span>         }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  25:</span>     }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  26:</span> }</pre>
</div>
</div>
<h2>View</h2>
<p align="justify">The view is the graphical representation of the component. Usually it is a an mxml file but it can be also an actions script file for advanced programmers. It binds his data to the model and use the controller to process the view events. Let’s name it <strong>SimpleAirMVC.mxml</strong>. I added <em>Air </em>to its name because i decided to make an air project in Flex Builder.</p>
<div>
<div style="border-style: none; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;">
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   1:</span> <span style="color: #0000ff">&lt;?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">="1.0"</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">="utf-8"</span>?<span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   2:</span> <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:WindowedApplication</span> <span style="color: #ff0000">xmlns:mx</span><span style="color: #0000ff">="http://www.adobe.com/2006/mxml"</span> <span style="color: #ff0000">layout</span><span style="color: #0000ff">="absolute"</span> <span style="color: #ff0000">height</span><span style="color: #0000ff">="226"</span> <span style="color: #ff0000">width</span><span style="color: #0000ff">="235"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   3:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:Script</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   4:</span>         <span style="color: #0000ff">&lt;!</span>[CDATA[</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   5:</span>         import mx.controls.List;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   6:</span>         import org.bserban.flex.simplemvc.model.ListModel;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   7:</span>         import org.bserban.flex.simplemvc.controller.Controller;</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">   8:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">   9:</span>         [Bindable]</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  10:</span>          private var model:ListModel = ListModel.getInstance();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  11:</span>         private function clickHandler():void</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  12:</span>             {</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  13:</span>                 var controler:Controller = new Controller();</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  14:</span>                 controler.addPerson(personTxt.text);</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  15:</span>                 personTxt.text="";</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  16:</span>             }</pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  17:</span>              ]]<span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  18:</span>     <span style="color: #0000ff">&lt;/</span><span style="color: #800000">mx:Script</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  19:</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  20:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:TextInput</span> <span style="color: #ff0000">x</span><span style="color: #0000ff">="10"</span> <span style="color: #ff0000">y</span><span style="color: #0000ff">="10"</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="personTxt"</span> <span style="color: #ff0000">text</span><span style="color: #0000ff">=""</span> <span style="color: #ff0000">width</span><span style="color: #0000ff">="145"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  21:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:Button</span> <span style="color: #ff0000">x</span><span style="color: #0000ff">="163"</span> <span style="color: #ff0000">y</span><span style="color: #0000ff">="10"</span> <span style="color: #ff0000">label</span><span style="color: #0000ff">="Add"</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="btnAdd"</span> <span style="color: #ff0000">click</span><span style="color: #0000ff">="clickHandler()"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4;"><span style="color: #606060">  22:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">mx:List</span> <span style="color: #ff0000">x</span><span style="color: #0000ff">="10"</span> <span style="color: #ff0000">y</span><span style="color: #0000ff">="40"</span> <span style="color: #ff0000">width</span><span style="color: #0000ff">="218"</span> <span style="color: #ff0000">dataProvider</span><span style="color: #0000ff">="{model.items}"</span><span style="color: #0000ff">&gt;&lt;/</span><span style="color: #800000">mx:List</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; font-size: 8pt; width: 100%; color: black; line-height: 12pt; font-family: consolas,'Courier New',courier,monospace; background-color: white;"><span style="color: #606060">  23:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">mx:WindowedApplication</span><span style="color: #0000ff">&gt;</span></pre>
</div>
</div>
<p>This a  simple way to implement a MVC in a small application. Things can become more complicated if the application is big. If this is the case then you should look over <a href="http://puremvc.org/">Pure MVC</a> framework or <a href="http://opensource.adobe.com/wiki/display/cairngorm/Cairngorm">Cairngorm</a>. They eliminate the dependencies between MVC layer by using events. It is an event driven approach.</p>
<p>You may download the source code here <a href="http://www.bserban.org/wp-content/uploads/2009/02/simplemvc.zip">SimpleAirMVC</a></p>
<h2>Further reading</h2>
<p>I recommend you to read the books <a href="http://oreilly.com/catalog/9780596528461/">ActionScript 3.0 Design Patterns</a> and <a href="http://www.amazon.com/Advanced-ActionScript-3-Design-Patterns/dp/0321426568/ref=sr_1_1/002-3137522-1200844?ie=UTF8&amp;s=books&amp;qid=1186807961&amp;sr=1-1">Advanced ActionScript 3 with Design Patterns</a>
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F02%2Fsimple-mvc-for-flex-and-air%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.bserban.org%2F2009%2F02%2Fsimple-mvc-for-flex-and-air%2F&amp;source=bserban&amp;style=normal&amp;service=bit.ly&amp;hashtags=AIR,Flex,flex+mvc,simple+flex+mvc" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bserban.org/2009/02/simple-mvc-for-flex-and-air/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
