<?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: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-1735220007410867655</id><updated>2011-11-05T21:39:52.548+01:00</updated><title type='text'>the need for speed, tests and clean code</title><subtitle type='html'>test driving of java applications</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-1754986351950129167</id><published>2010-12-28T09:15:00.001+01:00</published><updated>2010-12-28T09:18:20.520+01:00</updated><title type='text'>Synaptics,UltraNav,Thinkpad Scrolling in Netbeans,IntelliJ or other Java Swing Appz</title><content type='html'>I do love my Thinkpad! And of course I do love the red bubble called track point and its way of scrolling. But sometimes scrolling doesn't work. Most often it stops working in java apps using the swing framework. This includes Netbeans IDE and IntelliJ IDEA. This morning I thought its time to fight the evil of this problem and after an endless list of bug reports and forum questions with many crazy ideas(including JNI Hooks - buäks) I found one interesting hint to a file called TP4table.dat located at C:\Program Files\Synaptics\SynTP. I tried what this guy said but nothing changed - still no scrolling in IntelliJ. A refined google query using swing and TP4table.dat leaked the &lt;a href="http://swapnonil.com/2008/06/02/thinkpad-scrolling-fixed-for-safari-and-intellij/"&gt;evils secret&lt;/a&gt;. All you have to do is to add some lines to this file to make the driver send the right scrolling events to the app. In case of IntelliJ use the following:&lt;br /&gt;
&lt;br /&gt;
*,*,idea.exe,*,*,*,WheelStd,1,9&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It may be necessary to restart windows. If its not working try to add this line at the top of the ruleset definitions right under the comment&lt;br /&gt;
&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
; Pass 0 rules (These rules run first)&lt;br /&gt;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
and confront your brave Windows Machine with the challenge of a reboot. If its still not working rename the idea.exe file to java.exe. (There is a predefined rule for java in the TP4table.dat file) and start IntelliJ using this exe. If scrolling is working now you made a mistake copy and pasting or forgot to reboot your machine.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Happy new year with scrolling in Swing appz!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-1754986351950129167?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/1754986351950129167/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=1754986351950129167&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1754986351950129167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1754986351950129167'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2010/12/synapticsultranavthinkpad-scrolling-in.html' title='Synaptics,UltraNav,Thinkpad Scrolling in Netbeans,IntelliJ or other Java Swing Appz'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-7733361128568832246</id><published>2010-09-13T23:23:00.003+02:00</published><updated>2010-09-14T07:11:33.914+02:00</updated><title type='text'>HOWTO do global JNDI registered Connection Pooling (DataSource) in Tomcat</title><content type='html'>&lt;p&gt;
Using a connection pool of the servlet container seems to be a good idea IMHO. Here's a litlle HOWTO do so using tomcat and postgresql.
&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;
  Provide the jdbc driver by copying the postgresql-8.4-701.jdbc4.jar (or any other version working for you) to the CATALINA_HOME/lib directory.
 &lt;/li&gt;
 &lt;li&gt;Register the jndi resource by adding the following lines to your CATALINA_HOME/conf/server.xml under &amp;lt;GlobalNamingResources&amp;gt;
&lt;pre class="source-code"&gt;&amp;lt;Resource
 name=&amp;quot;jdbc/postgres-ds&amp;quot; type=&amp;quot;javax.sql.DataSource&amp;quot;
 driverClassName=&amp;quot;org.postgresql.Driver&amp;quot; url=&amp;quot;jdbc:postgresql://MYSERVER:5432/testdb&amp;quot;
 username=&amp;quot;MYUSER&amp;quot; password=&amp;quot;MYPASS&amp;quot;
 defaultAutoCommit=&amp;quot;false&amp;quot; 
 maxActive=&amp;quot;5&amp;quot; maxIdle=&amp;quot;2&amp;quot; maxWait=&amp;quot;30000&amp;quot; initialSize=&amp;quot;0&amp;quot; 
 validationQuery=&amp;quot;SELECT 1;&amp;quot; testOnBorrow=&amp;quot;true&amp;quot; testWhileIdle=&amp;quot;false&amp;quot;  
/&amp;gt;&lt;/pre&gt;
&lt;/li&gt;
 &lt;li&gt;Create or user the file /META-INF/context.xml(Using maven it is src/main/webapp/META-INF/context.xml in your webapps project with the following content:
&lt;pre class="source-code"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;Context&amp;gt;
 &amp;lt;ResourceLink name=&amp;quot;jdbc/dbds&amp;quot; global=&amp;quot;jdbc/postgres-ds&amp;quot; type=&amp;quot;javax.sql.DataSource&amp;quot;/&amp;gt;  
&amp;lt;/Context&amp;gt;&lt;/pre&gt;
&lt;/li&gt;
 &lt;li&gt;edit your web.xml and add the following lines to the root node:
&lt;pre class="source-code"&gt;&amp;lt;resource-ref&amp;gt;
 &amp;lt;description&amp;gt;postgreSQL Datasource example&amp;lt;/description&amp;gt;
 &amp;lt;res-ref-name&amp;gt;jdbc/dbds&amp;lt;/res-ref-name&amp;gt;
 &amp;lt;res-type&amp;gt;javax.sql.DataSource&amp;lt;/res-type&amp;gt;
 &amp;lt;res-auth&amp;gt;Container&amp;lt;/res-auth&amp;gt;
&amp;lt;/resource-ref&amp;gt;&lt;/pre&gt;
&lt;/li&gt;
 &lt;li&gt;Use the connection in a way like this:
&lt;pre class="source-code"&gt;InitialContext cxt = new InitialContext();
DataSource ds = (DataSource) cxt.lookup(&amp;quot;java:/comp/env/jdbc/dbds&amp;quot;);
Connection con = ds.getConnection();
con.setAutoCommit(false);
Statement statement = con.createStatement();
ResultSet rs = statement.executeQuery(&amp;quot;SELECT id, \&amp;quot;name\&amp;quot; FROM test;&amp;quot;);
while (rs.next()) {
 long long1 = rs.getLong(&amp;quot;id&amp;quot;);
 String name = rs.getString(&amp;quot;name&amp;quot;);
 System.out.println(long1 + &amp;quot; - &amp;quot; + name);
}

rs.close();
statement.close();
con.commit();
con.close();&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Additional Info:&lt;br/&gt;
Tomcat 6 is using the Apache dbcp project to do connection pooling. So the available connection pool configuration parameters are described &lt;a href="http://commons.apache.org/dbcp/configuration.html" target="_blank"&gt;here&lt;/a&gt;
&lt;br/&gt;&lt;br/&gt;
The pool is created at the time of the first connection request.
&lt;br/&gt;&lt;br/&gt;
Make sure to always close the connection. Connections that are not closed are not released. This means those connections can't be reused.
&lt;br/&gt;&lt;br/&gt;
If you are using eclipse wtp and Tomcat 7 you may get a nasty java.lang.NullPointerException at org.apache.catalina.core.StandardContext.getObjectNameKeyProperties. It is related to the &amp;lt;ResourceLink name=&amp;quot;jdbc/dbds&amp;quot; global=&amp;quot;jdbc/postgres-ds&amp;quot; type=&amp;quot;javax.sql.DataSource&amp;quot;/&amp;gt; setting in the context.xml file. The problem is described &lt;a href="http://www.eclipse.org/forums/index.php?t=msg&amp;goto=546852&amp;" target="_blank"&gt;here&lt;/a&gt; in more detail. Just enable the server option &amp;quot;Publish module contexts to separate XML files&amp;quot; and the problem is solved.
&lt;br/&gt;&lt;br/&gt;
If you are using eclipse wtp and Tomcat you may need to remove and add the tomcat server again so the wtp plugin recognizes the changed server.xml file.&lt;br/&gt;&lt;br/&gt;
I'll provide an example project if someone requests :-)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-7733361128568832246?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/7733361128568832246/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=7733361128568832246&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/7733361128568832246'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/7733361128568832246'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2010/09/howto-do-global-jndi-registered.html' title='HOWTO do global JNDI registered Connection Pooling (DataSource) in Tomcat'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-6700031027371775126</id><published>2010-09-08T08:09:00.001+02:00</published><updated>2010-09-08T08:10:49.417+02:00</updated><title type='text'>J4v4 rul3z</title><content type='html'>&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/H7QVITAWdBQ?fs=1&amp;amp;hl=de_DE"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/H7QVITAWdBQ?fs=1&amp;amp;hl=de_DE" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-6700031027371775126?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.youtube.com/watch?v=H7QVITAWdBQ&amp;has_verified=1' title='J4v4 rul3z'/><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/6700031027371775126/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=6700031027371775126&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6700031027371775126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6700031027371775126'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2010/09/j4v4-rul3z.html' title='J4v4 rul3z'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-2402839628835630529</id><published>2010-08-16T23:23:00.003+02:00</published><updated>2010-08-16T23:23:00.207+02:00</updated><title type='text'>Joomla template development using Ant</title><content type='html'>&lt;h2&gt;My personal 3 Problems developing Joomla templates&lt;/h2&gt;
&lt;p&gt;
First it is necessary to maintain a file called templateDetails.xml. In this file you have to define all the files used by the template. Adding a picture means adding this picture to the list of files. If you forget to do so, the file is not installed which results in template bugs.&lt;br/&gt;
Second building the template package means creating a zip file. This is like creating a jar file - who would want to do it using a file manager and a zip tool?&lt;br/&gt;
Last but not least it is not possible to reinstall a template. Once installed, you have to uninstall it prior to installing the new version of the template. Who would like to do this every time a css file changed? So most people are using a ftp client like FileZilla which supports "online file edit" or directory synchronization. In my case this means opening files with FileZilla, not with eclipse. DO NOT forget to sync them back!
&lt;/p&gt;
&lt;h2&gt;Ant to the rescue&lt;/h2&gt;
&lt;p&gt;I spent some time and created a custom ant task and a build script using the ftp sync feature built into ant. The custom ant task is responsible for maintaining the file list of the templateDetails.xml. It scans the template directory recursively and replaces the files section with the results. You can &lt;a href="https://sites.google.com/site/richardhauswald2/TemplateDetailsGenerator.jar" &gt;download&lt;/a&gt; it here. You can find the source code included in the jar file. I don't want to include those ugly lines doing their dirty job in this article.&lt;br/&gt;
The ant build script is quite simple:
&lt;pre class="source-code"&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;project name=&amp;quot;MyKewlTemplate&amp;quot; default=&amp;quot;myKewlTemplate&amp;quot;&amp;gt;
 &amp;lt;target name=&amp;quot;refreshFileList&amp;quot;&amp;gt;
  &amp;lt;taskdef name=&amp;quot;TemplateDetailsGenerator&amp;quot; classname=&amp;quot;de.rhauswald.ant.joomla.TemplateDetailsGenerator&amp;quot; classpath=&amp;quot;ant/TemplateDetailsGenerator.jar&amp;quot; /&amp;gt;
  &amp;lt;TemplateDetailsGenerator templatedirectory=&amp;quot;myKewlTemplate&amp;quot; /&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;target name=&amp;quot;clean&amp;quot;&amp;gt;
  &amp;lt;delete file=&amp;quot;build/myKewlTemplate.zip&amp;quot; /&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;target name=&amp;quot;myKewlTemplate&amp;quot; depends=&amp;quot;clean&amp;quot;&amp;gt;
  &amp;lt;antcall target=&amp;quot;refreshFileList&amp;quot; /&amp;gt;
  &amp;lt;zip destfile=&amp;quot;build/myKewlTemplate.zip&amp;quot; basedir=&amp;quot;myKewlTemplate&amp;quot; /&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;!-- include apache commons-net into  ant lib directory--&amp;gt;
 &amp;lt;target name=&amp;quot;sync&amp;quot;&amp;gt;
  &amp;lt;antcall target=&amp;quot;refreshFileList&amp;quot; /&amp;gt;
  &amp;lt;ftp password=&amp;quot;XXX&amp;quot; server=&amp;quot;XXX&amp;quot; userid=&amp;quot;XXX&amp;quot; passive=&amp;quot;true&amp;quot; newer=&amp;quot;true&amp;quot; remotedir=&amp;quot;templates/myKewlTemplate&amp;quot; verbose=&amp;quot;true&amp;quot; binary=&amp;quot;true&amp;quot;&amp;gt;
   &amp;lt;fileset dir=&amp;quot;myKewlTemplate&amp;quot;&amp;gt;
   &amp;lt;/fileset&amp;gt;
  &amp;lt;/ftp&amp;gt;
 &amp;lt;/target&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
Now my three problems are solved: The file list is auto generated before every build(ftp sync or zip). I can build the installation zip file with just one click. The ftp sync works like a charm. Change something, click the build button and ant uploads the changes only. In case I add a background picture and the proper lines to the css file a click at the build button does the following:
&lt;ol&gt;
&lt;li&gt;Add the new picture to the file list&lt;/li&gt;
&lt;li&gt;Upload the templateDetails.xml file&lt;/li&gt;
&lt;li&gt;Upload the picture&lt;/li&gt;
&lt;li&gt;Upload the css file&lt;/li&gt;
&lt;/ol&gt;
I can concentrate on writing div boxes and css now...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-2402839628835630529?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/2402839628835630529/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=2402839628835630529&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2402839628835630529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2402839628835630529'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2010/08/joomla-template-development-using-ant.html' title='Joomla template development using Ant'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-6128373905848330077</id><published>2010-08-14T23:23:00.000+02:00</published><updated>2010-08-14T23:23:00.482+02:00</updated><title type='text'>Speeding up maven dependency report</title><content type='html'>Executing the maven site goal with the default configuration can take a long time. In my case . Most of the time is consumed by the "Dependencies" report. This is the build summary with the default configuration:
&lt;pre class="source-code"&gt;
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 44 seconds
[INFO] Finished at: Fri Aug 13 09:31:14 CEST 2010
[INFO] Final Memory: 69M/429M
[INFO] ------------------------------------------------------------------------
&lt;/pre&gt;
The docs of the dependency report module offered two options enabled by default. Disabling both of them is done in the reporting section of the project pom this way:
&lt;pre class="source-code"&gt;
&amp;lt;plugin&amp;gt;
 &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;maven-project-info-reports-plugin&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;2.1&amp;lt;/version&amp;gt;
 &amp;lt;configuration&amp;gt;
  &amp;lt;dependencyDetailsEnabled&amp;gt;false&amp;lt;/dependencyDetailsEnabled&amp;gt;
  &amp;lt;dependencyLocationsEnabled&amp;gt;false&amp;lt;/dependencyLocationsEnabled&amp;gt;
 &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;

This speeds up the site generation extremely:
&lt;pre class="source-code"&gt;
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 22 seconds
[INFO] Finished at: Fri Aug 13 09:33:44 CEST 2010
[INFO] Final Memory: 65M/395M
[INFO] ------------------------------------------------------------------------
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-6128373905848330077?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/6128373905848330077/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=6128373905848330077&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6128373905848330077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6128373905848330077'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2010/08/speeding-up-maven-dependency-report.html' title='Speeding up maven dependency report'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-2131328650974176599</id><published>2010-08-13T08:56:00.005+02:00</published><updated>2010-08-15T11:26:46.956+02:00</updated><title type='text'>Windows Command / CMD Alternative</title><content type='html'>&lt;p&gt;I found an awesome tool today named "console". It can be used as an alternative command line window for windows. Everyone who has broken his fingers a hundred times using the cmd tool shipped with windows should give this piece of software a try!
&lt;/p&gt;
&lt;p&gt;
The &lt;a href="http://sourceforge.net/projects/console/"&gt;website&lt;/a&gt; states:

Console is a Windows console window enhancement. Console features include: multiple tabs, text editor-like text selection, different background types, alpha and color-key transparency, configurable font, different window styles
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-2131328650974176599?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/2131328650974176599/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=2131328650974176599&amp;isPopup=true' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2131328650974176599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2131328650974176599'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2010/08/windows-command-cmd-alternative.html' title='Windows Command / CMD Alternative'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-5915672711938023726</id><published>2010-04-13T20:00:00.000+02:00</published><updated>2010-04-13T20:14:47.483+02:00</updated><title type='text'>Howto set the Bacula Storage Daemon 's (bacula-sd) umask in Debian</title><content type='html'>The default Debian init script for the Bacula Storage Daemon is not providing a configuration option for the umask. Of cause it is possible to append a --umask to the start-stop-daemon lines init script but this is not update safe and last but not least it will change the checksums and intrusion detection scanners (debsums, tiger,...) will complain about this file. This leads to an ignore rule in the IDS which means more configuration, less security and more complexity.
&lt;br/&gt;&lt;br/&gt;
The solution is to use a pam module named pam_umask. It is contained in the package libpam-modules which should be installed by default. After switching on the module the only thing that needs to be done is to add a umask setting to the Bacula users GECOS field.
&lt;br/&gt;&lt;br/&gt;
For the copy paste fraction:&lt;br/&gt;
&lt;pre class="source-code"&gt;
apt-get install libpam-modules
echo "session   optional   pam_umask.so" &gt;&gt; /etc/pam.d/common-session
usermod -c umask=027 bacula
/etc/init.d/bacula-sd restart
&lt;/pre&gt;
pam_umask can also be used this way to modify the umask of any specific daemon user without a shell.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-5915672711938023726?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/5915672711938023726/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=5915672711938023726&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/5915672711938023726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/5915672711938023726'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2010/04/howto-set-bacula-storage-daemon-s.html' title='Howto set the Bacula Storage Daemon &apos;s (bacula-sd) umask in Debian'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-760280861712714314</id><published>2010-03-27T10:56:00.003+01:00</published><updated>2010-03-29T16:14:41.811+02:00</updated><title type='text'>TrueCrypt and Ubuntu 9</title><content type='html'>Today I installed True Crypt on an Ubuntu box. Tried apt-cache to search truecrypt without success. Cause I'm a damn good rftm'er I continued using google. Every page suggested to compile the sources. Not that I'm afraid of compiling source code but hey that's Ubuntu not Gentoo. So I stopped doing the rtfm stuff and had a look at the homepage of True Crypt. Downloaded a tar archive, extracted it and run the extracted executable. A few seconds later I got True Crypt running on the box. Why are all the linux guys always trying to compile things...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-760280861712714314?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/760280861712714314/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=760280861712714314&amp;isPopup=true' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/760280861712714314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/760280861712714314'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2010/03/truecrypt-and-ubuntu-9.html' title='TrueCrypt and Ubuntu 9'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-1976047959537068576</id><published>2010-03-26T23:23:00.002+01:00</published><updated>2010-03-29T16:21:06.239+02:00</updated><title type='text'>Debian Bacula vulnerability / security leak</title><content type='html'>Another shorty:


Bacula is a neat backup tool and Debian provides maintained packages for it. But the install script opens a big security hole. It generates all the necessary configuration files for the file and storage daemons, the director and the console client. It also generates the user names depending on the host name. And it seems to do this job in a secure way cause the passwords for the Bacula users are long enough to be very secure. This is indeed very important cause the file daemon runs as root. This is necessary so the file daemon is able to backup the whole system. The only downside is that those passwords are neither generated nor is the installer asking for them. This makes many users believe that those passwords are generated and not have to be changed.


Combining those facts leads to the following situation: Every default Bacula installation in Debian is using the same password to secure the file daemon which is capable of reading all the files of the system as root. So every non privileged user is able to use this daemon to get access to files he has no access to.


|-|4\/3 4 L07 0Ph p|-|U|\|...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-1976047959537068576?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/1976047959537068576/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=1976047959537068576&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1976047959537068576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1976047959537068576'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2010/03/debian-bacula-vulnerability-security.html' title='Debian Bacula vulnerability / security leak'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-5838282141106358162</id><published>2010-02-15T20:23:00.000+01:00</published><updated>2010-02-15T20:33:51.647+01:00</updated><title type='text'>How to determine the size of all postgres databases</title><content type='html'>&lt;p&gt;
A manic Monday, reading log files, a big WTF: No space left on device external backups... WTF? .... 5 Minutes later: found a reason: The backups of the test database server... 30 databases on this machine.... which ones are the biggest?
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;This query to the rescue:&lt;/b&gt;&lt;br/&gt;
select databases.datname, pg_database_size(databases.datname)/1024/1024 as size from (SELECT datname as datname FROM pg_database) as databases ORDER BY size DESC;
&lt;/p&gt;
&lt;p&gt;
One test database with 1,4GB ... another one with 0.9G... WTF? - Drop database... war is over
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-5838282141106358162?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/5838282141106358162/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=5838282141106358162&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/5838282141106358162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/5838282141106358162'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2010/02/how-to-determine-size-of-all-postgres_15.html' title='How to determine the size of all postgres databases'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-4277760843020808733</id><published>2009-12-14T23:23:00.000+01:00</published><updated>2009-12-14T23:23:00.322+01:00</updated><title type='text'>Disable IPv6 in Debian Lenny Linux</title><content type='html'>And here is how to do this:
&lt;ul&gt;
&lt;li&gt;
At first the stuff every web site is telling us:

In /etc/modprobe.d/aliases replace/add the following mappings:

alias net-pf-10 off
alias ipv6 off


(I found this at &lt;a href="http://fak3r.com/2008/12/02/howto-disable-ipv6-networking-in-debian/"&gt;fak3r.com&lt;/a&gt;)
&lt;/li&gt;
&lt;li&gt;
If you are using a firewall script which loads all available module before setting up the firewall, add the following lines to /etc/modprobe.d/aliases:

alias ip6_queue.ko off
alias ip6table_filter.ko off
alias ip6table_mangle.ko off
alias ip6table_raw.ko off
alias ip6table_security.ko off
alias ip6_tables.ko off
alias ip6t_ah.ko off
alias ip6t_eui64.ko off
alias ip6t_frag.ko off
alias ip6t_hbh.ko off
alias ip6t_hl.ko off
alias ip6t_HL.ko off
alias ip6t_ipv6header.ko off
alias ip6t_LOG.ko off
alias ip6t_mh.ko off
alias ip6t_REJECT.ko off
alias ip6t_rt.ko off
alias nf_conntrack_ipv6.ko off


You can do this by executing:

for module in `ls /lib/modules/YOUR-KERNEL-VERSION/kernel/net/ipv6/netfilter/`; do echo "alias $module off" &gt;&gt; /etc/modprobe.d/aliases; done
&lt;/li&gt;
&lt;/ul&gt;


Hope this helps :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-4277760843020808733?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/4277760843020808733/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=4277760843020808733&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/4277760843020808733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/4277760843020808733'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/12/disable-ipv6-in-debian-lenny-linux.html' title='Disable IPv6 in Debian Lenny Linux'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-7993797813275917017</id><published>2009-12-03T22:23:00.011+01:00</published><updated>2009-12-03T22:45:57.133+01:00</updated><title type='text'>Apache2 httpd, Apache Tomcat6 and rewrite problems</title><content type='html'>While configuring a Apache2 as Proxy for a bunch of Tomcats behind I found many postings that says "Use mod_rewrite and this set of rules" or "you have to use ajp and mod_jk". After some rtfm I found out that setting up a Apache2 httpd with multiple Apache Tomcats behind mapped using mod_proxy is pretty simple and straight forward. here is the HowTo:
&lt;br/&gt;
1. Add a site to the apache2:
&lt;pre class="source-code"&gt;
cat /etc/apache2/sites-enabled/artifactory
&amp;lt;Location /artifactory/&amp;gt;
    ProxyPass http://127.0.0.1:8100/artifactory/
    Order deny,allow
    Allow from all
&amp;lt;/Location&amp;gt;
&lt;/pre&gt;
2. Enable mod_proxy by creating the following links (ln -s target) in /etc/apache2/mods-enabled/
&lt;pre class="source-code"&gt;
proxy.conf -&gt; ../mods-available/proxy.conf
proxy_http.load -&gt; ../mods-available/proxy_http.load
proxy.load -&gt; ../mods-available/proxy.load
&lt;/pre&gt;
3. Modify the content of /etc/apache2/mods-enabled/proxy.conf :
&lt;pre class="source-code"&gt;
&amp;lt;IfModule mod_proxy.c&amp;gt;
ProxyRequests Off

&amp;lt;Proxy *&amp;gt;
    Order deny,allow
    Allow from all
&amp;lt;/Proxy&amp;gt;

&amp;lt;/IfModule&amp;gt;
&lt;/pre&gt;
4. reload the apache2 server:
&lt;pre class="source-code"&gt;
/etc/init.d/apache2 reload
&lt;/pre&gt;
5. modify $TOMCAT_HOME/conf/server.xml &lt;br/&gt;
Change from:&lt;br/&gt;
&lt;pre class="source-code"&gt;
&amp;lt;Connector port="8100" protocol="HTTP/1.1"
connectionTimeout="20000" redirectPort="8443" /&amp;gt;
&lt;/pre&gt;
to&lt;br/&gt;
&lt;pre class="source-code"&gt;
&amp;lt;Connector port="8100" protocol="HTTP/1.1"
connectionTimeout="20000" redirectPort="8443"
proxyName="YourDomain.YourTLD" proxyPort="80"/&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-7993797813275917017?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/7993797813275917017/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=7993797813275917017&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/7993797813275917017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/7993797813275917017'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/12/apache2-httpd-apache-tomcat6-and.html' title='Apache2 httpd, Apache Tomcat6 and rewrite problems'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-1795669641596247487</id><published>2009-09-14T22:10:00.018+02:00</published><updated>2009-09-19T10:42:24.554+02:00</updated><title type='text'>DragImagePainter or Getting Around isDragImageSupported() on Windows</title><content type='html'>Last week I had an interesting conversation with a project manager at a meeting of the Scrum User Group in Dresden. He asked me why so many common tasks need to be reprogrammed in every project. I tried to answer that question and argued that things need to be implemented in a different way for different purposes... But today I came to the conclusion the he's right. Reimplementing common tasks is expensive and it happens too often.



"The customer wants to relayout some components on the fly using Drag and Drop. While dragging a small drag image of the dragged component should be visible near the mouse pointer." - Sounds like a common use case to me. But Drag and Drop (DnD) in Swing does not support this. Of course Swing supports Drag and Drop out of the box - but only for a small amount of components. I don't know why this feature is missing in a framework which is in use since a decade.



On my way implementing this feature I stumble upon the method isDragImageSupported() of the class java.awt.dnd.DragSource. Windows does not support adding a DragImage to the mouse pointer. Google told me to look at &lt;a target="_blank" href="http://blogs.sun.com/geertjan/"&gt;Geertjan's Blog&lt;/a&gt;. He wrote a &lt;a target="_blank" href="http://blogs.sun.com/geertjan/entry/getting_around_isdragimagesupported_on_windows"&gt;nice and informative article&lt;/a&gt; how to implement this feature. Nicely done! But doing it the way he did means doing it again and again and the poor customer needs to pay for this :)


As I want customers of IT companies to be happy I tried to save the world. First of all I called my brother in arms &lt;a target="_blank" href="http://frickelwut.blogspot.com/"&gt;rosh&lt;/a&gt;. With combined holy hand grenades we wrote a kewl class called DragImagePainter. It needs to be instantiated in the java.awt.dnd.DragSourceListener. In method dragOver of the java.awt.dnd.DragSourceListener a call to the function paintDragImage will do the magic. Feel free to use AND REUSE the following piece of code:



&lt;pre class="source-code"&gt;
/**
* Utility class for painting a scaled and opaque image representation of a
* dragged component while it's being dragged.
*
* @author Richi
*
*/
public class DragImagePainter {
private final AlphaComposite ALPHA_COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
private final JComponent rootComponent;
private final JComponent draggableComponent;
private final int offsetY;
private final int imageWidth;

private Point lastKnownCursorPosition;

/**
 * @param rootComponent
 *            the root component of the current window
 * @param draggableComponent
 *            the component which is going to be dragged
 */
public DragImagePainter(JComponent rootComponent, JComponent draggableComponent) {
 this.rootComponent = rootComponent;
 this.draggableComponent = draggableComponent;
 this.offsetY = -15;
 this.imageWidth = 50;
}

/**
 * Paints a scaled and opaque image representation of the draggableComponent
 * provided in the constructor near the current mouse pointer position.
 *
 * @param currentCursorPositionX
 * @param currentCursorPositionY
 */
public void handleDragOver(int currentCursorPositionX, int currentCursorPositionY) {
 boolean imagePositionChanged = imagePositionChanged(currentCursorPositionX, currentCursorPositionY);
 if (imagePositionChanged) {
  double scaleFactor = calculateScaleFactor();
  int imageHeight = calculateImageHeight(scaleFactor);
  if (!isFirstRun())
   repaintLastKnownImageArea(imageHeight);
  Graphics2D rootComponentGraphics = (Graphics2D) rootComponent.getGraphics();
  paintDragImage(currentCursorPositionX, currentCursorPositionY, scaleFactor, rootComponentGraphics);
  lastKnownCursorPosition = new Point(currentCursorPositionX, currentCursorPositionY);
 }
}

/**
 * Needs to be called on {@link DragSourceListener}.dragEnd() to repaint the
 * area of the last painted drag image
 */
public void handleDropEnd() {
 double scaleFactor = calculateScaleFactor();
 int imageHeight = calculateImageHeight(scaleFactor);
 repaintLastKnownImageArea(imageHeight);
}

double calculateScaleFactor() {
 return (double) imageWidth / draggableComponent.getWidth();
}

private int calculateImageHeight(double scaleFactor) {
 return (int) Math.ceil(draggableComponent.getHeight() * scaleFactor);
}

boolean imagePositionChanged(int currentCursorPositionX, int currentCursorPositionY) {
 return isFirstRun() || lastKnownCursorPosition.x != currentCursorPositionX
   || lastKnownCursorPosition.y != currentCursorPositionY;
}

void repaintLastKnownImageArea(int height) {
 rootComponent.paintImmediately(lastKnownCursorPosition.x, lastKnownCursorPosition.y + offsetY, imageWidth,
   height);
}

boolean isFirstRun() {
 return lastKnownCursorPosition == null;
}

void paintDragImage(int currentCursorPositionX, int currentCursorPositionY, double scaleFactor,
  Graphics2D rootComponentGraphics) {
 Graphics2D dragPictureGraphics = (Graphics2D) rootComponentGraphics.create();

 dragPictureGraphics.translate(currentCursorPositionX, currentCursorPositionY + offsetY);
 dragPictureGraphics.scale(scaleFactor, scaleFactor);
 dragPictureGraphics.setComposite(ALPHA_COMPOSITE);

 draggableComponent.paint(dragPictureGraphics);
}

}
&lt;/pre&gt;


Use in this way:
&lt;pre class="source-code"&gt;
@Override
public void dragDropEnd(DragSourceDropEvent dragSourceDropEvent) {
dragImagePainter.handleDropEnd();
}
@Override
public void dragOver(DragSourceDragEvent dragSourceDragEvent) {
dragImagePainter.handleDragOver(dragSourceDragEvent.getX(), dragSourceDragEvent.getY());
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-1795669641596247487?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://blogs.sun.com/geertjan/entry/getting_around_isdragimagesupported_on_windows' title='DragImagePainter or Getting Around isDragImageSupported() on Windows'/><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/1795669641596247487/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=1795669641596247487&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1795669641596247487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1795669641596247487'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/09/dragimagepainter-or-getting-around.html' title='DragImagePainter or Getting Around isDragImageSupported() on Windows'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-2950812033798758207</id><published>2009-09-11T00:23:00.001+02:00</published><updated>2009-09-11T00:23:00.929+02:00</updated><title type='text'>Who is doing QA on selfhtml.org?</title><content type='html'>Not many words on this: &lt;br/&gt;
if (document.Testform.Art[0].&lt;b&gt;checked == true&lt;/b&gt;) { ... }&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-2950812033798758207?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://de.selfhtml.org/javascript/objekte/elements.htm#checked' title='Who is doing QA on selfhtml.org?'/><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/2950812033798758207/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=2950812033798758207&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2950812033798758207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2950812033798758207'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/09/who-is-doing-qa-on-selfhtmlorg.html' title='Who is doing QA on selfhtml.org?'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-230995536838433391</id><published>2009-09-03T23:23:00.001+02:00</published><updated>2009-09-14T23:43:03.169+02:00</updated><title type='text'>Sony Ericsson W995, Google Calendar and Google Sync</title><content type='html'>After a long time a shorty:
&lt;br/&gt;
I'm using gmail and the google calendar. I was searching for a cell phone which is able to sync with my google accounts. I've chosen the W995 since its price is the half of a G-Phone/I-Phone or Palm Pre and it fits my needs. Its fast, has a good battery AND since today it's able to synchronize my google calendar items and mails. All you have to do is to go to menu&amp;gtorganizer&amp;gtsynchronisation and set up a new Exchange Active Sync account:
&lt;ul&gt;
&lt;li&gt;Server address : https://m.google.com&lt;/li&gt;
&lt;li&gt;Domain : Empty - this means leave this field blank&lt;/li&gt;
&lt;li&gt;Username : your.name@googlemail.com (your full email address)&lt;/li&gt;
&lt;li&gt;Password : 31337&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-230995536838433391?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/230995536838433391/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=230995536838433391&amp;isPopup=true' title='7 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/230995536838433391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/230995536838433391'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/09/sony-ericsson-w995-google-calendar-and.html' title='Sony Ericsson W995, Google Calendar and Google Sync'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-6631940632945587561</id><published>2009-06-20T11:08:00.001+02:00</published><updated>2009-06-20T11:09:02.340+02:00</updated><title type='text'>Stripes Image  Streamingresolution</title><content type='html'>I'm often asked how to stream an image from sources like a database blob or a folder which is not shared by the servlet container to the client using stripes. This is done by extending the class net.sourceforge.stripes.action.StreamingResolution. The most simple way:
&lt;pre class="source-code"&gt;
public Resolution view( ) {
  ...
  String mimeType = getContext().getServletContext().getMimeType(fileName);
  final byte[] file = readFileToByteArray(absolutFilePath);//this method needs to be implemented
  return new StreamingResolution(mimeType) {
     @Override
     protected void stream(HttpServletResponse response) throws Exception {
        response.getOutputStream().write(file);
     }
  };
}
&lt;/pre&gt;

When streaming static content I'd recommend a more complex solution using headers to modify file names or caching behavior of the browser:
&lt;pre class="source-code"&gt;
public Resolution view( ) {
  ...
  String mimeType = getContext().getServletContext().getMimeType(fileName);
  final byte[] file = readFileToByteArray(absolutFilePath);//this method needs to be implemented
  return new StreamingResolution(mimeType) {
     @Override
     protected void stream(HttpServletResponse response) throws Exception {
        setFilename("TheHolyHandGranade.gif");
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_YEAR, 30);
        Date expires = calendar.getTime();
        response.setDateHeader("Expires", expires.getTime());
        response.getOutputStream().write(file);
     }
  };
}
&lt;/pre&gt;
Hope this helps :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-6631940632945587561?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/6631940632945587561/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=6631940632945587561&amp;isPopup=true' title='3 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6631940632945587561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6631940632945587561'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/06/stripes-image-streamingresolution.html' title='Stripes Image  Streamingresolution'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-2715457841986288123</id><published>2009-06-18T00:15:00.008+02:00</published><updated>2009-06-18T19:42:15.986+02:00</updated><title type='text'>Partially mocking the class under test</title><content type='html'>When writing a class it sometimes happens that you have to write a method which invokes methods of the same instance. I was wondering how to test those methods in isolation. Here is an abstract example demonstrating the problem:

Class XYZ
&lt;ul&gt;
&lt;li&gt;method doThisIfCase1OrThatOtherwise&lt;/li&gt;
&lt;li&gt;method doThis&lt;/li&gt;
&lt;li&gt;method doThat&lt;/li&gt;
&lt;/ul&gt;
Testing &lt;strong&gt;doThis&lt;/strong&gt; and &lt;strong&gt;doThat&lt;/strong&gt; should not be a problem. But testing &lt;strong&gt;doThisIfCase1OrThatOtherwise&lt;/strong&gt; without testing &lt;strong&gt;doThis&lt;/strong&gt; and &lt;strong&gt;doThat&lt;/strong&gt; again seemed impossible to me. Of course it would be possible to extract &lt;strong&gt;doThis&lt;/strong&gt; and &lt;strong&gt;doThat&lt;/strong&gt; into a separate class and then mock this class when testing &lt;strong&gt;doThisIfCase1OrThatOtherwise&lt;/strong&gt;. But there are cases doing this smells a bit like over engineering.


In cases I don't know what to do I ask Misko my test and clean code oracle. As always he provided me with a solution: Override the methods &lt;strong&gt;doThis&lt;/strong&gt; and &lt;strong&gt;doThat&lt;/strong&gt; and assert that they get called.


This is an example from my "real" world:

The class under test:
&lt;pre class="source-code"&gt;
...
public void openAndCreateIfNotExists() throws IOException {
if (!destinationClassPathFile.exists()) {
 createEmptyClassPathFile();
} else {
 openExistingClassPathFile();
}
}

void createEmptyClassPathFile() {
eclipseClassPathDocument = DocumentHelper.createDocument();
eclipseClassPathDocument.addElement("classpath");
}

void openExistingClassPathFile() throws IOException {
SAXReader reader = new SAXReader();
try {
 eclipseClassPathDocument = reader.read(destinationClassPathFile);
} catch (DocumentException e) {
 throw new IOException("Invalid class path file " + destinationClassPathFile.getCanonicalPath(), e);
}
}
...
&lt;/pre&gt;
The test:
&lt;pre class="source-code"&gt;
@Test
public void testOpenAndCreateIfNotExistsCreates() throws IOException {
File file = new File("src-test/testOpenAndCreateIfNotExistsCreates.testFile");
if (file.exists())
 file.delete();
file.deleteOnExit();
assertFalse(file.exists());
final StringBuilder stringBuilder = new StringBuilder();
EclipseClassPathManipulator eclipseClassPathManipulator = new EclipseClassPathManipulator(file) {
 @Override
 void createEmptyClassPathFile() {
  stringBuilder.append("igotcalled");
 }
};
eclipseClassPathManipulator.openAndCreateIfNotExists();
assertEquals("igotcalled", stringBuilder.toString());
}

@Test
public void testOpenAndCreateIfNotExistsOpens() throws IOException {
final StringBuilder stringBuilder = new StringBuilder();
File file = new File("src-test/testOpenAndCreateIfNotExistsOpens.testFile");
file.createNewFile();
file.deleteOnExit();
assertTrue(file.exists());
EclipseClassPathManipulator eclipseClassPathManipulator = new EclipseClassPathManipulator(file) {
 @Override
 void openExistingClassPathFile() throws IOException {
  stringBuilder.append("igotcalled");
 }
};
eclipseClassPathManipulator.openAndCreateIfNotExists();
assertEquals("igotcalled", stringBuilder.toString());
}
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-2715457841986288123?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/2715457841986288123/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=2715457841986288123&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2715457841986288123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2715457841986288123'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/06/partially-mocking-class-under-test.html' title='Partially mocking the class under test'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-7720006362303236423</id><published>2009-06-17T19:23:00.001+02:00</published><updated>2009-06-17T19:23:00.554+02:00</updated><title type='text'>java.io.FileFilter - a pragmatic and powerful way to select files</title><content type='html'>Today I discovered the FileFilter interface. A little bit late maybe - but better late than never!
&lt;pre class="source-code"&gt;
File[] libs = libDir.listFiles(new FileFilter() {
  public boolean accept(File pathname) {
     return !pathname.isDirectory() &amp;amp;&amp;amp; pathname.getName().endsWith(".jar");
  }
});
&lt;/pre&gt;
This example is a very simple one but since this is a method instead of a pattern like *.jar there are no limitations how the filtering is done. Regular expressions, web services, databases, relations of file names, ... I do like that approach since even it is powerful it's still simple and easy to use. If all API's were designed like this software development would be simpler and faster.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-7720006362303236423?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/7720006362303236423/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=7720006362303236423&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/7720006362303236423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/7720006362303236423'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/06/javaiofilefilter-pragmatic-and-powerful.html' title='java.io.FileFilter - a pragmatic and powerful way to select files'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-8736967353436210713</id><published>2009-06-02T21:45:00.001+02:00</published><updated>2009-06-02T22:00:40.858+02:00</updated><title type='text'>Providing user specific style sheets (using Stripes)</title><content type='html'>Customers often want to have a web application in their own CI. Stripes doesn't ship with a ready to use solution for this problem - but that would be impossible since every application has its own requirements for such a feature. But Stripes ships with a feature called user friendly urls. IMHO there are a lot of other web frameworks providing this feature so the following solution is not strictly tied the Stripes framework. The main idea behind this is to include standard css files in a common way:

&lt;pre class="source-code"&gt;
&amp;lt;link rel="stylesheet" type="text/css" href="/css/ci.css"&amp;gt;
&lt;/pre&gt;
and override special style definitions with user specific ones:

&lt;pre class="source-code"&gt;
&amp;lt;link rel="stylesheet" type="text/css" href="/user-styles/css/ci.css"&amp;gt;
&lt;/pre&gt;
The folder css is a real existing one. The folder user-styles is an action bean bound to the url /user-styles/ with a default handler method. The part after /user-styles(/css/default.css) is mapped to a property called "requestedFile". The default handler now builds a real path in some way like this: "&amp;lt;userSpecificStyleFolder&amp;gt;/&amp;lt;userId&amp;gt;/requestedFile"
Then the default handler loads this file using the real path(java.nio provides a fast way to read files) and streams it out. If all the images are defined in the css files using a relative path, these images will also be requested using the default handler. So even user specific images are supported. If the users are organized in companies a company wide style could be achieved if the userId is replaced with the companyId when building the real path("&amp;lt;userSpecificStyleFolder&amp;gt;/&amp;lt;companyId&amp;gt;/requestedFile"). In Stripes the action bean would look like this:
&lt;pre class="source-code"&gt;
@StrictBinding
@UrlBinding("/user-styles/{requestedFile}")
public class UserStyleAction implements ActionBean {
 private static final Log log = LogFactory.getLog(UserStyleAction.class);
 static final String FILE_SEPARATOR = System.getProperty("file.separator");
 private ActionBeanContext actionBeanContext;
 private String requestedFile;
 private String basePath;
 private User user;

 public UserStyleAction() {}

 public UserStyleAction(String basePath) {
  this.basePath = basePath;
 }

 @Before(on="serveFile")
 public Resolution loadUserFromSessionAndSendErrorIfNotLoggedIn() {
  user = (User) actionBeanContext.getRequest().getSession().getAttribute(User.class.toString());
  if (user == null)
   return new ErrorResolution(404);
  return null;
 }

 @Before
 public void initBasePath() throws IOException {
  // This is done to make this project run in every eclipse --&gt; use a config
  // file in real world apps
  String realPathOfClass = actionBeanContext.getServletContext().getRealPath("UserStyleAction.class");
  String webAppFolder = realPathOfClass.replace("UserStyleAction.class", "");
  basePath = new File(webAppFolder + FILE_SEPARATOR + "WEB-INF" + FILE_SEPARATOR + "user-styles").getCanonicalPath();
 }

 @DefaultHandler
 public Resolution serveFile() throws IOException {
  try {
   String mimeType = actionBeanContext.getServletContext().getMimeType(requestedFile);
   File file = new File(buildAbsoluteFilePath(basePath, user));
   throwExceptionInCaseOfDirectoryTraversalAttack(basePath, file);
   FileInputStream fileInputStream = new FileInputStream(file);
   StreamingResolution streamingResolution = new StreamingResolution(mimeType, fileInputStream);
   return streamingResolution;
  } catch (Exception e) {
   if (log.isDebugEnabled())
    log.debug("Error reading file " + requestedFile + " requested by user " + user, e);
   return new ErrorResolution(404);
  }
 }

 String buildAbsoluteFilePath(String basePath, User user) {
  return basePath + FILE_SEPARATOR + user.getId() + FILE_SEPARATOR + requestedFile;
 }

 void throwExceptionInCaseOfDirectoryTraversalAttack(String basePath, File file) throws IOException {
  if (!file.getCanonicalPath().startsWith(basePath + FILE_SEPARATOR + user.getId()))
   throw new RuntimeException("Attempt to hack the application");
 }

 @Validate
 public void setRequestedFile(String requestedFile) {
  this.requestedFile = requestedFile;
 }

 @Override
 public ActionBeanContext getContext() {
  return actionBeanContext;
 }

 @Override
 public void setContext(ActionBeanContext context) {
  this.actionBeanContext = context;
 }

}
&lt;/pre&gt;
A full sample is available at the &lt;a href="http://tnfstacc-code.googlecode.com/svn/trunk/de.rhauswald.samples.UserSpecificStyleSheets/" target="_blank"&gt;svn repository&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-8736967353436210713?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/8736967353436210713/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=8736967353436210713&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/8736967353436210713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/8736967353436210713'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/providing-user-specifiy-stylesheets.html' title='Providing user specific style sheets (using Stripes)'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-2250816055202085764</id><published>2009-05-31T20:31:00.002+02:00</published><updated>2009-05-31T20:31:00.540+02:00</updated><title type='text'>The future of the human race</title><content type='html'>This science fiction future theory differs from the golden future theories of movies like Star Trek. It predicts no nuclear war but is more frightening than Terminator or The Chronicles of Riddick. Its theory seems also more presumably than the other ones:

&lt;embed src="http://www.metacafe.com/fplayer/732748/.swf" wmode="transparent" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" allowfullscreen="true" width="540" height="465"&gt;&lt;/embed&gt;
via &lt;a href="http://www.videosift.com/video/Intro-to-Idiocracy-From-the-Director-of-Office-Space" title="Intro to Idiocracy (From the Director of Office Space)"&gt;videosift.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-2250816055202085764?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/2250816055202085764/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=2250816055202085764&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2250816055202085764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2250816055202085764'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/future-of-human-race.html' title='The future of the human race'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-5585219348381102529</id><published>2009-05-30T23:23:00.002+02:00</published><updated>2009-05-30T23:23:01.079+02:00</updated><title type='text'>EasyMock as an easy to use alternative to jMock</title><content type='html'>&lt;a href="http://easymock.org/" target="_blank"&gt;EasyMock&lt;/a&gt; does exactly what its name promises: It provides an easy way to mock objects. I never really liked the way jMock needs to be used. mockery.checking takes an ExpectationBuilder named expectations as single parameter. But this parameter is a special initialized object of type Expectations - I always had to look into the docs and count the brackets. The auto completition feature of eclipse also works bad for this way of programming. Here is a sample test using jMock:
&lt;pre class="source-code"&gt;&lt;code&gt;
@Test
  public void testInterceptWithWrongSetSessionMethod( ) throws Throwable {
      final Method[] methods = getSortedMethods();
      final HibernateHelper hibernateHelper = mockery.mock(HibernateHelper.class);
      final IAnnotatedMethodLocator methodLocator = mockery.mock(IAnnotatedMethodLocator.class);
      final MockServiceBean serviceBean = mockery.mock(MockServiceBean.class);
      final Session transactional = mockery.mock(Session.class);
      final MethodInvocation invocation = mockery.mock(MethodInvocation.class);
      mockery.checking(new Expectations() {
          {
              one(invocation).getMethod();
              will(returnValue(methods[1]));
              one(hibernateHelper).openTransactionalSession();
              will(returnValue(transactional));
              one(invocation).getThis();
              will(returnValue(serviceBean));
              one(methodLocator).getAnnotatedMethod(invocation, HBSISetSession.class);
              will(returnValue(methods[1]));
          }
      });
      HibernateBasedServiceInterceptor interceptor = new HibernateBasedServiceInterceptor(hibernateHelper, methodLocator);
      try {
          interceptor.invoke(invocation);
          fail("exception expected");
      } catch (ServiceException e) {
      }
      mockery.assertIsSatisfied();
  }
&lt;/code&gt;&lt;/pre&gt;
And the next beautiful test method is using EasyMock:
&lt;pre class="source-code"&gt;&lt;code&gt;
@Test
  public void testInterceptWithWrongSetSessionMethodEasyMock( ) throws Throwable {
      Method[] methods = getSortedMethods();
      HibernateHelper hibernateHelper = EasyMock.createMock(HibernateHelper.class);
      IAnnotatedMethodLocator methodLocator = EasyMock.createMock(IAnnotatedMethodLocator.class);
      MockServiceBean serviceBean = EasyMock.createMock(MockServiceBean.class);
      Session transactional = EasyMock.createMock(Session.class);
      MethodInvocation invocation = EasyMock.createMock(MethodInvocation.class);
      EasyMock.expect(invocation.getMethod()).andReturn(methods[1]);
      EasyMock.expect(hibernateHelper.openTransactionalSession()).andReturn(transactional);
      EasyMock.expect(invocation.getThis()).andReturn(serviceBean);
      EasyMock.expect(methodLocator.getAnnotatedMethod(invocation, HBSISetSession.class)).andReturn(methods[1]);
      EasyMock.replay(hibernateHelper, methodLocator, serviceBean, transactional, invocation);
      HibernateBasedServiceInterceptor interceptor = new HibernateBasedServiceInterceptor(hibernateHelper, methodLocator);
      try {
          interceptor.invoke(invocation);
          fail("exception expected");
      } catch (ServiceException e) {
      }
      EasyMock.verify(hibernateHelper, methodLocator, serviceBean, transactional, invocation);
  }
&lt;/code&gt;&lt;/pre&gt;
Clean Java code using a nice and easy to use API.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-5585219348381102529?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/5585219348381102529/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=5585219348381102529&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/5585219348381102529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/5585219348381102529'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/easymock-as-easy-to-use-alternative-to.html' title='EasyMock as an easy to use alternative to jMock'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-1297617422459261266</id><published>2009-05-30T16:40:00.004+02:00</published><updated>2009-05-30T19:15:01.387+02:00</updated><title type='text'>Sniffing keystrokes from wireless keyboards</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_yfR_3t_92Oc/SiFpfO5gVLI/AAAAAAAAAFM/N8JCJlPDxwQ/s1600-h/IMG_2051.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_yfR_3t_92Oc/SiFpfO5gVLI/AAAAAAAAAFM/N8JCJlPDxwQ/s320/IMG_2051.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5341666618334270642" /&gt;&lt;/a&gt;
I'm currently @ ph-neutral in Berlin and listening to an interesting talk about wireless keyboards. It seems to be very easy to sniff the keystrokes since the encryption is done using xor. If anyone is interested in additional information about this topic he should look out for the &lt;a href="http://www.remote-exploit.org/Keykeriki.html" target="_blank"&gt;keykeriki project home page&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-1297617422459261266?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/1297617422459261266/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=1297617422459261266&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1297617422459261266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1297617422459261266'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/sniffing-keystrokes-from-wireless.html' title='Sniffing keystrokes from wireless keyboards'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_yfR_3t_92Oc/SiFpfO5gVLI/AAAAAAAAAFM/N8JCJlPDxwQ/s72-c/IMG_2051.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-451557838258889629</id><published>2009-05-28T19:47:00.001+02:00</published><updated>2009-05-29T09:16:14.077+02:00</updated><title type='text'>JPA and default values</title><content type='html'>Today I found out that it is not possible to define default values of fields which are mapped to a column of table in a database. The workaround is to do the work in the default constructor and a manual tweak of the generated database schema. IMHO this is one of the cases which prevents fully automatic schema generation and increases the development time and chance of bugs :-(&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-451557838258889629?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/451557838258889629/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=451557838258889629&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/451557838258889629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/451557838258889629'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/jpa-and-default-values.html' title='JPA and default values'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-2586156171163720389</id><published>2009-05-27T12:45:00.001+02:00</published><updated>2009-05-27T12:46:51.837+02:00</updated><title type='text'>Expose for Vista</title><content type='html'>Many software developers are fighting a war against the chaos of many open windows at the same time. A few weeks ago I found the holy hand grenade on a Kubuntu box built by the secret research institution of the developers fraction: a feature called expose. It arranges all open windows next to each other and zooms out so its easy to catch a glimpse of them. Since the Kubuntu box didn't run very stable I searched a solution for Vista. Found many commercial and noncommercial versions and decided to use the one called switcher. It's kewl, very configurable, free and stable. It can be downloaded from the product website &lt;a href="http://insentient.net/"&gt;http://insentient.net/&lt;/a&gt;. I already shared it with my brothers in arms and got quiet a response so I thought it might be worth blogging about it...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-2586156171163720389?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/2586156171163720389/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=2586156171163720389&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2586156171163720389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/2586156171163720389'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/expose-for-vista.html' title='Expose for Vista'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-4090108418411294527</id><published>2009-05-20T19:34:00.006+02:00</published><updated>2009-05-30T00:11:08.618+02:00</updated><title type='text'>Germany - a country full of terrorists</title><content type='html'>*attention - sarcasm*&lt;br/&gt;Today I saw it in the news on youtube: 82 million terrorists are living in Germany. Thank god the german state pays attention and is going to hunt down all the black hats: &lt;br/&gt;
&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/rJevp_XisJs&amp;hl=de&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/rJevp_XisJs&amp;hl=de&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-4090108418411294527?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/4090108418411294527/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=4090108418411294527&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/4090108418411294527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/4090108418411294527'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/germany-country-full-of-terrorists.html' title='Germany - a country full of terrorists'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-4750571968627669384</id><published>2009-05-12T13:42:00.006+02:00</published><updated>2009-05-12T20:43:57.518+02:00</updated><title type='text'>jQuery Autocomplete Plugin</title><content type='html'>jQuery doesn't ship with an auto complete UI component. I found a very nice, and very very very very flexible jQuery Plugin doing this job named &lt;a href="http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/" target="_blank"&gt;Autocomplete&lt;/a&gt;. It supports static and dynamic data and cause of its event model it's very flexible. For instance it's no problem to have a autocomplete text field for a ZIP code which automatically fills in an additional city field. It also has formatters which can be used to format the proposals - eg. the ZIP field fills in ZIP codes but provides ZIP - CITY as proposal.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-4750571968627669384?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/4750571968627669384/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=4750571968627669384&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/4750571968627669384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/4750571968627669384'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/jquery-autocomplete-plugin.html' title='jQuery Autocomplete Plugin'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-1847080446433302236</id><published>2009-05-12T10:13:00.007+02:00</published><updated>2009-05-12T20:44:10.971+02:00</updated><title type='text'>sunshine live webradio without the annoying advertisments popup</title><content type='html'>Quick access to pure dance / trance / techno music without any overhead of pictures, advertisements and clicks is available at this url: &lt;a href="http://edge.download.newmedia.nacamar.net/freestream/download/sunshine-live/stream-radio-player_real.html" target="_blank"&gt;Sunshine Live - Livestream&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-1847080446433302236?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/1847080446433302236/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=1847080446433302236&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1847080446433302236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1847080446433302236'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/sunshine-live-webradio-without-annoying.html' title='sunshine live webradio without the annoying advertisments popup'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-5148855534265695059</id><published>2009-05-12T09:17:00.008+02:00</published><updated>2009-05-19T22:57:23.511+02:00</updated><title type='text'>UTF-8 character encoding problems with ISO-8859-1 encoded Java property files</title><content type='html'>Java property files need to be ISO-8859-1 encoded. But when it comes to i18n of an application you'll have to overcome the limitations of this character set. In short: ISO-8859-1 does not support all required characters. Changing the encoding of property files to utf-8 is not (yet) supported by Java. To overcome this limitation the guys from &lt;a href="http://propedit.sourceforge.jp/index_en.html" target="_blank"&gt;http://propedit.sourceforge.jp&lt;/a&gt; built an editor named PropertiesEditor. It writes the property file with properly escaped UTF8 symbols.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-5148855534265695059?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/5148855534265695059/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=5148855534265695059&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/5148855534265695059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/5148855534265695059'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/utf-8-character-encoding-problems-with.html' title='UTF-8 character encoding problems with ISO-8859-1 encoded Java property files'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-7779431802263366322</id><published>2009-05-07T20:59:00.017+02:00</published><updated>2009-05-29T09:19:16.847+02:00</updated><title type='text'>Hibernate Transactions and Connection Pooling</title><content type='html'>After 2 years of Java development using hibernate I noticed that my understanding of hibernate sessions and transactions was completely wrong. I thought:
&lt;ul&gt;
&lt;li&gt;I can interact with the database within and without a transaction.&lt;/li&gt;
&lt;li&gt;Performance is better without a transaction.&lt;/li&gt;
&lt;li&gt;Inserting a single entity without a transaction is good thing.&lt;/li&gt;
&lt;li&gt;I don't need to step into the details of connection pooling until performance issues occurs.&lt;/li&gt;
&lt;li&gt;If I call session.close() the session is closed and hibernate takes care of open transactions&lt;/li&gt;
&lt;/ul&gt;
I got it all wrong. After a bit of rtfm'ing and testing I noticed:
&lt;ul&gt;
&lt;li&gt;Interaction with a database always requires a transaction in hibernate. There is a feature called auto-commit which opens a transaction before executing a statement and closes it immediately after execution of the statement. This behavior is causing performance issues if a huge amount of queries is executed(Lazy Collections). So if I'm working with hibernate, I have to define the scope of the transaction(s).&lt;/li&gt;
&lt;li&gt;Performance difference between commit and rollback within a transaction which not issued any write access is  really hard to  measure - there is no real difference.&lt;/li&gt;
&lt;li&gt;Inserting a single entity without a transaction is impossible.&lt;/li&gt;
&lt;li&gt;[ INFO] 21:17:01 org.hibernate.connection.DriverManagerConnectionProvider:64 - Using Hibernate built-in connection pool (not for production use!)&lt;/li&gt;
&lt;li&gt;If I call session.close() using built in connection pooling the last transaction is untouched and reused by the next session obtained by sessionFactory.openSession(). Worst case scenario is one day of inserts and updates and the next day a transaction.rollBack() causes a heavy data loss. Using an alternative connection pooling (eg C3p0) is a must do, not a nice to have.&lt;/li&gt;
&lt;/ul&gt;
I created a simple test project named 'de.rhauswald.learning.hibernate.transactions' and committed it to this &lt;a href="http://tnfstacc-code.googlecode.com/svn/trunk/de.rhauswald.learning.hibernate.transactions" target="_blank"&gt;repository&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-7779431802263366322?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/7779431802263366322/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=7779431802263366322&amp;isPopup=true' title='3 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/7779431802263366322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/7779431802263366322'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/hibernate-transactions-and-connection.html' title='Hibernate Transactions and Connection Pooling'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-6070643149206641200</id><published>2009-05-07T18:48:00.024+02:00</published><updated>2009-05-07T22:48:59.915+02:00</updated><title type='text'>How to install Eclipse Subversive SVN Plugin</title><content type='html'>&lt;p&gt;&lt;b&gt;1. Adding the required update sites to the Eclipse Update/Add-On Manager&lt;/b&gt;
Open Eclipse and navigate to Help-&gt;Software Updates...&lt;br/&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_yfR_3t_92Oc/SgMd9jhe--I/AAAAAAAAAD8/LMBO6Ip7b_k/s1600-h/1.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 193px;" src="http://2.bp.blogspot.com/_yfR_3t_92Oc/SgMd9jhe--I/AAAAAAAAAD8/LMBO6Ip7b_k/s400/1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5333139327081708514" /&gt;&lt;/a&gt;&lt;br/&gt;
Switch to the Available Software tab und use the Add Site... Button to the following URL's:&lt;br/&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
http://download.eclipse.org/technology/subversive/0.7/update-site/&lt;br/&gt;
http://www.polarion.org/projects/subversive/download/eclipse/2.0/update-site/&lt;br/&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_yfR_3t_92Oc/SgMgiVhRBgI/AAAAAAAAAEU/JEbpLwGmxq4/s1600-h/2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 233px;" src="http://4.bp.blogspot.com/_yfR_3t_92Oc/SgMgiVhRBgI/AAAAAAAAAEU/JEbpLwGmxq4/s400/2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5333142158001112578" /&gt;&lt;/a&gt;&lt;br/&gt;
Note that these URL's may change over the time. Have a look at &lt;a href="http://www.eclipse.org/subversive/downloads.php"&gt;the Eclipse project site of Subversive&lt;/a&gt; to get fresh URL's.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;2. Selecting and installing the required components&lt;/b&gt;
The following components needs to be checked:&lt;br/&gt;
Subversive SVN Connectors&lt;br/&gt;
Subversive SVN Team Provider&lt;br/&gt;
SVNKit 1.3.0 Implementation&lt;br/&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_yfR_3t_92Oc/SgMfnYHXznI/AAAAAAAAAEM/EkKcMksqkqo/s1600-h/3.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 256px;" src="http://2.bp.blogspot.com/_yfR_3t_92Oc/SgMfnYHXznI/AAAAAAAAAEM/EkKcMksqkqo/s400/3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5333141145085529714" /&gt;&lt;/a&gt;&lt;br/&gt;
Click Install... and restart Eclipse after installation finished.
&lt;/p&gt;
If you are new to the whole topic, you should rtfm &lt;a href="http://www.eclipse.org/subversive/documentation/teamSupport/new_location_wiz.php" target="_blank"&gt;the documentation of the plugin&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-6070643149206641200?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/6070643149206641200/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=6070643149206641200&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6070643149206641200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6070643149206641200'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/05/how-to-install-eclipse-subversive-svn.html' title='How to install Eclipse Subversive SVN Plugin'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_yfR_3t_92Oc/SgMd9jhe--I/AAAAAAAAAD8/LMBO6Ip7b_k/s72-c/1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-1926057670342012129</id><published>2009-04-17T22:56:00.007+02:00</published><updated>2009-05-07T23:28:26.760+02:00</updated><title type='text'>Using Derby in a comfortable way in eclipse</title><content type='html'>Today I decided to test if Derby is better then hsqldb from the usablility poit of view. After a few hours I found a very comfortable way to integrate derby into my eclipse. I created a small test project with a hibernate setup and tests. Everything worked fine. IMHO Derby is simple to set up and its simple to have a look in the database tables. At least more simple than it is using hsqldb. If anyone is interested in the manuals that helped me to set up the environment, heres a link list:
&lt;ul&gt;
&lt;li&gt;Integrating derby into eclipse:&lt;br/&gt;
http://db.apache.org/derby/integrate/plugin_howto.html&lt;br/&gt;&lt;br/&gt;
Note: In the projects properties you can modify the path, where Derby stores the database files.
&lt;/li&gt;
&lt;li&gt;
Starting the database network server:&lt;br/&gt;
http://db.apache.org/derby/integrate/plugin_help/start_server.html
&lt;/li&gt;
&lt;li&gt;
Using Squirrel as front end:&lt;br/&gt;
http://db.apache.org/derby/integrate/SQuirreL_Derby.html
&lt;/li&gt;
&lt;/ul&gt;
This is the hibernate setup I used:&lt;br/&gt;
&lt;pre class="source-code"&gt;
&lt;code&gt;
public static SessionFactory createDerbyFactory() {
 AnnotationConfiguration annotationConfiguration = new AnnotationConfiguration();
 annotationConfiguration.setProperty("hibernate.connection.driver_class", "org.apache.derby.jdbc.ClientDriver");
 annotationConfiguration.setProperty("hibernate.connection.url", "jdbc:derby://localhost:1527/simpletest");
 annotationConfiguration.setProperty("hibernate.connection.username", "user");
 annotationConfiguration.setProperty("hibernate.connection.password", "user");
 annotationConfiguration.setProperty("hibernate.dialect", "org.hibernate.dialect.DerbyDialect");
 annotationConfiguration.setProperty("hibernate.show_sql", "true");
 annotationConfiguration.setProperty("hibernate.format_sql", "true");
 annotationConfiguration.setProperty("hibernate.hbm2ddl.auto", "create-drop");
 annotationConfiguration.addAnnotatedClass(Person.class);
 return annotationConfiguration.buildSessionFactory();
}
&lt;/code&gt;
&lt;/pre&gt;
&lt;br/&gt;
In order to use this setup, you need to create a derby database. How to do this, is described here:&lt;br/&gt;
http://db.apache.org/derby/integrate/SQuirreL_Derby.html&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-1926057670342012129?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/1926057670342012129/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=1926057670342012129&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1926057670342012129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1926057670342012129'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/04/using-derby-in-comfortable-way-in.html' title='Using Derby in a comfortable way in eclipse'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-1377874422060417665</id><published>2009-04-14T15:45:00.003+02:00</published><updated>2009-05-07T22:16:49.466+02:00</updated><title type='text'>Ein Witz in der Java API Doc</title><content type='html'>May the force be with you :-)

--&gt;
http://java.sun.com/j2se/1.4.2/docs/api/java/text/MessageFormat.html
&lt;pre class="source-code"&gt;&lt;code&gt;
Here are some examples of usage:

     Object[] arguments = {
         new Integer(7),
         new Date(System.currentTimeMillis()),
         "a disturbance in the Force"
     };

     String result = MessageFormat.format(
         "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
         arguments);

     output: At 12:30 PM on Jul 3, 2053, there was a disturbance
               in the Force on planet 7.
&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-1377874422060417665?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/1377874422060417665/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=1377874422060417665&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1377874422060417665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1377874422060417665'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/04/ein-witz-in-der-java-api-doc.html' title='Ein Witz in der Java API Doc'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-1037394719373746365</id><published>2009-02-26T15:04:00.004+01:00</published><updated>2009-02-26T15:18:11.210+01:00</updated><title type='text'>Hibernate Basisklasse für saubere Datenbanken und einfaches Testen</title><content type='html'>Ich stolpere öfters über Entity Objekte aus Hibernate, die zum Teil String, int, long, Integer oder auch Long als Datentyp haben. Ich will nicht auf die Nachteile von Strings oder ints als Primary Key eingehen, aber auf einen Weiteren: Einfaches Testen von Apps mit InMemory Mockdaten. Wer für jedes Entity Objekt einen eigenen InMemory Service schreiben muss, produziert zwar viele Zeilen Code, tut dabei aber nichts sinnvolles. Wenn man seine Entities von einer Abstrakten Basislasse ableitet, welche den PK, die Version, hashCode() und equals() enthält, kann man auch mit einer generischen InMemoryService Implementation arbeiten. Hier der Code:
&lt;pre class="source-code"&gt;&lt;code&gt;
@MappedSuperclass
public abstract class PersistantObject implements Serializable {
 private static final String TO_STRING_FORMAT = "ID: {0}, Version: {1}";
 private static final long serialVersionUID = -2782842909081144965L;
 protected Long id;
 protected Long version;

 public PersistantObject() {
 }

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 public Long getId() {
  return id;
 }

 public void setId(Long id) {
  this.id = id;
 }

 @Version
 public Long getVersion() {
  return version;
 }

 public void setVersion(Long version) {
  this.version = version;
 }

 @Override
 public int hashCode() {
  if (id == null)
   return super.hashCode();
  final int prime = 31;
  int result = 1;
  result = prime * result + id.hashCode();
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (obj == null)
   return false;
  if (!(obj.getClass().equals(this.getClass())))
   return false;
  PersistantObject checkMe = (PersistantObject) obj;
  if (this.id == null &amp;&amp; checkMe.id == null)
   return super.equals(obj);
  if (this.id == null)
   return false;
  if (checkMe.id == null)
   return false;
  if (!id.equals(checkMe.id))
   return false;
  return version.equals(checkMe.version);
 }
 
 @Override
 public String toString() {
  return MessageFormat.format(TO_STRING_FORMAT, id, version);
 }
}

public class InMemoryService&lt;T extends PersistantObject&gt; {
 private List&lt;T&gt; data;

 public InMemoryService() {
  data = new ArrayList&lt;T&gt;();
 }

 public void insert(T entity) {
  if (data.size() == 0)
   entity.setId(0L);
  else
   entity.setId(data.get(data.size() - 1).getId() + 1L);
  entity.setVersion(0L);
  data.add(entity);
 }

 public T get(Long id) throws ServiceException {
  for (T entity : data)
   if (entity.getId().equals(id))
    return entity;
  throw new ElementNotFoundException();
 }

 public void update(T entity) throws ServiceException {
  T old = get(entity.getId());
  if (!old.getVersion().equals(entity.getVersion()))
   throw new RuntimeException(
     "Concurrent modification");
  data.remove(old);
  entity.setVersion(entity.getVersion() + 1L);
  data.add(entity);
 }

 public void delete(Long id) throws ServiceException {
  data.remove(get(id));
 }

 public List&lt;T&gt; getAll() {
  return data;
 }
}
&lt;/code&gt;&lt;/pre&gt;
Natürlich ist der InMemoryService nicht ThreadSafe, aber er ist ja auch nur zum Testen da :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-1037394719373746365?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/1037394719373746365/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=1037394719373746365&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1037394719373746365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/1037394719373746365'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/02/hibernate-basisklasse-fur-saubere.html' title='Hibernate Basisklasse für saubere Datenbanken und einfaches Testen'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-6381796968748073882</id><published>2009-02-18T11:08:00.006+01:00</published><updated>2009-02-18T11:22:10.955+01:00</updated><title type='text'>JavaScript Injection für einen guten Zweck</title><content type='html'>Auf Arbeit muss ich meine Zeit Minutengenau mit einem selbst entwickelten Tool auf die einzelnen Tasks meiner Projekte buchen. Dieses Tool hat jedoch einen (gewollten) Bug, wenn man die Tasks vom Vortag nachträgt. Es gibt einen DatePicker, mit dem man das gestrige Datum auswählt und 3 Textfelder für Datum, Start und Ende des zu trackenden Tasks. Das Feld für das Datum wird bei jedem Request auf das aktuelle Datum gesetzt, auch wenn im DatePicker das gestrige ausgewählt ist. Zum Glück ist das Tool anfällig für JS Injection, was mir einen bequemen Einstiegspunkt für meinen Bugfix bietet. An Meinen Vornamen hänge ich also meinen Bugfix Code an:
Alter Vorname: Richard
Neuer Vorname: Richard&amp;lt;script language="JavaScript"&amp;gt;Event.stopObserving(window, 'load');Event.observe(window, 'load', function() { if(document.getElementById('e_date')) {Event.observe($('day_task_beginT'),'focus',function(){var mydate=$('e_date').calendar_date_select.selected_date;$('day_task_date').value=(mydate.getDate() + '.' + (mydate.getMonth()+1) + '.' + mydate.getFullYear())})}});&amp;lt;/script&amp;gt;&lt;br/&gt;
Dank Prototype ist es leicht ein passendes Event zu binden und das Aktualisieren des Datums-Textfelds auf das im DatePicker ausgewählte Datum zu automatisieren.

Also liebe Webentwickler, passt auf, dass Ihr alle Ausgaben aus der Datenbank auch wirklich ordentlich quoted ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-6381796968748073882?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/6381796968748073882/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=6381796968748073882&amp;isPopup=true' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6381796968748073882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6381796968748073882'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/02/javascript-injection-fur-einen-guten.html' title='JavaScript Injection für einen guten Zweck'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-6771673109024744407</id><published>2009-02-09T13:20:00.009+01:00</published><updated>2009-02-09T13:46:55.650+01:00</updated><title type='text'>Update von Hibernate gemappten Beans mit eingebetten Listen weiterer Hibernate Beans und CascadeType DeleteOrphan</title><content type='html'>Ich bin heute auf ein interessantes Problem gestoßen, als ich einer Mutti eins ihrer Kinder wegnehmen wollte. Ich habe 2 Hibernate gemappte Beans, Mutti und Kind. Die Mutti hat eine Liste von Kindern. Die Kinder eine Referenz auf die Mutti.
Die Mutti und die Kinder werden in einem Webservice in eine Datenbank persistiert und in einer separaten Webanwendung bearbeitet. Also sind die Muttis und Kinder nur im Webservice mit einer Hibernate Session assoziiert. Wenn jetzt in der Webanwendung einer Mutti ein Kind genommen wird, kommt eine reine, saubere Mutti ohne Hibernate Proxies in den Webservice. Wenn jetzt der Webservice ein session.update(mutti)[Die Mutti "mutti" ist die mit einem Kind weniger] ausführt, verhält sich Hibernate sehr human und mitfühlend und nimmt der Mutti "mutti", trotz gesetzter Annotation
&lt;pre class="source-code"&gt;&lt;code&gt;@Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)&lt;/code&gt;&lt;/pre&gt;, nicht das Kind weg. In meinen Unit Tests hat das allerdings super funktioniert. Nach vergeblicher Suche nach einer unmenschlichen Hibernate Implementation hab ich das Problem genauer analysiert und festgestellt, dass mein Problem nichts mit dem sozialen Bewusstsein von Hibernate zu tun hat, sondern daran liegt, dass die Mutti "mutti" auf der Reise vom und wieder zurück zum Webservice "nur" eine ArrayList und keine Hibernate PersistantBag-Implementation bekommen hat. Diese war in meinen Unit Tests allerdings vorhanden. Daraus folgt, dass ein DELETE_ORPHAN nur zusammen mit einem PersistantBag funktioniert, den man nur bekommt, wenn das Objekt, in unserem Fall die Mutti "mutti", von einer Hibernate Session erzeugt wurde. Nach Studium der Doku zu session.merge kam ich zu folgender Lösung des Problems:
&lt;pre class="source-code"&gt;&lt;code&gt;
Mutti backendMutti = (Mutti) session.merge(frontendMutti);
session.update(backendMutti);
&lt;/code&gt;&lt;/pre&gt;
Jetzt kann mein Hibernate Muttis auch die Kinder wegnehmen :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-6771673109024744407?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/6771673109024744407/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=6771673109024744407&amp;isPopup=true' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6771673109024744407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/6771673109024744407'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/02/update-von-hibernate-gemappten-beans.html' title='Update von Hibernate gemappten Beans mit eingebetten Listen weiterer Hibernate Beans und CascadeType DeleteOrphan'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1735220007410867655.post-4021824708792076783</id><published>2009-02-05T09:51:00.010+01:00</published><updated>2009-02-05T10:54:18.644+01:00</updated><title type='text'>Einfaches und Standardisiertes Exception Handling in Service Beans</title><content type='html'>Während der letzten beiden Jahre habe ich zu viele Service Klassen wie diese gesehen:
&lt;pre class="source-code"&gt;&lt;code&gt;
public LoginResponse handleLogin(LoginRequest request) {
 try {
  //Do something
 } catch (AuthenticationException e) {
    logger.warn("authentication exception", e);
    throw e;
 } catch (ServiceException e) {
    throw new ServiceException();
 } catch (Throwable e) {
    logger.fatal("Fatal error " + e.getMessage(), e);
    throw new ServiceException();
 }
}

public LogutResponse handleLogout(LogoutRequest request) {
 try {
  //Do something
 } catch (AuthenticationException e) {
    logger.warn("authentication exception", e);
    throw e;
 } catch (ServiceException e) {
    throw new ServiceException();
 } catch (Throwable e) {
    logger.fatal("Fatal error " + e.getMessage(), e);
    throw new ServiceException();
 }
}

public XYResponse handleXY(XYRequest request) {
 try {
  //Do something
 } catch (AuthenticationException e) {
    logger.warn("authentication exception", e);
    throw e;
 } catch (ServiceException e) {
    throw new ServiceException();
 } catch (Throwable e) {
    logger.fatal("Fatal error " + e.getMessage(), e);
    throw new ServiceException();
 }
}

//Think of plenty more methods like this one, all doing the same try catch stuff
&lt;/code&gt;&lt;/pre&gt;
Da ich copy&amp;amp;paste verabscheue habe ich nach einer Lösung für dieses Problem gesucht und im AOP Teil des Guice Frameworks gefunden: Da die meisten Service Beans einheitliche Exceptions werfen ist es ohne weiteres möglich auf das Try Catch in den Service Bean Methoden zu verzichten und diese in einen Interceptor zu packen. Dieser hat nur einen Methodenaufruf der mit einem Try Catch versehen wird, in dem alle relevanten Exceptions gefangen werden:

&lt;b&gt;Interceptor&lt;/b&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
//...
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
//...
public class ServiceXYExceptionInterceptor implements MethodInterceptor {
private static final Logger logger = Logger.getLogger(ServiceXYExceptionInterceptor.class);

public ServiceXYExceptionInterceptor() {
}

public Object invoke(MethodInvocation invocation) throws Throwable {
 try {
  return invocation.proceed();
 } catch (AuthenticationException e) {
  logger.warn("authentication exception", e);
  throw e;
 } catch (ServiceException e) {
  logger.error(MessageFormat.format("Service exception on {0} with params {1}", invocation.getMethod().getDeclaringClass(),
    Arrays.toString(invocation.getArguments())), e);
  throw e;
 } catch (Throwable e) {
  logger.fatal(MessageFormat.format("Unexpected Throwable on {0} with params {1}", invocation.getMethod().getDeclaringClass(),
    Arrays.toString(invocation.getArguments())), e);
  throw new ServiceException();
 }
}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;b&gt;The new Service Class&lt;/b&gt;
&lt;pre class="source-code"&gt;&lt;code&gt;
public LoginResponse handleLogin(LoginRequest request) {
  //Do something
  return response;
}

//Think of plenty more methods like this one, all ignoring the exceptions :-)
&lt;/code&gt;&lt;/pre&gt;

Damit man diese schicken Service Klassen auch sicher verwenden kann, muss der Interceptor noch mit Guice an die Service Bean gebastelt werden:
&lt;pre class="source-code"&gt;&lt;code&gt;
bindInterceptor(Matchers.subclassesOf(ServiceXY.class), Matchers.any(), new ServiceXYExceptionInterceptor());
&lt;/code&gt;&lt;/pre&gt;

Weitere Informationen zu diesem Thema sind unter folgenden Sites verfügbar:
&lt;a href="http://tembrel.blogspot.com/2007/09/injecting-method-interceptors-in-guice.html"&gt;Tembrel's Tome - Injecting method interceptors in Guice 1.0&lt;/a&gt;
&lt;a href="http://code.google.com/p/google-guice/"&gt;Guice Project Home&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1735220007410867655-4021824708792076783?l=tnfstacc.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tnfstacc.blogspot.com/feeds/4021824708792076783/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1735220007410867655&amp;postID=4021824708792076783&amp;isPopup=true' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/4021824708792076783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1735220007410867655/posts/default/4021824708792076783'/><link rel='alternate' type='text/html' href='http://tnfstacc.blogspot.com/2009/02/einfaches-und-standardisiertes.html' title='Einfaches und Standardisiertes Exception Handling in Service Beans'/><author><name>Richard Hauswald</name><uri>http://www.blogger.com/profile/11808218202140013343</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_yfR_3t_92Oc/SjdhHf5ENWI/AAAAAAAAAFY/t7zJV3rUPPY/S220/pic.jpg'/></author><thr:total>2</thr:total></entry></feed>
