<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4535323380112004503</id><updated>2011-10-01T18:06:00.160+02:00</updated><category term='Swing'/><category term='C#'/><category term='SwingX'/><category term='SoftSmithy'/><category term='Swing Application Framework'/><category term='exhibition'/><category term='JNLP'/><category term='YANPA'/><category term='Generics'/><category term='Java'/><category term='JList'/><category term='WPF'/><category term='Ant'/><category term='.NET'/><category term='OpenJDK'/><category term='NetBeans Platform'/><title type='text'>Florian Brunner's Software Engineering Blog</title><subtitle type='html'>This blog is about programming and software engineering. For the time being it will be mainly Java related. It will contain news and tips good to remember - for me and hopefully for others as well. ;-)</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://puces-blog.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://puces-blog.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Florian Brunner</name><uri>http://www.blogger.com/profile/10094773112480994318</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_PddJB6PO1kA/SpkAtRU38dI/AAAAAAAAACI/DWBU5BVjG_Y/S220/20090705-finnland-2-skaliert.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4535323380112004503.post-1786766095524216953</id><published>2011-03-05T15:55:00.008+01:00</published><updated>2011-03-05T17:09:47.082+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SoftSmithy'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><title type='text'>News from the Software Smithy</title><content type='html'>&lt;a href="http://www.softsmithy.org/"&gt;SoftSmithy&lt;/a&gt; news: I recently released a &lt;a href="https://sourceforge.net/projects/softsmithy/files/"&gt;new version&lt;/a&gt; of the &lt;a href="http://softsmithy.sourceforge.net/lib/docs/index.html"&gt;SoftSmithy Utility Library&lt;/a&gt; and the &lt;a href="http://softsmithy.sourceforge.net/devlib/docs/index.html"&gt;SoftSmithy Development Utility Library&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;In addition to the library updates, a lot of migration work has been done:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Project migration: Ant -&gt; Maven&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Project migration: Subversion -&gt; Mercurial&lt;br /&gt;&lt;/li&gt;&lt;li&gt;License upgraded: SPL -&gt; CDDL&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Project versioning aligned with Maven versioning, starting with v0.1 &lt;/li&gt;&lt;li&gt;Project layout restructured &lt;/li&gt;&lt;/ul&gt;For easier version management I aligned the version of the SoftSmithy Development Utility Library with the version of the SoftSmithy Utility Library. &lt;span&gt;As the SoftSmithy Development Utility Library has a dependency to the SoftSmithy Utility Library&lt;/span&gt;&lt;span style="font-weight: bold;"&gt; it's recommended to use the same version of both libraries until the APIs are stable!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I added new utility methods, classes and framework updates for locale-sensitive sorting, object matching, Swing JTable row headers, streams, lists, unit tests and more.&lt;br /&gt;&lt;br /&gt;You can  download the archives (including the jars, documentation, samples etc.) and read more about the changes here:&lt;br /&gt;&lt;a href="https://sourceforge.net/projects/softsmithy/files/softsmithy/v0.1/"&gt;SoftSmithy Utility Library v0.1&lt;/a&gt; (&lt;a href="http://softsmithy.sourceforge.net/lib/docs/index.html"&gt;online documenation&lt;/a&gt;)&lt;br /&gt;&lt;a href="https://sourceforge.net/projects/softsmithy/files/softsmithy-devlib/v0.1/"&gt;SoftSmithy Development Utility Library v0.1&lt;/a&gt; (&lt;a href="http://softsmithy.sourceforge.net/devlib/docs/index.html"&gt;online documentation&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;Since the project is now built with Maven, I deployed the artifacts (including source and javadoc artifacts) to &lt;span style="font-weight: bold;"&gt;Maven Central&lt;/span&gt;. You can use the following dependencies:&lt;br /&gt;&lt;br /&gt;For the &lt;span style="font-weight: bold;"&gt;SoftSmithy Utility Library&lt;/span&gt;:&lt;br /&gt;&lt;textarea name="code" class="xml"&gt;&lt;br /&gt;        &lt;dependency&gt;&lt;br /&gt;            &lt;groupid&gt;org.softsmithy.lib&lt;/groupid&gt;&lt;br /&gt;            &lt;artifactid&gt;lib-core&lt;/artifactid&gt;&lt;br /&gt;            &lt;version&gt;0.1&lt;/version&gt;&lt;br /&gt;        &lt;/dependency&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;For the &lt;span style="font-weight: bold;"&gt;SoftSmithy Development Utility Library&lt;/span&gt; (usually with scope = test):&lt;br /&gt;&lt;textarea name="code" class="xml"&gt;&lt;br /&gt;        &lt;dependency&gt;&lt;br /&gt;            &lt;groupid&gt;org.softsmithy.devlib&lt;/groupid&gt;&lt;br /&gt;            &lt;artifactid&gt;devlib-core&lt;/artifactid&gt;&lt;br /&gt;            &lt;version&gt;0.1&lt;/version&gt;&lt;br /&gt;            &lt;scope&gt;test&lt;/scope&gt;&lt;br /&gt;        &lt;/dependency&gt;&lt;br /&gt;&lt;/textarea&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4535323380112004503-1786766095524216953?l=puces-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://puces-blog.blogspot.com/feeds/1786766095524216953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://puces-blog.blogspot.com/2011/03/news-from-software-smithy.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/1786766095524216953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/1786766095524216953'/><link rel='alternate' type='text/html' href='http://puces-blog.blogspot.com/2011/03/news-from-software-smithy.html' title='News from the Software Smithy'/><author><name>Florian Brunner</name><uri>http://www.blogger.com/profile/10094773112480994318</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_PddJB6PO1kA/SpkAtRU38dI/AAAAAAAAACI/DWBU5BVjG_Y/S220/20090705-finnland-2-skaliert.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4535323380112004503.post-2104167675865777203</id><published>2010-10-10T11:05:00.003+02:00</published><updated>2010-10-10T11:56:57.078+02:00</updated><title type='text'>DON'T PANIC!</title><content type='html'>Today is a very special day! To begin with, today is also a very binary day: 10.10.10&lt;br /&gt;But as it happens, 101010 is the binary representation of the decimal value - right: 42! Also widely known as &lt;a href="http://en.wikipedia.org/wiki/Answer_to_the_Ultimate_Question_of_Life,_the_Universe,_and_Everything#Answer_to_the_Ultimate_Question_of_Life.2C_the_Universe_and_Everything_.2842.29"&gt;the Answer to the Ultimate Question of Life, the Universe, and Everything&lt;/a&gt;! So whether today someone finally knows how the world could be made a good and happy place or whether the earth has to make way for a hyperspatial express route or whatever happens today: &lt;a href="http://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker%27s_Guide_to_the_Galaxy#Knowing_where_one.27s_towel_is"&gt;Always know where your towel is&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Don%27t_Panic_%28The_Hitchhiker%27s_Guide_to_the_Galaxy%29#Don.27t_Panic"&gt;DON'T PANIC&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4535323380112004503-2104167675865777203?l=puces-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://puces-blog.blogspot.com/feeds/2104167675865777203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://puces-blog.blogspot.com/2010/10/dont-panic.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/2104167675865777203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/2104167675865777203'/><link rel='alternate' type='text/html' href='http://puces-blog.blogspot.com/2010/10/dont-panic.html' title='DON&apos;T PANIC!'/><author><name>Florian Brunner</name><uri>http://www.blogger.com/profile/10094773112480994318</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_PddJB6PO1kA/SpkAtRU38dI/AAAAAAAAACI/DWBU5BVjG_Y/S220/20090705-finnland-2-skaliert.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4535323380112004503.post-6782398239790583556</id><published>2010-06-27T23:40:00.001+02:00</published><updated>2010-06-28T00:40:39.011+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SoftSmithy'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>News from the Software Smithy</title><content type='html'>I recently released &lt;a href="http://sourceforge.net/projects/softsmithy/files/softsmithy/v20100524/"&gt;a new version&lt;/a&gt; of the &lt;a href="http://softsmithy.sourceforge.net/"&gt;SoftSmithy Utility Library&lt;/a&gt;. I added new utility methods and classes for locale-sensitive sorting, JPA and more. Have a look at the changelog at the end of the &lt;a href="http://sourceforge.net/projects/softsmithy/files/softsmithy/v20100524/README.txt/view"&gt;README file&lt;/a&gt; and at the &lt;a href="http://softsmithy.sourceforge.net/lib/docs/api/index.html"&gt;Javadoc&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;Alongside the SoftSmithy Utility Library (lib) I recently &lt;a href="http://sourceforge.net/projects/softsmithy/files/softsmithy-devlib/v20100524/"&gt;published&lt;/a&gt; the &lt;a href="http://softsmithy.sourceforge.net/#devlib"&gt;SoftSmithy Development Utility Library&lt;/a&gt; (devlib). The difference between these two libraries is the SoftSmithy Utility Library (lib) contains classes, which you usually want to deploy with your program, while the SoftSmithy Development Utility Library (devlib) contains classes, which are useful at development and deployment time etc., but you usually won't want them on the classpath of your program. Currently it's quite small. I just added a few utility classes for database population with JPA and for unit testing which are still subject to change while I keep looking for best practices. Have a look at the &lt;a href="http://softsmithy.sourceforge.net/devlib/docs/api/index.html"&gt;Javadoc&lt;/a&gt; for more details.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4535323380112004503-6782398239790583556?l=puces-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://puces-blog.blogspot.com/feeds/6782398239790583556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://puces-blog.blogspot.com/2010/06/news-from-software-smithy.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/6782398239790583556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/6782398239790583556'/><link rel='alternate' type='text/html' href='http://puces-blog.blogspot.com/2010/06/news-from-software-smithy.html' title='News from the Software Smithy'/><author><name>Florian Brunner</name><uri>http://www.blogger.com/profile/10094773112480994318</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_PddJB6PO1kA/SpkAtRU38dI/AAAAAAAAACI/DWBU5BVjG_Y/S220/20090705-finnland-2-skaliert.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4535323380112004503.post-977124914794164654</id><published>2010-02-18T13:13:00.007+01:00</published><updated>2010-02-18T14:09:30.555+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='YANPA'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans Platform'/><title type='text'>YANPA: Remote EJB Monitoring Application on the NetBeans Platform</title><content type='html'>&lt;a href="http://blogs.sun.com/geertjan/"&gt;Geertjan Wielenga&lt;/a&gt;, an Oracle/ Sun employee and a technical writer of the &lt;a href="http://netbeans.org/"&gt;NetBeans&lt;/a&gt; team, blogged in his YANPA (Yet Another &lt;a href="http://platform.netbeans.org/screenshots.html"&gt;NetBeans Platform Application&lt;/a&gt;) series about a pilot project of one of my customers where I could introduced the &lt;a href="http://platform.netbeans.org/"&gt;NetBeans Platform&lt;/a&gt;. You can read more about it &lt;a href="http://blogs.sun.com/geertjan/entry/monitoring_remote_ejbs_on_the"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4535323380112004503-977124914794164654?l=puces-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://puces-blog.blogspot.com/feeds/977124914794164654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://puces-blog.blogspot.com/2010/02/yanpa-remote-ejb-monitoring-application.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/977124914794164654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/977124914794164654'/><link rel='alternate' type='text/html' href='http://puces-blog.blogspot.com/2010/02/yanpa-remote-ejb-monitoring-application.html' title='YANPA: Remote EJB Monitoring Application on the NetBeans Platform'/><author><name>Florian Brunner</name><uri>http://www.blogger.com/profile/10094773112480994318</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_PddJB6PO1kA/SpkAtRU38dI/AAAAAAAAACI/DWBU5BVjG_Y/S220/20090705-finnland-2-skaliert.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4535323380112004503.post-1023216626027017182</id><published>2009-11-23T22:21:00.005+01:00</published><updated>2009-11-24T00:33:31.475+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JList'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><category scheme='http://www.blogger.com/atom/ns#' term='Generics'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenJDK'/><title type='text'>News - Swing-Generics (OpenJDK): JList patch commited</title><content type='html'>Great news from the OpenJDK &lt;a href="https://swing-generics.dev.java.net/"&gt;swing-generics&lt;/a&gt; project:&lt;a href="http://hg.openjdk.java.net/jdk7/swing/jdk/rev/7bcb1864f424"&gt;&lt;/a&gt; my patch to "generify" JList, along with AbstractListModel, DefaultListCellRenderer, DefaultListModel, ListCellRenderer and ListModel, &lt;a href="http://hg.openjdk.java.net/jdk7/swing/jdk/rev/7bcb1864f424"&gt;has been commited&lt;/a&gt; to the &lt;a href="http://hg.openjdk.java.net/jdk7/swing/"&gt;OpenJDK/ Swing repository&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;This patch helps writing more stable code.&lt;br /&gt;&lt;br /&gt;Eg. instead of writing something like:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;&lt;br /&gt;DefaultListModel model = new DefaultListModel();&lt;br /&gt;model.addElement("test");&lt;br /&gt;JList list = new JList(model);&lt;br /&gt;...&lt;br /&gt;String value = (String) list.getSelectedValue(); // unchecked cast&lt;br /&gt;Foo foo = (Foo) list.getSelectedValue(); // cast will fail at runtime&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;with this patch you can write now:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;&lt;br /&gt;DefaultListModel&lt;String&gt; model = new DefaultListModel&lt;String&gt;();&lt;br /&gt;model.addElement("test");&lt;br /&gt;JList&lt;String&gt; list = new JList&lt;String&gt;(model);&lt;br /&gt;...&lt;br /&gt;String value = list.getSelectedValue();&lt;br /&gt;Foo foo = list.getSelectedValue(); // compile time error&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Note that:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;JList.getSelectedValues(): Object[]&lt;br /&gt;&lt;/span&gt; has been &lt;span style="font-weight: bold;"&gt;deprecated&lt;/span&gt; and replaced with:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;JList.getSelectedValuesList(): List&amp;lt;E&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Have a look at the &lt;a href="http://hg.openjdk.java.net/jdk7/swing/jdk/file/7bcb1864f424/test/javax/swing/JList/6823603/bug6823603.java"&gt;jtreg tests&lt;/a&gt; to see more examples.&lt;br /&gt;&lt;br /&gt;If you're interested in the future of Swing, join the discussions in the &lt;a href="http://mail.openjdk.java.net/mailman/listinfo/swing-dev"&gt;OpenJDK Swing mailing list&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4535323380112004503-1023216626027017182?l=puces-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://puces-blog.blogspot.com/feeds/1023216626027017182/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://puces-blog.blogspot.com/2009/11/news-swing-generics-openjdk-jlist-patch.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/1023216626027017182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/1023216626027017182'/><link rel='alternate' type='text/html' href='http://puces-blog.blogspot.com/2009/11/news-swing-generics-openjdk-jlist-patch.html' title='News - Swing-Generics (OpenJDK): JList patch commited'/><author><name>Florian Brunner</name><uri>http://www.blogger.com/profile/10094773112480994318</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_PddJB6PO1kA/SpkAtRU38dI/AAAAAAAAACI/DWBU5BVjG_Y/S220/20090705-finnland-2-skaliert.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4535323380112004503.post-9135997498465756277</id><published>2009-10-31T13:18:00.001+01:00</published><updated>2009-10-31T13:19:47.286+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ant'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JNLP'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans Platform'/><title type='text'>NetBeans Platform: JNLP &amp; static codebase</title><content type='html'>Recently the question was asked on the dev@openide.netbeans.org mailing list, how to deploy a JNLP NetBeans Platform application to a web server, which doesn't support WAR-files.&lt;br /&gt;I had the same problem when I wanted to deploy the sample application of my last NetBeans Platform post (&lt;a href="http://puces-blog.blogspot.com/2009/04/netbeans-platform-meets-swing.html"&gt;NetBeans Platform meets Swing Application Framework: SessionStorage&lt;/a&gt;), which is a JNLP NetBeans Platform application, too, that I host along with its source &lt;a href="http://sourceforge.net/projects/puces-samples"&gt;at sourceforge.net&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here are the build.xml and platform.properties I used:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/build.xml?view=markup"&gt;build.xml&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/nbproject/platform.properties?view=markup"&gt;platform.properties&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;The Ant script will create the file  &lt;span class="hl str"&gt;&lt;span style="font-family:monospace;"&gt;&lt;/span&gt;"${nbdist.dir}/${app.name}-updated.war"&lt;/span&gt;. Just copy it to your web server and unzip it there. Then link to the master.jnlp to provide a starting-point to your application, eg. by &lt;a href="http://java.sun.com/docs/books/tutorial/deployment/deploymentInDepth/createWebStartLaunchButtonFunction.html"&gt;creating a web start launch button&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here is the complete code:&lt;br /&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/"&gt;http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can run this sample here:&lt;br /&gt;&lt;a href="http://puces-samples.sourceforge.net/"&gt;http://puces-samples.sourceforge.net/&lt;/a&gt;&lt;br /&gt;or here:&lt;br /&gt;&lt;a href="http://puces-blog.blogspot.com/2009/04/netbeans-platform-meets-swing.html"&gt;http://puces-blog.blogspot.com/2009/04/netbeans-platform-meets-swing.html &lt;/a&gt;&lt;br /&gt;(at the bottom of the page)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4535323380112004503-9135997498465756277?l=puces-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://puces-blog.blogspot.com/feeds/9135997498465756277/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://puces-blog.blogspot.com/2009/10/netbeans-platform-jnlp-static-codebase.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/9135997498465756277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/9135997498465756277'/><link rel='alternate' type='text/html' href='http://puces-blog.blogspot.com/2009/10/netbeans-platform-jnlp-static-codebase.html' title='NetBeans Platform: JNLP &amp; static codebase'/><author><name>Florian Brunner</name><uri>http://www.blogger.com/profile/10094773112480994318</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_PddJB6PO1kA/SpkAtRU38dI/AAAAAAAAACI/DWBU5BVjG_Y/S220/20090705-finnland-2-skaliert.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4535323380112004503.post-510242603155196979</id><published>2009-09-27T22:40:00.001+02:00</published><updated>2009-09-27T22:45:24.169+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='exhibition'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Technorama: The Magic of Software</title><content type='html'>Last Friday I visited the special exhibition &lt;a href="http://www.technorama.ch/News-Detail.22.0.html?&amp;amp;tx_ttnews%5Btt_news%5D=178&amp;amp;tx_ttnews%5BbackPid%5D=9&amp;amp;cHash=203b3ffd20"&gt;"The Magic of Software"&lt;/a&gt; at the &lt;a href="http://www.technorama.ch/"&gt;Technorama Winterthur, Switzerland&lt;/a&gt;. It's an event to the 20th anniversary of Microsoft Switzerland. Since &lt;a href="http://www.noser.com/"&gt;Noser Engineering AG&lt;/a&gt; (the company I work for) is Microsoft Gold Partner, we got the chance to provide an application to this exhibition, of which I helped to implement a small part.&lt;br /&gt;&lt;br /&gt;We implemented &lt;a href="http://www.noser.com/index.php?section=news&amp;amp;cmd=details&amp;amp;newsid=141&amp;amp;teaserId=1"&gt;a multi-touch truck disposition game&lt;/a&gt;. The user has to try to distribute a list of orders to a fixed number of trucks. The more order you can deliver in the given time the more points you get.&lt;br /&gt;&lt;br /&gt;At this technological excursion I got the chance to work with some of the newest Microsoft technologies:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;.NET 4.0 Beta (WPF, C#, XAML)&lt;/li&gt;&lt;li&gt;Windows 7 (RC)&lt;/li&gt;&lt;li&gt;Visual Studio Team System 2010 (Beta)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;The software runs on a &lt;a href="http://www.hp.com/united-states/campaigns/touchsmart"&gt;HP TouchSmart&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here are some pictures of the application at the exhibition (I took them with my cell phone, the quality isn't optimal):&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_PddJB6PO1kA/Sr_J8IYH0wI/AAAAAAAAACo/-cvs2lgPJMc/s1600-h/dsc00579-2.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 208px;" src="http://1.bp.blogspot.com/_PddJB6PO1kA/Sr_J8IYH0wI/AAAAAAAAACo/-cvs2lgPJMc/s320/dsc00579-2.jpg" alt="" id="BLOGGER_PHOTO_ID_5386245714236396290" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_PddJB6PO1kA/Sr_KFLQpJBI/AAAAAAAAACw/kSkb4jBuf8k/s1600-h/dsc00577-2.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 210px;" src="http://3.bp.blogspot.com/_PddJB6PO1kA/Sr_KFLQpJBI/AAAAAAAAACw/kSkb4jBuf8k/s320/dsc00577-2.jpg" alt="" id="BLOGGER_PHOTO_ID_5386245869629154322" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The exhibition is open until the 31th October, 2009. Try to beat my result! As you can see on the second picture, that shouldn't be hard. ;-) (rank: 111; points: 42'605)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4535323380112004503-510242603155196979?l=puces-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://puces-blog.blogspot.com/feeds/510242603155196979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://puces-blog.blogspot.com/2009/09/technorama-magic-of-software.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/510242603155196979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/510242603155196979'/><link rel='alternate' type='text/html' href='http://puces-blog.blogspot.com/2009/09/technorama-magic-of-software.html' title='Technorama: The Magic of Software'/><author><name>Florian Brunner</name><uri>http://www.blogger.com/profile/10094773112480994318</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_PddJB6PO1kA/SpkAtRU38dI/AAAAAAAAACI/DWBU5BVjG_Y/S220/20090705-finnland-2-skaliert.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_PddJB6PO1kA/Sr_J8IYH0wI/AAAAAAAAACo/-cvs2lgPJMc/s72-c/dsc00579-2.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4535323380112004503.post-6060774299791930934</id><published>2009-07-19T22:00:00.013+02:00</published><updated>2009-07-20T00:23:59.870+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Swing Application Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='SwingX'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans Platform'/><title type='text'>NetBeans Platform meets Swing Application Framework: SessionStorage</title><content type='html'>In this post I want to explain how to use the &lt;a href="https://appframework.dev.java.net/"&gt;Swing Application Framework&lt;/a&gt; &lt;span class="postbody"&gt;(&lt;a href="http://jcp.org/en/jsr/detail?id=296"&gt;JSR-296&lt;/a&gt;) &lt;/span&gt;as a utility library in a &lt;a href="http://platform.netbeans.org/"&gt;NetBeans Platform&lt;/a&gt; application to reuse its &lt;span style="font-style: italic;"&gt;session storage feature&lt;/span&gt;. Since I haven't found any documentation about this topic so far, I devote the first post of my new blog to this.&lt;br /&gt;&lt;br /&gt;In the following we create a sample application to demonstrate the problem space. We will use a &lt;span class="postbody"&gt;JXTable (&lt;a href="https://swingx.dev.java.net/"&gt;SwingX&lt;/a&gt;) and want the application to remember things like:&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="postbody"&gt;column order &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;visible/ hidden columns &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;column widths &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;sorting info&lt;/span&gt;&lt;span class="postbody"&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;Since the NetBeans Platform seems to provide only &lt;span class="postbody"&gt;some very generic hooks like &lt;a href="http://bits.netbeans.org/6.7/javadoc/org-openide-windows/org/openide/windows/doc-files/api.html#create-ser"&gt;state serialization&lt;/a&gt;, &lt;/span&gt;&lt;span class="postbody"&gt;&lt;a href="http://bits.netbeans.org/6.7/javadoc/org-openide-util/org/openide/util/NbPreferences.html"&gt;Preferences API support&lt;/a&gt; and &lt;a href="http://bits.netbeans.org/6.7/javadoc/org-netbeans-modules-settings/org/netbeans/spi/settings/doc-files/api.html"&gt;Settings API&lt;/a&gt; to persist session data,&lt;/span&gt; one would have to implement a lot of the details in a custom way.&lt;span class="postbody"&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;br /&gt;The Swing Application Framework can help out here however with its session storage feature.&lt;br /&gt;&lt;br /&gt;To make the session storage feature work inside a NetBeans Platform application, some issues have to be solved:&lt;br /&gt;First, the &lt;span style="font-style: italic;"&gt;LocalStorage&lt;/span&gt; class of the Swing Application Framework has an algorithm to find a suitable storage directory for various situations. The NetBeans Platform however has already its own place to store configuration data. And more, since a NetBeans Platform is modular, it would be preferable if each module would store its session storage data in its own directory to keep that data structured modularly as well and to avoid naming conflicts. Fortunately, the LocalStorage class provides a &lt;span style="font-style: italic;"&gt;setDirectory&lt;/span&gt; method to specify a different storage directory. This leads us however to the next issue: when running the application in JNLP mode the directory property of the LocalStorage class is ignored. Thus we also need to subclass the LocalStorage class if JNLP support is needed. I filed an enhancement request, which should make things easier once fixed:&lt;br /&gt;&lt;a href="https://appframework.dev.java.net/issues/show_bug.cgi?id=112"&gt;https://appframework.dev.java.net/issues/show_bug.cgi?id=112&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A LocalStorage can be retrieved from an &lt;span style="font-style: italic;"&gt;ApplicationContext&lt;/span&gt;, so we create our own ApplicationContext subclass - &lt;span style="font-style: italic;"&gt;ModuleApplicationContext&lt;/span&gt; - and reset the directory property of the LocalStorage in the contructor with a path to a module specific directory inside the NetBeans Platform configuration directory:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;/span&gt;&lt;pre class="java" name="code"&gt;public class ModuleApplicationContext extends ApplicationContext {&lt;br /&gt;&lt;br /&gt;   private static final String SESSION_STORAGE_DIR = "SessionStorage"; // NOI18N&lt;br /&gt;   private static final Object LOCK = new Object();&lt;br /&gt;&lt;br /&gt;   public ModuleApplicationContext(ModuleInfo moduleInfo) {&lt;br /&gt;       getLocalStorage().setDirectory(getModuleSessionStorageDir(moduleInfo));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private File getModuleSessionStorageDir(ModuleInfo moduleInfo) {&lt;br /&gt;       FileObject root = FileUtil.getConfigRoot();&lt;br /&gt;       try {&lt;br /&gt;           synchronized (LOCK) {&lt;br /&gt;               FileObject sessionStorageDir = getSessionStorageDir(root);&lt;br /&gt;               FileObject moduleStorageDir = getModuleSessionStorageDir(&lt;br /&gt;                       sessionStorageDir, moduleInfo);&lt;br /&gt;               return FileUtil.toFile(moduleStorageDir);&lt;br /&gt;           }&lt;br /&gt;       } catch (IOException ex) {&lt;br /&gt;           Logger.getLogger(ModuleApplicationContext.class.getName()).logp(&lt;br /&gt;                   Level.SEVERE, ModuleApplicationContext.class.getName(),&lt;br /&gt;                   "getModuleSessionStorageDir", ex.getMessage(), ex); // NOI18N&lt;br /&gt;           return FileUtil.toFile(root);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private FileObject getSessionStorageDir(FileObject root) throws IOException {&lt;br /&gt;       FileObject sessionStorageDir = root.getFileObject(SESSION_STORAGE_DIR);&lt;br /&gt;       if (sessionStorageDir == null) {&lt;br /&gt;           sessionStorageDir = root.createFolder(SESSION_STORAGE_DIR);&lt;br /&gt;       }&lt;br /&gt;       return sessionStorageDir;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private FileObject getModuleSessionStorageDir(FileObject sessionStorageDir,&lt;br /&gt;           ModuleInfo moduleInfo) {&lt;br /&gt;       String moduleStorageDirName = getModuleDirName(moduleInfo);&lt;br /&gt;       FileObject moduleStorageDir = sessionStorageDir.getFileObject(&lt;br /&gt;               moduleStorageDirName);&lt;br /&gt;       if (moduleStorageDir == null) {&lt;br /&gt;           try {&lt;br /&gt;               moduleStorageDir =&lt;br /&gt;                       sessionStorageDir.createFolder(moduleStorageDirName);&lt;br /&gt;           } catch (IOException ex) {&lt;br /&gt;               Logger.getLogger(ModuleApplicationContext.class.getName()).logp(&lt;br /&gt;                       Level.SEVERE, ModuleApplicationContext.class.getName(),&lt;br /&gt;                       "getModuleSessionStorageDir", ex.getMessage(), ex); // NOI18N&lt;br /&gt;               moduleStorageDir = sessionStorageDir;&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;       return moduleStorageDir;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private String getModuleDirName(ModuleInfo moduleInfo) {&lt;br /&gt;       try {&lt;br /&gt;           return URLEncoder.encode(moduleInfo.getCodeName(), "UTF-8"); // NOI18N&lt;br /&gt;       } catch (UnsupportedEncodingException ex) {&lt;br /&gt;           // should not happen with UTF-8&lt;br /&gt;           Logger.getLogger(ModuleApplicationContext.class.getName()).logp(&lt;br /&gt;                   Level.SEVERE, ModuleApplicationContext.class.getName(),&lt;br /&gt;                   "getModuleDirName", "UTF-8 not supported!", ex); // NOI18N&lt;br /&gt;           return moduleInfo.getCodeNameBase();&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span class="postbody"&gt;&lt;br /&gt;We add this class to a &lt;span style="font-style: italic;"&gt;Utility Library&lt;/span&gt; module and add its package (here: &lt;span style="font-style: italic;"&gt;blogspot.puce.sessionstate.util.modules&lt;/span&gt;) to the list of public packages. Later we can add a dependency to this module and reuse this class.&lt;/span&gt;&lt;span class="postbody"&gt; We also create a &lt;span style="font-style: italic;"&gt;Library Wrapper Module&lt;/span&gt; for the Swing Application Framework and add a dependency from the Utility Library module to this module.&lt;/span&gt;&lt;br /&gt;&lt;span class="postbody"&gt;&lt;br /&gt;As mentioned before, to support JNLP mode, we need to create a subclass of LocalStorage, which we call &lt;span style="font-style: italic;"&gt;ModuleLocalStorage&lt;/span&gt; and which respects the directory property:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;public class ModuleLocalStorage extends LocalStorage {&lt;br /&gt;&lt;br /&gt;   public ModuleLocalStorage(ApplicationContext context) {&lt;br /&gt;       super(context);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   @Override&lt;br /&gt;   public boolean deleteFile(String fileName) throws IOException {&lt;br /&gt;       File path = new File(getDirectory(), fileName);&lt;br /&gt;       return path.delete();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   @Override&lt;br /&gt;   public InputStream openInputFile(String fileName) throws IOException {&lt;br /&gt;       File path = new File(getDirectory(), fileName);&lt;br /&gt;       return new BufferedInputStream(new FileInputStream(path));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   @Override&lt;br /&gt;   public OutputStream openOutputFile(String fileName) throws IOException {&lt;br /&gt;       File path = new File(getDirectory(), fileName);&lt;br /&gt;       return new BufferedOutputStream(new FileOutputStream(path));&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;We add this class to the same package as &lt;span class="postbody"&gt;ModuleApplicationContext&lt;/span&gt; and change the constructor of &lt;span class="postbody"&gt;ModuleApplicationContext to register this LocalStorage:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;   public ModuleApplicationContext(ModuleInfo moduleInfo) {&lt;br /&gt;       // Needed due to issue https://appframework.dev.java.net/issues/show_bug.cgi?id=112&lt;br /&gt;       setLocalStorage(new ModuleLocalStorage(this));&lt;br /&gt;&lt;br /&gt;       getLocalStorage().setDirectory(getModuleSessionStorageDir(moduleInfo));&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;To support storage of the properties of JXTable, we need a SessionStorage.Property implementation for JXTable. Fortunatly, &lt;/span&gt;Jeanette (user name: kleopatra) provided such an implemenation in the jdnc-incubator project. At the time of writing, it's just available in source form. Here is the link to the version we use in this sample application:&lt;br /&gt;&lt;a href="https://jdnc-incubator.dev.java.net/source/browse/jdnc-incubator/src/kleopatra/java/org/jdesktop/appframework/swingx/XProperties.java?rev=1.3&amp;amp;view=markup"&gt;https://jdnc-incubator.dev.java.net/source/browse/jdnc-incubator/src/kleopatra/java/org/jdesktop/appframework/swingx/XProperties.java?rev=1.3&amp;amp;view=markup&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We can add this class to the Utility Libarary module as well.&lt;br /&gt;&lt;br /&gt;In order to use this implementation we add a static initializer to the &lt;span class="postbody"&gt;ModuleApplicationContext class and change its constructor:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;   static {&lt;br /&gt;       new XProperties().registerPersistenceDelegates();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public ModuleApplicationContext(ModuleInfo moduleInfo) {&lt;br /&gt;       // Needed due to issue https://appframework.dev.java.net/issues/show_bug.cgi?id=112&lt;br /&gt;       setLocalStorage(new ModuleLocalStorage(this));&lt;br /&gt;&lt;br /&gt;       getLocalStorage().setDirectory(getModuleSessionStorageDir(moduleInfo));&lt;br /&gt;       getSessionStorage().putProperty(JXTable.class,&lt;br /&gt;               new XProperties.XTableProperty());&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;We also create another Library Wrapper Module for the SwingX library and add a dependency from the Utility Library module to this module.&lt;a href="http://www.netbeans.org/issues/show_bug.cgi?id=157798"&gt;&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;br /&gt;To create an instance of &lt;/span&gt;&lt;span class="postbody"&gt;the ModuleApplicationContext class&lt;/span&gt;, we need to pass the &lt;span style="font-style: italic;"&gt;ModuleInfo&lt;/span&gt; of the module of the calling class to its constructor. Unfortunatly, there is no method to get the ModuleInfo for a class, so we have to iterate over all ModuleInfos. I filed an issue:&lt;br /&gt;&lt;span class="postbody"&gt;&lt;a href="http://www.netbeans.org/issues/show_bug.cgi?id=157828"&gt;http://www.netbeans.org/issues/show_bug.cgi?id=157828&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;br /&gt;Here is the work-around we can use:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="postbody"&gt;&lt;/span&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;   public static ModuleInfo getModuleInfo(Class&lt;?&gt; clazz) {&lt;br /&gt;       Collection&lt;? extends ModuleInfo&gt; moduleInfos = Lookup.getDefault().&lt;br /&gt;               lookupAll(ModuleInfo.class);&lt;br /&gt;       for (ModuleInfo moduleInfo : moduleInfos) {&lt;br /&gt;           if (moduleInfo.owns(clazz)) {&lt;br /&gt;               return moduleInfo;&lt;br /&gt;           }&lt;br /&gt;       }&lt;br /&gt;       return null;&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;span class="postbody"&gt;&lt;/span&gt;&lt;br /&gt;We put this method to a new utility class called &lt;span style="font-style: italic;"&gt;Modules&lt;/span&gt; and add this class to the same package as &lt;span style="font-style: italic;" class="postbody"&gt;ModuleApplicationContext.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here are the complete classes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/sessionstate-util/src/blogspot/puce/sessionstate/util/modules/ModuleApplicationContext.java?view=markup"&gt;ModuleApplicationContext.java&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/sessionstate-util/src/blogspot/puce/sessionstate/util/modules/ModuleLocalStorage.java?view=markup"&gt;ModuleLocalStorage.java&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/sessionstate-util/src/blogspot/puce/sessionstate/util/modules/Modules.java?view=markup"&gt;Modules.java&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Now we have all parts together and we can use them in other modules. So let's see them in action! We make a sample module and add a dependency to our Utility Library module and the two Library Wrapper modules for &lt;span style="font-style: italic;"&gt;SwingX&lt;/span&gt; and the &lt;span style="font-style: italic;"&gt;Swing Application Framework&lt;/span&gt;. To this sample module we add a &lt;span style="font-style: italic;"&gt;Module Installer&lt;/span&gt;, which initializes and holds a reference to a &lt;span style="font-style: italic;" class="postbody"&gt;ModuleApplicationContext&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;public class Installer extends ModuleInstall {&lt;br /&gt;&lt;br /&gt;   private static ModuleApplicationContext applicationContext;&lt;br /&gt;&lt;br /&gt;   @Override&lt;br /&gt;   public void restored() {&lt;br /&gt;       applicationContext = new ModuleApplicationContext(Modules.getModuleInfo(&lt;br /&gt;               Installer.class));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public static ModuleApplicationContext getApplicationContext() {&lt;br /&gt;       return applicationContext;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Then we add a &lt;span style="font-style: italic;"&gt;TopComponent&lt;/span&gt; to our sample module, which we call &lt;span style="font-style: italic;"&gt;JXTableSampleTopComponent&lt;/span&gt;. We change its LayoutManager to BoderLayout and add a panel, which we call &lt;span style="font-style: italic;"&gt;contentPanel&lt;/span&gt;, with BorderLayout.CENTER to the JXTableSampleTopComponent.&lt;br /&gt;&lt;br /&gt;Inside this sample application we want to show some sample data in a JXTable. The following Java/ Swing classes display a list of participants:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/sessionstate-sample/src/blogspot/puce/sessionstate/sample/Participant.java?view=markup"&gt;Participant.java&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/sessionstate-sample/src/blogspot/puce/sessionstate/sample/ParticipantTableModel.java?view=markup"&gt;ParticipantTableModel.java&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/sessionstate-sample/src/blogspot/puce/sessionstate/sample/ParticipantsPane.java?view=markup"&gt;ParticipantsPane.java&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/sessionstate-sample/src/blogspot/puce/sessionstate/sample/Bundle.properties?view=markup"&gt;Bundle.properties&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Apart from the &lt;span style="font-style: italic;"&gt;NbBundle&lt;/span&gt; to localize the column names, they don't use any NetBeans Platform APIs.&lt;br /&gt;&lt;br /&gt;We add now an instance of ParticipantsPane, which contains the JXTable, to the contentPanel of JXTableSampleTopComponent. Below the ParticipantsPane we add a button. Since the session storage feature of the Swing Application Framework relies on names set to the components, we must make sure that the components do have a name set: In the &lt;span style="font-style: italic;"&gt;Form Designer&lt;/span&gt; select the root in the &lt;span style="font-style: italic;"&gt;Inspector&lt;/span&gt; tab. Then in the &lt;span style="font-style: italic;"&gt;Properties&lt;/span&gt; tab set the &lt;span style="font-style: italic;"&gt;"Set Component Names"&lt;/span&gt; property to true. It's easy to forget to set the component names sometimes. &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;If you think your persistence code should work, but it doesn't, check if you've set the component names!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the constructor of JXTableSampleTopComponent we initialize the participants list field and assign it to the participants property of the ParticipantsPane instance:&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;private final List&amp;lt;Participant&amp;gt; participants;&lt;br /&gt;&lt;br /&gt;public JXTableSampleTopComponent() {&lt;br /&gt;    initComponents();&lt;br /&gt;    setName(NbBundle.getMessage(JXTableSampleTopComponent.class,&lt;br /&gt;            "CTL_JXTableSampleTopComponent")); // NOI18N&lt;br /&gt;    setToolTipText(NbBundle.getMessage(JXTableSampleTopComponent.class,&lt;br /&gt;            "HINT_JXTableSampleTopComponent")); // NOI18N&lt;br /&gt;//        setIcon(ImageUtilities.loadImage(ICON_PATH, true));&lt;br /&gt;&lt;br /&gt;    participants = new ArrayList&amp;lt;Participant&amp;gt;();&lt;br /&gt;    // some fictional participants&lt;br /&gt;    participants.add(new Participant("Carl", "Smith", 25)); // NOI18N&lt;br /&gt;    participants.add(new Participant("Lisa", "Collins", 27)); // NOI18N&lt;br /&gt;    participants.add(new Participant("Martin", "Brooks", 34)); // NOI18N&lt;br /&gt;&lt;br /&gt;    participantsPane.setParticipants(participants);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To make the &lt;span class="postbody"&gt;column order, column visibility, column widths and sorting info&lt;/span&gt; of the JXTable in our TopComponent persistent, we change the &lt;span style="font-style: italic;"&gt;writeProperties- &lt;/span&gt;and &lt;span style="font-style: italic;"&gt;readPropertiesImpl-&lt;/span&gt;methods of the JXTableSampleTopComponent. There we call the &lt;span style="font-style: italic;"&gt;save/ restore&lt;/span&gt; methods of the &lt;span style="font-style: italic;"&gt;SessionStorage&lt;/span&gt; of the ApplicationContext, which is referenced by our Installer. Note that due to a bug in the Swing Application Framework we need to remove the contentPane from the TopComponent before we save/ restore it and re-add later. I filed an issue: &lt;a href="https://appframework.dev.java.net/issues/show_bug.cgi?id=94"&gt;https://appframework.dev.java.net/issues/show_bug.cgi?id=94&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;   private static final String PREFERRED_ID = "JXTableSampleTopComponent"; // NOI18N&lt;br /&gt;   private static final String SESSION_STORAGE_XML = PREFERRED_ID + ".xml"; // NOI18N&lt;br /&gt;&lt;br /&gt;   void writeProperties(java.util.Properties p) {&lt;br /&gt;       // better to version settings since initial version as advocated at&lt;br /&gt;       // http://wiki.apidesign.org/wiki/PropertyFiles&lt;br /&gt;       p.setProperty("version", "1.0");&lt;br /&gt;       saveSession();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void saveSession() {&lt;br /&gt;       // remove and add needed due to a bug in the Swing Application Framework:&lt;br /&gt;       // https://appframework.dev.java.net/issues/show_bug.cgi?id=94&lt;br /&gt;       remove(getContentPanel());&lt;br /&gt;       try {&lt;br /&gt;           Installer.getApplicationContext().getSessionStorage().save(&lt;br /&gt;                   getContentPanel(), SESSION_STORAGE_XML);&lt;br /&gt;       } catch (IOException ex) {&lt;br /&gt;           Exceptions.printStackTrace(ex);&lt;br /&gt;       }&lt;br /&gt;       add(getContentPanel(), BorderLayout.CENTER);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private JPanel getContentPanel() {&lt;br /&gt;       return contentPanel;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void readPropertiesImpl(java.util.Properties p) {&lt;br /&gt;       String version = p.getProperty("version");&lt;br /&gt;       // TODO read your settings according to their version&lt;br /&gt;&lt;br /&gt;       // remove and add needed due to a bug in the Swing Application Framework:&lt;br /&gt;       // https://appframework.dev.java.net/issues/show_bug.cgi?id=94&lt;br /&gt;       remove(getContentPanel());&lt;br /&gt;       try {&lt;br /&gt;           Installer.getApplicationContext().getSessionStorage().&lt;br /&gt;                   restore(getContentPanel(), SESSION_STORAGE_XML);&lt;br /&gt;       } catch (IOException ex) {&lt;br /&gt;           Exceptions.printStackTrace(ex);&lt;br /&gt;       }&lt;br /&gt;       add(getContentPanel(), BorderLayout.CENTER);&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;This is it! The &lt;span class="postbody"&gt;column order, column visibility, column widths and sorting info &lt;/span&gt;of the JXTable of our TopComponent are persistent! Now let's look how to make these persistent if the JXTable is inside a dialog instead. For this we add an action listener to the button we added below the JXTable. Inside the action listener method we create a new instance of the ParticipantsPane and assign the participants list field to its participants property. Then we create a &lt;span style="font-style: italic;"&gt;DialogDescriptor&lt;/span&gt; with a close button and the ParticipantsPane as its content. Since the session storage feature of the Swing Application Framework already supports dialogs - by default a SessionStorage.Property for &lt;span style="font-style: italic;"&gt;Window&lt;/span&gt; is registered, which makes the dimension and position of a window persistent - we want to benefit from that and create a &lt;span style="font-style: italic;"&gt;Dialog&lt;/span&gt; object from the DialogDescriptor rather than using one of the &lt;span style="font-style: italic;"&gt;notify&lt;/span&gt; methods of the &lt;span style="font-style: italic;"&gt;DialogDisplayer&lt;/span&gt;. After creating the dialog object and setting its name (remember that the session storage feature relies on names set to the components), we register a &lt;span style="font-style: italic;"&gt;PropertyChangeListener&lt;/span&gt; to the DialogDescriptor to get notified, when the dialog is closed, so we can call there again the save method of the SessionStorage of the ApplicationContext, which is referenced by our Installer, to make the mentioned properties persistent. Note that we use a different file name for the dialog than for the TopComponent, so that one does not overwrite the other. After defining the PropertyChangeListener we call the restore method of the SessionStorage and set the visible property of the dialog to true to show it.&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;&lt;br /&gt;   private static final String PARTICIPANTS_DIALOG_XML =&lt;br /&gt;           "participantsDialog.xml"; // NOI18N&lt;br /&gt;&lt;br /&gt;   private void participantsDialogButtonActionPerformed(java.awt.event.ActionEvent evt) {                                                        &lt;br /&gt;       ParticipantsPane pp = new ParticipantsPane();&lt;br /&gt;&lt;br /&gt;       pp.setParticipants(participants); // NOI18N&lt;br /&gt;       pp.setName("participantsPane"); // NOI18N&lt;br /&gt;&lt;br /&gt;       DialogDescriptor dialogDescriptor = new DialogDescriptor(pp, NbBundle.&lt;br /&gt;               getMessage(JXTableSampleTopComponent.class,&lt;br /&gt;               "JXTableSampleTopComponent.ParticipantsDialog.title")); // NOI18N&lt;br /&gt;       final JButton closeButton =&lt;br /&gt;               new JButton(NbBundle.getMessage(JXTableSampleTopComponent.class,&lt;br /&gt;               "JXTableSampleTopComponent.ParticipantsDialog.button.text")); // NOI18N&lt;br /&gt;       dialogDescriptor.setOptions(&lt;br /&gt;               new Object[]{closeButton});&lt;br /&gt;       final Dialog participantsDialog =&lt;br /&gt;               DialogDisplayer.getDefault().createDialog(dialogDescriptor);&lt;br /&gt;       participantsDialog.setName("participantsDialog"); // NOI18N&lt;br /&gt;       dialogDescriptor.addPropertyChangeListener(new PropertyChangeListener() {&lt;br /&gt;&lt;br /&gt;           public void propertyChange(PropertyChangeEvent evt) {&lt;br /&gt;&lt;br /&gt;               if (evt.getPropertyName().equals(DialogDescriptor.PROP_VALUE) &amp;amp;&amp;amp;&lt;br /&gt;                       ((evt.getNewValue() == DialogDescriptor.CLOSED_OPTION) ||&lt;br /&gt;                       (evt.getNewValue() == closeButton))) {&lt;br /&gt;                   try {&lt;br /&gt;                       Installer.getApplicationContext().getSessionStorage().&lt;br /&gt;                               save(participantsDialog, PARTICIPANTS_DIALOG_XML);&lt;br /&gt;                   } catch (IOException ex) {&lt;br /&gt;                       Exceptions.printStackTrace(ex);&lt;br /&gt;                   }&lt;br /&gt;               }&lt;br /&gt;           }&lt;br /&gt;       });&lt;br /&gt;&lt;br /&gt;       try {&lt;br /&gt;           Installer.getApplicationContext().getSessionStorage().&lt;br /&gt;                   restore(participantsDialog, PARTICIPANTS_DIALOG_XML);&lt;br /&gt;       } catch (IOException ex) {&lt;br /&gt;           Exceptions.printStackTrace(ex);&lt;br /&gt;       }&lt;br /&gt;       participantsDialog.setVisible(true);&lt;br /&gt;   } &lt;br /&gt;&lt;/pre&gt;Now the mentioned dialog properties and the properties of its JXTable are persistent!&lt;br /&gt;Here are the complete classes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/sessionstate-sample/src/blogspot/puce/sessionstate/sample/JXTableSampleTopComponent.java?view=markup"&gt;JXTableSampleTopComponent.java&lt;/a&gt; &lt;/li&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0/sessionstate-suite/sessionstate-sample/src/blogspot/puce/sessionstate/sample/Installer.java?view=markup"&gt;Installer.java&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;When you run this sample application from inside the NetBeans IDE, you should see something like the following inside your suite-directory:&lt;br /&gt;&lt;span style="text-decoration: underline;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_PddJB6PO1kA/SmMMrIAAsZI/AAAAAAAAAB4/lKiyfwNFaZQ/s1600-h/sessionStorageFiles.jpg"&gt;&lt;img style="margin: 0px auto 10px; text-align: center; width: 320px; display: block; height: 162px; cursor: pointer;" id="BLOGGER_PHOTO_ID_5360141916522459538" alt="" src="http://2.bp.blogspot.com/_PddJB6PO1kA/SmMMrIAAsZI/AAAAAAAAAB4/lKiyfwNFaZQ/s320/sessionStorageFiles.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The XML files, which contain the session storage data, are inside the module specific directory "blogspot.puce.sessionstate.sample". This directory is inside the SessionStorage directory we created inside the NetBeans Platform application specific configuration directory.&lt;br /&gt;&lt;script src="http://java.com/js/deployJava.js"&gt;&lt;/script&gt;&lt;br /&gt;You can have a look at this sample application using Java WebStart:&lt;br /&gt;&lt;script&gt;var url = "http://puces-samples.sourceforge.net/sessionstate-1.0/master.jnlp"; deployJava.createWebStartLaunchButton(url, '1.6');&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Try to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="postbody"&gt;reorder the columns&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;change the column visibility by clicking on the button on the top-right side of the JXTable&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;change the column widths&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;change the column sorting by clicking on the column headers&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;click the button below the table and do the same for the JXTable inside the dialog&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;change the size of the dialog&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;change the position of the dialog&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;close and reopen the dialog and see how all these properties are persistent&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="postbody"&gt;close and restart the application and see how all these properties of the TopComponent and dialog are persistent&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Summary:&lt;/span&gt;&lt;br /&gt;This post showed you how we can reuse parts of the Swing Application Framework inside a NetBeans Platform application to make properties of components persistent. This could become especially interesting if &lt;a href="http://openjdk.java.net/projects/jdk7/features/#f205"&gt;the Swing Application Framework makes it into JDK 7&lt;/a&gt;. No Library Wrapper Module would be needed anymore and we might see &lt;span class="postbody"&gt;SessionStorage.Property implementations for many more components.&lt;br /&gt;&lt;br /&gt;Possible next step:&lt;br /&gt;Create &lt;/span&gt;&lt;span class="postbody"&gt;SessionStorage.Property implementations for the &lt;a href="http://bits.netbeans.org/6.7/javadoc/org-openide-explorer/"&gt;explorer views&lt;/a&gt; of the NetBeans Platform APIs.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What do you think? Was this post interesting? Do you think this proposed solution for persisting component properties is useful? Do you have any code improvements? Please let me know of your thoughts and comments!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Downloads:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://puces-samples.svn.sourceforge.net/viewvc/puces-samples/tags/sessionstate-1.0.tar.gz?view=tar"&gt;source code of the whole sample application&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Versions:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Java SE 6&lt;/li&gt;&lt;li&gt;NetBeans Platform/ IDE v6.7&lt;/li&gt;&lt;li&gt;Swing Application Framework v1.03&lt;/li&gt;&lt;li&gt;SwingX v0.9.5&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class="postbody"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4535323380112004503-6060774299791930934?l=puces-blog.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://puces-blog.blogspot.com/feeds/6060774299791930934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://puces-blog.blogspot.com/2009/04/netbeans-platform-meets-swing.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/6060774299791930934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4535323380112004503/posts/default/6060774299791930934'/><link rel='alternate' type='text/html' href='http://puces-blog.blogspot.com/2009/04/netbeans-platform-meets-swing.html' title='NetBeans Platform meets Swing Application Framework: SessionStorage'/><author><name>Florian Brunner</name><uri>http://www.blogger.com/profile/10094773112480994318</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='http://4.bp.blogspot.com/_PddJB6PO1kA/SpkAtRU38dI/AAAAAAAAACI/DWBU5BVjG_Y/S220/20090705-finnland-2-skaliert.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_PddJB6PO1kA/SmMMrIAAsZI/AAAAAAAAAB4/lKiyfwNFaZQ/s72-c/sessionStorageFiles.jpg' height='72' width='72'/><thr:total>2</thr:total></entry></feed>
