<?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>knallisworld &#187; Java</title> <atom:link href="http://www.knallisworld.de/blog/category/entwicklung/java/feed/" rel="self" type="application/rss+xml" /><link>http://www.knallisworld.de/blog</link> <description>Where is the beef?</description> <lastBuildDate>Thu, 02 Feb 2012 23:10:07 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <item><title>Eine Jar (OJDBC) nachtrÃ¤glich in die Ziel-Jar integrieren</title><link>http://www.knallisworld.de/blog/2010/11/23/eine-jar-ojdbc-nachtraglich-in-die-ziel-jar-integrieren/</link> <comments>http://www.knallisworld.de/blog/2010/11/23/eine-jar-ojdbc-nachtraglich-in-die-ziel-jar-integrieren/#comments</comments> <pubDate>Tue, 23 Nov 2010 18:00:36 +0000</pubDate> <dc:creator>knalli</dc:creator> <category><![CDATA[Java]]></category> <category><![CDATA[Technik]]></category> <category><![CDATA[Tutorial]]></category> <guid
isPermaLink="false">http://www.knallisworld.de/blog/?p=1318</guid> <description><![CDATA[FÃ¼r das visualDependencies-Projekt stand ich eben vor dem Problem, dass zur Laufzeit ein Oracle-JDBC-Treiber benÃ¶tigt wird. Leider kann man ihn jedoch nicht als AbhÃ¤ngigkeit konfigurieren, da zum einen das Projekt unter der GPL lÃ¤uft, und zum anderen es Ã¼berhaupt keinen offiziellen Weg dafÃ¼r gibt. FÃ¼r den eigenen Buildprozess kann man selbstverstÃ¤ndlich ein lokales Repository nutzen, [...]]]></description> <content:encoded><![CDATA[<p>FÃ¼r das visualDependencies-Projekt stand ich eben vor dem Problem, dass zur Laufzeit ein Oracle-JDBC-Treiber benÃ¶tigt wird. Leider kann man ihn jedoch nicht als AbhÃ¤ngigkeit konfigurieren, da zum einen das Projekt unter der GPL lÃ¤uft, und zum anderen es Ã¼berhaupt keinen offiziellen Weg dafÃ¼r gibt. FÃ¼r den eigenen Buildprozess kann man selbstverstÃ¤ndlich ein lokales Repository nutzen, das Artefakt lokal deployen bzw. den Buildserver entsprechend konfigurieren.</p><p>Da jedoch das Projekt im Form des Sourcecodes &#8220;fÃ¼r alle&#8221; erreichbar sein soll, fallen diese Optionen zumindest fÃ¼r diese Situationen weg. Es muss also eine MÃ¶glichkeit geben, den OJDBC-Treiber nachtrÃ¤glich in das fertige Applikations-Jar zu integrieren. Und ja, das ist eigentlich sehr trivial.</p><p>Im folgenden Ant-Script werden sowohl die Applikations-Jar (visualDependencies.one-jar.jar) als auch der JDBC-Treiber (ojdbc14.jar) in der Konfiguration vorbelegt. SelbstverstÃ¤ndlich kann man alle Properties Ã¼berschreiben bzw. das Script entsprechend anpassen.</p><p>Die wichtigen Teile sind: Das Ant-Jar-Command muss den Zusatz &#8220;update&#8221; erhalten, denn die Ziel-Jar soll nicht ersetzt werden. AuÃŸerdem muss ein Fileset mit einer Verzeichnisstruktur angegeben werden, da die Treiber-Jar innerhalb der Ziel-Jar im Verzeichnis lib liegen muss (Struktur einer One-Jar). Das war&#8217;s.</p><p>Hinweis: Das Ant-File ist fÃ¼r den Gebrauch in einer Maven-Umgebung konfiguriert (basedir=../../../ entspricht dem Root-Verzeichnis bei der Annahme, dass Script unter src/main/scripts/ liegt).</p><pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project name=&quot;visualDependencies&quot; default=&quot;help&quot; basedir=&quot;../../../&quot;&gt;
	&lt;!-- The path of the actual artifact (project name), without the file suffix. --&gt;
	&lt;property name=&quot;project.name&quot; value=&quot;visualDependencies.one-jar&quot; /&gt;
	&lt;!-- The path of the ojdbc driver, without the file suffix. --&gt;
	&lt;property name=&quot;ojdbc.name&quot; value=&quot;ojdbc14&quot; /&gt;
	&lt;!-- DO NOT CHANGE THIS LINES UNLESS YOU KNOW WHAT YOU DO! --&gt;
	&lt;property name=&quot;project.jar&quot; value=&quot;${project.name}.jar&quot; /&gt;
	&lt;property name=&quot;ojdbc.jar&quot; value=&quot;${ojdbc.name}.jar&quot; /&gt;
	&lt;!-- Set actual paths of artifacts. --&gt;
	&lt;property name=&quot;application.path&quot; location=&quot;${basedir}/target/${project.jar}&quot; /&gt;
	&lt;property name=&quot;ojdbc.parent.path&quot; location=&quot;${basedir}/oracle&quot; /&gt;
	&lt;property name=&quot;ojdbc.path&quot; location=&quot;${ojdbc.parent.path}/lib/${ojdbc.jar}&quot; /&gt;
	&lt;!-- Shows help (default target) --&gt;
	&lt;target name=&quot;help&quot;&gt;
		&lt;echo message=&quot;See http://www.knallisworld.de/blog/2010/11/23/eine-jar-ojdbc-nachtraglich-in-die-ziel-jar-integrieren/&quot; /&gt;
		&lt;echo message=&quot;Usage: attachOJDBC&quot; /&gt;
	&lt;/target&gt;
	&lt;!-- Checks if the artifacts are available. Throws exceptions if they not exist. --&gt;
	&lt;target name=&quot;checkDependencies&quot;&gt;
		&lt;available file=&quot;${application.path}&quot; property=&quot;application.exists&quot; /&gt;
		&lt;available file=&quot;${ojdbc.path}&quot; property=&quot;ojdbc.exists&quot; /&gt;
		&lt;fail unless=&quot;application.exists&quot; message=&quot;The application file (${application.path}) does not exist.&quot; /&gt;
		&lt;fail unless=&quot;ojdbc.exists&quot; message=&quot;The ojdbc file (${ojdbc.path}) does not exist.&quot; /&gt;
	&lt;/target&gt;
	&lt;!-- Integrates all files of ojdbc.parent.path into the target jar. --&gt;
	&lt;target name=&quot;attachOJDBC&quot; depends=&quot;checkDependencies&quot;&gt;
		&lt;jar update=&quot;true&quot; destfile=&quot;${application.path}&quot;&gt;
			&lt;fileset dir=&quot;${ojdbc.parent.path}&quot; /&gt;
		&lt;/jar&gt;
	&lt;/target&gt;
&lt;/project&gt;
</pre>]]></content:encoded> <wfw:commentRss>http://www.knallisworld.de/blog/2010/11/23/eine-jar-ojdbc-nachtraglich-in-die-ziel-jar-integrieren/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Apples Java-Support</title><link>http://www.knallisworld.de/blog/2010/10/29/apples-java-support/</link> <comments>http://www.knallisworld.de/blog/2010/10/29/apples-java-support/#comments</comments> <pubDate>Fri, 29 Oct 2010 05:55:51 +0000</pubDate> <dc:creator>knalli</dc:creator> <category><![CDATA[Apple]]></category> <category><![CDATA[Java]]></category> <guid
isPermaLink="false">http://www.knallisworld.de/blog/?p=1272</guid> <description><![CDATA[Nur, falls das irgendjemand durch die ganzen Blogs, Techs &#38; Co missverstanden hat: The runtime provided by Apple (effectively everything in the .jdk bundle) is deprecated, but will continue to be supported throughout the service lifetimes of 10.5 and 10.6. The JavaVM.framework and it&#8217;s sub-frameworks are still supported API. (Mike Swingler, Java Engineering, Apple Inc.) [...]]]></description> <content:encoded><![CDATA[<p>Nur, falls das irgendjemand durch die ganzen Blogs, Techs &amp; Co missverstanden hat:</p><blockquote><p>The runtime provided by Apple (effectively everything in the .jdk bundle) is deprecated, but will continue to be supported throughout the service lifetimes of 10.5 and 10.6. The JavaVM.framework and it&#8217;s sub-frameworks are still supported API.</p><p>(Mike Swingler, Java Engineering, Apple Inc.) <a
href="http://lists.apple.com/archives/java-dev/2010/Oct/msg00630.html">Quelle</a></p></blockquote><p>Die Runtime ist &#8220;Java&#8221;, wÃ¤hrend das Framework quasi nur eine Schnittstelle ist. Und diese Schnittstelle ist *nicht* deprecated. Ganz im Gegenteil, sie wurde im letzten Update sogar aufgewertet (zugegeben, die MÃ¶glichkeit mehrere unterschiedlicher JVMs ist nur auf OSX ein Novum).</p> ]]></content:encoded> <wfw:commentRss>http://www.knallisworld.de/blog/2010/10/29/apples-java-support/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Java auf dem Mac</title><link>http://www.knallisworld.de/blog/2010/10/24/java-auf-dem-mac/</link> <comments>http://www.knallisworld.de/blog/2010/10/24/java-auf-dem-mac/#comments</comments> <pubDate>Sun, 24 Oct 2010 11:49:50 +0000</pubDate> <dc:creator>knalli</dc:creator> <category><![CDATA[Apple]]></category> <category><![CDATA[Java]]></category> <guid
isPermaLink="false">http://www.knallisworld.de/blog/?p=1265</guid> <description><![CDATA[Mit dem jÃ¼ngsten Java-Update hat Apple angekÃ¼ndigt, dass ihre eigene Java-Version als &#8220;deprecated&#8221; markiert wurde und das nach dem Ã¼blichen Support-Lifecycle eine Java-Entwicklung eingstellt wird. Oder, mit anderen Worten: OS X 10.6 &#8220;Snow Leopard&#8221; ist die letzte OS X Version, die ein vor-installiertes Java (JVM+JDK) besitzt und innerhalb der Ã¼blichen Apple-Updates aktualisiert wird; Apple hat [...]]]></description> <content:encoded><![CDATA[<p>Mit dem jÃ¼ngsten Java-Update hat Apple angekÃ¼ndigt, dass ihre eigene Java-Version als &#8220;deprecated&#8221; markiert wurde und das nach dem Ã¼blichen Support-Lifecycle eine Java-Entwicklung eingstellt wird.</p><p>Oder, mit anderen Worten:</p><ul><li>OS X 10.6 &#8220;Snow Leopard&#8221; ist die letzte OS X Version, die ein vor-installiertes Java (JVM+JDK) besitzt und innerhalb der Ã¼blichen Apple-Updates aktualisiert wird;</li><li>Apple hat mit dem jÃ¼ngsten Update einige Ã„nderungen in der internen Java-Framework-Architektur gemacht, damit parallele JVMs (und auch Nicht-Apple-JVMs) besser erkannt werden kÃ¶nnen und (einfacher) aktiviert werden kÃ¶nnen (ein nahe liegende Grund ist bspw. das Testen einer Developer-JVM, was bisher entweder gar nicht ging oder nur mit groÃŸem Aufwand);</li><li>Apple macht damit in Zukunft genau das gleiche wie Microsoft.</li></ul><p>Viel FUD kommt aber in einigen (Java-)Entwickler- oder Apple/Mac-Communities (oder auch der offiziellen Java-Mailingliste von Apple) auf, da die AnkÃ¼ndigung wahlweise als Java-Verbannung, &#8220;Jobs hates Java&#8221; oder sonstiger streng objektiven Aussagen interpretiert wird.</p><p>ZunÃ¤chst einmal bedeutet das Wort &#8220;deprecated&#8221; nur, das beim Release der Schnittstelle/des Frameworks die &#8220;deprecated&#8221; Komponente eben zu einem spÃ¤teren Zeitpunkt hinfÃ¤llig wird. Damit ist also nicht etwa eine <a
href="http://www.golem.de/1010/78841.html">&#8220;veraltete [Java] Technik&#8221;</a> gemeint. Also, Apple sagt nur, das ihre eigene entwickelte JVM eingestellt wird. (Genau das steht auch in den Release Notes.)</p><p>Zusammengefasst kann man als Java-Mac-Entwickler derzeit nur sagen:</p><ul><li>Schade, dass man sich auf lange Sicht in Zukunft nicht mehr auf der sicheren Seite bewegt, das eine JVM (und sogar JDK!) auf dem OSX-System vorhanden ist. Auch dort wird man also in einigen Monaten Hinweise auf das Vorhandensein von Java oder automatische Installationsangebote wiederfinden.</li><li>Schade, dass es kein Vendor-Java gibt. (Es gibt Vorteile).</li><li>SchÃ¶n, denn die Releasezyklen sind bestenfalls so gut wie von Sun (Oracle), nie besser. Und aus der Vergangenheit wissen wir, dass OS X teilweise Wochen bis Monate (und im Falle von Java 6 sogar Jahre) auf neue Versionen warten musste. Das wÃ¤re bei Sun nicht passiert.</li><li>SchÃ¶n, denn die interne Grundlage mit dem jÃ¼ngsten Update sorgt dafÃ¼r, dass OS X&#8217; Java-Framework-Komponente erst wirklich Non-Apple-JVM-tauglich ist.</li></ul><p>Wirklich schlimm wÃ¤re es nur, wenn sich entweder keiner fÃ¼r eine (offizielle) Weiterentwicklung zur VerfÃ¼gung stellt oder die einzige Weiterentwicklung nur mit X11 funktioniert. Beides wÃ¼rde dann tatsÃ¤chlich das Aus bedeuten. Diese beiden Alternativen halte ich jedoch fÃ¼r unwahrscheinlich.</p><p>Zum Thema auch folgenderÂ <a
href="http://www.dzone.com/links/r/so_what_if_apple_deprecates_their_jdk.html">Beitrag</a>. Man beachte die beiden Kommentare von Ottinger und Gosling.</p><p>Und auch <a
href="http://www.dzone.com/links/r/good_news_apple_deprecated_java.html">der hier</a>, mit dem guten Hinweis auf die Apple Extension, die natÃ¼rlich &#8220;in Gefahr&#8221; sein kÃ¶nnte. FÃ¼r diejenigen, die die Ã¼berhaupt benÃ¶tigen.</p> ]]></content:encoded> <wfw:commentRss>http://www.knallisworld.de/blog/2010/10/24/java-auf-dem-mac/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>[Howto] Maven: Wie man eine ausfÃ¼hrbare Jar in eine Java-Webanwendung (War) via Webstart integriert.</title><link>http://www.knallisworld.de/blog/2010/09/04/howto-maven-wie-man-eine-ausfuhrbare-jar-in-eine-java-webanwendung-war-via-webstart-integriert/</link> <comments>http://www.knallisworld.de/blog/2010/09/04/howto-maven-wie-man-eine-ausfuhrbare-jar-in-eine-java-webanwendung-war-via-webstart-integriert/#comments</comments> <pubDate>Sat, 04 Sep 2010 17:06:20 +0000</pubDate> <dc:creator>knalli</dc:creator> <category><![CDATA[Allgemeines]]></category> <category><![CDATA[Empfehlungen]]></category> <category><![CDATA[Java]]></category> <category><![CDATA[Technologie/IT]]></category> <category><![CDATA[Tipps]]></category> <category><![CDATA[jar]]></category> <category><![CDATA[maven]]></category> <category><![CDATA[war]]></category> <category><![CDATA[webstart]]></category> <guid
isPermaLink="false">http://www.knallisworld.de/blog/?p=1225</guid> <description><![CDATA[Die Situation Es bestehen zwei lauffÃ¤hige, fertige Projekte in Maven, welche beide auch vollwertige Artefakte bilden kÃ¶nnen. Zum einen die Webanwendung &#8212; nennen wir sie hier mal webportal &#8212; mit einem WAR-Artefakt, etwa fÃ¼r einen Tomcat. Ob das Artefakt als Snapshot oder Release gemacht wird, ob es nur generiert oder auch in ein Repository deployt [...]]]></description> <content:encoded><![CDATA[<h3>Die Situation</h3><p>Es bestehen zwei lauffÃ¤hige, fertige Projekte in Maven, welche beide auch vollwertige Artefakte bilden kÃ¶nnen.</p><p><a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/Bildschirmfoto-2010-09-04-um-18.52.33.png"></a>Zum einen die Webanwendung &#8212; nennen wir sie hier mal <em>webportal</em> &#8212; mit einem WAR-Artefakt, etwa fÃ¼r einen Tomcat. Ob das Artefakt als Snapshot oder Release gemacht wird, ob es nur generiert oder auch in ein Repository deployt wird, ist hierbei nicht von weiterer Bedeutung.<a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/Nuvola_mimetypes_java_jar.png"><img
class="size-full wp-image-1232 alignright" title="Nuvola_mimetypes_java_jar" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/Nuvola_mimetypes_java_jar.png" alt="" width="128" height="128" /></a></p><p>Zum anderen die normale Clientanwendung &#8212; nennen wir sie doch einfach <em>userclient</em> &#8212; mit einem JAR-Artefakt. Wichtig ist natÃ¼rlich, dass hier eine startfÃ¤hige Main-Klasse vorhanden ist. Dies sollte jedoch der Regelfall sein, daher nur der formale Hinweis.</p><p>Zusammengefasst, und der Auftrag an dieses Howto ist also: Wie konfiguriert und erweitert man den Buildzyklus in welchem Projekt an welcher Stelle am geschicktesten, um auf einfachem Wege die JAR-Datei <em>userclient</em> in die Webanwendung <em>webportal</em> als Java Webstart zu integrieren. Dabei ist es hilfreich, wenn man via <em>pom.xml</em> (und natÃ¼rlich der Macht der Properties) die Versionen spezifizieren kann. Der gesamte Prozess von auswÃ¤hlen, signieren und ausliefern soll dabei automatisch und ohne weiteres Eingreifen des Entwicklers geschehen kÃ¶nnen. Idealerweise sollte das ganze auch optional sein &#8212; dazu gibt es dann mehr unter &#8220;Optimierungen und Verbesserungen&#8221;.</p><p><span
id="more-1225"></span></p><h3>Die Grundlagen</h3><p><a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/Bildschirmfoto-2010-09-04-um-18.54.54.png"><img
class="alignleft size-full wp-image-1234" title="Java 6 Webstart" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/Bildschirmfoto-2010-09-04-um-18.54.54.png" alt="" width="327" height="145" /></a>Ich mÃ¶chte jetzt nicht viel Ã¼ber die Grundlagen verlieren, nur so viel sei gesagt. Aus Sicht von Maven ist die Konfiguration &#8220;nur&#8221; ein weiteres Plugin von vielen. Daraus ergibt sich natÃ¼rlich auch die MÃ¶glichkeit, via Properties oder Profilen die Konfiguration sehr dynamisch zu halten. Webstart ist eine Technik, die an sich nichts mit Maven zu tun hat. Man kann auch &#8220;hÃ¤ndisch&#8221; seine Jar-Datei Ã¼ber eine URL verfÃ¼gbar machen. Man muss dann jedoch alles selber und richtig machen: Versionisierung, Signierung und Deployment. Die Signierung ist gerade dann wichtig, wenn die Applikation erweiterte/volle Rechte benÃ¶tigt.</p><h3>Die MÃ¶glichkeiten</h3><p>Es gibt eine Reihe von Maven-Plugins, die einen unterschiedliche AnsÃ¤tze und LÃ¶sungen bieten.</p><p>Das <a
href="http://maven.apache.org/plugins/maven-jar-plugin/">Maven Jar Plugin</a> bietet etwa unter anderem die MÃ¶glichkeit, die Jar-Dateien zu signieren. Dies wÃ¤re jedoch nur die halbe Miete, da weder die Jar-Dateien bekannt noch auslieferbar sind. Auch das <a
href="http://mojo.codehaus.org/keytool-maven-plugin/">Keytool plugin</a> ist nicht vollstÃ¤ndig, denn es unterstÃ¼tzt zwar das Keystore gestÃ¼tzte signieren, aber auch nicht mehr. Wohl aber kÃ¶nnen diese Plugin als Basis fÃ¼r andere dienen.</p><p>Weitaus mehr Funktionen kann das <a
href="http://mojo.codehaus.org/webstart/webstart-maven-plugin/">Webstart Maven Plugin</a> bieten. Es gibt verschiedene Arten der Erzeugung der Jnlp-Datei und dem damit verbundenen Sammeln, Bestimmen und Signieren der AbhÃ¤ngigkeiten in Form weiterer Jars oder Classfiles. Es ist auch ein hilfreiches Plugin, wenn man aus einem Projekt heraus direkt Jnlp &amp; Ressourcen erzeugen will.</p><p>In diesem Howto ist aber vor allem ein Ziel von Relevanz:Â Die Variante mit dem Jnlp-Download-Servlet: das Goal <a
href="http://mojo.codehaus.org/webstart/webstart-maven-plugin/jnlp-download-servlet-mojo.html">webstart:jnlp-download-servlet</a>.<a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/jnlp.gif"><img
class="alignright size-full wp-image-1235" title="jnlp" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/jnlp.gif" alt="" width="128" height="128" /></a></p><p>Dieses Goal erzeugt im Buildprozess ein weiteres Verzeichnis mit den Ressourcen des <em>userclients</em> und der dazugehÃ¶renden Jnlps. Ein spezielles Servlet Ã¼bernimmt die Auslieferungen.</p><h3>Die Konfiguration im Projekt <em>userclient</em></h3><p>Das Projekt muss und sollte nicht &#8220;wissen&#8221;, dass es Ã¼ber Webstart irgendwo eingebunden wird. Daher sind keine Ã„nderungen nÃ¶tig. Wohl aber muss bekannt sein, wie die aktuelle bzw. die gewÃ¼nschte Version ist und ggf. das Maven-Repository der Deploys.</p><h3>Die Konfiguration im Projekt <em>webportal</em></h3><p><a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/Bildschirmfoto-2010-09-04-um-18.52.33.png"><img
title="Maven" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/Bildschirmfoto-2010-09-04-um-18.52.33.png" alt="" width="170" height="50" /></a>Das <em>webportal</em> muss hingegen durchaus von der Existenz des <em>userclients</em> wissen, denn jenes es soll ja in diese Webanwendung integriert werden. Die Konfiguration besteht im Wesentlichen aus drei Schritten: JnlpDownloadServlet-AbhÃ¤ngigkeit einfÃ¼gen, Servlet in der web.xml registrieren und Build-Plugin in der pom.xml konfigurieren.</p><h4>JnlpDownloadservlet (pom.xml)</h4><p>Das Maven-Paket findet sich unter dem Namen <em>com.sun.java.jnlp</em> bzw.Â <em>jnlp-servlet</em> wieder. Als einfache AbhÃ¤ngigkeit ist es damit im Classpath und beispielsweise in der web.xml verwendbar. <a
href="http://coffeebreaks.org/tmp/maven-staging/webstart/site/jnlp101.html">Weitere Informationen.</a></p><pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
    &lt;groupId&gt;com.sun.java.jnlp&lt;/groupId&gt;
    &lt;artifactId&gt;jnlp-servlet&lt;/artifactId&gt;
    &lt;version&gt;5.0&lt;/version&gt;
&lt;/dependency&gt;
</pre><h4>web.xml</h4><p>Zur Basiskonfiguration muss nur das Servlet registriert und mit einem URL-Pattern verknÃ¼pft werden. Das klingt trivial, und das ist es auch.</p><pre class="brush: xml; title: ; notranslate">
&lt;servlet&gt;
  &lt;servlet-name&gt;JnlpDownloadServlet&lt;/servlet-name&gt;
  &lt;servlet-class&gt;jnlp.sample.servlet.JnlpDownloadServlet&lt;/servlet-class&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
  &lt;servlet-name&gt;JnlpDownloadServlet&lt;/servlet-name&gt;
  &lt;url-pattern&gt;/webstart/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;</pre><p>Damit wird die URL domain.tld/context/webstart an das Servlet gemappt. Dadurch kann das Servlet auch auf &#8220;virtuelle Dateianfragen&#8221; reagieren, etwa nach Jar-Dateien ohne Versions-Qualifkation (obwohl sie als versionierte Artefakte vorliegen).</p><p>Die Konfiguration lÃ¤sst noch einige Dinge erweitern, verÃ¤ndern und tweaken (siehe Absatz Optimierungen und Verbesserungen). FÃ¼r den Haupteinsatzzweck &#8211; das Bereitstellen einer oder mehrerer Jars via Webstart ist das jedoch vÃ¶llig ausreichend.</p><p><a
href="http://download.oracle.com/javase/6/docs/technotes/guides/javaws/developersguide/downloadservletguide.html">Weitere Informationen bei Oracle/Java</a>.Â Und <a
href="http://mojo.codehaus.org/webstart/webstart-maven-plugin/examples/advanced_jnlp_download_servlet.html">weitere Informationen bei Codehaus</a>.</p><h4>pom.xml</h4><p>Neben der AbhÃ¤ngigkeit des <em>JnlpDownloadServlet</em> muss das eigentlichen <em>Maven Webstart Plugin</em> fÃ¼r seinen Einsatz konfiguriert werden. Das Build-Plugin benÃ¶tigt zudem noch ein Template (fÃ¼r die Generierung der Jnlp), die wird weiter unten beschrieben.</p><p>Zur Grundkonfiguration gehÃ¶rt:</p><ol><li>Wo liegt das Jnlp-Template?</li><li>Wie heiÃŸt der Ausgabename der Jnlp?</li><li>Welche AbhÃ¤ngigkeiten gibt es fÃ¼r das Paket &#8212; hier wÃ¤re das der <em>userclient</em>?</li></ol><p>Des Weiteren lÃ¤sst sich bestimmen, ob etwa weitere (transitive) AbhÃ¤ngigkeiten mitausgeliefert werden sollen (bei Webstart ist das wohl meist sinnvoll), ob die Ressourcen signiert werden sollen und ob alles nochmals komprimiert deployt werden soll. <a
href="http://mojo.codehaus.org/webstart/webstart-maven-plugin/examples/advanced_jnlp_download_servlet.html">Weitere Informationen</a>.</p><p>Prinzipiell ist man weder auf eine AbhÃ¤ngigkeit pro Paket/JNLP beschrÃ¤nkt noch auf eine JNLP pro Plugin-Call geschweige denn des gesamten Projekts. Ãœber das KonfigurationsschlÃ¼sselwort <em>commonJarResources</em> kÃ¶nnen sogar gemeinsam verwendete AbhÃ¤ngigkeiten definiert werden.</p><p>Da der userclient erweiterte Rechte benÃ¶tigt, mÃ¼ssen alle Classfiles und Jars signiert werden. Wahlweise verwendet dafÃ¼r einen vorhandenen Keystore oder erstellt einen neuen. FÃ¼r diese Zwecke wird pro Buildvorgang ein neuer Keystore angelegt, damit signiert und danach wieder gelÃ¶scht.</p><p>Die Execution ist sinnigerweise <em>process-resources</em> mit dem Goal <em>jnlp-download-servlet</em>, denn streng genommen sind es ja nur weitere Ressourcen.</p><pre class="brush: xml; title: ; notranslate">
&lt;plugin&gt;
  &lt;groupId&gt;org.codehaus.mojo.webstart&lt;/groupId&gt;
  &lt;artifactId&gt;webstart-maven-plugin&lt;/artifactId&gt;
  &lt;executions&gt;
    &lt;execution&gt;
      &lt;phase&gt;process-resources&lt;/phase&gt;
      &lt;goals&gt;
        &lt;goal&gt;jnlp-download-servlet&lt;/goal&gt;
      &lt;/goals&gt;
    &lt;/execution&gt;
  &lt;/executions&gt;
  &lt;configuration&gt;
    &lt;outputDirectoryName&gt;webstart&lt;/outputDirectoryName&gt;
    &lt;excludeTransitive&gt;false&lt;/excludeTransitive&gt;
    &lt;jnlpFiles&gt;
      &lt;jnlpFile&gt;
        &lt;templateFilename&gt;template.vm&lt;/templateFilename&gt;
        &lt;outputFilename&gt;UserClient.jnlp&lt;/outputFilename&gt;
        &lt;jarResources&gt;
          &lt;jarResource&gt;
            &lt;groupId&gt;org.example.userclient&lt;/groupId&gt;
            &lt;artifactId&gt;example-userclient&lt;/artifactId&gt;
            &lt;version&gt;1.0.0&lt;/version&gt;
            &lt;mainClass&gt;org.example.userclient.Main&lt;/mainClass&gt;
          &lt;/jarResource&gt;
        &lt;/jarResources&gt;
      &lt;/jnlpFile&gt;
    &lt;/jnlpFiles&gt;
    &lt;outputJarVersions&gt;true&lt;/outputJarVersions&gt;
    &lt;verbose&gt;false&lt;/verbose&gt;
  &lt;/configuration&gt;
&lt;/plugin&gt;
</pre><p>Mit dieser Konfiguration werden die Jar-Dateien inkl. AbhÃ¤ngigkeiten in das Verzeichnis <em>webstart</em> gepackt &#8212; remember? wie in der <em>web.xml</em>. Das Template heiÃŸt <em>template.vm</em> und ist per default unter <em>src/main/jnlp</em> zu finden. Dies lieÃŸe sich mit <em>templateDirectory</em> Ã¼berrschreiben. Der Name der Jnlp lautet <em>UserClient.jnlp</em>, damit ergibt sich die spÃ¤tere Web-Url: <em>http://example.org/context/webstart/UserClient.jnlp</em>. Die eigentlichen Ressourcen und AbhÃ¤ngigkeiten werden in <em>jarResources/jarResource</em> definiert. Bei einfachen Projekten wird dies nur eine Ressource sein, theoretisch wÃ¤ren auch mehrere mÃ¶glich. Die Konfiguration Ã¤hnelt der der <em>dependencies</em>.</p><h4>template.vm</h4><p>Im Prinzip ist das Template eine unfertige Jnlp. Sie wird durch das Maven Plugin mit den endgÃ¼ltigen Daten befÃ¼llt. Da bereits die pom.xml Ã¼ber einige Informationen wie Projektnamen, -beschreibung oder -url verfÃ¼gt, kÃ¶nnen so sehr einfach die Daten mit Ã¼bernommen werden. Man kann jedoch auch die Platzhalter entfernen &#8212; es ist eben nur ein Template.</p><p>Ein Beispiel kÃ¶nnte so aussehen:</p><pre class="brush: xml; title: ; notranslate">
&lt;jnlp spec=&quot;$jnlpspec&quot; codebase=&quot;$$codebase&quot;&gt;
  &lt;information&gt;
    &lt;title&gt;$project.Name&lt;/title&gt;
    &lt;vendor&gt;$project.Organization.Name&lt;/vendor&gt;
    &lt;homepage href=&quot;$project.Url&quot;/&gt;
    &lt;description&gt;$project.Description&lt;/description&gt;
    &lt;icon href=&quot;../resources/images/logo.png&quot;/&gt;
    &lt;icon href=&quot;../resources/images/logo.png&quot; kind=&quot;splash&quot;/&gt;
#if($offlineAllowed)
&lt;offline-allowed/&gt;
#end
  &lt;/information&gt;
#if($allPermissions)
&lt;security&gt;
&lt;all-permissions/&gt;
&lt;/security&gt;
#end
  &lt;resources&gt;
    &lt;j2se version=&quot;$j2seVersion&quot;/&gt;
$dependencies
  &lt;/resources&gt;
  &lt;application-desc main-class=&quot;$mainClass&quot;&gt;&lt;/application-desc&gt;
&lt;/jnlp&gt;
</pre><p>Mehr oder weniger simpel, oder? Eventuell sollte man die Adressen zum Logo anpassen (oder entfernen); gerade die letzte Zeile erzeugt einen netten Splashscreen (Ladebild) wÃ¤hrend dem Starten und Laden der Anwendung. Das ist immer gerne willkommen.</p><p>Wichtig: Im Gegensatz zu dem einen oder anderen Beispiel ist es hierbei wichtig, dass die Variable $$codebase heiÃŸt. Nicht etwa ${codebase}. Insgesamt sind in der JNLP &#8212; sofern man sie Ã¼ber das Servlet ausliefert &#8212; folgende Variablen verfÃ¼gbar: codebase, name, context und site.</p><h3>Optimierungen und Verbesserungen</h3><p
style="text-align: center;"><a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/IMG_0095.jpg"><img
class="aligncenter size-large wp-image-1236" title="IMG_0095" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/09/IMG_0095-1024x475.jpg" alt="" width="768" height="356" /></a></p><h4>&#8220;Einmal signiert, bitte!&#8221;</h4><p>Um <em>all-permissions</em> nutzen zu kÃ¶nnen, mÃ¼ssen die Jars und Classfiles signiert werden. Das erreicht man, indem man unter dem XML-Knoten <em>configuration</em> einen Knoten <em>sign</em> anlegt, etwa:</p><pre class="brush: xml; title: ; notranslate">
&lt;sign&gt;
	&lt;keystore&gt;keystore.ks&lt;/keystore&gt;
	&lt;keypass&gt;pass&lt;/keypass&gt;
	&lt;storepass&gt;pass&lt;/storepass&gt;
	&lt;alias&gt;userclient&lt;/alias&gt;
	&lt;validity&gt;36500&lt;/validity&gt;
	&lt;dnameCn&gt;UserClient&lt;/dnameCn&gt;
	&lt;dnameOu&gt;Software Development&lt;/dnameOu&gt;
	&lt;dnameO&gt;The Example Networks&lt;/dnameO&gt;
	&lt;dnameL&gt;Cologne&lt;/dnameL&gt;
	&lt;dnameSt&gt;NRW&lt;/dnameSt&gt;
	&lt;dnameC&gt;DE&lt;/dnameC&gt;
	&lt;verify&gt;false&lt;/verify&gt;
	&lt;keystoreConfig&gt;
		&lt;delete&gt;true&lt;/delete&gt;
		&lt;gen&gt;true&lt;/gen&gt;
	&lt;/keystoreConfig&gt;
&lt;/sign&gt;
</pre><p>Hierbei wird der Keystore lokal erzeugt (keystoreConfig/gen ist true) und nach Gebrauch wieder gelÃ¶scht (keystoreConfig/delete ist true). SelbstverstÃ¤ndlich kann man hier auch a) noch einen Keystore-Generator (s.o.) nutzen oder einen fest konfigurierten, dauerhaften. Dann sollte man natÃ¼rlich die Konfiguration entsprechend anpassen.</p><h4>&#8220;Bitte Optional&#8221; &#8212; alles in ein Profil</h4><p>Die Profile in der <em>pom.xml</em> sind ein mÃ¤chtiges Werkzeug, um bestimmte Features zusammenzufassen. So kÃ¶nnte man das gesamte Build-Plugin in ein Profil &#8212; etwa mit dem Namen <em>with-webstart</em> &#8212; ablegen.</p><p>Selbst die AbhÃ¤ngigkeit zum JnlpDownloadServlet kann man dorthin verlagern &#8212; wenn man daran denkt, dass in diesem Falle auch die web.xml dynamisch erstellt werden soll.</p><h4>Macht der Properties</h4><p>Man kann die Gesamtkonfiguration um einiges komfortabler machen, indem man Properties einfÃ¼hrt und deren Standardwerte &#8220;oben&#8221; in der <em>pom.xml</em> definiert. Gute Kandidaten hierbei wÃ¤ren: userclient.version, keystore.file, keystore.keypass, keystore.storepass und keystore.alias.</p><h4>Noch mehr in Sachen Jnlp</h4><p>In der <em>web.xml</em> kann des Weiteren das verhalten des JnpDownloadServlet verÃ¤ndert werden. Ein Ãœberblick Ã¼ber einige MÃ¶glichkeiten: Â Mimetypen Ã¤ndern, Dateiendungen Ã¤ndern, weitere Mappings anlegen, spezielles Debugging.</p> ]]></content:encoded> <wfw:commentRss>http://www.knallisworld.de/blog/2010/09/04/howto-maven-wie-man-eine-ausfuhrbare-jar-in-eine-java-webanwendung-war-via-webstart-integriert/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Howto: Ein firmeneigenes Java-Maven-Repository aufsetzen</title><link>http://www.knallisworld.de/blog/2010/07/06/howto-ein-firmeneigenes-java-maven-repository-aufsetzen/</link> <comments>http://www.knallisworld.de/blog/2010/07/06/howto-ein-firmeneigenes-java-maven-repository-aufsetzen/#comments</comments> <pubDate>Tue, 06 Jul 2010 21:03:12 +0000</pubDate> <dc:creator>knalli</dc:creator> <category><![CDATA[Eclipse]]></category> <category><![CDATA[Empfehlungen]]></category> <category><![CDATA[Entwicklung]]></category> <category><![CDATA[Java]]></category> <category><![CDATA[Technik]]></category> <category><![CDATA[Tutorial]]></category> <guid
isPermaLink="false">http://www.knallisworld.de/blog/?p=1136</guid> <description><![CDATA[FÃ¼r diesen Artikel setze ich jetzt einfach mal voraus, dass die Begriffe und Technologien hinter Java, Maven, Repository, Eclipse und Tomcat bekannt und gelÃ¤ufig sind. Und nein, jeweiliger Profi muss man zum VerstÃ¤ndnis nicht sein. Was wollen wir? An ein firmeneigenes Repository &#8212; oder auch: corporate repository &#8212; gelten besondere Anforderungen. Diese kÃ¶nnen bei einem [...]]]></description> <content:encoded><![CDATA[<p>FÃ¼r diesen Artikel setze ich jetzt einfach mal voraus, dass die Begriffe und Technologien hinter Java, Maven, Repository, Eclipse und Tomcat bekannt und gelÃ¤ufig sind. Und nein, jeweiliger Profi muss man zum VerstÃ¤ndnis nicht sein.</p><h3>Was wollen wir?</h3><p>An ein firmeneigenes Repository &#8212; oder auch: <em>corporate repository</em> &#8212; gelten besondere Anforderungen. Diese kÃ¶nnen bei einem &#8220;einfach privat-eigenen&#8221; verÃ¤ndert werden, aber man kommt meistens auf folgende Punkte:</p><ol><li>Ein Repository soll den Entwicklern zum Deployen der eigenen Artifakte und Module zur VerfÃ¼gung gestellt werden. Wahlweise Ã¼bernimmt dies auch ein automatischer Build-Agent wie <a
href="http://hudson-ci.org/">Hudson</a>, <a
href="http://www.jetbrains.com/teamcity/">TeamCity</a> und haste-nicht-gesehen.</li><li>Ein Repositorymanager soll als p<em>roxy</em> fungieren. In einer Firma spart dies nicht nur einfache Bandbreite. Da ein solcher Manager in der Regel im lokalen Netz steht, sind die Interaktionszeiten um ein Vielfaches besser.</li><li>Ein so genanntes t<em>hird party pepository</em> fÃ¼r die AbhÃ¤ngigkeiten, die unbedingt notwendig sind und wovon es keine Maven-AbhÃ¤ngigkeiten gibt.</li></ol><p>FÃ¼r Punkt zwei spricht auch eine wesentlich einfachere Konfiguration der Clients (Entwicklerprofile), da nur noch ein Repository eingetragen werden muss. Alle &#8220;bekannten&#8221; Repositories werden zentral gebÃ¼ndelt, damit schwindet natÃ¼rlich gleichzeitig die &#8220;Freiheit&#8221; des einzelnen Entwicklers, andere &#8220;unbekannte&#8221; Repositories zu verwenden. Dies ist jedoch vernachlÃ¤ssigbar, weil: Diese &#8220;Freiheit&#8221; schrÃ¤nkt im Endeffekt den Buildprozess und auch die Wiederverwendbarkeit ein. Das HinzufÃ¼gen von weiteren Repositories in die POM ist aus GrÃ¼nden der Versionisierung und Nachhaltigkeit auch keine optimale LÃ¶sung. Dennoch, alles nur <a
href="https://wiki.jasig.org/display/UPM30/Nexus+Proxy+Example">eine Sache der Konfigurations der Clients</a>.</p><h3>Was brauchen wir?</h3><p>Es gibt eine Reihe von Repository-Managern, die allesamt viel kÃ¶nnen. Die Wahl auf <a
href="http://nexus.sonatype.org/">Nexus</a> fÃ¤llt hier aus folgenden GrÃ¼nden:</p><ul><li>der Footprint ist mit 30 Megabyte wesentlich kleiner als bspw. <a
href="http://www.jfrog.org/products.php">Artifactory</a></li><li>die interne Verzeichnisstruktur entspricht mehr oder weniger 1:1 der realen Organisationsstruktur eines Maven-Repositorys (im Vergleich: Artifactory speichert ein eigenes Datenbankstruktur Ã¤hnliches Layout)</li><li>Nexus und das Eclipse-Plugin <a
href="http://m2eclipse.sonatype.org/">m2eclipse</a> sind vom gleichen Hersteller Sonatype und ergÃ¤nzen sich; nach dem Umstellen bemerkt der Entwickler keinen Unterschied in der Suche, Auto-Discovery, o.Ã¤.</li></ul><p>Eine <a
href="http://www.sonatype.com/books/nexus-book/reference/index.html">umfangreiche Online-Dokumentation</a> ist auf der Nexus-Seite zu finden.</p><h3>Installation</h3><p>Nexus wird unter anderem als WAR ausgeliefert, insofern die Installation in einen Tomcat ein leichtes ist. Beachtenswert ist dabei nur, dass Nexus ein Verzeichnis <em>~/sonatype-work</em> erstellt. Da sich dort unter UmstÃ¤nden viele Nutzdaten ansammeln, kann ein Verschieben (symbolischer Link?) nicht verkehrt sein. Da sich mit der Laufe der Zeit einiges an Daten ansammeln kann, sollte der Platz nicht zu sparsam vermessen sein.</p><h3>Umfang</h3><p>Nachdem Tomcat bzw. Nexus gestartet ist, kann man sich mit dem Default-Daten admin/admin123 anmelden (analog Â mit den Daten der anderen beiden Benutzern!).</p><p>Nexus kommt bereits mit einer Reihen von vorkonfigurierten, eigenen <em>hosted repositories</em> einher.</p><ul><li>releases sammelt alle Release-Artifakte der Firma</li><li>snapshots sammelt alle Snapshot-Artifakte der Firma</li><li>third-party sammelt alle Release-Artifakte externer Quellen, wofÃ¼r es keine Maven-Repositories gibt (oder wo man jenes Repository nicht generell zur VerfÃ¼gung stellen will), gutes Beispiel ist ein (aktueller) Oracle-JDBC-Treiber</li></ul><p>Daneben gibt es so genannte <em>proxy repositories</em>, die praktisch gesehen nur aus einem Index bestehen. Wie ein Proxy hÃ¤ngen sie sich zwischen dem Client und dem tatsÃ¤chlichen Repository und <em>cachen</em> alle Artifakte lokal. Selbst der Index ist mehrere Megabytes groÃŸ, das sollte man nicht vernachlÃ¤ssigen. Voreingetragene <em>proxy</em> <em>repositories</em> sind Apache Snapshots, Codehaus Snapshots, Central Maven RepositoryÂ (Maven1/Maven2-Repository-Konverter sind in Nexus vorhanden a.k.a. <em>virtual repositories</em>).</p><p>Die <em>grouped repositories</em> sind auch rein virtuelle Gruppierungen von verschiedenen Repositories. Das Standard Repository &#8220;Public&#8221; ist in der einfachsten Konfiguration eine Sammlung aller (aktivierten) Repositories auf dem Manager &#8212; also sowohl der externen Spiegel, der Third-Parties als auch den eigenen Artifakten.</p><h3>Konfiguration</h3><p>Die Aktivierung und Verwaltung von (neuen) Repositories ist abhÃ¤ngig der eigenen BedÃ¼rfnisse. Meistens sinnvoll ist es jedoch, bei den drei groÃŸen Spiegeln (<em>proxy repositories</em>) in dem Konfigurationstab das Indizieren (Download Remote Indexes) zu aktivieren. Je nach Belieben kann man in der Gruppe Administration auch das Aktualisierungsverhalten steuern.</p><h3>Konfiguration: Deployment</h3><p>Um ein Deployment zu gewÃ¤hrleisten, muss man nebst Kenntnis der Repository-URL (eben <em>die</em> URL) nur wissen, ob der anonyme Zugriff erlaubt sein soll, oder ob man einen Deployment-Benutzer einrichten und nutzen willst. Falls eine Richtlinie vorschreiben sollte, dass dies nur ein Build-Agent machen darf, ist ein (geheimes) Passwort oder SchlÃ¼ssel unabdingbar.</p><h3>Konfiguration: Client</h3><p>Nehmen wir an, der Nexus-Manager ist auf dem Host 192.168.0.10:8080/nexus installiert. In der einfachen Installation und Konfiguration sammeln sich im <em>public repository</em> praktisch alle relevanten Artifakte (sowohl Releases als auch Snapshots).</p><pre class="brush: xml; title: ; notranslate">
&lt;settings&gt;
&lt;mirrors&gt;
&lt;mirror&gt;
&lt;id&gt;corporate&lt;/id&gt;
&lt;name&gt;CorporateÂ Repository&lt;/name&gt;
&lt;url&gt;http://192.168.0.10:8080/nexus/content/groups/public&lt;/url&gt;
&lt;mirrorOf&gt;*&lt;/mirrorOf&gt;
&lt;/mirror&gt;
&lt;/mirrors&gt;
&lt;/settings&gt;
</pre><p>Der Deployment-User benÃ¶tigt ggf. Zugangsdaten fÃ¼r das entsprechende Repository.</p><p>Ein Client wie m2eclipse sollte danach einen kompletten Rebuild des Index machen.</p> ]]></content:encoded> <wfw:commentRss>http://www.knallisworld.de/blog/2010/07/06/howto-ein-firmeneigenes-java-maven-repository-aufsetzen/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Eclipse 3.6: Ersteindruck</title><link>http://www.knallisworld.de/blog/2010/06/03/eclipse-3-6-ersteindruck/</link> <comments>http://www.knallisworld.de/blog/2010/06/03/eclipse-3-6-ersteindruck/#comments</comments> <pubDate>Thu, 03 Jun 2010 15:31:40 +0000</pubDate> <dc:creator>knalli</dc:creator> <category><![CDATA[Entwicklung]]></category> <category><![CDATA[Java]]></category> <category><![CDATA[Kurz notiert]]></category> <category><![CDATA[Technik]]></category> <guid
isPermaLink="false">http://www.knallisworld.de/blog/?p=1087</guid> <description><![CDATA[Der dritte Release Candidate von Eclipse 3.6 alias Helios wurde vor wenigen Tagen bereitgestellt &#8211; man kann wohl davon ausgehen, das dem baldigen Release Juni/Juli nicht mehr viel im Weg steht. Damit reiht sich nun ein weiterer Jupitermond in die Reihe der 3.x-Releases ein: besser, umfangreicher, aktueller. Auf dem ersten Blick sieht Eclipse wie immer [...]]]></description> <content:encoded><![CDATA[<p>Der dritte Release Candidate von Eclipse 3.6 alias Helios wurde vor wenigen Tagen bereitgestellt &#8211; man kann wohl davon ausgehen, das dem baldigen Release Juni/Juli nicht mehr viel im Weg steht.</p><p>Damit reiht sich nun ein weiterer Jupitermond in die Reihe der 3.x-Releases ein: besser, umfangreicher, aktueller.</p><p><a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.14.22.png"><img
class="aligncenter size-medium wp-image-1088" title="Eclipse 3.6 About" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.14.22-300x183.png" alt="" width="300" height="183" /></a></p><p>Auf dem ersten Blick sieht Eclipse wie immer aus. Zwar wurde der Welcome-Screen, wie immer, in Punkto Design und Content geÃ¤ndert.. aber ansonsten ist alles wie gehabt.</p><p>Zwecks des kleinen Reviews habe ich die 64-Bit-Version (Cocoa) fÃ¼r Mac OS X heruntergeladen; da ich aber auch noch eine Reihe von Plugins benÃ¶tige, diese dann spÃ¤ter nachinstalliert. Prinzipiell hat sich der Updatemanager zumindestens optisch nicht zum VorgÃ¤nger geÃ¤ndert. Immerhin: Mit schÃ¤tzungsweise 50 Einzelplugins ist der Installationsvorgang erstmalig in meiner persÃ¶nlichen Eclipse-Geschichte problemlos von statten gegangen &#8211; sonst hat es immer irgendwo ein bisschen geknallt. Manchmal mit, meist ohne Auswirkungen. Unter anderem war auch ein SVN Connector Plugin dabei.</p><p><a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.07.47.png"><img
class="aligncenter size-medium wp-image-1089" title="Eclipse SVN Connector" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.07.47-238x300.png" alt="" width="238" height="300" /></a></p><p>Es sieht so aus, als wÃ¤re in Eclipse kein VCS-Plugin (mehr) enthalten, vielmehr wird dies durch den Connector (ggf. bekannt aus 3.5) bekannt. Nach dem obligatorischen Neustart wird man sofort vom Connector-Wizard begrÃ¼ÃŸt und kann zwischen verschiedenen HavaHL und SVNKit-Versionen wÃ¤hlen. AusgewÃ¤hlt, installiert, neugestartet. Fertig. Import, From SVN.. und voilÃ¡. Projekt ist drin. Interessant: Neuerdings wird man informiert, dass man gespeicherte PasswÃ¶rter (SVN-Dialog) mittels Passphrasen absichern kann.</p><h3>Die kleinen Details</h3><div
id="attachment_1090" class="wp-caption alignnone" style="width: 255px"><a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.25.35.png"><img
class="size-full wp-image-1090" title="&quot;Eigenschaften&quot; in Galileo" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.25.35.png" alt="" width="245" height="120" /></a><p
class="wp-caption-text">&quot;Eigenschaften&quot; in Galileo</p></div><div
id="attachment_1091" class="wp-caption aligncenter" style="width: 310px"><a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.25.45.png"><img
class="size-medium wp-image-1091" title="&quot;Eigenschaften&quot; in Helios" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.25.45-300x141.png" alt="" width="300" height="141" /></a><p
class="wp-caption-text">&quot;Eigenschaften&quot; in Helios</p></div><p
style="text-align: left;">Ich habe mich im Vorfeld noch nicht mit den Ã„nderungen und Neuerungen von Helios auseinandergesetzt, daher stochere ich etwas herum. AugenfÃ¤llige Ã„nderung: Die Eigenschaftsfenster einer Dateiressource wurden um eine detaillierte Rechte-Verwaltung erweitert.</p><h3>Resources / Syncing</h3><p><a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.33.57.png"><img
class="aligncenter size-medium wp-image-1096" title="Resources linken" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.33.57-300x209.png" alt="" width="300" height="209" /></a></p><p>Ahaâ€¦ Resources kÃ¶nnen jetzt endlich gefiltert in einem Projekt eingefÃ¼gt werden. Soll heiÃŸen: Man kann nicht nur weitere Resourcen dazu linken sondern auch explizit welche ausschlieÃŸen. Yes!</p><p><a
href="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.33.59.png"><img
class="aligncenter size-medium wp-image-1097" title="Resources filtern" src="http://www.knallisworld.de/blog/wp-content/uploads/2010/06/Bildschirmfoto-2010-06-03-um-17.33.59-300x209.png" alt="" width="300" height="209" /></a></p><p>Der Produktiveinsatz in den nÃ¤chsten Wochen wird zeigen, was es sonst noch gibt.</p> ]]></content:encoded> <wfw:commentRss>http://www.knallisworld.de/blog/2010/06/03/eclipse-3-6-ersteindruck/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Java Reflection API &#8211; mit Cache, ey!</title><link>http://www.knallisworld.de/blog/2010/04/29/java-reflection-api-mit-cache-ey/</link> <comments>http://www.knallisworld.de/blog/2010/04/29/java-reflection-api-mit-cache-ey/#comments</comments> <pubDate>Wed, 28 Apr 2010 22:03:00 +0000</pubDate> <dc:creator>knalli</dc:creator> <category><![CDATA[Empfehlungen]]></category> <category><![CDATA[Entwicklung]]></category> <category><![CDATA[Java]]></category> <category><![CDATA[Technik]]></category> <guid
isPermaLink="false">http://www.knallisworld.de/blog/?p=1025</guid> <description><![CDATA[EinfÃ¼hrung in Reflection Die Java Reflection API ist Bestandteil des JDK und ermÃ¶glicht den Zugriff auf Methoden, Felder und Annotationen von Klassen und Objekte, also den Instanzen von Klassen. Mit Ausnahme von Annotationen geschieht der Zugriff immer auf einer Meta-Ebene. Mit einem einfachen Beispiel ist diese Meta-Ebene erklÃ¤rt. Stellen wir uns vor, wir wollen ganz [...]]]></description> <content:encoded><![CDATA[<h2>EinfÃ¼hrung in Reflection</h2><p>Die Java Reflection API ist Bestandteil des JDK und ermÃ¶glicht den Zugriff auf Methoden, Felder und Annotationen von Klassen und Objekte, also den Instanzen von Klassen. Mit Ausnahme von Annotationen geschieht der Zugriff immer auf einer Meta-Ebene.</p><p>Mit einem einfachen Beispiel ist diese Meta-Ebene erklÃ¤rt.</p><pre class="brush: java; title: ; notranslate">
class Foo {
private String bar = &quot;private value&quot;;
}
</pre><p>Stellen wir uns vor, wir wollen ganz exemplarisch von dem Objekt foo (<em>foo = new Foo()</em>)den Inhalt von dem Feld bar erhalten. Auf dem Ã¼blichen Weg ist das nicht mÃ¶glich, da das Feld ein privates ist.</p><p>Ãœber den zugehÃ¶rigen Klassentyp (via <em>getClass()</em>) stellt Java eine Reihe von Methoden aus dem Reflection-Paket zur VerfÃ¼gung, u.a. auch <em>Field getDeclaredField(String)</em>. Ein declared field ist ein Instanzattribut eines Objektes, wÃ¤hrend ein field (<em>Field getField(String)</em>) statische Felder finden.</p><pre class="brush: java; title: ; notranslate">
Field field = foo.getClass().getDeclaredField('bar');
</pre><p>Die Variable field enthÃ¤lt aber &#8211; wie man dem Typ entnehmen kann &#8211; aber nicht den Inhalt von bar, sondern ein Field-Objekt. Um an den Inhalt zu kommen, verwendet man die Methode <em>get(Object)</em>. Der Parameter bezeichnet den entsprechenden Kontext, also das Objekt foo von weiter oben.</p><pre class="brush: java; title: ; notranslate">
Object value = field.get(foo);
</pre><p>Das bedeutet im Klartext: Auch fÃ¼r eine weitere Instanz der Klasse Foo (etwa foo2) kann dieses Field fÃ¼r dieses Feld verwendet werden. Es beinhaltet nur die Metainformationen, nicht die eigentlichen Inhalte.</p><p>Dabei ist jedoch zu beachten, dass der SecurityManager aktiv werden kann; in diesem Falle wird eine Exception bei <em>get(Object)</em> geschmissen, weil das Feld nicht sichtbar ist.</p><pre class="brush: java; title: ; notranslate">
field.setAccessible(true);
</pre><p>schafft dabei Abhilfe.</p><h3>Und Methoden?</h3><p>Im Prinzip funktioniert das Schema bei Methoden genauso &#8211; aber bevor ich jetzt einen <a
href="http://de.wikipedia.org/wiki/Radio_Eriwan">Radio Eriwan</a>-Witz loslasseâ€¦</p><p>Im Gegensatz zu den vorherigen Feldern werden Methoden nicht nur Ã¼ber den Namen, sondern auch Ã¼ber die Parametertypen identifiziert (daher kÃ¶nnen Methoden sich vom Namen her in Java auch &#8220;Ã¼berladen&#8221;).</p><pre class="brush: java; title: ; notranslate">
class Bar {
private String name;
String getName() {
return name;
}
String getName(String defaultName) {
return (name == null) ? defaultName : name;
}
}
</pre><p>Die Metainformationen werden entsprechenderweise geladen:</p><pre class="brush: java; title: ; notranslate">
Method method1 = bar.getClass().getDeclaredMethod(&quot;getName&quot;);
Method method2 = bar.getClass().getDeclaredMethod(&quot;getName&quot;, String.class);
</pre><p>SelbstverstÃ¤ndlich ist bei Kenntnisnahme der Klasse auch folgende Zeile gleichwertend:</p><pre class="brush: java; title: ; notranslate">
Method method1 = Bar.class.getDeclaredMethod(&quot;getName&quot;);
</pre><p>Methoden haben im Gegensatz zu Feldern keinen &#8220;Inhalt&#8221;, sondern sind eine AktivitÃ¤t oder Operation &#8212; und zwar auf einem Objekt. Dementsprechend funktioniert das AusfÃ¼hren mittels der Method <em>Object invoke(Object, Object&#8230;args)</em>:</p><pre class="brush: java; title: ; notranslate">
Object result1 = method1.invoke(bar); // getName()
Object result2 = method2.invoke(bar, &quot;default name&quot;); // getName(&quot;defaultName&quot;)
</pre><h3>Und Annotationen?</h3><p>Annotationen sind &#8220;Anmerkungen&#8221; im Quellcode, und seit Java 5 fester Bestandteil des JDKs. Technisch gesehen sind Annotationen besondere Klassen mit eingeschrÃ¤nkten (Java-) MÃ¶glichkeiten, deren Instanz auf einem Meta-Attribut wie Klasse, Feld, Methode oder Methodenparameter &#8220;hÃ¤ngen&#8221;. Mit anderen Worten bedeutet dass, dass man mittels Reflection tatsÃ¤chlich eine Instanz einer Annotation erhÃ¤lt &#8212; allerdings mittels einem Proxy (aus der Java API).</p><pre class="brush: java; title: ; notranslate">
@Entity
class Account {
@Column(name=&quot;id_x&quot;)
private Long id;
}
</pre><p>Die Methode getAnnotation(Class) existiert in allen Typen: Class, Field und Method.</p><pre class="brush: java; title: ; notranslate">
Account account = new Account();
Entity annotation1 = Account.class.getAnnotation(Entity.class).annotationType();
Column annotation2 = Account.class.getDeclaredField(&quot;id&quot;).getAnnotation(Column.class).annotationType();
Assert.assertEquals(&quot;id_x&quot;, annotation2.name());
</pre><h2>Performance</h2><p>Im Regelfall benÃ¶tigt man keinen Zugriff auf Reflection und sollte es vermeiden. Nichtsdestotrotz gestalten sich Konfigurationen, welche auf Basis von Annotationen, meist als sehr einfach, simpel und vor allem Code-konzentriert. Das JPA-Mapping (etwa mit Hilfe von Hibernate) gestaltet sich via Annotationen wesentlich einfacher, schneller und schlanker als mit XML.</p><p><a
href="http://blog.smart-java.nl/blog/index.php/2010/04/25/reflection-slow-well-it-depends/">Jeder Zugriff Ã¼ber die Reflection API kostet Zeit</a>. FÃ¼r Konfigurationen und PlÃ¤ne ist das meist nebensÃ¤chlich; die JPA-Konfiguration wird beim Start der Applikation eingelesen, analysiert und gespeichert. Nebenbei profitiert das natÃ¼rlich von der anfÃ¤nglichen &#8220;Warmup-Phase&#8221;.</p><p>Besteht jedoch ein <em>Access on Demand</em>, so sollte man sich Gedanken um eine geeignete Cachestruktur machen. Wichtig ist dabei, die <span
style="text-decoration: underline;">Metadaten von den eigentlichen Inhalten zu trennen</span>.</p><h2>Cachen &amp; LÃ¶sungsansÃ¤tze</h2><p>Jeder der oben genannten Reflection-Getter gibt es auch jeweils eine getAll-Variante: Class.getDeclaredFields(),Class.getDeclaredMethods(), Class.getAnnotations(), Field.getAnnotations() und Method.getAnnotations().</p><p>Mit einem einfachen Algorithmus kann man die Laufzeit drastisch senken, wenn Objekte des gleichen Typs mittels Reflection untersucht werden.</p><pre class="brush: java; title: ; notranslate">
public class CacheReflectionUtil {
// cache of declared fields of class types
private final Map&lt;Class&lt;?&gt;, Field[]&gt; classDeclaredFields = new HashMap&lt;&gt;();
// Return the declared fields of the given class type.
public Field[] getDeclaredFields(Class&lt;?&gt; type) {
Field[] fields = classDeclaredFields.get(type);
if (fields == null) {
fields = type.getDeclaredFields();
classDeclaredFields.put(type, fields);
ensureAccessibility(fields);
}
return fields;
}
// Ensure that the given fields are accessible.
public void ensureAccessibility(Field[] fields) {
for (Field field : fields) {
// setAccessible will not only set a property but invoke SecurityManager stuff
if (field.isAccessible()) {
field.setAccessible(true);
}
}
}
// Return the declared field of the given class type.
public Field getDeclaredField(Class&lt;?&gt; type, String name) {
for (Field field : getDeclaredFields(type)) {
if (field.getName().equals(name)) {
return field;
}
}
return null;
}
}
</pre><p>Um einen stetigen Speicherverbrauch zu verhindern, empfiehlt sich das Nutzen einer Least-Recently-Used-Struktur. Das Apache-Commons-Paket bietet dies etwa mit der <a
href="http://commons.apache.org/collections/apidocs/org/apache/commons/collections/map/LRUMap.html">LRUMap</a> an.</p> ]]></content:encoded> <wfw:commentRss>http://www.knallisworld.de/blog/2010/04/29/java-reflection-api-mit-cache-ey/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Context Affair</title><link>http://www.knallisworld.de/blog/2010/04/28/context-affair/</link> <comments>http://www.knallisworld.de/blog/2010/04/28/context-affair/#comments</comments> <pubDate>Wed, 28 Apr 2010 19:04:34 +0000</pubDate> <dc:creator>knalli</dc:creator> <category><![CDATA[Entwicklung]]></category> <category><![CDATA[Java]]></category> <category><![CDATA[Kurz notiert]]></category> <category><![CDATA[Spring]]></category> <category><![CDATA[Technik]]></category> <category><![CDATA[Tipps]]></category> <guid
isPermaLink="false">http://www.knallisworld.de/blog/?p=1022</guid> <description><![CDATA[Bei Spring ist die globale Einheit in der Konfiguration der so genannte ApplicationContext. Dieser Context ist etwa ein Container im Applicationserver (beispielsweiseÂ web.xml). Soweit so gut. TatsÃ¤chlich ist der WebApplicationContext eine Spezialisierung des oben genannten ApplicationContext &#8212; und zustÃ¤ndig fÃ¼r Webanwendungen. Da ein Servlet die Steuerung im Applicationserver Ã¼bernimmt, benÃ¶tigt der Spring-Context ein DispatcherServlet. Damit [...]]]></description> <content:encoded><![CDATA[<p>Bei <a
href="http://www.springsource.org/about">Spring</a> ist die globale Einheit in der Konfiguration der so genannte <em>ApplicationContext</em>. Dieser Context ist etwa ein Container im Applicationserver (beispielsweiseÂ <em>web.xml</em>). Soweit so gut.</p><p>TatsÃ¤chlich ist der <em>WebApplicationContext</em> eine Spezialisierung des oben genannten ApplicationContext &#8212; und zustÃ¤ndig fÃ¼r Webanwendungen. Da ein Servlet die Steuerung im Applicationserver Ã¼bernimmt, benÃ¶tigt der Spring-Context ein <em>DispatcherServlet</em>. Damit ist die &#8220;Verbindung&#8221; User-&gt;Server-&gt;Spring geschaffen. Soweit so gut.</p><p>Konfiguriert man das DispatcherServlet etwa &#8211; sinnigerweise &#8211; mit dem Namen&#8221;dispatcher&#8221;, dann sucht Spring standardgemÃ¤ÃŸ nach einer <em>dispatcher-servlet.xml</em>. Diese XML-Konfigurationsdatei kann Ã¤hnlich der applicationContext.xml (u.Ã¤.) ganz normale Bean-Konfigurationen enthalten. Interessant ist dabei, dass dabei ein zusÃ¤tzlicher ServletContext erstellt wird. Das hat zwei Auswirkungen:</p><ol><li>Beans aus dem ServletContext sind nicht im ApplicationContext verfÃ¼gbar</li><li>Annotations-gestÃ¼tzte Konfigurationen mÃ¼ssen jeweilse in beiden Contexten konfiguriert, also aktiviert, werden</li></ol> ]]></content:encoded> <wfw:commentRss>http://www.knallisworld.de/blog/2010/04/28/context-affair/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Seltsames Hibernate/Oracle-Verhalten bei @SequenceGenerator</title><link>http://www.knallisworld.de/blog/2010/03/29/seltsames-hibernateoracle-verhalten-bei-sequencegenerator/</link> <comments>http://www.knallisworld.de/blog/2010/03/29/seltsames-hibernateoracle-verhalten-bei-sequencegenerator/#comments</comments> <pubDate>Mon, 29 Mar 2010 08:31:16 +0000</pubDate> <dc:creator>knalli</dc:creator> <category><![CDATA[Hibernate]]></category> <category><![CDATA[Java]]></category> <guid
isPermaLink="false">http://www.knallisworld.de/blog/?p=988</guid> <description><![CDATA[Situation: Ich habe eine Menge von EntitÃ¤ten (Oracle-Schema), die mittels der Klassen-Annotation @SequenceGenerator und dann entsprechend der Attribut-Annotation @GeneratedValue eine Sequenz zugeordnet werden. Problem: Obwohl sich durch die Log zweifelsfrei zeigen lÃ¤sst, dass Hibernate die Sequenz abfragt und auch den nÃ¤chsten Wert enthÃ¤lt, ignoriert Hibernate dies beim eigentlichen EinfÃ¼gen des neuen Tupels. Stattdessen wird wahlweise [...]]]></description> <content:encoded><![CDATA[<p>Situation: Ich habe eine Menge von EntitÃ¤ten (Oracle-Schema), die mittels der Klassen-Annotation @SequenceGenerator und dann entsprechend der Attribut-Annotation @GeneratedValue eine Sequenz zugeordnet werden.</p><p>Problem: Obwohl sich durch die Log zweifelsfrei zeigen lÃ¤sst, dass Hibernate die Sequenz abfragt und auch den nÃ¤chsten Wert enthÃ¤lt, ignoriert Hibernate dies beim eigentlichen EinfÃ¼gen des neuen Tupels. Stattdessen wird wahlweise irgendeine Integerzahl wie 250, 500 oder auch gerne mal 1412 kollisionsfrei verwendet. Auch den eingebauten ID-Generator mit Zahlen jenseits von 99999 wird gerne verwendet, was dann zu netten &#8220;Hey, dass passt doch gar nicht in das Feld rein!&#8221;-Fehlern fÃ¼hrt.</p><p>Erst folgende, zusÃ¤tzliche Einstellung als Eigenschaft fÃ¼r @SequenceGenerator scheint Hibernate dazu zu bewegen, doch die Sequence zu verwenden: allocationSize 1. (impliziert so gesehen die Sequenz).</p><blockquote><p>@SequenceGenerator(name = &#8220;LOCAL_GENERATOR&#8221;, sequenceName = &#8220;SEQ_NAME&#8221;, allocationSize = 1)</p></blockquote><p>DÃ¼rfte ein Bug sein.</p> ]]></content:encoded> <wfw:commentRss>http://www.knallisworld.de/blog/2010/03/29/seltsames-hibernateoracle-verhalten-bei-sequencegenerator/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Featurities meets Fallstrick: Die Spring Security 3.0 Konfigurationsodyssey</title><link>http://www.knallisworld.de/blog/2010/01/25/featurities-meets-fallstrick-die-spring-security-3-0-konfigurationsodyssey/</link> <comments>http://www.knallisworld.de/blog/2010/01/25/featurities-meets-fallstrick-die-spring-security-3-0-konfigurationsodyssey/#comments</comments> <pubDate>Mon, 25 Jan 2010 08:56:43 +0000</pubDate> <dc:creator>knalli</dc:creator> <category><![CDATA[Java]]></category> <category><![CDATA[Konfiguration]]></category> <category><![CDATA[Spring]]></category> <category><![CDATA[Technik]]></category> <category><![CDATA[Technologie/IT]]></category> <category><![CDATA[Tipps]]></category> <category><![CDATA[security]]></category> <category><![CDATA[tomcat]]></category> <guid
isPermaLink="false">http://www.knallisworld.de/blog/?p=944</guid> <description><![CDATA[Mit dem Majorrelease 3.0 wurde dem Modul Spring Security eine Menge von neuen Features angeignet. Spring Security ist die Modulkomposition, welches fÃ¼r das Java Framework Spring quasi die gesamte Authentifizierung, Autorisierung, Legitimierung jedwegiger Art ermÃ¶glicht. Leider wurden mit dem Release 2.x auf 3.0 eine Reihe von API-Changes vollzogen. Zugegeben, die waren auch sicher alle sinnvoll, [...]]]></description> <content:encoded><![CDATA[<p>Mit dem Majorrelease 3.0 wurde dem Modul Spring Security eine Menge von neuen Features angeignet. Spring Security ist die Modulkomposition, welches fÃ¼r das Java Framework Spring quasi die gesamte Authentifizierung, Autorisierung, Legitimierung jedwegiger Art ermÃ¶glicht.<img
class="alignright" src="http://www.springsource.com/sites/all/themes/spring09/logo.png" alt="" width="264" height="46" /></p><p>Leider wurden mit dem Release 2.x auf 3.0 eine Reihe von API-Changes vollzogen. Zugegeben, die waren auch sicher alle sinnvoll, weil Komponenten wie die Authentifizierung weiterÂ geteilt wurden und man somit wesentlich flexibler ist, neue Anforderungen zu ermÃ¶glichen (Baukastenprinzip). Aber die Dokumentation ist &#8211; gesamtheitlich betrachtet &#8211; irgendwie immer noch mies und oft nicht aktualisiert. Oder man findet im Internet einfach nur (alte) Beispiele.</p><p><img
class="alignleft" src="http://www.smileygarden.de/smilie/Crazy/65.gif" alt="" width="95" height="50" /></p><h3>Die http-Direktive</h3><p>Im Namespace von Spring Security existiert das Tagelement http, mit welchem man kurze, knappe und verstÃ¤ndliche Konfigurationen anlegen kann. Der Vorteil liegt klar auf der Hand: Man muss nicht alle Beans, Listener und Provider anlegen, denn das geschieht automatisch. Tja, wÃ¤ren da nicht ein paar EinschrÃ¤nkungen in der Funktionsvielfalt.</p><h3>Konkretes Beispiel: Remember Me</h3><p>Just wurde das <a
href="http://www.springsource.org/node/2280">Minor-Release 3.0.1 verÃ¶ffentlicht</a>, und nur wenige Tage spÃ¤ter zu erfahren, dass <a
href="http://forum.springsource.org/showthread.php?p=278747#post278747">Remember Me kaputt sei</a>. Egal, fahren wir erstmal weiter mit 3.0.0.</p><p>Laut Dokumentation ist es am einfachsten, wenn man die Direktive remember-me (Security Namespace) innerhalb der http-Direktive (Security Namespace) verwendet. Ohne irgendeine Angabe wird ein stinknormales, Cookie basiertes Tokenverfahren ohne (echten) privaten SchlÃ¼ssel verwendet. Reicht fÃ¼r den ersten Einsatz erstmal auf, soll ja erstmal funktionieren.</p><p><strong>FehlermÃ¶glichkeit 1a: Man loggt sich ein, und es passiert nichts (kein &#8220;RememberMe&#8221;-Cookie).</strong><br
/> LÃ¶sung: Wenn man einen eigenen Auth-Filter einsetzt, muss man diesem auch den RememberMe-Service &#8220;setten&#8221;. AuÃŸerdem muss der SecurityChainFilter (web.xml!) auch auf die login-Seite verweisen. Es dÃ¼rfen auch keine Filter bei der Konfigurierung von intercepted Urls (speziell hier: login, logout) gemacht werden.</p><p><strong>FehlermÃ¶glichkeit 1b: Es passiert noch immer nichts?</strong><br
/> LÃ¶sung: Vielleicht wurde vergessen, einen Parameternamen fÃ¼r den Request zu setzen. Der Standardname ist ein typischer Springname, der natÃ¼rlich unschÃ¶n ist. Und den kann man nicht Ã¼ber die RememberMe-Direktive setzen, also muss man eh einen eigenen Service definieren. BÃ¤m. Referenzierung geht dann zwar noch, aber fÃ¼r mehr ist die RememberMe-Direktive dann nicht mehr zu gebrauchen.</p><p><strong>FehlermÃ¶glichkeit 2a: Man besucht die Seite ohne Login, aber mit Cookie &#8211; und die Loginseite kommt (Log sagt kein gÃ¼ltiger Auth).</strong><br
/> LÃ¶sung: Man kann der Log trauen, wenn sie zwar beim Einloggen nun einen Token ablegt (kann man zum Beispiel sehr einfach mit <a
href="https://addons.mozilla.org/de/firefox/addon/573">diesem Firefox-Addon</a> inkl. Editor(!) verifizieren), dieses aber beim erneuten Besuchen der Seite (bzw. ohne JSPSESSION-Cookie) nicht verwendet bzw. wird nicht erkannt. Schlussendlich half u.a. das Umbenennen der Userservices-Bean in &#8220;userService&#8221;. AuÃŸerdem sollte die Loginseite keinen Filter/Access haben (s.o.) Lieber 2x prÃ¼fen!</p><p><strong>FehlermÃ¶glichkeit 2b: Es erscheint eine Ausnahme, dass der Key falsch sei.</strong><br
/> LÃ¶sung: Dazu muss man wissen: Sobald Â man eine individualisierte RememberMe-Konfiguration nutzt, wird auch der Key nicht mehr vernÃ¼nftig auf alle Komponenten (Provider, Filter, Manager) gesetzt. Beim Anlegen wird also der eigene Key verwendet, beim Auslesen der Standardkey. Yes! (s.o.)</p><p><strong>FehlermÃ¶glichkeit 3: Man besucht die Seite ohne Login, aber mit Cookie &#8211; aber wie in 2 nur die Loginseite.</strong><br
/> LÃ¶sung: Im Logger/Debugger kann man nun feststellen, dass zwar das Cookie gefunden wurde, das Token gefunden und validiert wurde aber dann keine Rechte existieren &#8211; aha? Wahrscheinlich fehlt im Provider noch ein zusÃ¤tzliches Setting der Komponenten. Am besten von RememberMe Service/Filter/Provider jeweils alle mÃ¶glichen Properties durchgehen. Jaja, wie gesagt.. <img
src='http://www.knallisworld.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /></p><p><strong>FehlermÃ¶glichkeit 4: Das Ausloggen (beispielsweise logout.html) hat nach Aktivierung von Rememberme plÃ¶tzlich keine Auswirkungen mehr.</strong><br
/> LÃ¶sung: Zwar wird die Seite gefunden, aber es wird kein &#8220;Logout&#8221; gemacht. Auch hier sollte man prÃ¼fen, ob ein SecurityChainFilter (web.xml) auch fÃ¼r die logout-Seite greift.</p><p><strong>FehlermÃ¶glichkeit 5: Das Besuchen der Seite wirft einen Fehler (ggf. &#8220;mit weiÃŸer Seite&#8221;), dass keine neue Session erstellt werden kann.</strong><br
/> LÃ¶sung: Richtig, nach einem Request ist ja dann auch zu spÃ¤t. Das Attribut create-session in der Direktive http sollte daher auf &#8220;ifRequeried&#8221; gestellt sein.</p><h3>Fazit:</h3><ul><li>SecurityChainFilter immer prÃ¼fen</li><li>Intercepted Urls prÃ¼fen</li><li>RememberMe-Direktive innerhalb der http-Direktive ist quasi abgesehen von der services-ref unbrauchbar.</li></ul><h3>Anmerkung:</h3><p>NatÃ¼rlich kann man sich das Problem mit den SecurityChains vom Hals schaffen, indem man stupide ein /* filtert. Das hat jedoch zur Auswirkung, das Spring Security auch jeden verdammten Request anguckt; bei zusÃ¤tzlichen (statischen) Inhalten wie Javascript, Stylesheets, Bildern, Flash u.Ã¤. ist das ein Overhead, der unnÃ¶tig ist.</p> ]]></content:encoded> <wfw:commentRss>http://www.knallisworld.de/blog/2010/01/25/featurities-meets-fallstrick-die-spring-security-3-0-konfigurationsodyssey/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
