<?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>Spackos62-Java Blog</title>
	<atom:link href="http://java.randgestalten.de/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://java.randgestalten.de</link>
	<description>java related stuff</description>
	<lastBuildDate>Fri, 02 Oct 2009 02:08:17 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>ToolbarBuilder &#8211; Use the builder pattern to create toolbars</title>
		<link>http://java.randgestalten.de/index.php/2009/09/toolbarbuilder-use-the-builder-pattern-to-create-toolbars/</link>
		<comments>http://java.randgestalten.de/index.php/2009/09/toolbarbuilder-use-the-builder-pattern-to-create-toolbars/#comments</comments>
		<pubDate>Mon, 28 Sep 2009 16:50:42 +0000</pubDate>
		<dc:creator>Thasso</dc:creator>
				<category><![CDATA[Swing]]></category>
		<category><![CDATA[builder]]></category>
		<category><![CDATA[toolbar]]></category>

		<guid isPermaLink="false">http://java.randgestalten.de/?p=132</guid>
		<description><![CDATA[Recently I discovered  Jeremys uber-ButtonUI&#8217;s. He provides UI classes to mimic Mac OS Button looks (and more) including segmented Buttons. The UI&#8217;s are nice, but while playing around with, I thought a builder approach would fit to easily create toolbars of buttons and components. Basically the problem is that segmentation configuration depends on Button order [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I discovered  <a href="http://javagraphics.blogspot.com/" target="_blank">Jeremys</a> uber-<a href="http://javagraphics.blogspot.com/2009/08/buttons-new-uis.html">ButtonUI</a>&#8217;s. He provides UI classes to mimic Mac OS Button looks (and more) including segmented Buttons. The UI&#8217;s are nice, but while playing around with, I thought a builder approach would fit to easily create toolbars of buttons and components. Basically the problem is that segmentation configuration depends on Button order ( <img src='http://java.randgestalten.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ), so changing the order of elements within a toolbar now also involves updating the segmentation configuration. Jeremy provides a nice <em>installUI</em> method that helps adding the appropriate button UIs, but I thought this could be improved further and I wanted to play with the <a href="http://en.wikipedia.org/wiki/Builder_pattern" target="_blank">builder pattern</a> and find a way to make it extensible without copy/pasting the whole builder.</p>
<p><span id="more-132"></span></p>
<p>The basic idea is straight forward. Create a builder, add components, get the toolbar from the builder. This is how it looks:</p>
<p><a href="http://java.randgestalten.de/wp-content/uploads/2009/09/simple-toolbar-1.png"><img class="alignnone size-full wp-image-140" style="border: 0pt none;" title="simple-toolbar-1" src="http://java.randgestalten.de/wp-content/uploads/2009/09/simple-toolbar-1.png" alt="simple-toolbar-1" width="168" height="84" /></a></p>
<p>And this is how it feels:</p>
<pre><code>JComponent toolbar = new ToolbarBuilder()
        .add(new JButton("A"))
        .add(new JButton[]{new JButton("B"), new JButton("C"), new JButton("D")})
        .addSeperator()
        .add(new JButton("E"))
        .getToolbar();</code></pre>
<p>Nothing special so far. Except for the method concatenation and the <em>Button</em>[] support, this could be done easily with a default toolbar. The builder supports some helper methods to make life easier when adding <em>Button</em>[], a <em>ButtonGroup</em> or <em>Actions</em>.</p>
<p>Now lets see what happens when we use one of <a href="http://javagraphics.blogspot.com/2009/08/buttons-new-uis.html" target="_blank">Jeremys ButtonUI</a> classes and activate segmentation.</p>
<p><a href="http://java.randgestalten.de/wp-content/uploads/2009/09/segmented-toolbar-1.png"><img class="alignnone size-full wp-image-139" style="border: 0pt none;" title="segmented-toolbar-1" src="http://java.randgestalten.de/wp-content/uploads/2009/09/segmented-toolbar-1.png" alt="segmented-toolbar-1" width="230" height="94" /></a></p>
<p>You see the nice mac like segmentation. To achieve this, we had to change the builder code slightly:</p>
<pre><code>JComponent toolbar = new ToolbarBuilder()
        .withUI(TexturedButtonUI.class)
        .withSegmentation(true)
        .add(new JButton("A"))
        .add(new JButton[]{new JButton("B"), new JButton("C"), new JButton("D")})
        .addSeperator()
        .createGroup()
           .add(new JButton("E"))
           .add(new JButton("F"))
        .close()
        .getToolbar();</code></pre>
<p>The UI class is switched to TexturedButtonUI and segmentation is turned on. To get an idea of group creation, we added an &#8220;F&#8221; button to create another group.</p>
<p>Notice that the builders <em>add()</em> method that takes <em>Button[], ButtonGroup, </em>or<em> Action[]</em> automatically create segmented groups. The second way is <em>createGroup()</em>, which creates and returns a builder that groups buttons and components. The segmentation is completely controlled by the  builder and the order of components just depends on order you add your buttons and components.</p>
<p>Another point to notice here is the ComponentFactory supported by the builder. Its not shown in the example, but you are not stuck with JToolBar &#8211; you can pass in any Component in the ToolbarBuilder constructor and, using a custom ComponentFactory, you can control how Buttons and group containers are created.</p>
<p>Now, up to this point I like the builder. I can pass in by own container, use custom UIs for my buttons and also get buttons created from Actions automatically. I can created groups of segmented buttons and other components. But, I soon realized that I use two other types of toolbars regularly. Jeremys <a href="http://javagraphics.blogspot.com/2008/06/customize-toolbar-implementing-mac-like.html" target="_blank">Customizable toolbar</a> and Ken Orrs UnifiedToolbar from the <a href="http://javagraphics.blogspot.com/2008/06/customize-toolbar-implementing-mac-like.html" target="_blank">Mac Widgets Project</a>. And that&#8217;s where the trouble began. One could write two completely separated builders for the two, but, I yell at my students if they don&#8217;t follow the <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself" target="_blank">DRY</a> principles so I should try to stick with my own rules and find a way to extend the existing builder. Before I explain the problem, here are the results.</p>
<p><a href="http://java.randgestalten.de/wp-content/uploads/2009/09/customized-toolbar.png"><img class="alignnone size-full wp-image-135" style="border: 0pt none;" title="customized-toolbar" src="http://java.randgestalten.de/wp-content/uploads/2009/09/customized-toolbar.png" alt="customized-toolbar" width="483" height="403" /></a></p>
<p>This is the customized toolbar created with the following code:</p>
<pre><code>JButton customize = new JButton("Customize...");
final CustomizedToolbar toolbar = new CustomizableToolbarBuilder("toolbar demo")
        .withSegmentation(true)
        .withUI(TexturedButtonUI.class)
        .add(customize)
        .add(new JCheckBox("Check box"))
        .add(new JLabel("Label"))
        .add(new JButton("Button"))
        .add(new JButton("Hidden"))
        .hide()
        .createGroupContainer()
           .add(new JButton("g1"))
           .add(new JButton("g2"))
        .close()
        .getToolbar();</code></pre>
<p>Fairly straight forward. Only one new method in use ( <em>.hide()</em> ) which removes the last added component from the default layout. In this case the &#8220;Hidden&#8221; button is not part of the default layout of the toolbar. This time the builder was a success as it really simplifies customizable toolbar creation.</p>
<p>For the UnifiedToolbar &#8211; please don&#8217;t take it too serious &#8211; Mac Widget comes with a good UnifiedToolbarBuilder and this was more of a test to see how one can extend the existing builder without too much hassle. So, lets take a look at the result.</p>
<p><a href="http://java.randgestalten.de/wp-content/uploads/2009/09/unified-toolbar-buttonui.png"><img class="alignnone size-full wp-image-136" style="border: 0pt none;" title="unified-toolbar-buttonui" src="http://java.randgestalten.de/wp-content/uploads/2009/09/unified-toolbar-buttonui.png" alt="unified-toolbar-buttonui" width="528" height="118" /></a></p>
<p>This almost looks like Kens <a href="http://code.google.com/p/macwidgets/wiki/Examples">original example</a>, except that I used Jeremys ButtonUI. Here is the code to create the UnifiedToolbar above. Notice that I left out the component creation, but in contrast to Kens example, the component creation is straight forward. I don&#8217;t set any properties or apply any UI changes.</p>
<pre><code>JComponent toolBar = new UnifiedToolbarBuilder()
        .createGroup("View")
           .withUI(TexturedButtonUI.class)
           .add(leftButton)
           .add(rightButton)
        .close()
        .center()
            .add(new JButton("MobileMe", blueGlobeIcon))
            .add(greyGlobeButton)
            .add(new JButton("Advanced", gear))
        .right()
            .createGroup("Search", textField)
        .getToolbar();</code></pre>
<p>A few things to note here. The UnifiedToobarBuilder adds components to the left by default. Component placement can be switched using center() or right() ( there is also a left() <img src='http://java.randgestalten.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ). The default UI class applied to buttons is UnifiedToolbarButtonUI that comes with MacWidgets. The builder comes with two new <em>createGroup()</em> methods that can be used to create &#8220;labeled&#8221; groups (i.e. the View group). As you can see, we used the TexturedButtonUI implementation again, but this time inside a group. Such configurations are always restricted to the group. This enables changing group specific parameters, without any changes to the rest of the toolbar and works for all .withXXX() methods.</p>
<p>To recreate the original example, switch to a null UI within the view group ( .withUI(null) ). This prevents the default UnifiedToolbarButtonUI to be applied and you will end up with (mac only) segmented buttons again. The appropriate properties are applied to all buttons automatically because the constructor of UnifiedToolbarBuilder contains a line:</p>
<pre><code>withProperty("JButton.buttonType", "segmentedTextured");</code></pre>
<p>This applies the property to all added components. Use the withProperty() method to change the default properties.</p>
<h3>Builder hierarchies</h3>
<p>Ok. So far so good, I am happy with the result <img src='http://java.randgestalten.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  But I didn&#8217;t expect so much trouble on the way. The basic idea is straight forward, but the tricky part is extending the default ToolbarBuilder.  It is not enough to change the existing implementation by overriding some methods. That would be easy and works as expected. Problems arise with new methods in the extending builder.  Well, that should not be a problem. And it isn&#8217;t. At least not when we live with the drawback of loosing the ability to concatenate method calls and change the group creation to some other implementation. Ok, ok, example:</p>
<pre><code>class A{
    public A methodA(){return this;}
}
class B extends A{
    public B methodB(){return this;};
}</code></pre>
<p>Remember &#8211; we want to get the builder back from the method calls. This is how we can concatenate calls. In the simple scenario above, we already have a problem. <code>new B().methodA()</code> returns an instance of type A. From that point on, we have lost access to B and all methods in B. I know that the returned instance is actually of type B and could cast. But that doesn&#8217;t feel right because I have to assume things about the implementation that might change over time. The other thing is to give up the concatenation <code>B b = new B(); b.methodA(); b.methodB() ... </code> will work. Well, as long as the returned instance is of no special interest and we can be sure that it is always our &#8216;b&#8217;. In case of the toolbar builders, that not the case. For example, if you create groups using .createGroup(), the method returns a NEW builder instance. Call close() on that new instance and you are back in the original builder. But, as I said, this is nothing I want to know and it should be hidden from the user.<br />
What I was looking for was a way to include the actual type of the returned builder instance and the only way I found was using generics. The generic information passed on to the actual implementations looks really really ugly (I will show you the base ToolbarBuilder in a second), but enables encoding the actual return type in all methods.</p>
<pre><code>class A&amp;lt;T extends A&amp;gt;{
    public T methodA(){return (T) this;}
}
class B extends A&amp;lt;B&amp;gt;<strong>{
   </strong> public B methodB(){return this;};
}<strong>
</strong></code></pre>
<p>This time, B extends A and tells it that the &#8220;global&#8221; return type should be &#8220;B&#8221;. We have to do a cast now, but thats internal and when you use the class you won&#8217;t notice (I also think the cast is fairly safe). With this structure in hand, we can do <code>new B().methodA().methodB();</code>. Notice that methodA() now returns an instance of type B, so we do not loose any functionality while calling methods in the builder hierarchy.<br />
There is a major drawback tough. What if I now want to extend B ? With the example above I would be stuck in the original problem, because B is not generified and will only return instances of type B instead of, say C. We could put generics on B too and create another sub class:</p>
<pre><code>class A&amp;lt;T extends A&amp;gt;{
    public T methodA(){return (T) this;}
}
class B&amp;lt;T extends B&amp;gt; extends A&amp;lt;T&amp;gt;{
    public T methodB(){return (T) this;};
}
class C&amp;lt;T extends C&amp;gt; extends B&amp;lt;T&amp;gt;{
    public T methodC(){return (T) this;};
}</code></pre>
<p>This time we already generified C, but the whole thing contains another problem. Now we have to provide the generic parameter to the constructor even if it looks silly : <code>new C&amp;lt;C&amp;gt;().methodB()</code> returns C. Without the generic information, you will only get back a B  ( <code>new C().methodB()</code> returns B) due to automatic type inference.</p>
<p>Anyways, its ugly and I don&#8217;t want to force a <code>new UnifiedToolbarBuilder&amp;lt;</code><code>UnifiedToolbarBuilder&amp;gt;</code><code>()</code> so the final Builder classes are not generified. (They are not final though, you can still extend and override methods). There are abstract classes that carry the generic information and can be used to create new builders.</p>
<p>If you find the time, just try it <img src='http://java.randgestalten.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  And of course, feedback, comments and suggestions are welcome !!</p>
<h3>Download</h3>
<p>The ToolbarBuilder is released under the BSD License.</p>
<p>You can get the ToolbarBuilder.jar file<a href="http://java.randgestalten.de/wp-content/uploads/2009/09/toolbarbuilder.jar"> here</a>.</p>
<p>The sources are provided <a href="http://java.randgestalten.de/wp-content/uploads/2009/09/toolbarbuilder-src.jar">here</a>.</p>
<p>API Documentaiton can be found <a href="http://java.randgestalten.de/files/toolbarbuilder-api/">here</a>.</p>
<p>Remember to put <a href="http://code.google.com/p/macwidgets/" target="_blank">MacWidgets</a> , the <a href="http://javagraphics.blogspot.com/2009/08/buttons-new-uis.html">ButtonUI</a> and/or the <a href="http://javagraphics.blogspot.com/2008/06/customize-toolbar-implementing-mac-like.html">Customizable Toolbar</a> in your ClassPath. The ToolbarBuilder was tested with Java 1.5 and 1.6.</p>
]]></content:encoded>
			<wfw:commentRss>http://java.randgestalten.de/index.php/2009/09/toolbarbuilder-use-the-builder-pattern-to-create-toolbars/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bounded beans in IntelliJ IDEA</title>
		<link>http://java.randgestalten.de/index.php/2009/06/bounded-beans-in-intellij-idea/</link>
		<comments>http://java.randgestalten.de/index.php/2009/06/bounded-beans-in-intellij-idea/#comments</comments>
		<pubDate>Fri, 19 Jun 2009 08:17:02 +0000</pubDate>
		<dc:creator>Thasso</dc:creator>
				<category><![CDATA[Other]]></category>

		<guid isPermaLink="false">http://java.randgestalten.de/?p=125</guid>
		<description><![CDATA[Well, for some reason I lost my Intellij IDEA configuration. I had a nice live template to create a firePropertyChange statement. This is not as nice as the bound setter plugin for eclipse as it does not create the method but the methods body.
Basically create a new Live Template and set the name to something [...]]]></description>
			<content:encoded><![CDATA[<p>Well, for some reason I lost my Intellij IDEA configuration. I had a nice live template to create a firePropertyChange statement. This is not as nice as the <a href="http://java.randgestalten.de/index.php/2008/10/generate-bounded-setters-plugin/">bound setter plugin</a> for eclipse as it does not create the method but the methods body.</p>
<p>Basically create a new <a href="http://blogs.jetbrains.com/idea/2006/03/defining-a-live-template-for-null-check/" target="_blank">Live Template</a> and set the name to something like &#8220;fpc&#8221;. The template is</p>
<pre>
<code>firePropertyChange("$name$", $name$, this.$name$ = $name$);</code>
</pre>
<p>and the variable definition for $name$ is <code>variableOfType("Object")</code>. Finally set the default value to &#8220;name&#8221; and you are ready to go. Let the IDE create a setter, remove the body, type fpc and hit tab. This will expand to the firePropertyChange statement and if you are lucky, the variable name is correct <img src='http://java.randgestalten.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Of course, the class has to be some sort of <a href="http://java.randgestalten.de/index.php/2008/10/a-simple-abstractbean/">AbstractBean</a> and provide a <code>firePropertyChange</code></p>
]]></content:encoded>
			<wfw:commentRss>http://java.randgestalten.de/index.php/2009/06/bounded-beans-in-intellij-idea/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Get the current SVN revision number in from Ant</title>
		<link>http://java.randgestalten.de/index.php/2009/05/get-the-current-svn-revision-number-in-from-ant/</link>
		<comments>http://java.randgestalten.de/index.php/2009/05/get-the-current-svn-revision-number-in-from-ant/#comments</comments>
		<pubDate>Thu, 14 May 2009 14:06:46 +0000</pubDate>
		<dc:creator>Thasso</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[ant]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://java.randgestalten.de/?p=119</guid>
		<description><![CDATA[Another minor Problem I struggled with the last couple times I was updating one of my build scripts was resolving the current SVN revision number from within ant. Google points out a few solutions,  but most of them require optional SVN tasks or do an exec. Someone (sorry, I would put a link if [...]]]></description>
			<content:encoded><![CDATA[<p>Another minor Problem I struggled with the last couple times I was updating one of my build scripts was resolving the current SVN revision number from within ant. Google points out a few solutions,  but most of them require optional SVN tasks or do an exec. Someone (sorry, I would put a link if I could remember) came up with the simple solution of using the stored SVN information from the filesystem. So:</p>
<pre>
<code>    &lt;loadfile property="svn.revision" srcFile="./.svn/entries"&gt;
        &lt;filterchain&gt;
        &lt;headfilter lines="1" skip="3"/&gt;
        &lt;deletecharacters chars="\n"/&gt;
        &lt;/filterchain&gt;
   &lt;/loadfile&gt;</code>
</pre>
<p>loads the current revision number into a property called <code>svn.revision</code>. I use this with svn 1.4 and 1.5 repositories and it works just fine.</p>
]]></content:encoded>
			<wfw:commentRss>http://java.randgestalten.de/index.php/2009/05/get-the-current-svn-revision-number-in-from-ant/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Appframework and accelerator keys</title>
		<link>http://java.randgestalten.de/index.php/2009/03/appframework-and-accelerator-keys/</link>
		<comments>http://java.randgestalten.de/index.php/2009/03/appframework-and-accelerator-keys/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 23:56:41 +0000</pubDate>
		<dc:creator>Thasso</dc:creator>
				<category><![CDATA[Swing]]></category>
		<category><![CDATA[appframework]]></category>

		<guid isPermaLink="false">http://java.randgestalten.de/?p=110</guid>
		<description><![CDATA[Today I re-researched on the topic of assigning accelerator keys to actions depending on the operating system using java appframework. The problem I have is simple. On Mac OS X the &#8220;meta&#8221; key maps to apples command key. On windows it maps to the &#8220;Alt&#8221; key. And thats is the beginning of all the trouble. [...]]]></description>
			<content:encoded><![CDATA[<p>Today I re-researched on the topic of assigning accelerator keys to actions depending on the operating system using java <a href="https://appframework.dev.java.net/" target="_blank">appframework</a>. The problem I have is simple. On Mac OS X the &#8220;meta&#8221; key maps to apples command key. On windows it maps to the &#8220;Alt&#8221; key. And thats is the beginning of all the trouble. Assume you want to define a &#8220;save&#8221; action. On Mac the shortcut should be &#8220;command-S&#8221;, on windows it should be &#8220;ctrl-S&#8221;. In terms of appframework (or java keystrokes) that means you need:</p>
<pre><code>save.Action.accelerator=meta pressed S</code></pre>
<p>if you are on Mac OS X and</p>
<pre><code>save.Action.accelerator=ctrl pressed S</code></pre>
<p>if you are on Windows. The simple way to to this is</p>
<pre><code>save.Action.accelerator=shortcut S</code></pre>
<p>and &#8220;shortcut&#8221; will map to the meta key on the mac and to the ctrl key on windows. Remember, this is appframework specific and not a real Keystroke definition. I didn&#8217;t find the documentation anywhere ( I am sure it somewhere <img src='http://java.randgestalten.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ), but I found that while browsing the source code. It doesn&#8217;t solve all the problems related to accelerator/mnemonic/keystrokes on differen paltforms ! But, at least for me, it solved 90% of the problems, because we develope <a href="http://bio.informatik.uni-jena.de/epos">our app</a> in english (so no other locales involved) and &#8220;ctrl&#8221; is also fine for the linux/unix/solaris platform. I you want to do more or just want to read more about the problem, there is a <a href="http://markmail.org/message/mqkjgdeigfr6w2t2#query:java%20appframework%20accelerator+page:1+mid:q5thlgty3xlw6kb2+state:results">thread from the appframwork mailing list</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://java.randgestalten.de/index.php/2009/03/appframework-and-accelerator-keys/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Set JPA entities at runtime</title>
		<link>http://java.randgestalten.de/index.php/2009/02/set-jpa-entities-at-runtime/</link>
		<comments>http://java.randgestalten.de/index.php/2009/02/set-jpa-entities-at-runtime/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 13:41:19 +0000</pubDate>
		<dc:creator>Thasso</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[EclipseLink]]></category>
		<category><![CDATA[EPoS]]></category>
		<category><![CDATA[JPA]]></category>

		<guid isPermaLink="false">http://java.randgestalten.de/?p=82</guid>
		<description><![CDATA[We use JPA as persistence mechanism for EPoS. The JPA implementation for the next release will be EclipseLink and I was adding that over the weekend. One important thing: I don&#8217;t know the entity classes at compile time. That makes it impossible to add the class names to the persistence.xml directly. Somehow we need a [...]]]></description>
			<content:encoded><![CDATA[<p>We use JPA as persistence mechanism for <a href="http://bio.informatik.uni-jena.de/epos">EPoS</a>. The JPA implementation for the next release will be <a href="http://www.eclipse.org/eclipselink/">EclipseLink</a> and I was adding that over the weekend. One important thing: I don&#8217;t know the entity classes at compile time. That makes it impossible to add the class names to the persistence.xml directly. Somehow we need a way to specify the classes at runtime (well, at least at initialization time, when we boto up the EntityManagerFactory). That is something taht seems to be not part of the JPA spec for Java SE environments ( in Java EE, you can let it <a href="http://java-persistence.blogspot.com/2008/02/testing-eclipselink-jpa-in-javase.html">search the jar files for entity classes</a>).</p>
<p>Ok, so we need a way to manipulate the content of the persistence.xml at runtime to add the class entries and I found way, hacking into the mechanism that reads the content of the persistence.xml.<br />
Basically, what we do is, we occupy the stream that represents the file and manipulate it at runtime. To do so, we have to extend the initialization process, but, thanks to protected variables used by the EclipseLink team, this works without any manipulation of the EclipseLink source code. We have to extend some classes, to make it work, but thats it. And it turned out that the changes are rather minimal and the hack works straight forward. So, lets jump into the code and get things running. Still, keep in mind, we work on top of internal initialization code ! There is a good chance that this breaks with a new release, although I think it will be straight forward to keep things running&#8230;at least as long as the EclipseLink team sticks to protected access modifiers for some of their variables.</p>
<p><span id="more-82"></span></p>
<p>The interface we have to implement is org.eclipse.persistence.internal.jpa.deployment.Archive. This defines the access mechanism used by EclipseLink and the implementations are used to access the content of the persistence.xml via  the getEntry method:</p>
<pre><code>/**
* Returns the InputStream for the given entry name. Returns null if no such
* entry exists. The entry name must be relative to the root of the module.
*
* @param entryPath the file name relative to the root of the module.
* @return the InputStream for the given entry name or null if not found.
*/
InputStream getEntry(String entryPath) throws IOException;</code></pre>
<p>Well, we don&#8217;t want to provide a complete implementation, we just want to know when the persistence.xml is accessed. Therefore we implemented a WrapperArchive that delegates to a parent archive and checks for access to persistence.xml.</p>
<pre><code>...
public InputStream getEntry(String entryPath) throws IOException {
    if (entryPath.equals("META-INF/persistence.xml")) {
        return createPersitenceString(parent
                .getEntry("META-INF/persistence.xml"));
    }
    return parent.getEntry(entryPath);
}
...
protected InputStream createPersitenceString(InputStream in) {
    BufferedReader bi = new BufferedReader(new InputStreamReader(in));
    StringBuffer b = new StringBuffer();
    String l = null;
    try {
        l = bi.readLine();
        while (l != null) {
            if (l.trim().startsWith("<!--$$CLASSES$$-->")) {
                if (entityCalsses != null) {
                    for (String clazz : entityCalsses) {
                        b.append("");
                        b.append(clazz);
                        b.append("");
                        b.append("\n");
                    }
                }
            } else {
                b.append(l);
            }
            l = bi.readLine();
        }
    } catch (IOException e) {
        Logger.getLogger(getClass()).error("Error while creating dynamic persistence.xml", e);
    }
    return new ByteArrayInputStream(b.toString().getBytes());
}
...</code></pre>
<p>All other methods delegate directly to the parent archive and we intercept access to <code>META-INF/persistence.xml</code>. If someone tries to get a stream to the persistence.xml, we intercept that call, read the original stream, manipulate it and return the changed content. Well, we just look for &lt;!&#8211;$$CLASSES$$&#8211;&gt; somewhere in the original, and replace that with the class definitions. I know, I know, there are better ways, but this works for now.<br />
Now, all we have to do is make sure that the WrapperArchive is used. To achieve this, we extend the PersistenceProvider:</p>
<pre><code>public class DynamicPersistenceProvider extends PersistenceProvider{
    private DynamicPersistenceProvider() {
        super();
        initializationHelper = new DynamicInitializationHelper();
    }
    public DynamicPersistenceProvider(String[] classes) {
        this();
        WrapperArchive.setEntityCalsses(Arrays.asList(classes));
    }
}</code></pre>
<p>The dynamic provider is initialized with the set of entity classes and we can use the openness of the EclipseLink implementation (thanks for using protected variables !!!). Internally they use an initialization helper that is used to get access to a JPAInitializer that has a method <code>initialize(Map, PersistenceInitializerHelper)</code> that creates the archives. To get that in, we implement the a DynamicInitializationHelper that extends PersistenceInitializationHelper:</p>
<pre><code>public class DynamicInitializationHelper extends PersistenceInitializationHelper{
    public JPAInitializer getInitializer(ClassLoader classLoader, Map m) {
        return DynamicJavaSECMPInitializer.getJavaSECMPInitializer();
    }
}</code></pre>
<p>This returns our own JPAInitializer</p>
<pre><code>public class DynamicJavaSECMPInitializer extends JavaSECMPInitializer {
    public static synchronized DynamicJavaSECMPInitializer getJavaSECMPInitializer() {
        if (javaSECMPInitializer == null || !(javaSECMPInitializer instanceof DynamicJavaSECMPInitializer)) {
           javaSECMPInitializer = new DynamicJavaSECMPInitializer();
        }
        initializeTopLinkLoggingFile();
        return (DynamicJavaSECMPInitializer) javaSECMPInitializer;
    }
    public void initialize(Map m, PersistenceInitializationHelper persistenceHelper) {
        initializeClassLoader(persistenceHelper);
        final Set pars = PersistenceUnitProcessor.findPersistenceArchives(initializationClassloader);
        for (Archive archive: pars) {
            AbstractSessionLog.getLog().log(SessionLog.FINER, "cmp_init_initialize", archive);
            initPersistenceUnits(WrapperArchive.createWrapperArchive(archive), m, persistenceHelper);
        }

    }
}</code></pre>
<p>where we override the <code>initialize</code> method. The content is copy pasted from the original implementation except that we make sure that we create the WrapperArchives here. Also, again, thanks to the protected variables, we change the static reference to the JavaSECMPInitializer singleton to our dynamic version.</p>
<p>At the end of the day its not much code to achieve the runtime manipulation and we can do something like this</p>
<pre><code>...
String[] classes = new String[]{Person.class.getName()};
EntityManagerFactory emf = new DynamicPersistenceProvider(classes)
    .createEntityManagerFactory(persistenceUnitName, loadConfiguration());</code></pre>
<p>and end up with a persistence unit that contains a Person entity.<br />
There is only one little drawback that I discovered so far. When using dynamic weaving ( -javaagent:eclipselink.jar ), the JavaSECMPInitializer singleton seems to be initialized somewhere else. My workaround for now, I close the EntityManagerFactory immediately after the first creation and recreate a new one. That way lazy loading works and I am happy for the moment. I have to digg a bit deeper to find out why we need to do that, but for the moment I am happy <img src='http://java.randgestalten.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Here is the <a href="http://java.randgestalten.de/files/dynamicPersistence.zip">source code</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://java.randgestalten.de/index.php/2009/02/set-jpa-entities-at-runtime/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>BeansBinding ELProperty as simple template engine</title>
		<link>http://java.randgestalten.de/index.php/2008/10/beansbinding-elproperty-as-simple-template-engine/</link>
		<comments>http://java.randgestalten.de/index.php/2008/10/beansbinding-elproperty-as-simple-template-engine/#comments</comments>
		<pubDate>Thu, 30 Oct 2008 00:55:55 +0000</pubDate>
		<dc:creator>Thasso</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[BeansBinding]]></category>
		<category><![CDATA[EL]]></category>

		<guid isPermaLink="false">http://java.randgestalten.de/?p=77</guid>
		<description><![CDATA[I just read an article about using adding EL support on your projects and I was looking for a nice alternative to Velocity anyways.
I know EL basics from BeansBinding, which I use in most of my UI projects. EL itself looks pretty interesting, but, well, sort of complicated. Even finding the proper jar files seems [...]]]></description>
			<content:encoded><![CDATA[<p>I just read an article about using <a href="http://weblogs.java.net/blog/felipeal/archive/2008/10/adding_el_suppo.html">adding EL support on your projects</a> and I was looking for a nice alternative to Velocity anyways.</p>
<p>I know EL basics from <a href="https://beansbinding.dev.java.net/">BeansBinding</a>, which I use in most of my UI projects. EL itself looks pretty interesting, but, well, sort of complicated. Even finding the proper jar files seems to be a problem, or at least <em>&#8220;another of life&#8217;s obscure mysteries&#8221;</em> and using EL for a simple search and replace example implies implementing some  <em>internals</em>. I was looking for something that I can just use.</p>
<p>Luckily, the first comment mentions the ELProperty class from BeansBinding, and that jar is just a few mouse clicks away, so I thought I give it a try&#8230;and&#8230;well&#8230;it works <img src='http://java.randgestalten.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><span id="more-77"></span></p>
<pre class="code"><code>public static void main(String[] args) {
    Person mom = new Person("Ann", null);
    Person son = new Person("Dave", mom);
    Dog dog = new Dog("Foxy");

    ELProperty el = ELProperty
            .create("${name}'s mom is ${mother.name}");
    System.out.println(el.getValue(son));

    ELProperty mapEL = ELProperty
            .create("${mother.name}'s dog is ${dog.name}");
    Map map = new HashMap();
    map.put("mother", mom);
    map.put("dog", dog);
    System.out.println(mapEL.getValue(map));
}</code></pre>
<p>ELProperty.create() creates a new instance from a template string. You can fill the template with values using getValue() method. This one takes either an Object with proper getter methods or a Map to resolve variables. And this is the result of the simple example:</p>
<pre><code>Dave's mom is Ann
Ann's dog is Foxy</code></pre>
<p><a href="http://java.randgestalten.de/files/ELBeansTest.java">Full Sample Code</a> ( You need the beansbinding jar in the classpath)</p>
]]></content:encoded>
			<wfw:commentRss>http://java.randgestalten.de/index.php/2008/10/beansbinding-elproperty-as-simple-template-engine/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>combine multiple jar files and remove signatures</title>
		<link>http://java.randgestalten.de/index.php/2008/10/combine-multiple-jar-files-and-remove-signatures/</link>
		<comments>http://java.randgestalten.de/index.php/2008/10/combine-multiple-jar-files-and-remove-signatures/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 22:56:48 +0000</pubDate>
		<dc:creator>Thasso</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[ant]]></category>
		<category><![CDATA[jar]]></category>
		<category><![CDATA[signature]]></category>

		<guid isPermaLink="false">http://java.randgestalten.de/?p=65</guid>
		<description><![CDATA[I just came across a situation where I had to join multiple jar files and my own classes into one jar bundle. Ant comes in handy:

&#60;jar destfile="${app.id}-${app.version}.jar"
  index="true"
  filesetmanifest="merge"&#62;
  &#60;fileset dir="${classes.dir}"/&#62;
  &#60;zipgroupfileset dir="${lib.dir}" includes="*.jar" /&#62;
&#60;/jar&#62;

This takes all the files in ${classes.dir}, packs them in a jar and add the content of [...]]]></description>
			<content:encoded><![CDATA[<p>I just came across a situation where I had to join multiple jar files and my own classes into one jar bundle. Ant comes in handy:</p>
<pre>
<code>&lt;jar destfile="${app.id}-${app.version}.jar"
  index="true"
  filesetmanifest="merge"&gt;
  &lt;fileset dir="${classes.dir}"/&gt;
  &lt;zipgroupfileset dir="${lib.dir}" includes="*.jar" /&gt;
&lt;/jar&gt;</code>
</pre>
<p>This takes all the files in <code>${classes.dir}</code>, packs them in a jar and add the content of all the jar files in <code>${lib.dir}</code>. In this case, we merge multiple manifests, but this can be changed according to the jar <a href="http://ant.apache.org/manual/CoreTasks/jar.html">task documentation</a>.<br />
<span id="more-65"></span><br />
This works as long as none of your files is signed. You know that you are in trouble when you get messages like</p>
<pre>
<code>java.lang.SecurityException: no manifiest section for signature file entry ....</code>
</pre>
<p>I found a solution <a href="http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&#038;f=65&#038;t=000103">here</a>, and the say that one has to remove the SUN_MICR files. This can be done manually, but keep it in mind when ever you update your libraries. I find it more elegant when ant just removes the files. Unfortunately it is to possible to specify excludes for zipgroupfileset. The alternative to zipgroupfileset is zipfileset, which allows exclude patterns and extraction of zip files via the src parameter. And thats the problem. You can only specify exactly one file as src. I don&#8217;t want to specify all my jars manually. Therefore I creates a single jar first, using zipgroupfileset and then move this file through a zip/zipfileset where we can exclude specific files. </p>
<pre>
<code>&lt;jar destfile="${app.id}-${app.version}.jar"
  index="true"
  filesetmanifest="merge"&gt;
  &lt;fileset dir="${classes.dir}"/&gt;
  &lt;zipgroupfileset dir="${lib.dir}" includes="*.jar" /&gt;
&lt;/jar&gt;
&lt;zip destfile="temp-jar-file.jar"&gt;
  &lt;zipfileset src="${app.id}-${app.version}.jar" excludes="META-INF/*.RSA, META-INF/*.DSA, META-INF/*.SF" /&gt;
&lt;/zip&gt;
&lt;move file="temp-jar-file.jar" tofile="${app.id}-${app.version}.jar"/&gt;</code>
</pre>
<p>You end up with a single, signature free jar file. This is not the most elegant solution, which would be either to enable multiple src files in zipfileset or an excludes parameter for zipgroupfileset that matches against the content of files, not the input files. But still, its small and does not need any third party ant tasks. </p>
]]></content:encoded>
			<wfw:commentRss>http://java.randgestalten.de/index.php/2008/10/combine-multiple-jar-files-and-remove-signatures/feed/</wfw:commentRss>
		<slash:comments>39</slash:comments>
		</item>
		<item>
		<title>Add Copyright to Java Sources</title>
		<link>http://java.randgestalten.de/index.php/2008/10/add-copyright-to-java-sources/</link>
		<comments>http://java.randgestalten.de/index.php/2008/10/add-copyright-to-java-sources/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 20:57:34 +0000</pubDate>
		<dc:creator>Thasso</dc:creator>
				<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Other]]></category>
		<category><![CDATA[QAlign2]]></category>

		<guid isPermaLink="false">http://java.randgestalten.de/?p=59</guid>
		<description><![CDATA[Just found a nice Eclipse plugin that adds license information to a all the files (well, you can select them) in a project. You can specify the license, enter your own, customize the output &#8230;. nice !
Just reminds me, we had a java class that did that for QAlign 2 Panta Rei source code distribution.
Yeah, [...]]]></description>
			<content:encoded><![CDATA[<p>Just found a <a href="http://www.wdev91.com/?p=cpw_ug">nice Eclipse plugin</a> that adds license information to a all the files (well, you can select them) in a project. You can specify the license, enter your own, customize the output &#8230;. nice !</p>
<p>Just reminds me, we had a java class that did that for <a href="http://gi.cebitec.uni-bielefeld.de/qalign">QAlign 2 Panta Rei</a> source code distribution.</p>
<p>Yeah, <a href="http://java.randgestalten.de/files/AppendDisclaimer.java">there it is</a>, May 21, 2005 written in Michas old apartment in Barcelona while working on QAlign2.</p>
<div id="attachment_60" class="wp-caption aligncenter" style="width: 310px"><a href="http://java.randgestalten.de/wp-content/uploads/2008/10/barca.jpg"><img src="http://java.randgestalten.de/wp-content/uploads/2008/10/barca-300x225.jpg" alt="The QAlign2 crew" title="barca" width="300" height="225" class="size-medium wp-image-60" /></a><p class="wp-caption-text">The QAlign2 crew</p></div>
<p><span id="more-59"></span></p>
<p>And &#8211; do never ever trust Micha when he says that he never copied a &#8220;Start Wars &#8211; Episode I&#8221; script into a static final String variable in one of the source code files <img src='http://java.randgestalten.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<pre><code>import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/*
 * Created on May 21, 2005
 */

/**
 * Class scans given directory for sourcefiles and appends a disclaimer
 *
 * This is a quick hack version of a good appending methods and it is NOT memory efficient. Thats
 * why "Start Wars - Episode I" will not work as disclaimer. The disclaimer itself should NOT be inlined
 * in sourcecode comment tags, this is done by {@see #readDiscalimer()} (Let it be the pure disclaimer, without any \/* *\/).
 * Also the size of source files is limited to the heap size of the vm. If one uses this with large source
 * or disclaimer files extend the VM max heap size (e.g. -Xmx512m).
 *
 * Remember, the scanFile() method automatically appends "\r\n" to each line while writing the files.
 *
 * parameters
 * -d  The source directory
 * -f  The disclaimer
 * -v &amp;lt;0..2&amp;gt; verbose output
 * @author Thasso
 */
public class AppendDisclaimer {
    /**
     * the input directory
     */
    public static String inputDir = ".";
    /**
     * Filename of the disclaimer
     */
    public static String disclaimerFile = null;
    /**
     * String representation of the disclaimer
     */
    public static String disclaimer;

    /**
     * verbose level
     */
    public static int verbose = 0;

    public static void main(String[] args) {
        if(args.length &amp;lt; 1){
            printUsage();
        }
        // Parse arguments
        for (int i = 0; i &amp;lt; args.length; i++) {
            if(args[i].equalsIgnoreCase("-d")){
                inputDir = args[i+1];
            }
            if(args[i].equalsIgnoreCase("-v")){
                verbose = args[i+1] != null ? Integer.parseInt(args[i+1]):2;
            }
            if(args[i].equalsIgnoreCase("-f")){
                disclaimerFile = args[i+1];
            }
        }
        if(disclaimerFile == null)
            printUsage("Discalimer file not set ! Use -f to define a disclaimer");

        readDiscalimer();        

        // read filelist from directory
        File input = new File(inputDir);
        if(!input.isDirectory() ||!input.canRead()){
            printUsage("Can not read from directory " + input.getAbsolutePath());
        }
        if(verbose &amp;gt; 0)
            System.out.println("Scanning Directory :\n\t"+input.getAbsolutePath());

        List javaFiles = readDirectory(input, ".java");
        //Scan files and append disclaimer
        for (Iterator it = javaFiles.iterator(); it.hasNext();) {
            File f = (File) it.next();
            scanFile(f);
        }
    }

    /**
     * read the disclaimer from file
     */
    private static void readDiscalimer() {
        File f = new File(disclaimerFile);
        StringBuffer d = new StringBuffer();
        if(!f.exists())
            printUsage("Disclaimer " + disclaimerFile + " not found");
        if(!f.canRead())
            printUsage("Disclaimer " + disclaimerFile + " not readable");

        try {
            BufferedReader in = new BufferedReader(new FileReader(f));
            d.append("/*\r\n");
            String l = in.readLine();
            while(l != null){
                d.append(" * "+l+"\r\n");
                l = in.readLine();
            }
            d.append("*/\r\n");
            disclaimer = d.toString();
            in.close();
        } catch (FileNotFoundException e) {
            printUsage("Disclaimer " + disclaimerFile + " not found");
        } catch (IOException e) {
            printUsage("Error while reading from file " + disclaimerFile);
        }
    }

    /**
     * Memory consuming scna file method.
     * Creates a buffer and appends the disclaimer. Than reads the file and appends it to
     * the buffer, line by line, adding \\r\\n to each line.
     * When done, writes out the file with a simple and absolute inefficent buffer.toString() call.
     *
     * @param f
     */
    private static void scanFile(File f){
        BufferedReader in = null;
        StringBuffer content = new StringBuffer();
        content.append(disclaimer+"\r\n"+"\r\n");
        if(verbose &amp;gt; 1)
            System.out.println("Reading file " + f.getName());

        try {
            in = new BufferedReader(new FileReader(f));
            String line = in.readLine();
            while(line != null){
                content.append(line+"\r\n");
                line = in.readLine();
            }
            in.close();
        } catch (FileNotFoundException e) {
            printUsage("File  not found " + f.getName());
        } catch (IOException e) {
            printUsage("Could not read file " + f.getName());
        }finally{
            try {
                in.close();
            } catch (IOException e1) {}
        }
        if(verbose &amp;gt; 1)
            System.out.println("Writing file " + f.getName());

        BufferedWriter w = null;
        try {
            w = new BufferedWriter(new FileWriter(f));
            w.write(content.toString());
            w.close();
        } catch (IOException e) {
            printUsage("Could not write file " + f.getName());
        }finally{
            try {
                w.close();
            } catch (IOException e) {}
        }
    }

    /**
     * Recurcive scan directory for files with given suffix
     *
     * @param dir directory to scan
     * @param suffix files suffix
     */
    protected static List readDirectory(File dir, String suffix) {
        ArrayList files = new ArrayList();
        if(dir.isFile())
            return null;

        if(verbose &amp;gt; 1)
            System.out.println("Scanning Directory :\n\t"+dir.getAbsolutePath());

        File[] all = dir.listFiles();
        ArrayList dirs = new ArrayList();
        for (int i = 0; i &amp;lt; all.length; i++) {
            if(all[i].isFile()){
                if(all[i].getName().endsWith(suffix)){
                    files.add(all[i]);
                }
            }else if(all[i].isDirectory()){
                dirs.add(all[i]);
            }
        }
        for (Iterator it = dirs.iterator(); it.hasNext();) {
            File d = (File) it.next();
            List l = readDirectory(d, suffix);
            files.addAll(l);
        }
        return files;
    }

    /**
     * print string and the usage
     * @param string
     */
    private static void printUsage(String string) {
        System.err.println(string + "\n\n");
        printUsage();
    }

    /**
     * print the usage
     */
    private static void printUsage() {
        System.err.println(""
                +" This is a quick hack version of a good appending methods and it is NOT memory efficient. \r\n"
                + " Thats why "Start Wars - Episode I" will not work as disclaimer.\r\n"
                + " The disclaimer itself should NOT be inlined\r\n"
                + " in sourcecode comment tags, this is done automaticaly (Let it be the pure disclaimer, without any /* */) \r\n"
                + " Also the size of source files is limited to the heap size of the vm. If one uses this with large source\r\n"
                + " or disclaimer files extend the VM max heap size (e.g. -Xmx512m).\r\n"
                + " \r\n"
                + " Remember, the scanFile() method automatically appends "\\r\\n" to each line while writing the files.\r\n"
                + " \r\n"
                + " parameters\r\n"
                + " -d  The source directory\r\n"
                + " -f  The disclaimer\r\n"
                + " -v &amp;lt;0..2&amp;gt; verbose output\r\n"

        );
        System.exit(1);
    }

}
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://java.randgestalten.de/index.php/2008/10/add-copyright-to-java-sources/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ANT build.xml template</title>
		<link>http://java.randgestalten.de/index.php/2008/10/ant-buildxml-template/</link>
		<comments>http://java.randgestalten.de/index.php/2008/10/ant-buildxml-template/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 09:37:02 +0000</pubDate>
		<dc:creator>Thasso</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[ant]]></category>

		<guid isPermaLink="false">http://java.randgestalten.de/?p=56</guid>
		<description><![CDATA[Just that I have it at one place. This is my ant build.xml template. It assumes a simple project structure:

src/ - all java soources in here
lib/
  devel/ - development libraries
  runtime/ - runtime libraries

If your project follows this struicture, you can get the following tasks out of the box:

Buildfile: build.xml

Main targets:

 clean  [...]]]></description>
			<content:encoded><![CDATA[<p>Just that I have it at one place. This is my ant build.xml template. It assumes a simple project structure:</p>
<pre>
src/ - all java soources in here
lib/
  devel/ - development libraries
  runtime/ - runtime libraries
</pre>
<p>If your project follows this struicture, you can get the following tasks out of the box:</p>
<pre>
Buildfile: build.xml

Main targets:

 clean          Clean
 compile        Compile all source files
 compile-tests  Compile all source files
 dist           Build library and pack jar file
 dist-one       Build library and pack jar file
 doc            Create Javadoc
 html-reports   Creates HTML from test reports
 test           Run JUnit Tests
Default target: dist
</pre>
<p>You can modify the properties to adapt different names or a different project structure. The script creates a <code>target</code> directory that contains the results.</p>
<p>Compiling and packing should work out of the box, but the test sections expects a junit and ant-junit jars  in <code>lib/devel</code>. They can also be placed in one of Ants lib directories.</p>
<p><a href="http://java.randgestalten.de/files/build.xml">The build file</a></p>
]]></content:encoded>
			<wfw:commentRss>http://java.randgestalten.de/index.php/2008/10/ant-buildxml-template/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WTF per minute</title>
		<link>http://java.randgestalten.de/index.php/2008/10/wtf-per-minute/</link>
		<comments>http://java.randgestalten.de/index.php/2008/10/wtf-per-minute/#comments</comments>
		<pubDate>Tue, 21 Oct 2008 10:06:08 +0000</pubDate>
		<dc:creator>Thasso</dc:creator>
				<category><![CDATA[Other]]></category>

		<guid isPermaLink="false">http://java.randgestalten.de/?p=53</guid>
		<description><![CDATA[Yes, that is the right code quality measurement
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.osnews.com/story/19266/WTFs_m">Yes, that is the right code quality measurement</a></p>
]]></content:encoded>
			<wfw:commentRss>http://java.randgestalten.de/index.php/2008/10/wtf-per-minute/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

