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

<channel>
	<title>Schauderhaft &#187; Java</title>
	<atom:link href="http://blog.schauderhaft.de/category/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.schauderhaft.de</link>
	<description>Softwaredevelopment, Projectmanagement, Qualitymanagement and all things &#34;schauderhaft&#34;</description>
	<lastBuildDate>Sun, 25 Jul 2010 14:04:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Enum Singleton</title>
		<link>http://blog.schauderhaft.de/2009/05/10/enum-singleton/</link>
		<comments>http://blog.schauderhaft.de/2009/05/10/enum-singleton/#comments</comments>
		<pubDate>Sun, 10 May 2009 13:21:30 +0000</pubDate>
		<dc:creator>Jens Schauder</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.schauderhaft.de/2009/05/10/enum-singleton/</guid>
		<description><![CDATA[If you consider a singleton for solving a problem, you really should think again if it is the correct solution or if you are coding the equivalent of global variable. If you still want to use the singleton approach, ask your colleagues if this would be a good approach. If they agree, I might have [...]]]></description>
			<content:encoded><![CDATA[<p>If you consider a singleton for solving a problem, you really should think again if it is the correct solution or if you are coding the equivalent of global variable. If you still want to use the singleton approach, ask your colleagues if this would be a good approach. If they agree, I might have a new idea for you.</p>
<p>The crucial part of a singleton implementation is to ensure that no one creates a second instance. The common approach is to use a private constructor. This works ok, but you still could call such a constructor if you are running privileged code. And the private constructor is kind of ugly since its only purpose is to prevent anybody from calling it. And if serialization is important for your app you have to take care of it manually. Joshua Bloch proposes in his book &#8220;<a href="http://www.amazon.de/gp/product/0321356683?ie=UTF8&amp;tag=schauderhafte-21&amp;linkCode=as2&amp;camp=1638&amp;creative=19454&amp;creativeASIN=0321356683">Effective Java</a><img src="http://www.assoc-amazon.de/e/ir?t=schauderhafte-21&amp;l=as2&amp;o=3&amp;a=0321356683" style="border-style: none ! important; margin: 0px" width="1" border="0" height="1" />&#8221; to use a <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Enum.html">Enum</a> for singleton implementations like this:</p>
<p>public enum Elvis {</p>
<p>INSTANCE;</p>
<p>public void leaveTheBuilding(){.}</p>
<p>}</p>
<p>Which is simple, easy and rock solid. You can&#8217;t break it as long as you don&#8217;t use byte code manipulation.</p>
<p>At first I was a little skeptical. Would readers of the piece of code understand its meaning and intent? After all enums are for collections of fixed objects, right? But by now I am convinced. Although it was completely new for me there is no problem in understanding it. The enum makes it obvious that there will be only one instance, and the name of the single instance makes it obvious what the intention is.</p>
<p>So my opinion on this is: Don&#8217;t use singletons! But if you have to, make it an enum.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schauderhaft.de/2009/05/10/enum-singleton/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sun, IBM and Oracle</title>
		<link>http://blog.schauderhaft.de/2009/05/06/sun-ibm-and-oracle/</link>
		<comments>http://blog.schauderhaft.de/2009/05/06/sun-ibm-and-oracle/#comments</comments>
		<pubDate>Wed, 06 May 2009 13:12:13 +0000</pubDate>
		<dc:creator>Jens Schauder</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://blog.schauderhaft.de/2009/05/06/sun-ibm-and-oracle/</guid>
		<description><![CDATA[When I first read the then news of IBM considering to buy Sun I was a little worried. What would it mean to my favorite programming language java? IBM is a strong player in the JCP and with Eclipse they made a IDE available that is constantly among the two most used and the three [...]]]></description>
			<content:encoded><![CDATA[<p>When I first read the then news of <a href="http://java.dzone.com/news/ibm-and-sun-final-stages">IBM considering to buy Sun</a> I was a little worried. What would it mean to my favorite programming language java? IBM is a strong player in the JCP and with Eclipse they made a IDE available that is constantly among the two most used and the three best IDEs for years. But IBM is at least from my point of view also the biggest roadblock in wider acceptance of the current JDKs 1.5 and 1.6 since Websphere is still heavily used, although few can name any, let alone a good reason for using it. And in many cases even an old version of Websphere is used, so many colleagues of mine are stuck with java 1.4. Also what IBM build on top of eclipse is called <a href="http://www.infoq.com/presentations/10-Ways-to-Better-Code-Neal-Ford">WSAD for a reason and not WJOY</a> as Neal Ford puts it.</p>
<p>But now these worries feel like wishful thinking. <a href="http://java.dzone.com/articles/oracle-buys-sun-coverage">Oracle bought SUN</a>. And seriously what useful product has come from oracle apart from their database? I don&#8217;t know any. And oracle proves again and again that they don&#8217;t know an inkling about language design. Java developers are complaining about the implementation of generics (which are flawed) and miss closures? Have a look at oracles languages: the oracle dialect of SQL and their iterative language PL/SQL. No surprise analytic functions a still not widely used, They have the strangest syntax I have ever met, at least I came a cross the model clause, which immediately caused a rash on my fingers. PL/SQL main purpose seems to be to serve as an example what happens if you don&#8217;t have coding guidelines. Half the functions use underscores to separate words in names, the other doesn&#8217;t. It is full of inconsistent parameter lists. Three variations of &#8216;Collections&#8217; but none that works properly. I could go on and on. So if Oracle starts getting involved in Java with their regular teams, it is time to look for a new language and probably even for a new platform.</p>
<p>But wait, let us finish this rant with a little exercise in creativity and positive thinking. What is the good stuff that could come out of a strong involvement of oracle in the java world.</p>
<ul>
<li>A strong oracle hibernate SQL dialect: How about a plug-in in to hibernate that would NOT use SQL for communicating with the database, but a extremely compact binary format. It could seriously limit the bandwidth needed, by deviating from the scheme of SQL/JDBC where you always get a list of rows as a result, instead it could return serialized objects, so parts of rows that represent only one object could get transferred once instead of multiple times. </li>
<li>Java plus a LINQ for Java could replace PL/SQL, combining the benefits of Java (nice, well designed language) with those of PL/SQL (high integration with SQL, fast manipulation of massive amounts of data). This could even become a standard, available in all major databases. </li>
<li>Oracle finally understands the meaning of User Interface Design, relaunches all their websites and client products in a format that is actually usable. </li>
<li>Oracle sets up a Oracle Community Process for steering the development of their products </li>
<li>Oracle realizes that a database is not cast in stone, but must evolve. Therefore they start building the infrastructure for
<ul>
<li>version control of database artifacts </li>
<li>modular database design </li>
<li>unit testing of database artifacts </li>
<li>and refactoring </li>
</ul>
</li>
</ul>
<p>Ok, dream time is over. Back to work everybody. Or for me: back to vacation <img src='http://blog.schauderhaft.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schauderhaft.de/2009/05/06/sun-ibm-and-oracle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why Hibernate is so much more powerful than JDBC</title>
		<link>http://blog.schauderhaft.de/2008/11/27/why-hibernate-is-so-much-more-powerful-than-jdbc/</link>
		<comments>http://blog.schauderhaft.de/2008/11/27/why-hibernate-is-so-much-more-powerful-than-jdbc/#comments</comments>
		<pubDate>Thu, 27 Nov 2008 18:28:51 +0000</pubDate>
		<dc:creator>Jens Schauder</dc:creator>
				<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Softwareentwicklung]]></category>

		<guid isPermaLink="false">http://blog.schauderhaft.de/2008/11/27/why-hibernate-is-so-much-more-powerful-than-jdbc/</guid>
		<description><![CDATA[Should I use Hibernate for the next project? How does it compare to JDBC
This question get&#8217;s asked a lot. And the first answer is most of the times: That is comparing apples and oranges. And of course that is true. But if you are a little kid apples are round and tasty and so are [...]]]></description>
			<content:encoded><![CDATA[<p>Should I use Hibernate for the next project? How does it compare to JDBC</p>
<p>This question get&#8217;s asked a lot. And the first answer is most of the times: That is comparing apples and oranges. And of course that is true. But if you are a little kid apples are round and tasty and so are oranges, so it is a reasonable question what exactly is the difference between apples and oranges?</p>
<p>Both (Hibernate and JDBC not apples and oranges) are used for tying application logic to your database. Hibernate is actually using JDBC. Actually you can use Hibernate in a very similiar way as JDBC. So how exactly does one work with JDBC?</p>
<p>You create a connection, create query from that (using SQL), change the objects (carefully keeping track of what you changed), transform you change log in SQL Statements and send those to the database (using the old or a new connection).</p>
<p>If you don&#8217;t like Hibernate, but are forced to use it you do it the same way:<br />
start a session, create a query from that (using HQL), disconnect the objects, change the objects, (carefully keeping track of what you changed), start a new session and use it to store the new state of the objects in the database.</p>
<p>So you are saving, the DML statements for storing the objects, therefore you have to learn HQL, Hibernate, and all the weird error messages you get from it.</p>
<p>But you can use Hibernate very differently:</p>
<p>Open a session, query for some objects (using Criteria), work with these and commit the session.</p>
<p>That is when the real power of hibernate reveals itself. You are using <strong>neither</strong> HQL <strong>nor</strong> SQL, at least for the standard tasks. This takes away a lot of the ugly kind of error you only get when you actually run the code. You don&#8217;t have to keep track what exactly you changed. Hibernate is doing that for you. At least on the first go you don&#8217;t have to worry when to load exactly what piece of information, instead Hibernate will do it on the fly for you (and of course you will have to control it in some cases where Hibernates choices aren&#8217;t the right once).</p>
<p>But you can benefit from Hibernate even more: <a href="/2008/03/06/das-beste-buch-uber-software-design/">Do the design</a> in the <a href="/2008/04/03/naked-objects/">domain model</a>, i.e. design you model classes the way they should look like from an OO perspective, then add the necessary Hibernate Annotations, thereby deciding on mapping strategies for inheritance and the like. In my experience this results in a richer, more expressive domain model and in a <strong>cleaner </strong>database design.</p>
<p>The reason for this is, that by using this approach you are bringing the power of refactoring to the database! How about an experiment. Go to your favorite database administrator and tell her that someone was ignoring the naming conventions. A couple of table names (about 70) and a couple of columns (about 600) have to be changed, oh and someone hast to change all the sql statements as well. How are your chances to get this refactoring done? Zero? Not too long ago I had exactly that kind of change as a task. Iwas done after 4 hours! It was quite easy. I did the changes to the domain model using the refactoring features of the IDE, that was it (almost). I had to change about 4 or 5 special purpose HQL Statements, and semi automatically create a change script for the database. Yes this was on an application that was installed on a client side, so I had to take care of migration scripts.</p>
<p>I am not saying that you should do this kind of refactoring, but how often do you <a href="/2008/08/22/database-refactoring/">refactor your database</a>? It is still considered voodoo science but with Hibernate you can at least use a powerful IDE and doen&#8217;t have to put up with the crappy stuff you get from database tool vendors. With other tools not many people go through the trouble of changing a column name, because it is wrong in one way or the other. In Java I never stop changing a method or attribute name that I consider wrong as long as it isn&#8217;t used in some public API of course.</p>
<p>As usual it comes at a cost.</p>
<ul>
<li>Hibernate has learning curve. People of hibernate.org claim do have learned hibernate in two weeks. I don&#8217;t think so. They might know enough to use it. But just as with SQL or Java or whatever, it takes time to really master it.</li>
<li>Hibernate is no magic pixy dust. It makes decision and uses default. If those don&#8217;t fit your needs, you might encounter problems, e.g. performance hits. In these cases you have to change the mapping, write HQL, or even SQL or do whatever needs doing to fix the problem.</li>
<li>If you are working with a legacy database or can&#8217;t use the approach described above then the benefit from using Hibernate is smaller.</li>
</ul>
<p>If you disagree, let me know in the comments. ff you agree, let me know as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schauderhaft.de/2008/11/27/why-hibernate-is-so-much-more-powerful-than-jdbc/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Annotations und Dependencies</title>
		<link>http://blog.schauderhaft.de/2008/11/19/annotations-und-dependencies/</link>
		<comments>http://blog.schauderhaft.de/2008/11/19/annotations-und-dependencies/#comments</comments>
		<pubDate>Wed, 19 Nov 2008 21:16:14 +0000</pubDate>
		<dc:creator>Jens Schauder</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Softwareentwicklung]]></category>

		<guid isPermaLink="false">http://blog.schauderhaft.de/2008/11/19/annotations-und-dependencies/</guid>
		<description><![CDATA[Seit mit JDK 1.5 (aka Java2 Version 5 (Kopfschüttel)) Annotations eingeführt wurden, wurden viele XML Dateien durch Annotations ersetzt. Prinzipiell sind Annotations auch eine feine Sache, aber bei der ganzen Begeisterung für die (nicht mehr so ganz) neue Technologie schiesst man leicht über das Ziel hinaus. Falls euch das noch nicht passiert ist, dann ist [...]]]></description>
			<content:encoded><![CDATA[<p>Seit mit JDK 1.5 (aka Java2 Version 5 (Kopfschüttel)) Annotations eingeführt wurden, wurden viele XML Dateien durch Annotations ersetzt. Prinzipiell sind Annotations auch eine feine Sache, aber bei der ganzen Begeisterung für die (nicht mehr so ganz) neue Technologie schiesst man leicht über das Ziel hinaus. Falls euch das noch nicht passiert ist, dann ist dieser Artikel für euch. Falls doch, könnt ihr zusammen mit mir in Erinnerungen schwelgen.</p>
<p>Das Schöne an Annotations ist, das sie Teil der Java Sprache sind und mit übersetzt werden, dementsprechend gibt es Compiler Fehler wenn man zu großen Murcks macht. Nehmen wir zum Beispiel an, wir wollen per Konfiguration zu einer Property einer Klasse definieren, was für eine Art Filter für die Suche nach diesem Attribut verwendet werden kann.</p>
<p>Mit XML könnte das so aussehen:</p>
<div class="geshi no xml">
<ol>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;entity</span> <span class="re0">class</span>=<span class="st0">&quot;de.schauderhaft.Person&quot;</span><span class="re2">&gt;</span></span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;attrib</span> <span class="re0">name</span>=<span class="st0">&quot;name&quot;</span> <span class="re0">filter</span>=<span class="st0">&quot;de.schauderhaft.LikeFilter&quot;</span><span class="re2">&gt;</span></span><span class="sc3"><span class="re1">&lt;/attrib<span class="re2">&gt;</span></span></span></div>
</li>
<li class="li1">
<div class="de1"><span class="sc3"><span class="re1">&lt;/entity<span class="re2">&gt;</span></span></span></div>
</li>
</ol>
</div>
<p>Vertippt man sich dabei bei einem der beiden enthaltenen Klassennamen hat man verloren und wird erst zur Laufzeit mit Fehlermeldungen bombardiert. Mit Annotations geht das viel besser:</p>
<div class="geshi no java">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">class</span> Person<span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; @Filter<span class="br0">&#40;</span>theClass= de.<span class="me1">schauderhaft</span>.<span class="me1">LikeFilter</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw3">String</span> getName<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span> &#8230;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Für die Person muss der Klassenname nicht noch einmal angegeben werden, da wir uns ja in eben dieser Klasse befinden. Auch die Zuordnung zu der Property ist allein dadurch klar, dass die Annotation eben am Getter steht. Und der Klassenname der Filterklasse? Wenn der falsch geschrieben ist, meckert der Compiler, und besser, man schreibt ihn garnicht erst falsch, da er per autocompletion entsteht. Aber ist das wirklich das gelbe vom Ei?</p>
<p>Die Probleme werden offensichtlich, wenn man versucht die Person-Klasse außerhalb des ursprünglich vorgesehenen Kontexts zu verwenden. Erstens: die Filter Annotation ist im Zweifelsfall nicht bekannt, da sie Teil eines speziellen Frameworks ist. Zweitens, die Klasse  de.schauderhaft.LikeFilter ist ebenfalls nicht bekannt. Mit ein wenig Sorgfalt und wenigen einfachen Regeln lassen sich aber beide Probleme in den Griff bekommen.</p>
<ol>
<li>Wenn ihr ein Framework baut, welches eigene Annotations nutzt, macht die Annotations als kleines JAR separat verfügbar. So können Klassen mit den Annotations versehen werden und vergrößern den Classpath nur geringfügig. Und wenn die Annotations gut entworfen sind, dann behalten sie einen großen Teil ihrer Aussagekraft. Und können auch außerhalb ihres ursprünglich geplanten Einsatzsgebietes verwendet werden.</li>
<li>Überlegt euch gut, ob ihr wirklich Klassen als Parameter von Annotations verwendet. Die sind zwar charmant, aber sie machen die annotierte Klasse abhängig von der Klasse, die als Parameter angegeben wurde. In vielen Fällen geht dies Abhängigkeit in die falsche Richtung, in dem obigen Beispiel von der Model Schicht in die GUI Schicht. Ein String, ein Enum, oder wenn es denn vom Typ Class sein soll, ein Interface sind oft die bessere Wahl. Sie transportieren auf abstakte Weise Informationen, ohne festzulegen, wie diese verwendet werden sollen. Im Beispiel: Nach dem Namensattribut soll Like Syntax gesucht werden, unabhängig davon, ob daraus eine Eingabebox in einem Webdialog, einer Swingmaske, oder ein Argument eines Webservices wird.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.schauderhaft.de/2008/11/19/annotations-und-dependencies/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Swing ist tot, es lebe &#8230;?</title>
		<link>http://blog.schauderhaft.de/2008/11/07/swing-ist-tot-es-lebe/</link>
		<comments>http://blog.schauderhaft.de/2008/11/07/swing-ist-tot-es-lebe/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 21:28:00 +0000</pubDate>
		<dc:creator>Jens Schauder</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Softwareentwicklung]]></category>

		<guid isPermaLink="false">http://blog.schauderhaft.de/2008/11/07/swing-ist-tot-es-lebe/</guid>
		<description><![CDATA[Vor fast zwei Jahren habe ich die Arbeit an einem Swing basierten Projekt begonnen. Die anderen Teammitglieder fragten mich, was ich von der Entscheidung für Swing und gegen Webtechniken hielt. Ich habe ihnen gratuliert. In meiner Erfahrung werden viel zu viele Webanwendungen gebaut. Klar, Webanwendungen haben Vorteile, aber eben nicht nur. Und für viele Dinge [...]]]></description>
			<content:encoded><![CDATA[<p>Vor fast zwei Jahren habe ich die Arbeit an einem Swing basierten Projekt begonnen. Die anderen Teammitglieder fragten mich, was ich von der Entscheidung für Swing und gegen Webtechniken hielt. Ich habe ihnen gratuliert. In meiner Erfahrung werden viel zu viele Webanwendungen gebaut. Klar, Webanwendungen haben Vorteile, aber eben nicht nur. Und für viele Dinge ist ein Rich Client in zwei Schichten Architektur einfach einfacher. Und ich hatte volles Vertrauen in Swing. Ich hatte das letze mal etwa 2002 mit Swing gearbeitet und dachte mir, so langsam müsste es ja wohl gar sein. Nun ja, es war schneller geworden (ich sage nur <a href="/2008/04/24/komplexitat-und-die-neuen-sprachen/">Quake Tuning</a>). Aber wir sind auf Bugs und Probleme gestoßen, die ich für Toolkit mit einer solch langen Geschichte nicht erwartet hätte. Ein Sanduhr als Wartecursor anzeigen macht mehr Stress als man glauben mag. Defaultbuttons verlieren spontan diese Eigenschaft, nach wie vor kein ausgereifter Standard-Datepicker. Es war schon ein wenig ernüchternd.</p>
<p>Aber es war Licht am Ende des Tunnels. Für Java 7 sollte <a href="http://weblogs.java.net/blog/zixle/archive/2007/02/update_on_beans.html">Beans Binding</a> kommen und das <a href="https://appframework.dev.java.net/">Application Framework</a> und <a href="http://www.infoq.com/news/JSR303-validation-standard">Validation</a>. Alles Dinge für die wir 3rd Party Libraries eingesetzt haben. Doch dann kam es doch wieder ganz anders. Beans Binding kommt nicht von der Stelle, das Application Framework kommt nicht weiter und schließlich wird auch SwingX, einer der wenigen Impulsgeber von Swing erst völlig vor den Kopf gestoßen und am Ende nicht weiter unterstützt. Summa Summarum:</p>
<p><a href="http://www.pushing-pixels.org/?p=758"><strong>Swing ist tot</strong></a></p>
<p>Klar, Support wird weiter geleistet. Bugs werden auch noch gefixt &#8230; aber mit Weiterentwicklungen von SUNs Seite ist wohl nicht zu rechnen. Falls Kollegen vom oben erwähnten Projekt dies lesen: Swing war immer noch die richtige Wahl und es gibt keinen Grund in Panik zu verfallen. Aber wenn man heute ein Projekt beginnt, wofür sollte man sich entscheiden?</p>
<p>Swing obwohl dort nichts mehr passiert?</p>
<p>SWT &#8230; welches mich nie überzeugt hat, und das außerhalb von Eclipse auch nicht wirklich beeindruckt?</p>
<p>Oder doch auf Webbasis aufbauen und mit Javascript die Dynamik erkaufen, die man von einem Rich Client erwartet?</p>
<p>JavaFX, was vermutlich bedeutet erstmal 3Jahre zu warten bis der Kram ausgereift ist?</p>
<p>Was ganz anderes wie Flash oder Silverlight?</p>
<p>Ich hab keine Ahnung, und ich weiß nicht was das soll. Trotz allem genöles, ist Swing eine attraktive Technik. Wieso wird dieses Gebiet nicht weiterverfolgt?</p>
<p>Wofür würdet ihr euch entscheiden, wenn ihr einen Rich Client produzieren solltet, der auch über die nächsten 10 Jahre attraktiv, benutzbar und wartbar bleiben soll?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schauderhaft.de/2008/11/07/swing-ist-tot-es-lebe/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Equals ist böse</title>
		<link>http://blog.schauderhaft.de/2008/10/05/equals-ist-bose/</link>
		<comments>http://blog.schauderhaft.de/2008/10/05/equals-ist-bose/#comments</comments>
		<pubDate>Sun, 05 Oct 2008 09:50:46 +0000</pubDate>
		<dc:creator>Jens Schauder</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Softwareentwicklung]]></category>

		<guid isPermaLink="false">http://blog.schauderhaft.de/2008/10/05/equals-ist-bose/</guid>
		<description><![CDATA[Ich kann mich noch vage daran erinnern, als ich mich 1997 das erste Mal mit Java beschäftigte. Ich probierte mich an meinen ersten .java Dateien und hangelte mich an Java Tutorial entlang. Ziemlich bald stieß ich auf auf die equals Methode. Ich war begeistert. Jede Klasse kann selbst entscheiden, welche Instanzen von ihr als gleich [...]]]></description>
			<content:encoded><![CDATA[<p>Ich kann mich noch vage daran erinnern, als ich mich 1997 das erste Mal mit Java beschäftigte. Ich probierte mich an meinen ersten .java Dateien und hangelte mich an Java Tutorial entlang. Ziemlich bald stieß ich auf auf die equals Methode. Ich war begeistert. Jede Klasse kann selbst entscheiden, welche Instanzen von ihr als gleich gelten. Cool &#8211; dachte ich damals.</p>
<p>Wie bei so vielem hat sich die Begeisterung nach einiger Zeit gelegt. Wie jeder Java Entwickler mittlerweile begriffen haben sollte, ist equals nicht korrekt implementierbar, wenn man per Vererbung Eigenschaften zu Klassen hinzufügt. Wer es noch nicht kennt, kann es in <a href="http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf">Effective Java online</a> nachlesen. Wer das Buch noch nicht hat, sollte es vermutlich schleunigst <a href="http://www.amazon.de/gp/product/0321356683?ie=UTF8&amp;tag=schauderhafte-21&amp;linkCode=as2&amp;camp=1638&amp;creative=6742&amp;creativeASIN=0321356683">bestellen</a><img src="http://www.assoc-amazon.de/e/ir?t=schauderhafte-21&amp;l=as2&amp;o=3&amp;a=0321356683" style="border: medium none  ! important; margin: 0px ! important" width="1" border="0" height="1" />.</p>
<p>Aber das ist nur die technische Seite. Die bekommt man durch Vermeidung von Hierarchien mit konkreten Klassen ganz gut in den Griff. Das Problem das ich heute ins Bewusstsein bringen will, ist dass das Konzept prinzipiell Fehlerhaft ist. Meine Behauptung ist:</p>
<h2>Es gibt kein korrektes EQUAL!</h2>
<p>Warum? Man frage einen Mathematiker: Was ist Gleichheit? Er wird sagen (so in etwa) eine Relation mit bestimmten Eigenschaften. Und das wichtige dabei: EINE Relation von beliebig vielen. Java bietet primär aber nur zwei an: equals und Identität (==), und das reicht einfach nicht.</p>
<p>Beispiel: Eine Datenbank basierte Anwendung.</p>
<p>Eine wichtige Gleichheits Relation ist sicherlich die tatsächliche Zeile in der Datenbanktabelle aus der eine Instanz entstanden ist.</p>
<p>Eine andere ist der sogenannte fachliche Schlüssel, also z.B. die E-Mailadresse einer Person.</p>
<p>Eine weitere der korrekte fachliche Schlüssel, also z.B. die E-Mailadresse modulo aller Tippfehler.</p>
<p>Die nächste die Gleichheit bezüglich aller enthaltenen Felder, wobei dann natürlich sofort die Frage entsteht, welche Gleichheitsrelation bei referenzierten Objekten verwendet werden sollen.</p>
<p>Eine wichtige, oft vergessene Gleichheitsrelation ist die Gleichheit in der Darstellung. Zwei Objekte, die gleich dargestellt werden, können vom Benutzer nicht unterschieden werden, sollten also auch nie innerhalb einer Darstellung als unterschiedliche Objekte verwendet werden.</p>
<p>Alles nur ein theoretisches Problem? Mit nichten. <a href="http://www.onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page=3">Längliche Diskussionen</a> über die korrekte Implementation von Identität im Hibernate Umfeld belegen die real existierenden Schwierigkeiten.<br />
Hibernate hat eine Bestimmte Art und Weise mit Identität umzugehen. Danach kann man sich ausrichten. Leider haben auch andere Bibliotheken dies, z.B. JGoodies. Prinzipiell hat jede Bibliothek, die eine Map oder ein Set verwendet eine Interpretation von Gleichheit, die nicht immer mit der anderer Bibliotheken identisch sein muss.</p>
<h2>Und die Lösung?</h2>
<p>Die Lösung lautet wie so oft: Nachdenken! Welche Bereiche meiner Anwendung benötigen welche Interpretation von Gleichheit. Kann ich mich auf die einfache und wohldefinierte Identität zurückziehen? Kann ich mich darauf verlassen, dass die equals()-Implementation der verwendeten Klassen korrekt ist? Und wenn nicht, wie kann ich an den entscheidenden Stellen die richtige Implementierung zur Verfügung stellen? Bei Drittbibliotheken könnte dies durch Proxy Objekte möglich sein, manchmal auch durch Comparator Implementierungen. Wenn man selbst eine bestimmte Interpretation von Gleichheit erfordert, die implementierenden Klassen aber möglichst wenig einschränken möchte, könnte ein Lookup Mechanismus helfen: Anstatt direkt equals() aufzurufen, wird entweder in einer zentralen Map, oder per Namenskonvention oder ähnlichem nach einem geeigneten Comparator gesucht, und nur wenn dieser nicht gefunden wird, dann wird equals verwendet.</p>
<p>Diese prinzipielle Vorgehen würde ich mir auch bei anderen Eigenschaften, die Bibliotheken von Klassen einfordern wünschen: Weniger auf Implementierung bestimmter Methoden setzen, dafür mehr auf per Konvention oder im Notfall Konfiguration auffindbare Implementierungen  setzen.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schauderhaft.de/2008/10/05/equals-ist-bose/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hibernate Sessions in Two Tier Rich Client Applications</title>
		<link>http://blog.schauderhaft.de/2008/09/28/hibernate-sessions-in-two-tier-rich-client-applications/</link>
		<comments>http://blog.schauderhaft.de/2008/09/28/hibernate-sessions-in-two-tier-rich-client-applications/#comments</comments>
		<pubDate>Sun, 28 Sep 2008 10:10:33 +0000</pubDate>
		<dc:creator>Jens Schauder</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Softwareentwicklung]]></category>

		<guid isPermaLink="false">http://blog.schauderhaft.de/2008/09/28/hibernate-sessions-in-two-tier-rich-client-applications/</guid>
		<description><![CDATA[One of the most populare articles in this blog so far ist the one about, well: Hibernate Sessions in Two Tier Rich Client Applications. Although the original article is writen in german I keep refering to this article, even in english communities. Therefore I decided to break my habit of writing articles in german only [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most populare articles in this blog so far ist the one about, well: <a href="/2007/12/17/hibernate-sessions-in-fat-client-anwendungen/">Hibernate Sessions in Two Tier Rich Client Applications</a>. Although the original article is writen in german I keep refering to this article, even in english communities. Therefore I decided to break my habit of writing articles in german only and provide a english version which you are reading right now.</p>
<p>This is NOT a direct translation so there might be some differnces in scope, focus and detail.</p>
<p>Everybody working with Java and Databases is probably aware of Hibernate. It is a great solution for mapping a database schema to a object model. It is used in hundreds of applications. So on my current project we decided to use it as well. But big surprise. While Support in the user forum of hibernate is pretty good most of the time we hit one kind of a problem which had no apropriate solution available: How to handle Sessions in a Two Tier Hibernate Application (Swing or SWT typically).</p>
<p>How could such a essential problem be unsolved? Well Rich Client Applications are not hip anymore. Everybody goes for web applications and in that context the session handling is well understood and there is a easy straight forward solution that works in most cases: On each request open a session, do all your work including constructing the result (e.g. JSP) , close the session. But there is no equivalent for a request in a swing application. And since Rich Client Applications are kind of old fashioned nobody bothers to find (and write about) a clean solution for this problem.</p>
<p>We tried a lot of things, starting with the antipattern of a single session per application. This doesn&#8217;t work at all for any kind of serious app for the following reasons:</p>
<ul>
<li>No transaction control between different parts of the application. When you flush/commit a session, everything gets flushed. So imagine a application with two open edit frames. The user hits save in one frame and surprise, her half done changes in the other frame get saved as well. Not good.</li>
<li>Memory Leak. The Hibernate Session keeps track of every entity ever loaded by that session. So if you don&#8217;t close the session from time to time the session will grow until the application blows up or the whole database is contained in the session. If nothing else this will cause performance issues.</li>
</ul>
<p>Of course if you write a really small simple application this might work, but not for us. As said before we tried a lot of things to solve our problem in the assumption that our requirements are so common that it can&#8217;t be hard to find the solution. We were wron. So if the solution to a problem isn&#8217;t easy to find, what should be your first step? Wrong (probably)! Your first step should be to exactly identify the problem. In this case this meant: What are the requirements we had? What are the relevant features/limitations of Hibernate? The requirements were:</p>
<ul>
<li>We want Lazy Loading: Lazy Loading is a real powerfull feature whe working with a rich domain model (as we did) especially in a Swing Application. You just display what every attribute you can reach by any kind of object navigation, hibernate will ensure the data is there. Awesome. This was one of the main selling points for Hibernate vs. plain JDBC. So it wasn&#8217;t realy an option to loose it.</li>
<li>Different views of the same entity should show the same state. So if you edit an Object the same Object shown in some kind of list-view should show the updated state immediatly.</li>
<li>It should be obvious for the user what is going to be saved when she hits the save button.</li>
<li>The whole mechanism must be fairly easy to use, since the team was growing and not everybody was a hibernate expert. Also lazy loading problems are sometimes hard to debug and fix.</li>
</ul>
<p>The relevant properties of the Hibernate session are</p>
<ul>
<li>For lazy loading to work an entity must be attached to a open session.</li>
<li>A entity wich contains at least one collection (which are well above 50% of our class) can only be attached to one session at a time.</li>
<li>A session keeps a reference to any entity it loads, until the entity get evicted or the session gets closed.</li>
<li>A Hibernate session guarantees to return the same instance everytime a specific entity is requested.</li>
</ul>
<p>If you look at it in this compact form it is rather obvious that you can&#8217;t have your cake and eat it too. The automatic refresh in all views of an object would be easily implemented, when there is only one session. But we simply couldn&#8217;t do this. So the decision was made that the automatic refresh is (obviously) not as important as clean transactional control plus lazy loading. So we will have more then one session. But which part of the application is using which session? The Hibernate site uses the term &#8216;Unit-of-Work&#8217;. Each unit of work should be contained in its own session. But this is basically back to step one. A request in a webapp ist a unit of work, but where is a unit of work in a rich client app? Imagine this example: The user fires up the application and opens a search dialog resulting in a list of objects. Clearly we are accessing the database, so we just startet a unit of work. Now she double clicks an item in the list. The entity gets opened in a editor, she edits it and hits save. Work commited, transaction closed, unit of work ended. Wow, thats easy, isn&#8217;t it? No it isn&#8217;t: She clicks on a different item, edits it, saves it. So now we have opened one session and closed two sessions. Not good.</p>
<p>The answer is actually fairly easy once found: Use one session per frame/internal frame/dialog. Modal dialogs use the session of the frame the got starteted from. Background tasks get their own session. The critical point is the transfer of objects from one frame to another. It is tempting to just pass the object but then you have a object from the wrong session in the frame. Instead pass just the Id (the primary key) and use that to load the object in the new session. This approach solved most of our problems nicely.</p>
<p>Most problems? Yes and no. We have some things that we don&#8217;t like to much. I think I know how to solve them but I haven&#8217;t implemented them yet. So I can&#8217;t really promis anything.</p>
<ul>
<li>Instant refresh in other (readonly) views. When editing a object the changed state is not represented in other views of the same object. This could be fixed by a hibernate interceptor or event listener. It would listen for update events, then check if this entity is contained in any other session, check if that session is read only and if so trigger a refresh of that object. We haven&#8217;t implemented that simple due to time constraints.</li>
<li>Saving in background. Most of the stuff we do is simple object editing, but on fairly complex object graphs. So saving an object to DB may take some time. Due to the tight integration of Frames and session we can&#8217;t easily delegate this work to a background thread. The same is true of lazy loading. In long lists of complex objects scrolling to new cells for the first time might cause some lag, because lazy loading happens in the Event Handling Thread. The first part should be fairly easy to fix:Open a new Session, find the dirty Objects, merge the dirty Objects in the new Session, do a flush of the new session in a background thread. One just has to make sure the background thread uses its own instances, not the same instances as the original frame/session. The lazy loading in background is more difficult to solve. For almost everything in the GUI we use a <a href="http://www.jgoodies.com/index.html">JGoodies</a> PresentationModel and the associated ValueModels, so the swing objects don&#8217;t access directly any attributes of our Hibernate entities. These ValueModel could be used to implement a seperation of two differnt threads: The Swing Event Handling Thread on one side and a seperate thread for all the model work, including lazy loading. But this would mean the whole application is split in two threads, instead of the normal aproach of having one main thread and a couple of worker threads for special work. I think it should be feasibly and actually enforces a very strict and clean architecture, and result in a highly responsive gui, but it would also be a lot of (debugging) work and as everybody knows: Concurrency is hard. So we decided that we don&#8217;t need it in this application.</li>
</ul>
<p>If you are going to implement this kind of session handling I strongly suggest to use a director/mediator pattern for all your frames. While always a good idea, it becomes important in this case because it gives you a well defined spot to do your session handling. And of course you should be aware of the alternatives:</p>
<ul>
<li>Go with a single long living session. Only feasable with smallish applications</li>
<li>Kick Lazy Loading and close your session after retrieving your objects. This loses many of the interesting benefits hibernate offers.</li>
</ul>
<p>In any case I how this write up shed some light on the issues and helped to make a informed decission.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schauderhaft.de/2008/09/28/hibernate-sessions-in-two-tier-rich-client-applications/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Ich habe das Rad erfunden</title>
		<link>http://blog.schauderhaft.de/2008/04/03/naked-objects/</link>
		<comments>http://blog.schauderhaft.de/2008/04/03/naked-objects/#comments</comments>
		<pubDate>Thu, 03 Apr 2008 19:08:19 +0000</pubDate>
		<dc:creator>Jens Schauder</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Softwareentwicklung]]></category>

		<guid isPermaLink="false">http://blog.schauderhaft.de/2008/04/03/naked-objects/</guid>
		<description><![CDATA[Yup, ich hab mittlerweile auch mitbekommen, dass das ein anderer schon vor mir getan hat. Ok, es geht nicht um das Rad, es geht um ein Framework, wie ich es vor einiger Zeit  skizziert habe. Ein solches Framework habe ich in den vergangenen Monaten mit einem Kunden meines Arbeitgebers implementiert. Die prinzipielle Idee ist [...]]]></description>
			<content:encoded><![CDATA[<p>Yup, ich hab mittlerweile auch mitbekommen, dass das ein anderer schon vor mir getan hat. Ok, es geht nicht um das Rad, es geht um ein <a href="/2008/02/17/neue-java-frameworks-braucht-das-land/">Framework</a>, wie ich es vor einiger Zeit  skizziert habe. Ein solches Framework habe ich in den vergangenen Monaten mit einem Kunden <a href="http://www.lineas.de">meines Arbeitgebers</a> implementiert. Die prinzipielle Idee ist es <a href="http:///2008/03/06/das-beste-buch-uber-software-design/">Domain Driven Design</a> zu betreiben, in dem (praktisch) nur das Domain Model implementiert wird und die GUI daraus automatisch generiert wird. Ich bin auf diesen Ansatz gestoßen, da wir in dem fragliche Projekt zunächst keine konkreten Anforderungen hatten, und dadurch die Zeit nutzten um uns unser Leben so einfach wie möglich zu machen. Was wir wussten war, dass wir Stammdaten zu pflegen hatten. Also begannen wir Generische Dialoge zu konstruieren, die eine Klasse analysieren und daraus ableiten, wie sie dargestellt und editiert werden können.  Zunächst sollten die Dialoge nur für &#8216;einfache&#8217; Objekte genutzt werden, aber bei den meisten Anforderungen, die sich zunächst nicht aus dem Framework befriedigen ließen kamen wir zu dem Schluss, dass sich relativ einfach generische Prinzipen ableiten lassen. Zusätzlich lassen sich unsere Dialoge durch Annotations am Domain Model beeinflussen. Zum Beispiel wird darüber gesteuert, in welcher Reihenfolge und in welchen Gruppen Steuerelemente angezeigt werden. Insbesondere werten wir auch die Annotations von JPA (aka Hibernate Annotations) und Hibernate Validator aus, so dass unser GUI automatisch die selben Prüfungen durchführt, wie sie als Constraints in der Datenbank hinterlegt sind (die ebenfalls zu 95% aus den Annotations generiert wird).</p>
<p>Man könnte meinen, dass eine solche GUI krude aussieht. Und das tat sie zunächst auch, aber mittlerweile sind unsere generischen Dialoge soweit gediehen, dass die tatsächlichen Benutzer sie ausdrücklich loben. Ich behaupte, dass ich mit diesem Framework ein Domain Model aus 10 Klassen in weniger als einem Tag runterschreiben kann, inklusive Datenbank, Gui, Tests und Deployment. Die Frage wie das Domain Model auszusehen muss natürlich immer noch beantwortet werden, aber so haben wir endlich die Zeit, um uns genau diese Dinge gründlich Gedanken zu machen, da wir uns nicht mehr mit dem mühseligen auswählen und anordnen von GUI Komponenten beschäftigen müssen, und auch die Datenbank in der Struktur einfach nebenbei entsteht und sich die Datenbankspezialisten darum kümmern können wie sie die Datenbank schnell bekommen, und nicht darum, welcher Datentyp verwendet wird.</p>
<p>So viel zu meinem Rad. In den letzten Wochen habe ich viel hin und her überlegt, wie ich diese Erfahrungen nutzen kann, denn das Framework gehört natürlich unserem Kunden (und natürlich gibt es schon wieder viele Dinge, die ich jetzt anders oder besser machen würde). Und bei diesen Überlegungen bin ich auf einen früheren Erfinder des Rades gestoßen, und sein Rad: <a href="http://www.nakedobjects.org/home/index.shtml">Naked Objects</a>. Während wir in dem oben skizzierten Projekt über das Konzept der GUI Generierung eher zufällig gestolpert sind, hat sich Richard Pawson, wie er es in seiner <a href="http://www.nakedobjects.org/downloads/Pawson%20thesis.pdf">PhD Thesis</a> beschreibt, gezielt der Fragestellung genähert. Seine Idee ist die folgende: So genannte &#8216;Feature Complete Objects&#8217; beschreiben sowohl ihre Daten, als auch ihr mögliches Verhalten und die möglichen Interaktionen. Also im Prinzip alles, was ein Benutzer egal ob Entwickler oder Endanwender mit diesem Objekt machen kann. Da der Endanwender meist keine Programmiersprache beherrscht, muss ein Wrapper erzeugt werden, der es dem Benutzer erlaubt die Objekte zu manipulieren. Dies ist nichts anderes als eine generische GUI, so wie ich sie oben skizziert habe. Das Framework Naked Objects, das von Robert Matthews gestartet wurde, kann sowohl eine Swing GUI, als auch einen Webclient erzeugen.</p>
<p>Also wieder einmal das Rad zu spät erfunden. Wikipedia führt sogar noch weitere Raderfinder, oder zumindest <a href="http://en.wikipedia.org/wiki/Naked_objects#Software_frameworks">Radbauer</a> auf. Aber auch wenn ich wohl nicht als Erfinder in die Analen der Softwareentwicklung eingehen werde, halte ich das  Konzept für einen hoch interessanten Ansatz, bei dem es aber sicher noch eine Menge zu tun gibt. Ich bin zum Beispiel weder von der generierten GUI von Naked Objects 100% überzeugt, noch von dem Ansatz wirklich 100% zu generieren. Mindestens für eine Übergangszeit halte ich es für absolut wichtig immer noch die Möglichkeit zu haben einfache einen Dialog zu öffnen und den eigenen GUI-Code dort zu verewigen.</p>
<p>Ich werde das Projekt und das Blog von Richard Pawson jedenfalls weiter beobachten, in dem er unter anderem über <a href="http://blog.nakedobjects.org/2007/10/19/naked-objects-and-aop-part-2/">neue Ideen für das Framework schreibt.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schauderhaft.de/2008/04/03/naked-objects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hibernate Naming Strategie für Oracle die zweite</title>
		<link>http://blog.schauderhaft.de/2008/03/29/hibernate-naming-strategie-fur-oracle-die-zweite/</link>
		<comments>http://blog.schauderhaft.de/2008/03/29/hibernate-naming-strategie-fur-oracle-die-zweite/#comments</comments>
		<pubDate>Sat, 29 Mar 2008 22:40:34 +0000</pubDate>
		<dc:creator>Jens Schauder</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://blog.schauderhaft.de/2008/03/29/hibernate-naming-strategie-fur-oracle-die-zweite/</guid>
		<description><![CDATA[Vor einiger Zeit habe ich eine einfache Naming Strategie vorgestellt, die sicherstellt, dass die generierten Namen sich an die etwas geizigen Beschränkungen von Oracle hält. Ich habe die Starategie noch einmal ein wenig überarbeitet. Sie verteilt jetzt großzügiger Underscores, so dass sie mehr Stellen hat, an denen sie einen Namen kürzen kann.
Natürlich gilt wieder: Benutzung [...]]]></description>
			<content:encoded><![CDATA[<p>Vor einiger Zeit habe ich eine einfache <a href="/2008/02/22/hibernate-namingstrategy-fur-oracle/">Naming Strategie</a> vorgestellt, die sicherstellt, dass die generierten Namen sich an die etwas geizigen Beschränkungen von Oracle hält. Ich habe die Starategie noch einmal ein wenig überarbeitet. Sie verteilt jetzt großzügiger Underscores, so dass sie mehr Stellen hat, an denen sie einen Namen kürzen kann.</p>
<p>Natürlich gilt wieder: Benutzung auf eigene Gefahr.</p>
<pre>
public class OracleNamingStrategy
        extends DefaultComponentSafeNamingStrategy
{

  protected static String addUnderscores(String name)
  {
    if (name == null) return null;
    StringBuffer buf = new StringBuffer(
            name.replace('.', '_')
    );
    for (int i = 1; i &lt; buf.length() - 1; i++)
    {
      if (Character.isLowerCase(buf.charAt(i - 1)) &amp;&amp;
          Character.isUpperCase(buf.charAt(i))
      // &amp;&amp; Character.isLowerCase(buf.charAt(i + 1))
      )
      {
        buf.insert(i++, '_');
      }
    }
    return buf.toString().toLowerCase();
  }

  @Override
  public String collectionTableName(String ownerEntity,
      String ownerEntityTable, String associatedEntity,
      String associatedEntityTable, String propertyName)
  {
    return abbreviateName(super.collectionTableName(
        addUnderscores(ownerEntity),
        addUnderscores(ownerEntityTable),
        addUnderscores(associatedEntity),
        addUnderscores(associatedEntityTable),
        addUnderscores(propertyName)));
  }

  @Override
  public String foreignKeyColumnName(String propertyName,
      String propertyEntityName, String propertyTableName,
      String referencedColumnName)
  {
    return abbreviateName(super.foreignKeyColumnName(
        addUnderscores(propertyName),
        addUnderscores(propertyEntityName),
        addUnderscores(propertyTableName),
        addUnderscores(referencedColumnName)));
  }

  @Override
  public String logicalCollectionColumnName(
      String columnName,
      String propertyName, String referencedColumn)
  {
    return abbreviateName(super.logicalCollectionColumnName(
        addUnderscores(columnName),
        addUnderscores(propertyName),
        addUnderscores(referencedColumn)));
  }

  @Override
  public String logicalCollectionTableName(String tableName,
      String ownerEntityTable,
      String associatedEntityTable, String propertyName)
  {
    return abbreviateName(super.logicalCollectionTableName(
        addUnderscores(tableName),
        addUnderscores(ownerEntityTable),
        addUnderscores(associatedEntityTable),
        addUnderscores(propertyName)));
  }

  @Override
  public String logicalColumnName(String columnName,
        String propertyName)
  {
    return abbreviateName(super.logicalColumnName(
        addUnderscores(columnName),
        addUnderscores(propertyName)));
  }

  @Override
  public String propertyToColumnName(String propertyName)
  {
    return abbreviateName(super.propertyToColumnName(
          addUnderscores(propertyName)));
  }

  private static final int MAX_LENGTH = 30;

  public static String abbreviateName(String someName)
  {
    if (someName.length() &lt;= MAX_LENGTH) return someName;

    String[] tokens = splitName(someName);
    shortenName(someName, tokens);

    return assembleResults(tokens);
  }

  private static String[] splitName(String someName)
  {
    StringTokenizer toki = new StringTokenizer(someName, "_");
    String[] tokens = new String[toki.countTokens()];
    int i = 0;
    while (toki.hasMoreTokens())
    {
      tokens[i] = toki.nextToken();
      i++;
    }
    return tokens;
  }

  private static void shortenName(
       String someName, String[] tokens)
  {
    int currentLength = someName.length();
    while (currentLength &gt; MAX_LENGTH)
    {
      int tokenIndex = getIndexOfLongest(tokens);
      String oldToken = tokens[tokenIndex];
      tokens[tokenIndex] = abbreviate(oldToken);
      currentLength -=
         oldToken.length() - tokens[tokenIndex].length();
    }
  }

  private static String assembleResults(String[] tokens)
  {
    StringBuilder result = new StringBuilder(tokens[0]);
    for (int j = 1; j &lt; tokens.length; j++)
    {
      result.append("_").append(tokens[j]);
    }
    return result.toString();
  }

  private static String abbreviate(String token)
  {
    final String VOWELS = "AEIOUaeiou";
    boolean vowelFound = false;
    for (int i = token.length() - 1; i &gt;= 0; i--)
    {
      if (!vowelFound)
        vowelFound = VOWELS.contains(
            String.valueOf(token.charAt(i)));
      else if (!VOWELS.contains(
            String.valueOf(token.charAt(i))))
        return token.substring(0, i + 1);
    }
    return "";
  }

  private static int getIndexOfLongest(String[] tokens)
  {
    int maxLength = 0;
    int index = -1;
    for (int i = 0; i &lt; tokens.length; i++)
    {
      String string = tokens[i];
      if (maxLength &lt; string.length())
      {
        maxLength = string.length();
        index = i;
      }
    }
    return index;
  }

  @Override
  public String classToTableName(String aClassName)
  {

    return abbreviateName(super.classToTableName(addUnderscores(aClassName)));
  }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.schauderhaft.de/2008/03/29/hibernate-naming-strategie-fur-oracle-die-zweite/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Debugging mit Sound und Log4J</title>
		<link>http://blog.schauderhaft.de/2008/03/12/debugging-mit-sound-und-log4j/</link>
		<comments>http://blog.schauderhaft.de/2008/03/12/debugging-mit-sound-und-log4j/#comments</comments>
		<pubDate>Wed, 12 Mar 2008 20:46:00 +0000</pubDate>
		<dc:creator>Jens Schauder</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Softwareentwicklung]]></category>

		<guid isPermaLink="false">http://blog.schauderhaft.de/2008/03/12/debugging-mit-sound-und-log4j/</guid>
		<description><![CDATA[Ein Freund von mir erzählte von einiger Zeit von einem interessanten kleinen Feature, das er in einer Entwicklungsumgebung (ich denke auf einem Mac) gefunden hatte. Eine Art Breakpoint, der aber nicht die Ausführung unterbrach, sondern ein einfach einen kurzen Ton produzierte. Konsequenz: Es war sehr einfach zu kontrollieren, ob und wie häufig die entsprechende Codezeile [...]]]></description>
			<content:encoded><![CDATA[<p>Ein Freund von mir erzählte von einiger Zeit von einem interessanten kleinen Feature, das er in einer Entwicklungsumgebung (ich denke auf einem Mac) gefunden hatte. Eine Art Breakpoint, der aber nicht die Ausführung unterbrach, sondern ein einfach einen kurzen Ton produzierte. Konsequenz: Es war sehr einfach zu kontrollieren, ob und wie häufig die entsprechende Codezeile ausgeführt wurde.</p>
<p>Das ganze erinnerte mich sehr an die LED Matrizen an Supercomputern, die in SciFi Filmen so gerne gezeigt werden. Die hielt ich lange Zeit für eine Erfindung von Hollywood, bis ich selbst einmal an einem solchen System arbeiten durfte. Es war im Jahr 1997 und der Rechner stand ein paar 100km entfernt von mir. LEDs sah ich also nicht. Es gab aber eine kleine Webanwendung mit äquivalenter Funktion: Für jeden Prozessor wurde angezeigt, ob er aktiv war, oder vor sich hin idlete. Die LEDs waren also ein wichtiges debugging und tuning Werkzeug.</p>
<p>Vor ein paar Wochen habe ich die Idee mit dem Sound tatsächlich sinnvoll einsetzen können: In meinem aktuellen Projekt bauen wir eine auf Basis von Swing und Hibernate eine Rich Client Anwendung. Kritisch dabei ist, das jeder Dialog, die für sich vorgesehen Session verwendet und nur diese. Genau in diesem Bereich gab es ein Problem. Es war aber überhaupt nicht klar, bei welchem Fensterwechsel etwas schief ging. Also in unseren SessionManager ein <tt>Toolkit.getDefaultToolkit().beep()</tt> eingebaut, wann immer er eine neue Session erzeugt oder vernichtet. Und wenig später war die Stelle eingekreist, an der das Problem lag.</p>
<p>Nun ist ein hart verdrahtetes <tt>Toolkit.getDefaultToolkit().beep()</tt> aber nicht die feine englische Art, also habe ich das ganze einfach mal als Log4J Appender implementiert:</p>
<pre>
public class PingAppender extends AppenderSkeleton {

    protected void append(LoggingEvent arg0) {
        Toolkit.getDefaultToolkit().beep();
    }

    public void close() {}

    public boolean requiresLayout() {
        return false;
    }
}</pre>
<p>Das ganze in der Log4J Konfiguration verwenden:</p>
<pre>
&lt;appender name="ping" class="de.schauderhaft.log4j.PingAppender"&gt;
    &lt;filter class="org.apache.log4j.varia.LevelRangeFilter"&gt;
        &lt;param name="LevelMin" value="ERROR"&gt;&lt;/param&gt;
        &lt;param name="AcceptOnMatch" value="true"&gt;&lt;/param&gt;
    &lt;/filter&gt;
&lt;/appender&gt;
[..]
&lt;root&gt;
    [..]
    &lt;appender-ref ref="ping"&gt;&lt;/appender-ref&gt;
&lt;/root&gt;</pre>
<p>Und schon piepst es, wenn ein Error geloggt wird. Natürlich kann man das ganze noch Bedarf verfeinern: <a href="http://pod6.com/blog_wp/2006/04/05/debugging-with-sound/">Je nach Thread, Loglevel oder Logger eine anderen Ton</a>, oder eine andere Tonhöhe.</p>
<p>Und wer Langeweile hat, kann zu einer existierenden Anwendung einen Appender bauen, der ein Musikstück spielt, wenn die richtigen Aktionen in der Anwendung ausgeführt werden.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.schauderhaft.de/2008/03/12/debugging-mit-sound-und-log4j/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
