<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4435599137875974089</id><updated>2026-04-20T19:41:56.041+05:30</updated><category term="java"/><category term="testing"/><category term="Spring"/><category term="JUnit"/><category term="Tomcat"/><category term="jdbc"/><category term="struts"/><category term="AWS"/><category term="Apache HTTPD"/><category term="Logging"/><category term="EC2"/><category term="Excel"/><category term="Hibernate"/><category term="SimpleDB"/><category term="VB Script"/><category term="ant"/><category term="apache james"/><category term="jsf"/><category term="performance"/><category term="potlet"/><category term="servlet"/><category term="tiles"/><category term="web"/><category term="weblogs api"/><category term="xml-rpc"/><title type='text'>Coding Chronicles</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-343468139938496090</id><published>2012-02-07T22:24:00.001+05:30</published><updated>2012-02-07T22:24:59.136+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Apache HTTPD"/><category scheme="http://www.blogger.com/atom/ns#" term="Tomcat"/><title type='text'>Hosting Multiple Domains On A Single Apache HTTPD / Tomcat Server Combination</title><content type='html'>This is a quick and easy guide on how to deploy multiple domains on a single Tomcat sever fronted by a single Apache HTTPD server. I am assuming you already have installed mod_jk and got the communication between Apache and Tomcat working.&lt;br /&gt;
&lt;br /&gt;
First the Tomcat changes ( I am using Tomcat 7 but it should work the same in Tomcat 6 too). Edit server.xml file in conf directory and scroll down until you see the &amp;lt;Host&amp;gt; section there. Copy the host section and paste it again so you have two host sections and modify the name attributes to contain the two domain names. Also point appBase attributes to two different folders (create them under the Tomcat directory). You will deploy your apps to the ROOT folders under each appbase directory so that they can be accessed as http://www.domain1.com and http://www.domain2.com&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:xml&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[
&lt;host name=&quot;www.domain1.com&quot;  appBase=&quot;webapps-domain1&quot;
      unpackWARs=&quot;true&quot; autoDeploy=&quot;true&quot;&gt;


  &lt;valve className=&quot;org.apache.catalina.valves.AccessLogValve&quot; directory=&quot;logs&quot;
           prefix=&quot;domain1_access_log.&quot; suffix=&quot;.txt&quot;
           pattern=&quot;%h %l %u %t &amp;quot;%r&amp;quot; %s %b&quot; /&gt;

  &lt;/Host&gt;

  &lt;host name=&quot;www.domain2.com&quot;  appBase=&quot;webapps-domain2&quot;
      unpackWARs=&quot;true&quot; autoDeploy=&quot;true&quot;&gt;

      &lt;valve className=&quot;org.apache.catalina.valves.AccessLogValve&quot; directory=&quot;logs&quot;
           prefix=&quot;domain2_access_log.&quot; suffix=&quot;.txt&quot;
           pattern=&quot;%h %l %u %t &amp;quot;%r&amp;quot; %s %b&quot; /&gt;

  &lt;/Host&gt;


]]&gt;
&lt;/script&gt;
&lt;br /&gt;
workers.properties can be as simple as following two lines. Which connects to the worker w1 to ajp port of Tomcat.&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;worker.list=w1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;worker.w1.port=8009&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Now to the Apache 2 configuration. Make sure you have uncommented &lt;b&gt;NameVirtualHost *:80&lt;/b&gt; line in httpd.conf. Now add two &amp;lt;VirtualHost&amp;gt; sections for the two domains as below. Note that I have left out other mod_jk configuration directives.&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ServerName www.domain1.com&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; JkMount&amp;nbsp; /* w1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ServerName www.domain2.com&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; JkMount&amp;nbsp; /* w1&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/343468139938496090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/343468139938496090' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/343468139938496090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/343468139938496090'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2012/02/hosting-multiple-domains-on-single.html' title='Hosting Multiple Domains On A Single Apache HTTPD / Tomcat Server Combination'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-2792407905514733474</id><published>2012-02-07T17:47:00.000+05:30</published><updated>2012-02-08T09:04:23.166+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jdbc"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring"/><category scheme="http://www.blogger.com/atom/ns#" term="Tomcat"/><title type='text'>JDBC Driver Class Names and URL Formats For Popular Databases</title><content type='html'>A recurring pain for me is digging up JDBC driver class names and URL formats when ever I need to connect to a database over JDBC. So I thought I will document driver / URL details plus additional info such as Spring DBCP configuration, Tomcat datasource configuration and connection validation SQL information for all popular databases.&lt;br /&gt;
&lt;br /&gt;
I have published this info on the internet and you can view them at &lt;a href=&quot;http://www.kengsi.com/jdbcwiz.html&quot;&gt;http://www.kengsi.com/jdbcwiz.html&lt;/a&gt;. Hope this will help few others by having this information in one single place. I will add more databases as time goes on so if you don&#39;t see information about a database driver you are interested in, please do let me know.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://www.kengsi.com/jdbcwiz.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0r7LQQ8Ji9n2hN3qd8KpKLakBb0agVYgQYGxKquEUQXeNtOwK_3X1LFMB-Rr-7D1KFwBvs_1OnTFRAskgp1leQgxclz6wq9OF_6fvXaFLLoJXP3_8B2i54d6Pw-rMcEvuGeCeQOx58YlY/s640/jdbcwiz.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/2792407905514733474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/2792407905514733474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/2792407905514733474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/2792407905514733474'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2012/02/jdbc-driver-class-names-and-url-formats.html' title='JDBC Driver Class Names and URL Formats For Popular Databases'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0r7LQQ8Ji9n2hN3qd8KpKLakBb0agVYgQYGxKquEUQXeNtOwK_3X1LFMB-Rr-7D1KFwBvs_1OnTFRAskgp1leQgxclz6wq9OF_6fvXaFLLoJXP3_8B2i54d6Pw-rMcEvuGeCeQOx58YlY/s72-c/jdbcwiz.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-1444854526218333264</id><published>2012-01-27T16:44:00.000+05:30</published><updated>2012-01-27T16:44:55.485+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="performance"/><title type='text'>Quick and Simple LRU Cache in Java</title><content type='html'>Many times I have come across the need to cache values where using a fully fledged caching library like EHCache is an overkill. All I want is a bounded Map of key / value pairs with an LRU eviction policy. There are few options mentioned on the web and few common ones are&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt; &lt;b&gt;LinkedHashMap &lt;/b&gt;from JDK&lt;/li&gt;
&lt;/ul&gt;
Example from &lt;a href=&quot;http://www.exampledepot.com/egs/java.util/coll_Cache.html&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;. This is not really LRU but removing the oldest entry added to the map when it reaches the capacity. Also LinkedHashMap is not thread safe and as you can see in the example you need to wrap it with Collections.synchronizedMap which makes every get / put method to lock the map. This will not perform that well in a multi-threaded environment.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;LRUMap &lt;/b&gt;from &lt;a href=&quot;http://commons.apache.org/collections/apidocs/org/apache/commons/collections/map/LRUMap.html&quot; target=&quot;_blank&quot;&gt;Commons Collections&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
This uses LRU algorithm to evict objects but again is not thread safe and you need to wrap it in a synchronized map interface as in the LinkedHashMap&#39;s case which will incur a performance penalty on muti-threaded access.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt; &lt;b&gt;ConcurrentLinkedHashMap &lt;/b&gt;on &lt;a href=&quot;http://code.google.com/p/concurrentlinkedhashmap/&quot; target=&quot;_blank&quot;&gt;Google Code&lt;/a&gt; (Winner)&lt;/li&gt;
&lt;/ul&gt;
This open source implementation is the one I finally settled on. It&#39;s easy to use as you can construct the cache in a single line, thread safe and doesn&#39;t seem to have a big performance hit due to locking in muti-threaded apps. According to the diagram on the main page, get and put performance seems to be comparable to ConcurrentHashMap from the JDK.&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:java&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[
    //create a cache with a bound capacity of 1000 entries
    ConcurrentMap&lt;String, Long&gt; pageIdCache = new ConcurrentLinkedHashMap.Builder&lt;String, Long&gt;()
    .maximumWeightedCapacity(1000)
    .build();

]]&gt;
&lt;/script&gt;
&lt;br /&gt;
As you can see it&#39;s pretty simple to create a cache and you can use the put an get methods from the Map interface to add and retrieve entries from the cache</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/1444854526218333264/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/1444854526218333264' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/1444854526218333264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/1444854526218333264'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2012/01/quick-and-simple-lru-cache-in-java.html' title='Quick and Simple LRU Cache in Java'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-8326797169988700852</id><published>2012-01-27T08:31:00.000+05:30</published><updated>2012-01-27T08:31:11.123+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Apache HTTPD"/><category scheme="http://www.blogger.com/atom/ns#" term="Tomcat"/><title type='text'>Apache HTTPD Redirect Root URL to Sub Context / Directory</title><content type='html'>Yesterday I had to front an application running on Tomcat with Apache HTTPD server and one of the requirements was to automatically redirect the root URL to the Tomcat&#39;s web app context&lt;br /&gt;
&lt;br /&gt;
e.g. &lt;b&gt;http://www.mycompany.com&lt;/b&gt; to &lt;b&gt;http://www.mycompany.com/application&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Sounded pretty simple and did a Google search, went through few pages that had examples on how to do it but none of them worked. Most involved .htaccess files and using RewiteCond /RewriteRule combinations.&lt;br /&gt;
&lt;br /&gt;
I was getting frustrated with finding a simple solution for the simple problem and after about an hour of searching and trying things I finally found the simple solution that worked. All it needed was the following single line in your VirtualHost section.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;-webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; color: black; display: inline !important; float: none; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 18px; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: pre; widows: 2; word-spacing: 0px;&quot;&gt;RedirectMatch ^/$ /application/&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
That&#39;s it and it will redirect all requests to root URL to the specified sub directory or sub context.</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/8326797169988700852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/8326797169988700852' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/8326797169988700852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/8326797169988700852'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2012/01/apache-httpd-redirect-root-url-to-sub.html' title='Apache HTTPD Redirect Root URL to Sub Context / Directory'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-4063405772966003156</id><published>2012-01-26T09:03:00.001+05:30</published><updated>2012-08-19T14:45:21.350+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="EC2"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><title type='text'>Few Easy Steps to Install Sun/Oracle JDK on EC2 Linux</title><content type='html'>I use the Amazon Linux AMI on all my EC2 instances and they come with OpenJDK IcedTea pre installed on them. I have had few issues with OpenJDK when running some applications and I always install the Sun/Oracle JDK 6 on them. Below are the few easy steps / commands to download and install JDK 6 once you log in to the EC2 instance using an SSH client.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Update:&lt;/b&gt;&lt;br /&gt;
Oracle doesn&#39;t provide direct download URLs for JDKs anymore. I have updated the steps with the trick mentioned &lt;a href=&quot;http://blog.kdecherf.com/2012/04/12/oracle-i-download-your-jdk-by-eating-magic-cookies/&quot; target=&quot;_blank&quot;&gt;here&amp;nbsp;&lt;/a&gt;to get the installation file with wget&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:bash&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[
wget --no-cookies --header &quot;Cookie: gpw_e24=xxx;&quot; http://download.oracle.com/otn-pub/java/jdk/6u34-b04/jdk-6u34-linux-i586-rpm.bin
sudo bash
chmod +x jdk-6u34-linux-i586-rpm.bin
./jdk-6u34-linux-i586-rpm.bin
alternatives --install /usr/bin/java java /usr/java/default/bin/java 20000
update-alternatives --config java
ln -s /usr/java/default/jre /usr/lib/jvm/jre
ln -s /usr/share/java /usr/lib/jvm-exports/jre

]]&gt;
&lt;/script&gt;

Run &lt;b&gt;java -version&lt;/b&gt; to make sure you have the Sun/Oracle JDK as your default jvm now.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/4063405772966003156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/4063405772966003156' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/4063405772966003156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/4063405772966003156'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2012/01/few-easy-steps-to-install-sunoracle-jdk.html' title='Few Easy Steps to Install Sun/Oracle JDK on EC2 Linux'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-6928495744053762460</id><published>2012-01-23T14:13:00.000+05:30</published><updated>2012-01-23T14:13:38.325+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="servlet"/><category scheme="http://www.blogger.com/atom/ns#" term="web"/><title type='text'>Servlet Filter to Set Response Headers</title><content type='html'>Frequent requirement when developing Java web apps is to set different response headers based of on content type / URL. Last project it was to set cache headers on dynamic URLs so they will never be cached and today I had to do the opposite for static content, where cache headers were set on static content so they will be cached for a very long time by the browsers.&lt;br /&gt;
&lt;br /&gt;
It&#39;s basically the same thing but just setting different response header values. So I decided to write a general purpose Servlet filter to achieve this in a few lines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:java&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[
public class ResponseHeaderFilter implements Filter{

 private String header;
 private String value;
 
 public void init(FilterConfig fc) throws ServletException {
  header = fc.getInitParameter(&quot;header&quot;);
  value = fc.getInitParameter(&quot;value&quot;);
 }
 
 public void doFilter(ServletRequest req, ServletResponse res,
   FilterChain fc) throws IOException, ServletException {
  HttpServletResponse response = (HttpServletResponse) res;
  response.setHeader(header, value);
  fc.doFilter(req, res);
 }
 
 public void destroy() {
  
 }
}

]]&gt; 
&lt;/script&gt;
&lt;br /&gt;
We configure the filter in web.xml and set the required response header / value pair as init params&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:xml&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[
    &lt;filter&gt;
        &lt;filter-name&gt;cache&lt;/filter-name&gt;
        &lt;filter-class&gt;com.xyz.filter.ResponseHeaderFilter&lt;/filter-class&gt;
        &lt;init-param&gt;
         &lt;param-name&gt;header&lt;/param-name&gt;
         &lt;param-value&gt;Cache-Control&lt;/param-value&gt;
        &lt;/init-param&gt;
        &lt;init-param&gt;
         &lt;param-name&gt;value&lt;/param-name&gt;
         &lt;param-value&gt;public, max-age=31536000&lt;/param-value&gt;
        &lt;/init-param&gt;
    &lt;/filter&gt;
]]&gt; 
&lt;/script&gt;
&lt;br /&gt;
Here we are setting the Cache-Control response header and setting the expiry date to 1 year from request time. Now we add the appropriate filter mapping to apply the filter to static content we are interested in.&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:xml&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[
    &lt;filter-mapping&gt;
        &lt;filter-name&gt;cache&lt;/filter-name&gt;
        &lt;url-pattern&gt;*.css&lt;/url-pattern&gt;
        &lt;url-pattern&gt;*.js&lt;/url-pattern&gt;
        &lt;url-pattern&gt;*.gif&lt;/url-pattern&gt;
        &lt;url-pattern&gt;*.png&lt;/url-pattern&gt;
        &lt;url-pattern&gt;*.jpg&lt;/url-pattern&gt;
    &lt;/filter-mapping&gt;
]]&gt; 
&lt;/script&gt;
&lt;br /&gt;
And we are done. In summary all we are doing here is setting cache headers to all static content like .js, .css etc... so they will be cached by the client browsers for a very long time making the pages load faster and reducing the bandwidth usage / load on the server significantly.&lt;br /&gt;
&lt;br /&gt;
Please note you shouldn&#39;t add far future cache expiration dates if you plan to make changes to the static content at any time as the modified content might not be downloaded by client browsers. The strategy we take is to make a new copy of the file when we modify and link to the new file. e.g. style-1.1.css when modified will be made site-1.2.css, &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/6928495744053762460/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/6928495744053762460' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/6928495744053762460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/6928495744053762460'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2012/01/servlet-filter-to-set-response-headers.html' title='Servlet Filter to Set Response Headers'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-2788007796114467744</id><published>2011-11-22T21:36:00.001+05:30</published><updated>2011-11-22T21:57:47.453+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Excel"/><category scheme="http://www.blogger.com/atom/ns#" term="VB Script"/><title type='text'>Excel Macros, VB Script and HTTP Basic Authentication</title><content type='html'>I came across an Excel sheet that retrieve data from a web site by calling a URL using a macro (VB Script). The site was using basic authentication and the macro wasn&#39;t working since it was not sending the user credentials in the request header. I haven&#39;t worked with Excel Macros or VB Script so turned to Google for some help.&lt;br /&gt;
&lt;br /&gt;
Didn&#39;t find anything that was working but found some half answers which I managed to cobble together to get a working solution. Thought I would write it down here for anyone trying to do the same in future.&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:java&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[
Function GetData() As Boolean
  Dim objHTTP As New MSXML2.XMLHTTP

  Dim strURL As String
  Dim strUserName As String
  Dim strPassword As String

  strUserName = &quot;xxx&quot;
  strPassword = &quot;xxx&quot;
  
  strURL = &quot;http://xyz.com&quot;

  objHTTP.Open &quot;GET&quot;, strURL, False
  objHTTP.setRequestHeader &quot;Authorization&quot;, &quot;Basic &quot; &amp; Base64Encode(strUserName &amp; &quot;:&quot; &amp; strPassword)
  
  objHTTP.setRequestHeader &quot;Content-Type&quot;, &quot;text&quot;
  objHTTP.send &quot;Nothing&quot;

  Dim strResponseReceived As String
  
  strResponseReceived = objHTTP.responseText
  MsgBox strResponseReceived

End Function



Function Base64Encode(sText)
    Dim oXML, oNode

    Set oXML = CreateObject(&quot;Msxml2.DOMDocument.3.0&quot;)
    Set oNode = oXML.createElement(&quot;base64&quot;)
    oNode.DataType = &quot;bin.base64&quot;
    oNode.nodeTypedValue = Stream_StringToBinary(sText)
    Base64Encode = oNode.Text
    Set oNode = Nothing
    Set oXML = Nothing
End Function

Function Stream_StringToBinary(Text)
  Const adTypeText = 2
  Const adTypeBinary = 1

  &#39;Create Stream object
  Dim BinaryStream &#39;As New Stream
  Set BinaryStream = CreateObject(&quot;ADODB.Stream&quot;)

  &#39;Specify stream type - we want To save text/string data.
  BinaryStream.Type = adTypeText

  &#39;Specify charset For the source text (unicode) data.
  BinaryStream.Charset = &quot;us-ascii&quot;

  &#39;Open the stream And write text/string data To the object
  BinaryStream.Open
  BinaryStream.WriteText Text

  &#39;Change stream type To binary
  BinaryStream.Position = 0
  BinaryStream.Type = adTypeBinary

  &#39;Ignore first two bytes - sign of
  BinaryStream.Position = 0

  &#39;Open the stream And get binary data from the object
  Stream_StringToBinary = BinaryStream.Read

  Set BinaryStream = Nothing
End Function
]]&gt;
&lt;/script&gt;
&lt;br /&gt;
&lt;br /&gt;
Base64Encoding function copied from &lt;a href=&quot;http://stackoverflow.com/questions/496751/base64-encode-string-in-vbscript&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; and</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/2788007796114467744/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/2788007796114467744' title='89 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/2788007796114467744'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/2788007796114467744'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2011/11/excel-macros-vb-script-and-http-basic.html' title='Excel Macros, VB Script and HTTP Basic Authentication'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>89</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-5121288124625727111</id><published>2011-11-16T21:57:00.001+05:30</published><updated>2011-11-17T20:16:08.056+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jdbc"/><title type='text'>Why Developers Shouldn&#39;t Be Using JDBC Connections, Statements and PreparedStatements</title><content type='html'>I cringe in pain every time I come across a project that&#39;s still using JDBC API interfaces / classes like Connection, Statement, PreparedStatement. Most of them are not legacy projects either.&lt;br /&gt;
&lt;br /&gt;
I truly believe in this day and age you shouldn&#39;t be working directly with these low level interfaces and the associated boiler plate code you eventually end up writing. Basically you will have to get the connection, create statements or prepared statements, get the result set and once you are done close everything in a finally clause. This will not only create long, ugly and hard to read code but will make it very easy to introduce errors by say forgetting to close a connection.&lt;br /&gt;
&lt;br /&gt;
So if you are not building a toy Java application you should really be using a high level API that automatically handles these tasks for you. I am not a very big fan of fancy ORM libraries and my preferred data access library has been Spring JDBC for the last two years or so. It gives you the full power of raw SQLs while making it easy do what you want to do with minimum coding. End result is simple, readable and most importantly maintainable and less error prone data access code.&lt;br /&gt;
&lt;br /&gt;
Once you have configured Spring JDBC, an update or a select can be done in one line of code.&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:java&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[
 
jdbcTemplate.update(
        &quot;update t_actor set = ? where id = ?&quot;, 
        &quot;Banjo&quot;, 5276L);

int countOfActorsNamedJoe = jdbcTemplate.queryForInt(
        &quot;select count(*) from t_actor where first_name = ?&quot;, &quot;Joe&quot;);
]]&gt;
&lt;/script&gt;
&lt;br /&gt;
&lt;br /&gt;
So if you are still using low level JDBC code in your applications, its time to consider moving to something like Spring JDBC. You can move your code gradually to the new APIs as Spring JDBC can and will coexist with low level JDBC code. &lt;br /&gt;
&lt;br /&gt;
Take a look at the &lt;a href=&quot;http://static.springsource.org/spring/docs/current/spring-framework-reference/html/jdbc.html&quot; target=&quot;_blank&quot;&gt;Spring documentation&lt;/a&gt; to get a more in depth idea of all available features of Spring JDBC</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/5121288124625727111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/5121288124625727111' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5121288124625727111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5121288124625727111'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2011/11/why-developers-shouldnt-be-using-jdbc.html' title='Why Developers Shouldn&#39;t Be Using JDBC Connections, Statements and PreparedStatements'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-5375460875594518061</id><published>2011-11-11T16:12:00.001+05:30</published><updated>2011-11-11T16:20:32.797+05:30</updated><title type='text'>Exporting / Generating CSV Files in Java</title><content type='html'>I have had to generate CSV files in several projects in last few months and I have settled on using &lt;a href=&quot;http://opencsv.sourceforge.net/&quot; target=&quot;_blank&quot;&gt;OpenCSV&lt;/a&gt; library as it make the task very simple. All you need is the opencsv.jar and a few lines of code.&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:java&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[ 

public void exportUsers(OutputStream out){        
    List&lt;user&gt; users = userDao.getAll();
    
    CSVWriter writer = new CSVWriter(new PrintWriter(out), &#39;,&#39;);
    
    String[] header = new String[]{
            &quot;First Name&quot;,
            &quot;Last Name&quot;,
            &quot;Company&quot;,
            &quot;Email&quot;,
            &quot;Phone&quot;,
            &quot;Country&quot;
        };
    writer.writeNext(header);
    
    
    for (User user : users) {
        
        String[] fields = new String[]{
            user.getFirstName(),
            user.getLastName(),
            user.getCompany(),
            user.getEmail(),
            user.getPhone(),
            user.getCountry()
        };
        
        writer.writeNext(fields);
    }
    try {
        writer.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    
}
        
]]&gt;
&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/5375460875594518061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/5375460875594518061' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5375460875594518061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5375460875594518061'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2011/11/exporting-generating-csv-files-in-java.html' title='Exporting / Generating CSV Files in Java'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-5934173709813827313</id><published>2011-11-11T14:50:00.001+05:30</published><updated>2011-11-11T16:03:25.429+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="SimpleDB"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring"/><title type='text'>Reading All Items from an Amazon SimpleDB Query Result</title><content type='html'>As you may have noticed select queries in SimpleDB  have a maximum limit to the number of results returned and you will have to use the &lt;i&gt;nextToken &lt;/i&gt;mechanism to get all results from a query. A solution was posted on &lt;a href=&quot;https://forums.aws.amazon.com/thread.jspa?threadID=74039&quot; target=&quot;_blank&quot;&gt;aws forum&lt;/a&gt; but since I have modified it a bit, thought I will post it here again.&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:java&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[
    protected AmazonSimpleDB sdb;

    @Autowired
    public void setSdb(AmazonSimpleDB sdb) {
        this.sdb = sdb;
    }

    protected List&lt;Item&gt; getItems(String query){
        logger.debug(&quot;Executing query: &quot; + query);
        List&lt;Item&gt; items  = new ArrayList&lt;Item&gt;();
        
        String nextToken = null;
        do{
            SelectRequest selectRequest = new SelectRequest(query);
            selectRequest.setConsistentRead(false);
   
            if(nextToken != null){
                selectRequest.setNextToken(nextToken);
            }
   
            SelectResult result = sdb.select(selectRequest); 
            items.addAll(result.getItems());
            nextToken = result.getNextToken();
   
        }while(nextToken != null);
        
        logger.debug(&quot;Found matching items: &quot; + items.size());
        return items;
    }

]]&gt;
&lt;/script&gt; 
&lt;br /&gt;
&lt;br /&gt;
The variable sdb is the AmazonSimpleDB implementation class which in my case is the AmazonSimpleDBClient initialized and injected using Spring. Following is the relevant Spring configuration section (I am initializing an AmazonS3Client too which is not required if you are only using SimpleDB).&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:xml&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[

&lt;context:property-placeholder location=&quot;classpath:aws.properties&quot; /&gt;
 
 &lt;bean id=&quot;awsCredentials&quot; class=&quot;com.amazonaws.auth.BasicAWSCredentials&quot;&gt;
  &lt;constructor-arg index=&quot;0&quot; value=&quot;${aws.id}&quot;/&gt;
  &lt;constructor-arg index=&quot;1&quot; value=&quot;${aws.secret}&quot;/&gt;
 &lt;/bean&gt;
 
 &lt;bean id=&quot;sdb&quot; class=&quot;com.amazonaws.services.simpledb.AmazonSimpleDBClient&quot;&gt;
  &lt;constructor-arg ref=&quot;awsCredentials&quot;&gt;&lt;/constructor-arg&gt;
 &lt;/bean&gt;
 
 &lt;bean id=&quot;s3client&quot; class=&quot;com.amazonaws.services.s3.AmazonS3Client&quot;&gt;
  &lt;constructor-arg ref=&quot;awsCredentials&quot;&gt;&lt;/constructor-arg&gt;
 &lt;/bean&gt;

]]&gt;
&lt;/script&gt; 
&lt;br /&gt;
AWS ID and Secret values are read from the aws.properties file in the classpath, which looks like below.&lt;br /&gt;
&lt;br /&gt;
&lt;script class=&quot;brush:java&quot; type=&quot;syntaxhighlighter&quot;&gt;
&lt;![CDATA[

aws.id=xxxxxxxxxxx
aws.secret=xxxxxxxxxxxxxxxxxxxxx

]]&gt;
&lt;/script&gt; 
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/5934173709813827313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/5934173709813827313' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5934173709813827313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5934173709813827313'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2011/11/reading-all-items-from-amazon-simpledb.html' title='Reading All Items from an Amazon SimpleDB Query Result'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-1743094113966329115</id><published>2007-12-07T18:08:00.000+05:30</published><updated>2007-12-07T19:28:00.502+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="jsf"/><category scheme="http://www.blogger.com/atom/ns#" term="potlet"/><title type='text'>Changing View JSP In doView Of A Portlet With JSF</title><content type='html'>I&#39;m playing around with JBoss portal server, Portlets and JSF these days and I had to change the view of a portlet when a value in database changed. The value is changed from another portlet and the portlet I was developing had to look for the change every time it was rendered and reset it self if the value had changed. Looked simple enough but I had to waste a good part of a day to find a good solution.&lt;br /&gt;&lt;br /&gt;I&#39;m new to all these technologies and depend on Google to find me solutions but I couldn&#39;t find anything that helped me to do this with Sun Reference Implementation of JSF. I found one that described how to do it in IBM implementation of JSF which obviously didn&#39;t work on Sun RI. The problem is you just can&#39;t redirect to a JSP in the doView method if you are using JSF. I tried to do it by overriding the doView method in FacesPortlet.&lt;br /&gt;&lt;br /&gt;Then I found &lt;a href=&quot;http://www.jsfcentral.com/listings/A92000?link&quot;&gt;this article on JSF Central&lt;/a&gt; which described how to redirect a user to a login page if the user is not logged in and that&#39;s exactly what I wanted. All I had to do was&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Write a PhaseListener and in the beforePhase method do my database check and set the view ID to my  start page view id if the value had changed.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Change the getPhaseId method to return PhaseId.RENDER_RESPONSE which makes the PhaseListner fire every time a page is rendered. The PhaseId.RESTORE_VIEW event is not fired every time a portlet is rendered.&lt;/li&gt;&lt;li&gt;Configure the PhaseListener in faces-config.xml&lt;/li&gt;&lt;/ol&gt;That was it, pretty easy and would have been if I knew a little bit more about JSF :)&lt;br /&gt;&lt;table border=&quot;1&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; width=&quot;100%&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;&lt;pre&gt;&lt;br /&gt;public class DBPhaseListener implements PhaseListener {&lt;br /&gt;&lt;br /&gt;  public void beforePhase(PhaseEvent event) {&lt;br /&gt;      FacesContext fc = event.getFacesContext();&lt;br /&gt;&lt;br /&gt;      System.out.println(&quot;Current View ID&quot; + fc.getViewRoot().getViewId());&lt;br /&gt;      if (changed()) {&lt;br /&gt;          System.out.println(&quot;Changing view&quot;);&lt;br /&gt;          NavigationHandler nh = fc.getApplication().getNavigationHandler();&lt;br /&gt;          nh.handleNavigation(fc, null, &quot;main&quot;);&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private boolean changed() {&lt;br /&gt;      // code to check db changes&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void afterPhase(PhaseEvent event) {&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public PhaseId getPhaseId() {&lt;br /&gt;      return PhaseId.RENDER_RESPONSE;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;And the faces-config.xml&lt;br /&gt;&lt;br /&gt; &lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:#3f7f7f;&quot;&gt;&lt;span style=&quot;color: rgb(63, 127, 127);font-family:&#39;Courier New&#39;;font-size:10;&quot;  &gt;faces-config&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:black;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:black;&quot;   &gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:#3f7f7f;&quot;&gt;&lt;span style=&quot;color: rgb(63, 127, 127);font-family:&#39;Courier New&#39;;font-size:10;&quot;  &gt;lifecycle&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:black;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:black;&quot;   &gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&lt;br /&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:#3f7f7f;&quot;&gt;&lt;span style=&quot;color: rgb(63, 127, 127);font-family:&#39;Courier New&#39;;font-size:10;&quot;  &gt;phase-listener&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:black;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:black;&quot;   &gt;com.test.DBPhaseListener&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;/&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:#3f7f7f;&quot;&gt;&lt;span style=&quot;color: rgb(63, 127, 127);font-family:&#39;Courier New&#39;;font-size:10;&quot;  &gt;phase-listener&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;/&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:#3f7f7f;&quot;&gt;&lt;span style=&quot;color: rgb(63, 127, 127);font-family:&#39;Courier New&#39;;font-size:10;&quot;  &gt;lifecycle&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&lt;br /&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;navigation-rule&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;from-view-id&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;/from-view-id&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;navigation-case&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;from-outcome&gt;main&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;/from-outcome&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;to-view-id&gt;/WEB-INF/jsp/index.jsp&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;/to-view-id&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;/navigation-case&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;/navigation-rule&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;             &lt;br /&gt;          &lt;span style=&quot;font-family:Courier New;font-size:85%;color:black;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:black;&quot;   &gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:#3f7f7f;&quot;&gt;&lt;span style=&quot;color: rgb(63, 127, 127);font-family:&#39;Courier New&#39;;font-size:10;&quot;  &gt;!-- rest of the faces-config --&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;&quot;  &gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;/&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:#3f7f7f;&quot;&gt;&lt;span style=&quot;color: rgb(63, 127, 127);font-family:&#39;Courier New&#39;;font-size:10;&quot;  &gt;faces-config&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family:Courier New;font-size:85%;color:teal;&quot;&gt;&lt;span style=&quot;;font-family:&#39;Courier New&#39;;font-size:10;color:teal;&quot;   &gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/1743094113966329115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/1743094113966329115' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/1743094113966329115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/1743094113966329115'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/12/changing-view-jsp-in-doview-of-portlet.html' title='Changing View JSP In doView Of A Portlet With JSF'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-5684124587870874354</id><published>2007-09-25T13:15:00.000+05:30</published><updated>2007-09-25T13:55:18.086+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="JUnit"/><category scheme="http://www.blogger.com/atom/ns#" term="struts"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Testing HTTPS Secured Actions with StrutsTestCase</title><content type='html'>If you have secured some Struts actions using SSLEXT&#39;s Struts plugin (org.apache.struts.action.SecurePlugIn) you will have to invoke the action over https, else SSLEXT will redirect to the configured HTTPS port.&lt;br /&gt;&lt;br /&gt;So in order to test secured actions using MockStruts test cases you need to inform SecurePlugIn that the request came over https. This is quite easy as the HttpServletRequestSimulator class that&#39;s used by MockStruts has a setScheme method. All you have to do is set the scheme to HTTPS in the inherited request object before calling the actionPerform method in the test class.&lt;br /&gt;&lt;br /&gt;e.g.&lt;br /&gt;&lt;br /&gt;&lt;table border=&quot;1&quot; width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td&gt;&lt;font color=&quot;#000000&quot;&gt;&lt;pre&gt;&lt;br /&gt;public class LoginTest extends MockStrutsTestCase {&lt;br /&gt;  public void testlogin() {&lt;br /&gt;     setConfigFile(&quot;/WEB-INF/struts-config.xml&quot;);&lt;br /&gt;     setRequestPathInfo(&quot;/login&quot;);&lt;br /&gt;     addRequestParameter(&quot;username&quot;, &quot;test&quot;);&lt;br /&gt;     addRequestParameter(&quot;password&quot;, &quot;test1234&quot;);&lt;br /&gt;&lt;br /&gt;     //set the request&#39;s scheme to HTTPS&lt;br /&gt;     request.setScheme(&quot;HTTPS&quot;);&lt;br /&gt;     //invoke action&lt;br /&gt;     actionPerform();&lt;br /&gt;     &lt;br /&gt;     verifyNoActionErrors();&lt;br /&gt;     verifyForward(&quot;success&quot;);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/5684124587870874354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/5684124587870874354' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5684124587870874354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5684124587870874354'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/09/testing-https-secured-actions-with.html' title='Testing HTTPS Secured Actions with StrutsTestCase'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-6895151643025392435</id><published>2007-09-07T16:22:00.000+05:30</published><updated>2007-09-07T16:22:03.888+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring"/><category scheme="http://www.blogger.com/atom/ns#" term="struts"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Speed up MockStruts Test Execution by Caching Spring Context</title><content type='html'>If you are using MockStruts to test your Struts/Spring application  most of your test execution time would be spent on initializing or trying to initialize the Spring context for each test method.&lt;br /&gt;&lt;br /&gt;This is true if you use Spring&#39;s ContextLoaderPlugIn, where it tries to initialize a custom spring context using the parent context.&lt;br /&gt;&lt;br /&gt;Spring will look for the parent context in the ServletContext object where it store it. Since MockStruts will create a new ServletContext  for each test method Spring will try to create the context each time.  This results  in addition of about 4 second per test method (on my workstation).&lt;br /&gt;&lt;br /&gt;Note: I&#39;m using MappingDispatchAction with multiple actions in a single Action class, therefore I have mutiple test methods in a single test class too.&lt;br /&gt;&lt;br /&gt;The above 4 second penalty per test method can be removed by simply caching and storing the Spring context in ServletContext object before each test execution. This reduced the execution time of the whole test suite drastically in the application I was working on.&lt;br /&gt;&lt;br /&gt;In order to achieve the above I used a base class extending MockStrutsTestCase as shown below and used it as the parent class for all the Struts test cases&lt;br /&gt;&lt;br /&gt;&lt;table border=&quot;1&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; width=&quot;100%&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;&lt;pre&gt;&lt;br /&gt;import org.springframework.context.ApplicationContext;&lt;br /&gt;import org.springframework.web.context.ContextLoader;&lt;br /&gt;import org.springframework.web.context.WebApplicationContext;&lt;br /&gt;import servletunit.struts.MockStrutsTestCase;&lt;br /&gt;&lt;br /&gt;public abstract class BaseStrutsTestCase extends MockStrutsTestCase {&lt;br /&gt;&lt;br /&gt;    /** Spring context */&lt;br /&gt;    private static ApplicationContext applicationContext;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Setup Spring context&lt;br /&gt;     * &lt;br /&gt;     * @throws Exception&lt;br /&gt;     *             exception&lt;br /&gt;     */&lt;br /&gt;    protected void setUp() throws Exception {&lt;br /&gt;        super.setUp();&lt;br /&gt;&lt;br /&gt;        if (applicationContext == null) {&lt;br /&gt;            // this is the first time. Initialize the Spring context.&lt;br /&gt;            applicationContext = (new ContextLoader()).initWebApplicationContext(getRequest().getSession()&lt;br /&gt;                    .getServletContext());&lt;br /&gt;        } else {&lt;br /&gt;            // Spring context is already initialized. Set it in servlet context&lt;br /&gt;            // so that Spring&#39;s ContextLoaderPlugIn will not initialize it again&lt;br /&gt;            getRequest().getSession().getServletContext().setAttribute(&lt;br /&gt;                    WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, applicationContext);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Returns the Spring application context&lt;br /&gt;     * &lt;br /&gt;     * @return initialized Spring application context&lt;br /&gt;     */&lt;br /&gt;    public ApplicationContext getApplicationContext() {&lt;br /&gt;        return applicationContext;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Also remember to set forkMode to perBatch or once in ants junit task as shown below if you have set the fork attribute to true.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;junit fork=&quot;true&quot; forkmode=&quot;once&quot; haltonfailure=&quot;&quot;&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&amp;lt;/junit&amp;gt;&lt;br /&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/6895151643025392435/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/6895151643025392435' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/6895151643025392435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/6895151643025392435'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/09/speed-up-mockstruts-test-execution-by.html' title='Speed up MockStruts Test Execution by Caching Spring Context'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-5757531884177113316</id><published>2007-08-08T14:48:00.000+05:30</published><updated>2007-08-08T17:43:10.450+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Hibernate"/><category scheme="http://www.blogger.com/atom/ns#" term="JUnit"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Unit Testing with Junit, Spring and Hibernate - Part 2</title><content type='html'>This is a continuation from my previous &lt;a href=&quot;http://livingtao.blogspot.com/2007/07/achieve-automatic-transaction-rollback.html&quot;&gt;post on Spring and MockStrutsTestCase&lt;/a&gt; and focus on testing Hibernate DAO&#39;s. As I mentioned in the previous post, Spring framework provides a nifty base class (AbstractTransactionalDataSourceSpringContextTests) that provides automatic transaction rollback, exposing a JDBC template to interact with the DB and auto wiring of beans.&lt;br /&gt;&lt;br /&gt;Lets take a simple DAO class that save a User object to the database:&lt;br /&gt;&lt;table border=&quot;1&quot; width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td&gt;&lt;font color=&quot;#000000&quot;&gt;&lt;pre&gt;&lt;br /&gt;public class UserDaoImpl extends HibernateDaoSupport implements UserDao {&lt;br /&gt;  public void save(User user) {&lt;br /&gt;      getHibernateTemplate().save(user);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;Now in order to test this you would write a test class as below extending from AbstractTransactionalDataSourceSpringContextTests class.&lt;br /&gt;&lt;br /&gt;&lt;table border=&quot;1&quot; width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td&gt;&lt;font color=&quot;#000000&quot;&gt;&lt;pre&gt;&lt;br /&gt;public class UserDaoTest extends AbstractTransactionalDataSourceSpringContextTests {&lt;br /&gt;  private UserDao userDao;&lt;br /&gt;  private SessionFactory sessionFactory = null;&lt;br /&gt;&lt;br /&gt;  protected String[] getConfigLocations() {&lt;br /&gt;      return new String[]{&quot;test-spring-config.xml&quot;};&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * Spring will automatically inject UserDao object on startup&lt;br /&gt;   * @param userDao&lt;br /&gt;   */&lt;br /&gt;  public void setUserDao(UserDao userDao) {&lt;br /&gt;      this.userDao = userDao;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * Spring will automatically inject the Hibernate session factory on startup&lt;br /&gt;   * @param sessionFactory&lt;br /&gt;   */&lt;br /&gt;  public void setSessionFactory(SessionFactory sessionFactory) {&lt;br /&gt;      this.sessionFactory = sessionFactory;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /**&lt;br /&gt;   * Test the save method&lt;br /&gt;   *&lt;br /&gt;   */&lt;br /&gt;  public void testSave(){&lt;br /&gt;      String query = &quot;select count(*) from user where first_name = &#39;Firstname&#39;&quot;;&lt;br /&gt;      int count = jdbcTemplate.queryForInt(query);&lt;br /&gt;      assertEquals(&quot;A user already exists in the DB&quot;, 0, count);&lt;br /&gt;    &lt;br /&gt;      User user = new User();&lt;br /&gt;      user.setFirstName(&quot;Firstname&quot;);&lt;br /&gt;    &lt;br /&gt;      userDao.saveUser(user);&lt;br /&gt;    &lt;br /&gt;      // flush the session so we can get the record using JDBC template&lt;br /&gt;      SessionFactoryUtils.getSession(sessionFactory, false).flush();&lt;br /&gt;    &lt;br /&gt;      count = jdbcTemplate.queryForInt(query);&lt;br /&gt;      assertEquals(&quot;User was not found in the DB&quot;, 1, count);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;The test class has to implement the protected String[] getConfigLocations() method from the base class and return a String array of Spring config files which will be used to initialize the Spring context.&lt;br /&gt;&lt;br /&gt;UserDao and SessionFactory properties are defined with the setter methods and the base class will take care of injecting them automatically from the Spring context. Auto wiring will not work if there are multiple objects implementing the same interface. In such a case you can remove the setter method and retrieve the object using the exposed applicationContext as below.&lt;br /&gt;&lt;br /&gt;&lt;table border=&quot;1&quot; width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td&gt;&lt;font color=&quot;#000000&quot;&gt;&lt;pre&gt;   /**&lt;br /&gt;   * Overridden method from base class which gets called automatically&lt;br /&gt;   */&lt;br /&gt;  protected void onSetUpBeforeTransaction() throws Exception {&lt;br /&gt;      super.onSetUpBeforeTransaction();&lt;br /&gt;      userDao = (UserDao) applicationContext.getBean(&quot;userDao&quot;);&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;The base class also exposes a JDBC template object (jdbcTemplate) that can be used to query data or setup test data in the database. Note that you need to have a data source and a transaction manager defined in your Spring config in order to use the AbstractTransactionalDataSourceSpringContextTests base class. The data source defined in the config file will be bound to the exposed JDBC template.&lt;br /&gt;&lt;br /&gt;In the testSave method first we verify there is no record in the User table where first name equals to &#39;Firstname&#39; using the jdbc template object. Then we call the save method on the UserDao passing it a User object.&lt;br /&gt;&lt;br /&gt;Now we simple verify there is a record in the table where first name equals to &#39;Firstname&#39;. Before running the query we flush the current Hibernate session to make sure jdbcTemplate can see the newly added record.&lt;br /&gt;&lt;br /&gt;Thats it and when the testSave method exits the current transaction will be rolled back and the record inserted to the User table will not be saved. This is great as your test database will always be at a know state at the start and end of a test method.&lt;br /&gt;&lt;br /&gt;The spring config file will like below (test-spring-config.xml) :&lt;br /&gt;&lt;br /&gt;&lt;table border=&quot;1&quot; width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td&gt;&lt;font color=&quot;#000000&quot;&gt;&lt;pre&gt;&amp;lt;!DOCTYPE beans PUBLIC &amp;quot;-//SPRING//DTD BEAN//EN&amp;quot; &amp;quot;http://www.springframework.org/dtd/spring-beans.dtd&amp;quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;beans&amp;gt;  &lt;br /&gt;    &amp;lt;bean name=&amp;quot;userDao&amp;quot; class=&amp;quot;com.dao.UserDaoImpl&amp;quot;&amp;gt;&lt;br /&gt;       &amp;lt;property name=&amp;quot;sessionFactory&amp;quot;&amp;gt;&lt;br /&gt;           &amp;lt;ref bean=&amp;quot;sessionFactory&amp;quot;/&amp;gt;&lt;br /&gt;       &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/bean&amp;gt;&lt;br /&gt; &lt;br /&gt;    &amp;lt;bean id=&amp;quot;sessionFactory&amp;quot; class=&amp;quot;org.springframework.orm.hibernate3.LocalSessionFactoryBean&amp;quot;&amp;gt;&lt;br /&gt;       &amp;lt;property name=&amp;quot;dataSource&amp;quot;&amp;gt;&lt;br /&gt;           &amp;lt;ref bean=&amp;quot;dataSource&amp;quot;/&amp;gt;&lt;br /&gt;       &amp;lt;/property&amp;gt;&lt;br /&gt;       &amp;lt;property name=&amp;quot;mappingResources&amp;quot;&amp;gt;&lt;br /&gt;           &amp;lt;list&amp;gt;&lt;br /&gt;               &amp;lt;value&amp;gt;hibernates/User.hbm.xml&amp;lt;/value&amp;gt;&lt;br /&gt;           &amp;lt;/list&amp;gt;&lt;br /&gt;       &amp;lt;/property&amp;gt;&lt;br /&gt;       &amp;lt;property name=&amp;quot;hibernateProperties&amp;quot;&amp;gt;&lt;br /&gt;           &amp;lt;props&amp;gt;&lt;br /&gt;               &amp;lt;prop key=&amp;quot;hibernate.query.factory_class&amp;quot;&amp;gt;org.hibernate.hql.classic.ClassicQueryTranslatorFactory&amp;lt;/prop&amp;gt;&lt;br /&gt;               &amp;lt;prop key=&amp;quot;hibernate.dialect&amp;quot;&amp;gt;org.hibernate.dialect.OracleDialect&amp;lt;/prop&amp;gt;&lt;br /&gt;           &amp;lt;/props&amp;gt;&lt;br /&gt;      &amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/bean&amp;gt;&lt;br /&gt;  &lt;br /&gt;&lt;br /&gt;    &amp;lt;bean id=&amp;quot;dataSource&amp;quot; class=&amp;quot;org.apache.commons.dbcp.BasicDataSource&amp;quot; destroy-method=&amp;quot;close&amp;quot;&amp;gt;&lt;br /&gt;       &amp;lt;property name=&amp;quot;driverClassName&amp;quot; value=&amp;quot;oracle.jdbc.driver.OracleDriver&amp;quot;/&amp;gt;&lt;br /&gt;       &amp;lt;property name=&amp;quot;url&amp;quot; value=&amp;quot;jdbc:oracle:thin:@localhost:1521:ORCL&amp;quot; /&amp;gt;&lt;br /&gt;       &amp;lt;property name=&amp;quot;username&amp;quot; value=&amp;quot;test&amp;quot; /&amp;gt;&lt;br /&gt;       &amp;lt;property name=&amp;quot;password&amp;quot; value=&amp;quot;test&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;/bean&amp;gt;&lt;br /&gt;    &lt;br /&gt;&lt;br /&gt;    &amp;lt;bean id=&amp;quot;txManager&amp;quot; class=&amp;quot;org.springframework.orm.hibernate3.HibernateTransactionManager&amp;quot;&amp;gt;&lt;br /&gt;       &amp;lt;property name=&amp;quot;sessionFactory&amp;quot;&amp;gt;&amp;lt;ref local=&amp;quot;sessionFactory&amp;quot;/&amp;gt;&amp;lt;/property&amp;gt;&lt;br /&gt;    &amp;lt;/bean&amp;gt;&lt;br /&gt;   &lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/5757531884177113316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/5757531884177113316' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5757531884177113316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5757531884177113316'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/08/unit-testing-with-junit-spring-and.html' title='Unit Testing with Junit, Spring and Hibernate - Part 2'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-2954136377461407110</id><published>2007-07-27T14:24:00.000+05:30</published><updated>2007-07-27T17:38:52.385+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><title type='text'>How to Properly Iterate a Collection in Java</title><content type='html'>There are multiple ways to iterate a collection in Java among many other things but that doesn&#39;t mean all are equally elegant or easy on the eyes. Just as some ways to skin a cat are messier than others (Not that I have ever skinned a cat or any other animal for that matter). Anyhoo I&#39;m making this post in hopes of at least few developers starting on Java will see it before starting to write code in a commercial project.&lt;br /&gt;&lt;br /&gt;I came across a code base of a project that was developed mostly by a bunch of junior developers and most of the code that iterates a collection was in the following format&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;List administrators = getAdministrators();&lt;br /&gt;&lt;br /&gt;if (administrators.size() &gt; 0) {&lt;br /&gt;    Iterator administratorsItr = administrators.iterator();&lt;br /&gt;       Administrator administrator = null;&lt;br /&gt;       while (administratorsItr.hasNext()) {&lt;br /&gt;          administrator = (Administrator) administratorsItr.next();&lt;br /&gt;          //rest of the code block removed&lt;br /&gt;       }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Just looking at that piece of code made my head spin :). The worst part was that this is the style most of the junior developers had adopted and could be seen all over the code base.&lt;br /&gt;&lt;br /&gt;Just for the record I would have written it in the following way (actually would have let the IDE write it for me)&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;List administrators = getAdministrators();&lt;br /&gt;&lt;br /&gt;for (Iterator iter = administrators.iterator(); iter.hasNext();) {&lt;br /&gt;   Administrator administrator = (Administrator) iter.next();&lt;br /&gt;   //rest of the code block removed&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;The above two code blocks achieve the same thing, the difference been, first is 9 lines long and the second is 4 lines. Most importantly you can figure out whats going on easily by looking at the second code block.&lt;br /&gt;&lt;br /&gt;The worst part is IDEs like IntelliJ IDEA will write it for you. All you have to do is type &lt;span style=&quot;font-weight: bold;&quot;&gt;itco&lt;/span&gt; and press ctrl + space keys just after the &lt;span style=&quot;font-style: italic;&quot;&gt;List administrators = ... &lt;/span&gt;line.&lt;br /&gt;&lt;br /&gt;I don&#39;t know if there is something similar on Eclipse but you can import all these nifty IDEA Live Templates into Eclipse. Just head over to &lt;a href=&quot;http://www.thekua.com/rant/2005/11/29/intellij-live-templates-for-eclipse/&quot;&gt;this page&lt;/a&gt; where you can find the xml file and instructions on how to import the file.</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/2954136377461407110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/2954136377461407110' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/2954136377461407110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/2954136377461407110'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/07/how-to-properly-iterate-collection-in.html' title='How to Properly Iterate a Collection in Java'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-5075506333248450153</id><published>2007-07-17T16:29:00.000+05:30</published><updated>2007-07-18T14:40:52.264+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="JUnit"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Achieve Automatic Transaction Rollback with MockStrutsTestCase and Spring</title><content type='html'>Spring provides a convenience base class (&lt;a target=&quot;_blank&quot; href=&quot;http://static.springframework.org/spring/docs/1.2.x/reference/testing.html#d0e15735&quot;&gt;AbstractTransactionalDataSourceSpringContextTests &lt;/a&gt;which extends the TestCase class from Junit) to automatically rollback any updates made to the database at the end of a test method. This works great when integration testing Service and DAO beans but it wont help when integration testing the Struts layer with MockStrutsTestCase.&lt;br /&gt;&lt;br /&gt;Spring does not provide a class such as AbstractTransactionalDataSourceSpringContextTests that extends from the MockStrutsTestCase. This might be due to practical issues with the way Spring context initialization works when using MockStrutsTestCase. I tried achieving the transaction rollback in the same way as was done in the AbstractTransactionalDataSourceSpringContextTests class but it didn&#39;t work out as the application code started a new transaction and commited as usual without using the transaction I started in my own subclass of MockStrutsTestCase.&lt;br /&gt;&lt;br /&gt;Another option left for me was to go down to the Transaction Manager level and achieve the rollbacks there. The application uses Hibernate at the DAO level and it was using  &lt;a target=&quot;_blank&quot;  href=&quot;http://www.springframework.org/docs/api/org/springframework/orm/hibernate3/HibernateTransactionManager.html&quot;&gt;HibernateTransactionManager&lt;/a&gt;  as the transaction manager implementation when running test cases . Therefore I had to write a new class extending from HibernateTransactionManager which overrides  the doCommit() method.  The overridden method will call doRollback() method in the super class.  This would rollback the current running transaction even if the declarative transaction handling code in Spring calls doCommit  on the transaction manager.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package com.xyz.txn;&lt;br /&gt;&lt;br /&gt;import org.springframework.orm.hibernate3.HibernateTransactionManager;&lt;br /&gt;&lt;br /&gt;public class HibernateRollbackTxnManager extends HibernateTransactionManager {&lt;br /&gt;&lt;br /&gt; /*&lt;br /&gt;  * doCommit method that calls the doRollback method of the super class.&lt;br /&gt;  *&lt;br /&gt;  */&lt;br /&gt; protected void doCommit(DefaultTransactionStatus txnStatus) {&lt;br /&gt;     super.doRollback(txnStatus);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally override the default transaction manager in your test spring bean configuration with the rollback only implementation.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;bean id=&quot;txnManager&quot; class=&quot;com.com.xyz.txn.HibernateRollbackTxnManager&quot;&amp;gt;&lt;br /&gt;      &amp;lt;property name=&quot;sessionFactory&quot;&amp;gt;&amp;lt;ref local=&quot;sessionFactory&quot;&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;  &amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The same strategy would work with other transaction managers such as &lt;a target=&quot;_blank&quot;  href=&quot;http://www.springframework.org/docs/api/org/springframework/jdbc/datasource/DataSourceTransactionManager.html&quot;&gt;DataSourceTransactionManager&lt;/a&gt; too.</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/5075506333248450153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/5075506333248450153' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5075506333248450153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5075506333248450153'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/07/achieve-automatic-transaction-rollback.html' title='Achieve Automatic Transaction Rollback with MockStrutsTestCase and Spring'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-6791032050473732188</id><published>2007-06-25T10:45:00.000+05:30</published><updated>2007-06-25T17:25:41.804+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="ant"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Save Time Fixing Ant Errors With -verbose Switch</title><content type='html'>Resolving ant errors can be a pain sometimes because of the vague error messages you get on the console. Yesterday I was getting a &quot;Process fork failed.&quot; error on my Junit task and all I got on the console was&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;BUILD FAILED&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;C:\work\builds\build.xml:58: Process fork failed.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I wasted a couple of hours on google looking for an answer and after failing to fix the issue with several suggested solutions, I stumbled upon one post that suggested enabling the verbose output of Ant. All you had to do was pass -verbose as a command line parameter to ant&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;ant -verbose &amp;lt;target&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;That made ant display lot of details including the actual exception. In my case it was:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;C:\work\build\build.xml:58: Process fork failed.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeAsForked(JUnitTask.java:871)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:679)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.executeOrQueue(JUnitTask.java:1413)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.taskdefs.optional.junit.JUnitTask.execute(JUnitTask.java:633)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.Task.perform(Task.java:364)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.Target.execute(Target.java:341)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.Target.performTasks(Target.java:369)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1216)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.Project.executeTarget(Project.java:1185)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:40)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.Project.executeTargets(Project.java:1068)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.Main.runBuild(Main.java:668)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.Main.startAnt(Main.java:187)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.launch.Launcher.run(Launcher.java:246)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt;    at org.apache.tools.ant.launch.Launcher.main(Launcher.java:67)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold; font-family: courier new;font-size:85%;&quot; &gt;Caused by: java.io.IOException: CreateProcess: C:\bea92\jdk150_04\jre\bin\java.exe&lt;/span&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family: courier new;&quot;&gt; ...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I found the issue a little bit above the exception on the console and it was the massive classpath value passed into the java.exe. Obviously the Windows command line has a limitation on the length of command line arguments and the value for classpath was exceeding it.&lt;br /&gt;&lt;br /&gt;When I checked the build file I found the error, where it was adding the files in a directory instead of the directory into the classpath. Fixed that small error and all was fine again.&lt;br /&gt;&lt;br /&gt;Anyway glad I got to know about the verbose switch in Ant and hopefully I wouldn&#39;t have to waste a lot of time again fixing ant issues again.</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/6791032050473732188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/6791032050473732188' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/6791032050473732188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/6791032050473732188'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/06/save-time-fixing-ant-errors-with.html' title='Save Time Fixing Ant Errors With -verbose Switch'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-1061096720340230188</id><published>2007-06-12T09:57:00.000+05:30</published><updated>2007-06-12T14:35:23.043+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jdbc"/><title type='text'>Why would anyone want to buy a commercial JDBC driver?</title><content type='html'>In all the projects that I worked on over the last 5 to 6 years, nobody even thought about using a commercial JDBC driver. When I started on J2EE development you had to buy a JDBC driver for MS SQL server. This was around 2000-2001 when Microsoft didn&#39;t have an implementation.&lt;br /&gt;&lt;br /&gt;We bought a driver from i-net software (Opta if I remember correctly) which I guess was the best commercial driver available at that time. Later on the application was ported to Oracle and we were happy to use the Oracle thin driver instead of bothering to buy another commercial implementation.&lt;br /&gt;&lt;br /&gt;Since then I have worked for several big enterprise clients, developing Java web applications that connected to Oracle, MS SQL Server and DB2 (ver 7.2) databases. All these applications were using the database vendor provided drivers and all was well except for the DB2 driver (net driver).&lt;br /&gt;&lt;br /&gt;I used to visit i-net software web site frequently as their Crystal Clear reporting tool was used in some earlier projects. Today I stumbled upon their site again after a long time and I started wondering why no one even considers using commercial drivers anymore including myself.&lt;br /&gt;&lt;br /&gt;I could think up of a few possible reasons to shell out few bucks for a JDBC driver.&lt;br /&gt;&lt;br /&gt;1. Performance&lt;br /&gt;2. Reliability&lt;br /&gt;3. Available features (JDBC 3.0, XA support etc...)&lt;br /&gt;&lt;br /&gt;Now if we take Oracle thin driver and the above list, I don&#39;t see how a third party driver can provide significant performance and reliability over the thin driver.&lt;br /&gt;&lt;br /&gt;As for features, thin driver has every thing you would need on an average project. Commercial implementations usually have few additional bells and whistles (e.g. i-net Opta driver supports SSL encryption and implements JDBC 4.0 API) which usually are not that important.&lt;br /&gt;&lt;br /&gt;I guess same could be said for the SQL Server drivers from Microsoft  and hopefully the new DB2   drivers from IBM,  that is they does the job for your average project.&lt;br /&gt;&lt;br /&gt;Also given the fact that application servers like BEA Weblogic includes its own drivers for all major databases including SQL Server, DB2, Sybase and Informix, I really don&#39;t see a reason to buy a JDBC driver from a third party.&lt;br /&gt;&lt;br /&gt;Having said that, I would love to know about instances where a commercial driver was used and the reasons behind it.&lt;br /&gt;&lt;br /&gt;P.S. Elaborating on the issue with the older DB2 driver:&lt;br /&gt;&lt;br /&gt;DB2 v7.2 didn&#39;t come with a type 4 JDBC driver and we had to use what was called the net driver. There was this funny problem where it failed to see some records in a table. Select queries would not return these records when connected through the net driver. We never figured out why and only solution was to delete the record and insert them back. Luckily for us it only happened in the QA server :). Anyhoo the database was upgraded to DB2 version 8 and the driver to the type 4 version that came with it.</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/1061096720340230188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/1061096720340230188' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/1061096720340230188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/1061096720340230188'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/06/why-would-anyone-want-to-buy-commercial.html' title='Why would anyone want to buy a commercial JDBC driver?'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-3209909426154099034</id><published>2007-05-29T15:58:00.001+05:30</published><updated>2007-07-03T10:40:34.037+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><title type='text'>Myth - Defining loop variables inside the loop is bad for performance</title><content type='html'>&lt;p class=&quot;MsoNormal&quot;&gt;I like to define loop variables inside the loop on the line where the assignment is happening. For example if I was iterating through a String collection I would do it like below&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;private void test() {&lt;br /&gt;   for (Iterator iter = list.iterator(); iter.hasNext();) {&lt;br /&gt;       String str = (String) iter.next();&lt;br /&gt;       System.out.println(str);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;&lt;br /&gt;The other day a colleague of mine was doing a peer review and he said this was bad and I should have defined the String variable str outside the loop. What he suggested was something like below.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private void test() {&lt;br /&gt;   String str;&lt;br /&gt;   for (Iterator iter = list.iterator(); iter.hasNext();) {&lt;br /&gt;       str = (String) iter.next();&lt;br /&gt;       System.out.println(str);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When I questioned the logic behind it he said something like&lt;o:p&gt;:&lt;br /&gt;&lt;br /&gt;&lt;/o:p&gt;    &lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;If you define str inside the loop it will get initialized in each iteration and that’s bad for performance.&lt;/span&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Or something like that… and so the argument started. I mean str is a frigging variable not an object that would get initialized or anything. The compiler wouldn’t go allocating memory to str in each iteration and my belief was that it didn’t matter whether you declare str inside the loop or outside the loop. The compiler wouldn’t care and would generate the same byte code in either case.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p class=&quot;MsoNormal&quot;&gt;I did some googling around and came across this &lt;a href=&quot;http://weblogs.java.net/blog/ddevore/archive/2006/08/declare_variabl_1.html&quot;&gt;blog &lt;/a&gt;which discusses the same thing though his preference was to declare the variable outside the loop. The first example was very similar to what I had in mind but it was with primitives. The second example with StringBuffer is a totally different story from mine.&lt;br /&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;So I had to do my own test, I wrote another class with the str declared outside the loop and compiled them both. Then using javap utility that comes with the JDK printed the byte code for both implementations (ie. javap –c –private &amp;lt;classname&amp;gt;)&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Byte Code genarated when the variable is declared inside the loop:&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;private void test();&lt;br /&gt;Code:&lt;br /&gt;0:   aload_0&lt;br /&gt;1:   getfield        #15;&lt;br /&gt;4:   invokevirtual   #22;&lt;br /&gt;7:   astore_1&lt;br /&gt;8:   goto    28&lt;br /&gt;11:  aload_1&lt;br /&gt;12:  invokeinterface #26,&lt;br /&gt;17:  checkcast       #32;&lt;br /&gt;20:  astore_2&lt;br /&gt;21:  getstatic       #34;&lt;br /&gt;24:  aload_2&lt;br /&gt;25:  invokevirtual   #40;&lt;br /&gt;28:  aload_1&lt;br /&gt;29:  invokeinterface #46,&lt;br /&gt;34:  ifne    11&lt;br /&gt;37:  return&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;Byte Code genarated when the variable is declared outside the loop:&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;private void test();&lt;br /&gt;Code:&lt;br /&gt;0:   aload_0&lt;br /&gt;1:   getfield        #15;&lt;br /&gt;4:   invokevirtual   #22;&lt;br /&gt;7:   astore_2&lt;br /&gt;8:   goto    28&lt;br /&gt;11:  aload_2&lt;br /&gt;12:  invokeinterface #26,&lt;br /&gt;17:  checkcast       #32;&lt;br /&gt;20:  astore_1&lt;br /&gt;21:  getstatic       #34;&lt;br /&gt;24:  aload_1&lt;br /&gt;25:  invokevirtual   #40;&lt;br /&gt;28:  aload_2&lt;br /&gt;29:  invokeinterface #46,&lt;br /&gt;34:  ifne    11&lt;br /&gt;37:  return&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;Basically it’s the same byte code except the variable numbers are switched (ie. line 11 aload_1 become aload_2). So it really doesn&#39;t make a difference and where you declare the variable is a just a matter of taste.&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;&quot;&gt; &lt;/span&gt;&lt;/p&gt;&lt;a href=&quot;http://www.dzone.com/links/java_myth_defining_loop_variables_inside_the_loop.html&quot;&gt; &lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/3209909426154099034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/3209909426154099034' title='137 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/3209909426154099034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/3209909426154099034'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/05/myth-defining-loop-variables-inside.html' title='Myth - Defining loop variables inside the loop is bad for performance'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>137</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-495275164041025855</id><published>2007-05-24T13:26:00.000+05:30</published><updated>2007-05-24T14:37:51.420+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="weblogs api"/><category scheme="http://www.blogger.com/atom/ns#" term="xml-rpc"/><title type='text'>How to notify JavaBlogs.com about blog updates with XML-RPC</title><content type='html'>Javablogs supports notification of blog updates with a remote API, which enables new blog post to appear on Javablogs immediately (&lt;a href=&quot;http://www.javablogs.com/api.jsp&quot;&gt;javablogs API&lt;/a&gt;). I use blogger and as far as I can tell it doesn&#39;t support pinging javablogs.com. So i set out to write my own XML-RPC client to make my posts appear quickly (Yes I&#39;m the impatient type).&lt;br /&gt;&lt;br /&gt;Did a search for XML-RPC clients on the web and I found this open source Java library from &lt;a href=&quot;http://xmlrpc.sourceforge.net/&quot;&gt;Redstone&lt;/a&gt;. Downloaded the jar file and followed the instructions on Redstone page and the page describing the &lt;a href=&quot;http://www.xmlrpc.com/weblogsCom&quot;&gt;Weblogs API&lt;/a&gt;. I have to say when I started on this I didn&#39;t think it would be this easy but after about 10 minutes I had it working :).&lt;br /&gt;&lt;br /&gt;Just add the following lines inside a main method and execute:&lt;br /&gt;&lt;div class=&quot;java&quot; align=&quot;left&quot;&gt;&lt;table bg=&quot;&quot; style=&quot;color: rgb(255, 255, 255);&quot; border=&quot;0&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;   &lt;tbody&gt;&lt;tr&gt;&lt;br /&gt;&lt;!-- start source code --&gt;&lt;br /&gt;&lt;td align=&quot;left&quot; valign=&quot;top&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;String weblogName = &lt;/span&gt;&lt;span style=&quot;color: rgb(42, 0, 255);&quot;&gt;&quot;Living Tao&quot;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;String weblogUrl = &lt;/span&gt;&lt;span style=&quot;color: rgb(42, 0, 255);&quot;&gt;&quot;http://livingtao.blogspot.com/&quot;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(63, 127, 95);&quot;&gt;//create a client pointing to the rpc service on javablogs&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;XmlRpcClient client = &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;new &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;XmlRpcClient&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(42, 0, 255);&quot;&gt;&quot;http://javablogs.com/xmlrpc&quot;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;true&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(63, 127, 95);&quot;&gt;//invoke the method to queue the blog for an update&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;Object token = client.invoke&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(42, 0, 255);&quot;&gt;&quot;weblogUpdates.ping&quot;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;new &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;[] { &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;weblogName, weblogUrl&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;} )&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;System.out.println&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;token&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;/code&gt;   &lt;/td&gt;&lt;br /&gt;&lt;!-- end source code --&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The code will out put the following result on successful execution:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;{flError=0, message=Success. 1 blogs have been queued for update}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/495275164041025855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/495275164041025855' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/495275164041025855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/495275164041025855'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/05/how-to-notify-javablogscom-about-blog.html' title='How to notify JavaBlogs.com about blog updates with XML-RPC'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-1978134318107507540</id><published>2007-05-23T17:04:00.000+05:30</published><updated>2007-05-23T18:08:25.301+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><title type='text'>final - Least used keyword in Java development?</title><content type='html'>I&#39;ve been writing Java code for a long time and I never thought about making a class or a method final until recently. Actually the only place the final keyword was used was when declaring constants. I still don&#39;t think you will gain much on performance by using final but the biggest selling point is the correctness it brings to the code.&lt;br /&gt;&lt;br /&gt;So far our development team has not looked at the correct usage of final keyword during peer reviews, but going forward it will be added to the peer review guideline document. Hope I&#39;ll see more finals in our code after that [if anyone follows the guideline that is :) ]&lt;br /&gt;&lt;br /&gt;Anyway here is a link to a good explanation on final keyword: &lt;a href=&quot;http://renaud.waldura.com/doc/java/final-keyword.shtml&quot;&gt;The Final Word on the final Keyword&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/1978134318107507540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/1978134318107507540' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/1978134318107507540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/1978134318107507540'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/05/final-least-used-keyword-in-java.html' title='final - Least used keyword in Java development?'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-8280650000404473926</id><published>2007-05-21T16:02:00.000+05:30</published><updated>2007-05-21T16:59:33.425+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="apache james"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Testing application generated emails with Apache James server</title><content type='html'>Most of our applications send out emails to customers, different groups of people within the organization etc... Most of these emails were in HTML and had all sorts of fancy formatting in them. It was a pain developing and testing these emails and they took too much developer time.&lt;br /&gt;&lt;br /&gt;We needed an easy way to test them locally in developer machines without using an external SMTP server.&lt;br /&gt;&lt;br /&gt;The plan was to run a James server in every developer machine which forwarded all the emails it receives to an email account on the same server.&lt;br /&gt;&lt;br /&gt;Following were the steps followed to achieve this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1. Download and Run James Server&lt;br /&gt;&lt;br /&gt;Downloaded the latest zip bundle from apache site (ver 2.3.1). Extracted to a folder and executed run.bat in the bin directory to start the server for the first time. This will extract the james.sar file in apps directory to the apps/james directory. Now you will be able to modify the configuration file (config.xml) in apps/james/SAR-INF.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2. Create a local email account.&lt;br /&gt;&lt;br /&gt;Open a command window and type &lt;span style=&quot;font-family:courier new;&quot;&gt;telnet localhost 4555&lt;/span&gt;. When asked for the user name and password type &lt;span style=&quot;font-family:courier new;&quot;&gt;root &lt;/span&gt;for both. Now you will be in the admin console and create a email account by typing &lt;span style=&quot;font-family:courier new;&quot;&gt;adduser test test&lt;/span&gt;. This will create an email account named test with the password set to test.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;3. Delete remote delivery mailet.&lt;br /&gt;&lt;br /&gt;Open up the config.xml and locate the RemoteDelivery mailet section &lt;span style=&quot;font-family:courier new;&quot;&gt;&amp;lt;mailet match=&quot;All&quot; class=&quot;RemoteDelivery&quot;&amp;gt;...&amp;lt;/mailet&amp;gt;&lt;/span&gt; and remove the tag including all its content.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;4. Add a forward mailet to forward all mails&lt;br /&gt;&lt;br /&gt;Insert the following mailet in the place where the RemoteDelivery mailet was.&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&amp;lt;mailet match=&quot;All&quot; class=&quot;Forward&quot;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;    &amp;lt;forwardto&amp;gt;test@localhost&amp;lt;/forwardto&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;&amp;lt;/mailet&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;5. Save config.xml and Restart the James Server&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now all emails generated by the application (which is configured to use the SMTP server on localhost) will be handled by the James server running in the local machine and it will forward all emails to the test@localhost email account regardless of recipient addresses in email messages.&lt;br /&gt;&lt;br /&gt;You can configure Outlook Express or any other client to read the mails sent to test@localhost.</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/8280650000404473926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/8280650000404473926' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/8280650000404473926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/8280650000404473926'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/05/testing-application-generated-emails.html' title='Testing application generated emails with Apache James server'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-1675567602817761029</id><published>2007-05-18T17:08:00.001+05:30</published><updated>2007-05-18T18:12:54.557+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="Logging"/><title type='text'>When to call isDebugEnabled() before writing debug messages</title><content type='html'>When using a logging framework like log4j most developers never check whether debug is enabled before writing a debug message or always makes the check. The theory behind it is to prevent unnecessary string concatenations if debug messages are disabled, which is the case most of the times on production environments.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;java&quot;&gt;&lt;code class=&quot;java&quot;&gt;&lt;span class=&quot;java10&quot;&gt;logger.debug&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;java5&quot;&gt;&quot;Saved order successfully. Order ID : &quot; &lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;+ order.getId&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;() +&lt;br /&gt;&quot; items in order &quot; + order.getItems().size())&lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;br /&gt;In the above case there is a new string object created by concatenating all the parameters before making the call to debug method. This is done regardless of debug is enabled or not which will be a unnecessary performance overhead if debug is disabled.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;java&quot;&gt;&lt;code class=&quot;java&quot;&gt;&lt;span class=&quot;java4&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;    logger.isDebugEnabled&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;()){&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;    logger.debug&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;java5&quot;&gt;&quot;Before saving the order&quot;&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;br /&gt;In the above code section the if condition is not necessary as there is no String concatenations involved and ends up adding two redundant lines of code.&lt;br /&gt;&lt;br /&gt;Therefore the rule would be to do a isDebugEnabled check only if there is any String concatenation involved in the call to debug. This seems to be obvious but developers somehow keep getting this wrong.</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/1675567602817761029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/1675567602817761029' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/1675567602817761029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/1675567602817761029'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/05/when-to-call-isdebugenabled-before.html' title='When to call isDebugEnabled() before writing debug messages'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-5527200108255004438</id><published>2007-05-18T12:13:00.000+05:30</published><updated>2007-05-22T12:33:02.830+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="Logging"/><title type='text'>Reduce logger initialization code in your Java applications</title><content type='html'>You might have logger initialization code in most of the classes in an application (e.g. Action, Service and DAO classes). This is actually unnecessary if these types of classes extend from your own base classes.&lt;br /&gt;&lt;br /&gt;An application using log4j  logging framework will  initialize the logger in a class as&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;java&quot;&gt;&lt;code class=&quot;java&quot;&gt;&lt;span class=&quot;java4&quot;&gt;private static final &lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;Logger logger = Logger.getInstance&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;TestAction.getClass&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;br /&gt;This is done in each and every class which needs to use a logger. Now if we use a base class for lets say all Struts Actions called BaseAction, it can contain the logger initialization code as below.&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;java&quot;&gt;&lt;code class=&quot;java&quot;&gt;&lt;span class=&quot;java4&quot;&gt;package &lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;com.test.web;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;java4&quot;&gt;import &lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;org.apache.log4j.Logger;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;java4&quot;&gt;import &lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;org.apache.struts.action.Action;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;java4&quot;&gt;public abstract class &lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;BaseAction &lt;/span&gt;&lt;span class=&quot;java4&quot;&gt;extends &lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;Action&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;java3&quot;&gt;//initializes the logger object&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;java4&quot;&gt;protected final &lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;Logger logger = Logger.getInstance&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;java4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;.getClass&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;java10&quot;&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;java8&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now all sub classes that extends from BaseAction (implementation action classes) will have the logger object created on initialization with the proper class name. Even though in theory this creates a new logger object per instance of TestAction class, it wont be an issue since Struts will maintain only a single instance of TestAction to serve all requests mapped to it.&lt;br /&gt;&lt;br /&gt;This could be applied to all Service, DAO classes as well if you are using a framework like Spring to manage them, where only one instance per implementation class will be created.&lt;br /&gt;&lt;br /&gt;P.S. This post was modified as per comments by fabien...</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/5527200108255004438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/5527200108255004438' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5527200108255004438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/5527200108255004438'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/05/reduce-logger-initialization-code-from.html' title='Reduce logger initialization code in your Java applications'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4435599137875974089.post-9197806388998808917</id><published>2007-05-17T15:39:00.000+05:30</published><updated>2007-08-30T18:14:35.825+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="struts"/><category scheme="http://www.blogger.com/atom/ns#" term="tiles"/><title type='text'>Global Exception Handling for Struts and Tiles Applications</title><content type='html'>&lt;style type=&quot;text/css&quot;&gt;&lt;br /&gt;    &lt;!--code { font-family: Courier New, Courier; font-size: 10pt; margin: 0px; }--&gt;&lt;br /&gt;&lt;/style&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);font-size:100%;&quot; &gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Update: The solution explained in this post has been tested only on Weblogic 8.1 and 9.2. On Tomcat 5.x this will not work and please post a comment with the results if you happen to test this on any other server or find a work around for the Tomcat issue.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I was looking at implementing a global error page for unhandled exceptions in a Struts / Tiles application. Normally this was achieved by adding a &lt;global-exceptions&gt; section in struts-config.xml with a custom exception handler to log the exceptions and the url to the global error page.&lt;/global-exceptions&gt;&lt;/span&gt;&lt;p style=&quot;color: rgb(0, 0, 0);&quot; class=&quot;MsoNormal&quot;&gt;  &lt;/p&gt;&lt;p style=&quot;color: rgb(0, 0, 0);&quot; class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;This would forward to the error page if an unhandled exception was thrown from the Struts action but will not do so if the exception occurred in one of the tiles JSPs. An exception in a tile would result in a partly rendered page but this was fine in previous app as there were hardly any logic in JSP files and it was very rare to have an exception at the JSP level in production.&lt;/span&gt;&lt;/p&gt;  &lt;p style=&quot;color: rgb(0, 0, 0);&quot; class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style=&quot;color: rgb(0, 0, 0);&quot; class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;In the new app though this wasn’t the case as there were lot of logic that went in to JSPs in the form of custom tags etc… that could potentially throw all sorts of exceptions at run time and I wanted to handle all these exceptions in a unified manner.&lt;/span&gt;&lt;/p&gt;    &lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;br /&gt;&lt;b style=&quot;&quot;&gt;New Solution &lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);font-size:100%;&quot; &gt;&lt;span style=&quot;&quot;&gt;I abandoned the global-exceptions approach in struts-config altogether and added a &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&amp;lt;error-page&amp;gt; &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);font-size:100%;&quot; &gt;&lt;span style=&quot;&quot;&gt; section to the web.xml file which instructed the app server to forward the request to the specified URL on all unhandled exceptions.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;  &lt;/p&gt;      &lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;&quot;&gt;&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: rgb(153, 0, 0);font-size:85%;&quot; &gt;&amp;lt;error-page&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(153, 0, 0);font-size:85%;&quot; &gt;    &lt;/span&gt;&lt;span style=&quot;color: rgb(153, 0, 0);font-size:85%;&quot; &gt;&amp;lt;exception-type&amp;gt;java.lang.Throwable&amp;lt;/exception-type&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(153, 0, 0);font-size:85%;&quot; &gt;    &lt;/span&gt;&lt;span style=&quot;color: rgb(153, 0, 0);font-size:85%;&quot; &gt;&amp;lt;location&amp;gt;/error &amp;lt;/location&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(153, 0, 0);font-size:85%;&quot; &gt;  &lt;/span&gt;&lt;span style=&quot;color: rgb(153, 0, 0);font-size:85%;&quot; &gt;&amp;lt;/error-page&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;  &lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;&quot;&gt;&lt;span style=&quot;;font-family:georgia;font-size:100%;&quot;  &gt;Then added a servlet and a servlet mapping to the /error URL&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt; &lt;span style=&quot;color: rgb(153, 0, 0);font-size:85%;&quot; &gt;&amp;lt;servlet&amp;gt;&lt;br /&gt;&amp;lt;servlet-name&amp;gt;exceptionHandler&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&amp;lt;servlet-class&amp;gt;com.test.ExceptionHandlerServlet&amp;lt;/servlet-class&amp;gt;&lt;br /&gt;&amp;lt;init-param&amp;gt;&lt;br /&gt;&amp;lt;param-name&amp;gt;errorPageURL&amp;lt;/param-name&amp;gt;&lt;br /&gt;&amp;lt;param-value&amp;gt;error.html&amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/init-param&amp;gt;&lt;br /&gt;&amp;lt;load-on-startup&amp;gt;3&amp;lt;/load-on-startup&amp;gt;&lt;br /&gt;&amp;lt;/servlet&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;servlet-mapping&amp;gt;&lt;br /&gt;&amp;lt;servlet-name&amp;gt;exceptionHandler&amp;lt;/servlet-name&amp;gt;&lt;br /&gt;&amp;lt;url-pattern&amp;gt;/error&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;&amp;lt;/servlet-mapping&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;The ExceptionHandlerServlet would log the exception and redirect the browser to the URL defined in the servlet configuration (error.html).&lt;br /&gt;&lt;br /&gt;ExceptionHandlerServlet Code:&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;java&quot; align=&quot;left&quot;&gt;&lt;table bg=&quot;&quot; style=&quot;color: rgb(255, 255, 255);&quot; border=&quot;0&quot; cellpadding=&quot;3&quot; cellspacing=&quot;0&quot;&gt;   &lt;tbody&gt;&lt;tr&gt;  &lt;!-- start source code --&gt;&lt;br /&gt;&lt;td align=&quot;left&quot; valign=&quot;top&quot;&gt;&lt;code&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;protected &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;void &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;doPost&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;HttpServletRequest request, HttpServletResponse response&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;throws &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;ServletException, IOException &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;     &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;try &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;logger.debug&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(42, 0, 255);&quot;&gt;&quot;Handling exception in ErrorHandlerServlet&quot;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;Throwable exception = &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;null&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: rgb(63, 127, 95);&quot;&gt;// Check if struts has placed an exception object in request&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;Object obj = request.getAttribute&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;Globals.EXCEPTION_KEY&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;if &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;obj == &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;null&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;) {&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;             &lt;/span&gt;&lt;span style=&quot;color: rgb(63, 127, 95);&quot;&gt;// Since no struts exception is found,&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;             &lt;/span&gt;&lt;span style=&quot;color: rgb(63, 127, 95);&quot;&gt;// check if a JSP exception is available in request.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;obj = request.getAttribute&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(42, 0, 255);&quot;&gt;&quot;javax.servlet.jsp.jspException&quot;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;if &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;obj != &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;null&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;&amp;&amp;amp; &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;obj &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;instanceof &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;Throwable&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;)) {&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;exception = &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;Throwable&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;obj;&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;if &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;logger.isDebugEnabled&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;()) {&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;               &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;logger.debug&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(42, 0, 255);&quot;&gt;&quot;Request URI: &quot; &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;+ request.getAttribute&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(42, 0, 255);&quot;&gt;&quot;javax.servlet.forward.request_uri&quot;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;))&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: rgb(63, 127, 95);&quot;&gt;// request uri containing the original URL value will be available&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: rgb(63, 127, 95);&quot;&gt;// only on servers implementing servlet 2.4 spec&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;String requestURI = &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;request.getAttribute&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(42, 0, 255);&quot;&gt;&quot;javax.servlet.forward.request_uri&quot;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;logger.error&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(42, 0, 255);&quot;&gt;&quot;Exception while handling request: &quot; &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;+ requestURI, exception&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;response.sendRedirect&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;errorPageURL&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color: rgb(127, 0, 85);&quot;&gt;&lt;b&gt;catch &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;Exception e&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;) {&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: rgb(63, 127, 95);&quot;&gt;// Throwing exceptions from this method can result in request&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: rgb(63, 127, 95);&quot;&gt;// going in to an infinite loop forwarding to the error servlet recursively.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;e.printStackTrace&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(255, 255, 255);&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(0, 0, 0);&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;color: rgb(0, 0, 0);font-size:100%;&quot; &gt;&lt;span style=&quot;font-family:georgia;&quot;&gt;Now on all unhandled exceptions the servlet will log the exception. Yet on some occasions where the exception was thrown in one of the tile JSPs the browser would display a partially rendered page and would not redirect to the error page.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;p style=&quot;color: rgb(0, 0, 0);&quot; class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family:georgia;&quot;&gt;This was due to tiles flushing content to the response buffer before the whole page was rendered. In such a situation the browser will happily display what it received and the redirect to the error page will have no effect.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;color: rgb(0, 0, 0);&quot; class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;In order to prevent or minimize the flushing of response buffer:&lt;br /&gt;&lt;br /&gt;1.    Set flush attribute to false in all tiles insert tags&lt;br /&gt;2.    Increase the response buffer size to minimize auto flushing&lt;br /&gt;&lt;br /&gt;This was achieved by modifying the tiles layout jsp page.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;color: rgb(153, 0, 0);&quot;&gt;&amp;lt;!-- sets the response buffer size to 64kb --&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(153, 0, 0);&quot;&gt;&amp;lt;%@ page buffer=&quot;64kb&quot;%&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(153, 0, 0);&quot;&gt;&amp;lt;%@ taglib uri=&quot;/WEB-INF/struts-tiles.tld&quot; prefix=&quot;tiles&quot;%&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(153, 0, 0);&quot;&gt;…&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(153, 0, 0);&quot;&gt;&amp;lt;tiles:insert attribute=&quot;header&quot; flush=&quot;false&quot; /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(153, 0, 0);&quot;&gt;&amp;lt;tiles:insert attribute=&quot;leftnav&quot; flush=&quot;false&quot; /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(153, 0, 0);&quot;&gt;&amp;lt;tiles:insert attribute=&quot;body&quot; flush=&quot;false&quot; /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: rgb(153, 0, 0);&quot;&gt;&amp;lt;tiles:insert attribute=&quot;footer&quot; flush=&quot;false&quot; /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: rgb(0, 0, 0);font-size:100%;&quot; &gt;In the above code segment all html formatting was removed for clarity. The response buffer was set to 64 kilobytes and this value should be decide based on the average page size of the application and the performance impact of the increased memory usage.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://livingtao.blogspot.com/feeds/9197806388998808917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/4435599137875974089/9197806388998808917' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/9197806388998808917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4435599137875974089/posts/default/9197806388998808917'/><link rel='alternate' type='text/html' href='http://livingtao.blogspot.com/2007/05/global-exception-handling-for-struts.html' title='Global Exception Handling for Struts and Tiles Applications'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry></feed>