<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CEMDQ3g7fCp7ImA9WhRRFEk.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434</id><updated>2011-11-27T17:07:52.604-08:00</updated><category term="Reviews" /><category term="PerforceNB" /><category term="Perforce" /><category term="NetBeans" /><category term="News" /><category term="Thoughts for monday morning" /><category term="NetBeans Platform" /><title>Notes and other thoughts</title><subtitle type="html">Notes and others thoughts</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://javasign.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>27</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/Javasign" /><feedburner:info uri="javasign" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CEQFR348eip7ImA9Wx9XEko.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-2003954045189296853</id><published>2010-07-27T15:58:00.001-07:00</published><updated>2011-01-05T16:05:16.072-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-05T16:05:16.072-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Perforce" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans Platform" /><category scheme="http://www.blogger.com/atom/ns#" term="PerforceNB" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>PerforceNB 1.0.5.1 build for 6.9 - Call for help!</title><content type="html">&lt;iframe align="left" frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?t=notesandother-20&amp;amp;o=1&amp;amp;p=8&amp;amp;l=bpl&amp;amp;asins=1849511764&amp;amp;fc1=000000&amp;amp;IS2=1&amp;amp;lt1=_blank&amp;amp;m=amazon&amp;amp;lc1=0000FF&amp;amp;bc1=000000&amp;amp;bg1=FFFFFF&amp;amp;f=ifr" style="height: 245px; padding-right: 10px; padding-top: 5px; width: 131px;"&gt;&lt;/iframe&gt;I am aware that in this new modern world, one of the main problems is  time. That happens to me, also. I don't write here to complain about  that. I write this call only for two things.  &lt;br /&gt;
First is to thank everybody who have enough patience to try and  use this plugin. I write this plugin only to give something back to  NetBeans and to NetBeans great community. That thing is enough.  &lt;br /&gt;
The second thing is that I ask for some help from you, the guys  who spent time and nerves using this plugin. If you want to contribute  to this plugin, you are welcomed. Just ask for proper rights. If you  can't afford time for that, please fill bugs and suggestions. As many as  possible. I can't cover everything and I am sure you have many  brilliant and useful ideas to make your and mine life easier using this  plugin.  &lt;br /&gt;
Finally, thanks to all of you. NetBeans rocks!&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://kenai.com/projects/perforcenb/pages/Home"&gt;http://kenai.com/projects/perforcenb/pages/Home&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-2003954045189296853?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QO9pLBlCMcpfLefe5Iiqao2u7OU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QO9pLBlCMcpfLefe5Iiqao2u7OU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QO9pLBlCMcpfLefe5Iiqao2u7OU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QO9pLBlCMcpfLefe5Iiqao2u7OU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/1mW7F9SLvXc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/2003954045189296853/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2010/07/perforcenb-1051-build-for-69-call-for.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/2003954045189296853?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/2003954045189296853?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/1mW7F9SLvXc/perforcenb-1051-build-for-69-call-for.html" title="PerforceNB 1.0.5.1 build for 6.9 - Call for help!" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://javasign.blogspot.com/2010/07/perforcenb-1051-build-for-69-call-for.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYFSXY9fip7ImA9WxFSGEg.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-5321854338960116177</id><published>2010-04-21T06:21:00.000-07:00</published><updated>2010-04-21T06:21:58.866-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-21T06:21:58.866-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Perforce" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans Platform" /><category scheme="http://www.blogger.com/atom/ns#" term="PerforceNB" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title /><content type="html">PerforceNB 1.0.4 is available.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;New features&lt;/b&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt; Make actions work with ignored files &lt;/li&gt;
&lt;li&gt; Ignore management of file based on mask and absolute paths  (now there is only for relative to project paths) &lt;/li&gt;
&lt;li&gt; Opened files viewer (all opened files with all changelists) &lt;/li&gt;
&lt;li&gt; Refresh, Revert and Revert Unchanged actions for opened files  viewer &lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;&lt;a href="" name="Solved_important_issues"&gt;&lt;/a&gt;Solved important  issues&lt;/h3&gt;&lt;ul&gt;&lt;li&gt; Ignore management does not work properly &lt;/li&gt;
&lt;li&gt; Fix connection selection dialog box &lt;/li&gt;
&lt;/ul&gt;&lt;h3&gt;&lt;a href="" name="Known_problems"&gt;&lt;/a&gt;Known problems&lt;/h3&gt;&lt;ul&gt;&lt;li&gt; Projects located outside perforce root directory are not  properly managed &lt;/li&gt;
&lt;li&gt; Refactory and some actions are not working properly &lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
You can download&amp;nbsp; and read about on &lt;a href="http://kenai.com/projects/perforcenb/pages/Home"&gt;PerforceNB Home  page&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-5321854338960116177?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2iIz-UkgsTmlMXtjQrlNqlmfX3U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2iIz-UkgsTmlMXtjQrlNqlmfX3U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2iIz-UkgsTmlMXtjQrlNqlmfX3U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2iIz-UkgsTmlMXtjQrlNqlmfX3U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/sDELaA7dQT0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/5321854338960116177/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2010/04/perforcenb-1.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/5321854338960116177?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/5321854338960116177?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/sDELaA7dQT0/perforcenb-1.html" title="" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2010/04/perforcenb-1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMCQnszfip7ImA9WxBbFE0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-6695729971729111037</id><published>2010-03-12T05:27:00.000-08:00</published><updated>2010-03-12T07:07:43.586-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-12T07:07:43.586-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Perforce" /><category scheme="http://www.blogger.com/atom/ns#" term="News" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans Platform" /><category scheme="http://www.blogger.com/atom/ns#" term="PerforceNB" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>PerforceNB 1.0.3 beta release</title><content type="html">PerforceNB is a Perforce version control client for NetBeans IDE.&lt;br /&gt;
&lt;br /&gt;
Today I released the version 1.0.3 which I consider is a beta quality release.&lt;br /&gt;
&lt;br /&gt;
The features available for 1.0.3 are:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Connection configuration, multiple connection, each project can  have its own connection &lt;/li&gt;
&lt;li&gt;Colored labels and version information in Project View, File  View (local and depot revision) &lt;/li&gt;
&lt;li&gt;Implemented actions: &lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Manage / Unmanage by perforce (on projects) &lt;/li&gt;
&lt;li&gt;Add &lt;/li&gt;
&lt;li&gt;Edit &lt;/li&gt;
&lt;li&gt;Delete &lt;/li&gt;
&lt;li&gt;Revert &lt;/li&gt;
&lt;li&gt;Revert unchanged &lt;/li&gt;
&lt;li&gt;Refresh (don't sync, just refresh the cache below and redraw  the interface) &lt;/li&gt;
&lt;li&gt;Diff against have revision &lt;/li&gt;
&lt;li&gt;Submit (works only with default change list) &lt;/li&gt;
&lt;li&gt;Manage connections (creates, edits multiple connections)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Sync action (on selected file/files/folders/project). You can  sync from the latest version or from a specific changelist.&amp;nbsp; &lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Out of sync decoration for updated files with different  revisions &lt;/li&gt;
&lt;li&gt;Cache is now persisted on local storage when NetBeans is  closed, and is reloaded from local storage when NetBeans open projects.  Now there is no need to query Perforce server when NB starts for every  project. This is a big improvement when we have many projects, loading  is very fast. &lt;/li&gt;
&lt;li&gt;Ignored files management (rules for all projects). (In the next  version will be added support for ignored files based on mask and on  absolute paths.) &lt;/li&gt;
&lt;li&gt;Automated actions (add, edit, delete, move) &lt;/li&gt;
&lt;li&gt;Option to enable/disable the automated actions&lt;/li&gt;
&lt;li&gt;Icon marking projects managed by perforce system (enable/disabled depending if there are pending actions or not). &lt;/li&gt;
&lt;li&gt;a lot of bug fixes&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;You can download&amp;nbsp; and read about on &lt;a href="http://kenai.com/projects/perforcenb/pages/Home"&gt;PerforceNB Home page&lt;/a&gt;.&lt;br /&gt;
&lt;ul&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-6695729971729111037?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xfnnztNDrd_D3na7RXIJXue0BTw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xfnnztNDrd_D3na7RXIJXue0BTw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xfnnztNDrd_D3na7RXIJXue0BTw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xfnnztNDrd_D3na7RXIJXue0BTw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/V5TT2QJmnSg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/6695729971729111037/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2010/03/perforcenb-103-beta-release.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/6695729971729111037?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/6695729971729111037?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/V5TT2QJmnSg/perforcenb-103-beta-release.html" title="PerforceNB 1.0.3 beta release" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2010/03/perforcenb-103-beta-release.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYDR3k_fSp7ImA9WxBbEEk.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-944861570375037749</id><published>2010-03-08T03:19:00.000-08:00</published><updated>2010-03-08T03:19:36.745-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-08T03:19:36.745-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Thoughts for monday morning" /><category scheme="http://www.blogger.com/atom/ns#" term="Reviews" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans Platform" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>Five things I like most at NetBeans Platform 6.8</title><content type="html">NetBeans 6.8 is there since December 2009. It did not look like a very important upgrade at first. At least not very important for Platform developers. But using the new version of platform, some things which may appear small at first, has been visibly improved. The most important improvements are listed here (according to my personal feelings). For a complete overview of changes in platform API you can take a look &lt;a href="http://bits.netbeans.org/6.8/javadoc/apichanges.html"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Wrapped libraries&lt;/b&gt;&lt;br /&gt;
That was one of the major headaches  source. Developing modules for NetBeans (as for other platforms) requires sometimes links to other libraries. Third-party libraries, other than the modules provided by the platform, needs to be linked and wrapped in your custom pluggins or platform-based applications.&lt;br /&gt;
&lt;br /&gt;
Wrapping libraries was done in the past in two ways. By creating a module library wrapper plugin for every library which need to be imported. But when you have to link a bigger library, which have a lot of jars, that was a pain. Because a module library wrapper could be created only for one jar. You can end up with easy to have twenty-thirty libraries only to link to something like apache logging libraries or Seam or similar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The second approach was to create a big jar with all jars from library. For this operation, NetBeans is helpfull, but you have other two problem to solve. First is that the new jar will have it's own manifest. That means that if there is information in manifest files of every jar, that information is lost or not complete. If that information is important, you have a nice problem to solve. The second is that you can loose control over which libraries you have, which versions. Become very difficult in time to maintain the upgrades.&lt;br /&gt;
&lt;br /&gt;
Solution is the new wrapped libraries feature. Now each plugin module in NetBeans can have it's own dependencies on external libraries. For configuration, you have a new tab panel to add as much as needed libraries. The cool thing is that you can specify also the source code and javadocs for every wrapped jar. That was not possible in the old versions. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;ActionListeners are everywhere&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
That could not look as important as it is. In the old versions you could use ActionListeners only for always enabled type of actions. Not you can use the same interface also for context aware and callback action types. That is really cool, even it does not sounds like that at first. A main aspect here is that it is used a "well known" interface.&lt;br /&gt;
&lt;br /&gt;
The first consequence is that if you want to migrate a swing-based app on NetBeans platform, is easier because you just have to pipe your actions. The second consequence is that you don't have to use specific platform interfaces like cookies. I don't say that cookies were bad, but they are old and there is better and much usable alternative. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Declarative Asynchronous actions&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
That's small, but makes code cleaner and flexible. Also throws away the need to manage yourself the asynchronous behavior of your actions. Nice done.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Enhanced IO API&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We already had colors and links. And it was very useful. But now is even more flexible.&lt;br /&gt;
&lt;br /&gt;
You can color the output as you like because you can output with IOColorPrint.print. So you can made your output lines from peaces colored independently. You can also put more hypelinks on the same line. You can, again, add an importance marker, which improves readability on verbose outputs. Finally, you can specify the parent of an IOTab and set its icon and tooltip message. All of them are small things, but used together can be very helpful on creating really effective and friendly output for your application. I appreciate very much an application which let you know what is going on.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Annotations&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
That's not a specific point. There are some very useful annotations added. The point is, thought, not the specific annotations added. But the trend to use as much as possible annotations. I hope that this trend will continue. I already used @OptionsPanelController.SubRegistration and @ConvertAsJavaBean. But there are more, take a look.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-944861570375037749?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0sn_ViuHxPDSOKje3ShdGS7F5nA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0sn_ViuHxPDSOKje3ShdGS7F5nA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0sn_ViuHxPDSOKje3ShdGS7F5nA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0sn_ViuHxPDSOKje3ShdGS7F5nA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/KgfRCtU3w2o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/944861570375037749/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2010/03/five-things-i-like-most-at-netbeans.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/944861570375037749?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/944861570375037749?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/KgfRCtU3w2o/five-things-i-like-most-at-netbeans.html" title="Five things I like most at NetBeans Platform 6.8" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2010/03/five-things-i-like-most-at-netbeans.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcMR3w-cCp7ImA9WxBUFk0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-5482428168935261196</id><published>2010-02-22T23:29:00.000-08:00</published><updated>2010-03-02T23:58:06.258-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-02T23:58:06.258-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Perforce" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>PerforceNB 0.2.alpha release</title><content type="html">In the latest time, for some reasons, I could not work on the developing of PerforceNB plugin. The situation is not the same. New releases will come frequently, I expect it very often (2/3 weeks per release) until the plugin has enough features.&lt;br /&gt;
In the meantime I release the next version 0.2. This version is different in the sense that almost everything was rewritten from scratch. I think now I understood well enough the p4api provided by perforce and it was time for new ideas.&lt;br /&gt;
If you think you need a Perforce plugin for NetBeans please try that. And if you want a better tool please give some time and fill an entry on &lt;a href="http://kenai.com/jira/browse/PERFORCENB"&gt;Issue tracking&lt;/a&gt; or on &lt;a href="http://kenai.com/projects/perforcenb/forums/forum"&gt;Discussion board&lt;/a&gt;.&lt;br /&gt;
The source and other information is available on&amp;nbsp;&lt;a href="http://kenai.com/projects/perforcenb/pages/Home"&gt;PerforceNB Home&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-5482428168935261196?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/RTvEQj5rV8ZOtnXXpYn4o-daOxQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RTvEQj5rV8ZOtnXXpYn4o-daOxQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/RTvEQj5rV8ZOtnXXpYn4o-daOxQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RTvEQj5rV8ZOtnXXpYn4o-daOxQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/aqV_EONBTP0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/5482428168935261196/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2010/02/perforcenb-02alpha-release.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/5482428168935261196?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/5482428168935261196?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/aqV_EONBTP0/perforcenb-02alpha-release.html" title="PerforceNB 0.2.alpha release" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2010/02/perforcenb-02alpha-release.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIFSXg4fip7ImA9WxBVE0g.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-8993947849874018145</id><published>2009-12-23T01:55:00.000-08:00</published><updated>2010-02-16T12:01:58.636-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-16T12:01:58.636-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Thoughts for monday morning" /><title>Common misconceptions about EJB</title><content type="html">Java Enterprise is often a topic for many programmers in the free world (non m$ like one, I suppose ..). I don't think it was always a first option. There were and still there are pros and cons discussions. Still, Java Enterprise is an available solution. Thought, with a lot of books and good articles around, I often hear simply "amazing" thoughts about Java Enterprise. What is worst is that many of these are believed by so called Java Enterprise developers.&lt;br /&gt;
A lot of people still have some misconceptions about Java Enterprise. How this could happen? Perhaps due to the degree of configuration complexity of the firsts variants of the standard. Maybe because of the rigidity of the Sun guys, who kept in iron hands the previous releases (previous than 3.0). Perhaps because in the past the standard was not under JCP. Maybe none of this. I really don't know. But I will present some thoughts that I heard, and give some opinions on that.&lt;br /&gt;
&lt;b&gt;EJB is for web applications&lt;/b&gt;&lt;br /&gt;
Simply wrong. Java Enterprise has nothing to do with web applications. To be more exact, Java Enterprise has the same link to web applications, as it has with other type of client applications. EJB is about business, about business distributed components and about integration. The consumers of these components can be any type of application that understands JNDI and IIOP, nothing more. Even if we see around a lot of web frameworks that are well integrated with EJB, that does not mean EJB is only for web.&lt;br /&gt;
&lt;b&gt;With JPA you don't have to work with databases&lt;/b&gt;&lt;br /&gt;
I always considered that a good programmer is a lazy person. But a lazy programmer is a programmer which chooses to work less but smart instead of easy but with repeated tasks. If you choose EJB with persistence, than you choose to work with an abstract layer, which models your business. You choose to separate these layers. That does not exclude to improve the performance of database. There are often situations when a proper index can solve a big bottleneck. Don't be extreme on that. Persistence layer let you concentrate more on your functionality, don't exclude tuning database process.&lt;br /&gt;
&lt;b&gt;EJB applications are always lazy&lt;/b&gt;&lt;br /&gt;
That is not true. I agree that Java Enterprise comes with a penalty performance. There is a cost for the ease of design and for generality. My idea is that every design tries to solve some classes of problems in trade of others. The art in application design (if there is one) is to make a good trade on that. It’s like in chess. If you want a benefit you have to leave something. The choices are core of the process. If your choices are good, the penalties are not relevant for your business. Going back to EJB, the initial performance penalties are traded for other benefits. As a sample, putting in place a cluster or a cache is not an easy job in state-of-art systems, in EJB this task is very easy. By choosing what components to be cached, the caching levels, by choosing a proper clustering structure you can benefit a lot. A common thing that is missed is the usage of entity managers. A almost always saw that the entity managers used are the default ones provided by wizards. That’s a bad choice. You must reconsider every opportunity. There are a lot of services for EJB components which can be configured with ease, that's the point. Don't put on work the wizards and consider you work done. You work begun after the wizards. Remember well, the choices are very important, and EJB container makes that job very easy.&lt;br /&gt;
&lt;b&gt;Use EJB everywhere, is the best&lt;/b&gt;&lt;br /&gt;
Nothing is the best for everything. EJB has its place in software fauna. But it’s not best for anything you can think of. Sometimes you must consider using light web frameworks, sometimes is better to use light web scripting languages with fast databases. I can give clear receipts. If I put my two cents in, the rigid thinking does not do you any favors.&lt;br /&gt;
&lt;b&gt;EJB is only about components and services for these components&lt;/b&gt;&lt;br /&gt;
I don’t agree. It’s true that components and container services for these components worth a lot. But there is something more, which I consider at least as important as the previous. This valuable thing is integration with external systems. I lot of people forgot that. But one of the main goals of EJB is the integration of external systems. The integration potential is, sometimes, the main reason to choose EJB in place of others technologies. We can review the times when EJB was put on place. A lot of big software consumers had a lot of big systems provided by different software vendors. It is a usual. Every system produces a part of the big picture. A lot of effort and money and knowledge are buried in those systems. The next step is to obtain the big picture. You can’t rewrite everything from scratch. You have to integrate the existent system. You have to put all the pieces together. EJB is good at that. Did you hear about resource adapters? Did you saw a detailed sample of a CORBA component written in C working with EJB? I bet you don’t. Unfortunately I never saw books with covers well this topic. Three pages from five hundred are not enough, but that is the sad average. I am still waiting for a good book to cover this, to exploit this potential.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-8993947849874018145?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/_AFopnqxsmnS_njtLf6BN02lBQ0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_AFopnqxsmnS_njtLf6BN02lBQ0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/_AFopnqxsmnS_njtLf6BN02lBQ0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_AFopnqxsmnS_njtLf6BN02lBQ0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/q9jhYkxABJE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/8993947849874018145/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/12/common-misconceptions-about-ejb.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/8993947849874018145?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/8993947849874018145?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/q9jhYkxABJE/common-misconceptions-about-ejb.html" title="Common misconceptions about EJB" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/12/common-misconceptions-about-ejb.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIBRn4zeyp7ImA9WxBTE0s.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-4771016862435624127</id><published>2009-11-25T02:30:00.000-08:00</published><updated>2009-12-09T04:42:37.083-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-09T04:42:37.083-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>NetBeans Platform: Output windows in simple words</title><content type="html">&lt;i&gt;I/O APIs&lt;/i&gt; is among the most used modules from &lt;i&gt;NetBeans Platform&lt;/i&gt;. This is one of the most common way to show information about your activity. The name can be misleading, but is much simpler that it seems. This module manages the output windows which you already have or you can create, where text information can be put.&lt;br /&gt;
There are a a lot of scenarios where you need output windows. You need them to show logs for bootstrapping tasks, to show log information, to receive feedback from a compiler or builder or other type of tool.&lt;br /&gt;
&lt;br /&gt;
The story about output windows in &lt;i&gt;NetBeans&lt;/i&gt; can be simple or complicated. The hard way is to implement yourself everything and control everything. That could be feasible if you plan to implement a rich output windows with a lot of controls on it. But for simple scenarios, what you have from the platform is simple enough.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Setup&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
From your &lt;i&gt;NetBeans Platform&lt;/i&gt; module, all you have to do is to add "&lt;i&gt;I/O APIs&lt;/i&gt;" as a module dependency. That's all.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;"Hello world!" from output window&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;IOProvider&lt;/i&gt; is a factory for output window components. These output windows are represented by &lt;i&gt;InputOutput&lt;/i&gt; class and hosted into a container, represented by &lt;i&gt;IOContainer&lt;/i&gt;. It's easy and enough to proceed. First, we ask for the default provider to get an InputOutput with a specific title. We can create a new one or get an existing one. After that we activate the output and write to it. Here's the code.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;InputOutput io = IOProvider.getDefault().getIO("TestIO", true);
io.select();
io.getOut().print("Hello world!"); 
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Put some colors and behavior on line&lt;/b&gt;s&lt;br /&gt;
&lt;br /&gt;
We can easily color the line from output. Also we can put some action on the line. If we create a line with an listener (our listener), the line from output would behave as a hyperlink in a browser. When the listened line will be selected, clicked or deleted, we can do something through listener. Let's see some more code.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;try {
&amp;nbsp;&amp;nbsp;&amp;nbsp; InputOutput io = IOProvider.getDefault().getIO("My title", false);
&amp;nbsp;&amp;nbsp;&amp;nbsp; IOColorLines.println(io, "This is a yellow line", Color.yellow);
&amp;nbsp;&amp;nbsp;&amp;nbsp; IOColorLines.println(io, "This is e red important line",
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; null, true, Color.red);
&amp;nbsp;&amp;nbsp;&amp;nbsp; IOColorLines.println(io, "one dynamic line with event",
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new LineListener(), true, Color.green);
} catch (IOException ex) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; Logger.getLogger(SameIOAction.class.getName()).log(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Level.SEVERE, null, ex);
}

[...]
class Listener implements OutputListener {
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void outputLineSelected(OutputEvent ev) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; JOptionPane.showMessageDialog(null, "line with content " +
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ev.getLine() + " was selected");
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void outputLineAction(OutputEvent ev) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; JOptionPane.showMessageDialog(null, "line with content " +
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ev.getLine() + " was actioned");
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void outputLineCleared(OutputEvent ev) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; JOptionPane.showMessageDialog(null, "line with content " +
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ev.getLine() + " was cleared");
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Put some decorations on output windows&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Using another class from the package, &lt;i&gt;IOTab&lt;/i&gt;, you can easily add a tooltip text and a small icon on an output window. As a sample:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;InputOutput io = IOProvider.getDefault().getIO("My title", false);
IOTab.setToolTipText(io, "My tooltip text for Hello world!");
[..]
&lt;/pre&gt;&lt;b&gt;&lt;br /&gt;
&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;And you can do more..&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
There is also a simple way to add some &lt;i&gt;Swing&lt;/i&gt; actions on output window. The output window has a small toolbar on the left side of it. If you pass an array of &lt;i&gt;Swing Actions&lt;/i&gt; on the moment of creation, these actions will be available for use on your output window. Just to name a very often scenario: you have a long process to run, you want to give full text feedback, but you want to be able to stop the process when you think is appropriate. Just create a&lt;i&gt; Swing Action&lt;/i&gt; to fire the canceling job and add it to the &lt;i&gt;InputOutput&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;Action[] actionList = new Action[5];
[..] // add actions here
InputOutput io = IOProvider.getDefault().getIO("My title", actionList);
&lt;/pre&gt;&lt;br /&gt;
Thought there are some limitations: you can't put here more than 5 actions and each action should have the&amp;nbsp;property &lt;i&gt;Action.SMALL_ICON&lt;/i&gt; defined. &lt;br /&gt;
&lt;br /&gt;
Have fun with &lt;i&gt;InputOutput&lt;/i&gt; windows!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-4771016862435624127?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dh7_QdEQea5kmLR5-De29tz4VII/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dh7_QdEQea5kmLR5-De29tz4VII/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dh7_QdEQea5kmLR5-De29tz4VII/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dh7_QdEQea5kmLR5-De29tz4VII/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/Q1vQAUgAhZs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/4771016862435624127/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/11/netbeans-platform-output-windows-in.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/4771016862435624127?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/4771016862435624127?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/Q1vQAUgAhZs/netbeans-platform-output-windows-in.html" title="NetBeans Platform: Output windows in simple words" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/11/netbeans-platform-output-windows-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcDRHw8fip7ImA9WxBUFk0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-7951043169010470173</id><published>2009-11-05T02:51:00.000-08:00</published><updated>2010-03-02T23:57:55.276-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-02T23:57:55.276-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Perforce" /><category scheme="http://www.blogger.com/atom/ns#" term="News" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>PerforceNB 0.1.alpha release</title><content type="html">In the last period of time I worked on a NetBeans plugin for Perforce version system client. This the first release. It has a lot of missing features, still I use it on a daily basis. So it's usable. &lt;br /&gt;
If you need a Perforce client for NetBeans like me, give it a chance.&lt;br /&gt;
And give feedback. I can promise I will take into consideration.&lt;br /&gt;
&lt;br /&gt;
The home page for plugin is &lt;a href="http://kenai.com/projects/perforcenb/pages/Home"&gt;http://kenai.com/projects/perforcenb/pages/Home.&lt;/a&gt;&lt;br /&gt;
To download it you can use either &lt;a href="http://kenai.com/projects/perforcenb/downloads"&gt;http://kenai.com/projects/perforcenb/downloads &lt;/a&gt;or &lt;a href="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=22133"&gt;http://plugins.netbeans.org/PluginPortal&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Implemented features on 0.1.alpha&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Connection configuration (basic form, one connection for all opened projects) &lt;/li&gt;
&lt;li&gt;Colored labels and version information in Project View and Explorer &lt;/li&gt;
&lt;li&gt;Basic operations like add, delete, checkout, revert &lt;/li&gt;
&lt;li&gt;Get latest revision (one operation for all projects) &lt;/li&gt;
&lt;li&gt;File differences &lt;/li&gt;
&lt;li&gt;Submit selection dialog and action (works only with default chagelist) &lt;/li&gt;
&lt;li&gt;Automatic integration in Perforce of IDE file operations like create, delete, edit, move, rename &lt;/li&gt;
&lt;li&gt;Automatic integration in Perforce of file operations outside IDE&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-7951043169010470173?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5JLZSzB-T4rfMocj0zUHm4DROgU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5JLZSzB-T4rfMocj0zUHm4DROgU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5JLZSzB-T4rfMocj0zUHm4DROgU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5JLZSzB-T4rfMocj0zUHm4DROgU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/uEhfzZOvADk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/7951043169010470173/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/11/perforcenb-01alpha-release.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/7951043169010470173?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/7951043169010470173?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/uEhfzZOvADk/perforcenb-01alpha-release.html" title="PerforceNB 0.1.alpha release" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/11/perforcenb-01alpha-release.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYFRng-cCp7ImA9WxBUFk0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-7643465608496583822</id><published>2009-11-02T17:11:00.000-08:00</published><updated>2010-03-02T23:58:37.658-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-02T23:58:37.658-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Perforce" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>NetBeans Platform: Implement Perforce client - part IV</title><content type="html">&lt;b&gt;Automatically add, checkout, delete or move files&lt;/b&gt;&lt;br /&gt;
This is the last article about the Perforce client. That does not mean that is fully implemented, niether I will abandon the project. The NetBeans Perforce client will continue to be developed. By me, and hopefully by others. The point with this string of articles it to illustrate in which way it can be implemented a versioning client in NetBeans.&lt;br /&gt;
&lt;br /&gt;
Since last article, the Perforce client was enriched with many functionalities. Thought, only the last one is relevant for our purpose. The topic is how to integrate into Perforce the IDE file manipulation operations like add, delete, rename, move or edit. You can add here also, how to handle the same situations, when files were modified outside IDE.&lt;br /&gt;
&lt;br /&gt;
The key to this functionality is a class called VCSInterceptor. This class is used by NetBeans to announce the eventually versioning system about some change over files. Either if the change was operated form inside or outside of IDE.&lt;br /&gt;
&lt;br /&gt;
I will split the methods from VCSInterceptor into five categories: queries, delete, move, create and change. You can find the source (comments are very intereting to read) &lt;a href="http://netbeans.sourcearchive.com/documentation/6.5/VCSInterceptor_8java-source.html"&gt;here&lt;/a&gt;. Take a close look there.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;queries&lt;/b&gt;&lt;br /&gt;
This category contain only one method isMutable(File file). This method is used to ovveride the default behavior proposed by the versioning systems which uses read-only files. When a file is read only, the IDE will see the file in this state, so it will not edit it. But when this method returns true, you let the IDE know that you actually can edit the file, even if is marked as read-only from the file system.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;delete&lt;/b&gt;&lt;br /&gt;
beforeDelete and doDelete work together. The first let the IDE know if you want to implement the delete action for the specified file, in the second method you actually write the delete operation. There is another one method, afterDelete. This method is called after the file was deleted from the files system. Besides the moment of the notification, there is another very important difference. All methods are called when a delete operation was realized from IDE, but only the later (afterDelete) is fired when a file was deleted outside IDE. Take this into consideration when you implement the delete handling.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;move&lt;/b&gt;&lt;br /&gt;
beforeMove, doMove, afterMove. Follows the same pattern as for delete operation. beforeMove is used to tell to the IDE that is want or don't want to handle the file move. doMove implements the real move action and afterMove is called (hard to believe, but ) .. after the mov operation. The only difference from delete is that all operations are called only for IDE file rename/move opertions. For this kind of operations outside IDE, NetBeans will fire two events: afterDelete for the source and afterCreate for the target. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;create&lt;/b&gt;&lt;br /&gt;
Following the same pattern, for create we have beforeCreate, doCreate and afterCreate. Adding new files from outside IDE will fire only the last event (like on delete operations). I will go on, I hate to repeat.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;change&lt;/b&gt;&lt;br /&gt;
This breaks the pattern. There is an beforeEdit method called when a file is about to be opened in edit mode. The is a perfect moment to do a checkout if you are in IDE.&amp;nbsp; After that we have two events, beforeChange and afterChange. These events are related to content. beforeChange is called before the file content are about to be changed. afterChange end the cycle. One thing to mention here is that only afterChange is called if the file is updated outside IDE (javadoc does not mention that, but you can trust me on that). The later is a perfect place to put a checkout for outside IDE file modifications.&lt;br /&gt;
&lt;br /&gt;
Just before presenting the source code for that, I have to mention that you don't need to implement all methods. These methods tries to catch all the possible events for all the possible versioning system scenarios. In my case i found to be enough to implement only 7 from 13. And I hope I covered all.&lt;br /&gt;
&lt;br /&gt;
Here is the interceptor code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public class PerforceInterceptor extends VCSInterceptor {

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean isMutable(File file) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true; // really, for all? we will see that
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; /**
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Automatically add to perforce the new added file.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * The code is here to handle also the files added from outside IDE.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * @param file file in question
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void afterCreate(File file) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (PerforceModuleConfig.getInstance().isPerforceExcluded(file)) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileStatus status = getUpdatedFileStatus(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (status == null || FileStatus.STATUS_UNKNOWN.equals(status)) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // this is what we really care
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; P4Client p4client = PerforceSystem.getP4Client();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p4client.actionAdd(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (PerforceActionException ex) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exceptions.printStackTrace(ex);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; /**
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Called when a file is uptodate and is about to be modified.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * The file is automatically checked out.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * @param file file in question
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void beforeEdit(final File file) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (PerforceModuleConfig.getInstance().isPerforceExcluded(file)) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileStatus status = getUpdatedFileStatus(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!FileStatus.STATUS_VERSIONED_UPTODATE.equals(status)) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; P4Client p4client = PerforceSystem.getP4Client();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p4client.actionEdit(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (PerforceActionException ex) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exceptions.printStackTrace(ex);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; /**
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Check out the uptodate file. The method is called when the file was
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * modified outside IDE.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Same logic as {@link #beforeEdit(java.io.File) }.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * @param file file in question
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void afterChange(File file) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; beforeEdit(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; /**
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Mark for delete files which are delete from outside/inside IDE.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Handle different scenarios depending on the status of the file.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * @param file file in question
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void afterDelete(File file) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; P4Client p4client = PerforceSystem.getP4Client();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileStatus status = getUpdatedFileStatus(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (status == null) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; switch (status) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case STATUS_VERSIONED_ADD:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p4client.actionRevert(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (file.exists()) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; file.delete();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case STATUS_VERSIONED_UPTODATE:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p4client.actionDelete(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case STATUS_VERSIONED_EDIT:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p4client.actionRevert(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (file.exists()) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p4client.actionDelete(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (PerforceActionException ex) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exceptions.printStackTrace(ex);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean beforeMove(File file, File file1) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (PerforceModuleConfig.getInstance().isPerforceExcluded(file)) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; @SuppressWarnings("fallthrough")
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void doMove(File source, File target) throws IOException {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; P4Client p4client = PerforceSystem.getP4Client();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileStatus status = getUpdatedFileStatus(source);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (status == null) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; switch (status) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case STATUS_VERSIONED_UPTODATE:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p4client.actionEdit(source);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case STATUS_VERSIONED_ADD:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case STATUS_VERSIONED_EDIT:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p4client.actionMove(source, target);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } catch (Exception ex) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exceptions.printStackTrace(ex);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; /**
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Retrieves the file status. If the cache is not hit, we do it the hard
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * way, we push in cache the value from perforce system.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * @param file file in question
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * @return the status of the file or null if the file is not handled at all.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp; private FileStatus getUpdatedFileStatus(File file) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileStatusCache cache = PerforceSystem.getCache();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileInformation fileInfo = cache.getFileInfo(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (fileInfo == null) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cache.refreshFiles(new String[]{file.getAbsolutePath()});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fileInfo = cache.getFileInfo(file);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (fileInfo == null) ? null : fileInfo.getStatus();
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}&amp;nbsp;&lt;/pre&gt;&lt;pre class="prettyprint"&gt;&amp;nbsp;&lt;/pre&gt;As I said, foolow the source code and the project PerforceNB on kenai site&amp;nbsp; at &lt;a href="http://kenai.com/projects/perforcenb/pages/Home"&gt;http://kenai.com/projects/perforcenb/&lt;/a&gt;.&amp;nbsp; See you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-7643465608496583822?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5_R7JL45ukPl7fD-5OI1R_7j40g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5_R7JL45ukPl7fD-5OI1R_7j40g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5_R7JL45ukPl7fD-5OI1R_7j40g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5_R7JL45ukPl7fD-5OI1R_7j40g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/jUBWeqiU734" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/7643465608496583822/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/11/netbeans-platform-implement-perforce.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/7643465608496583822?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/7643465608496583822?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/jUBWeqiU734/netbeans-platform-implement-perforce.html" title="NetBeans Platform: Implement Perforce client - part IV" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/11/netbeans-platform-implement-perforce.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEICSXc7fCp7ImA9Wx9XEko.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-3195200457697145612</id><published>2009-10-13T06:57:00.000-07:00</published><updated>2011-01-05T16:09:28.904-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-05T16:09:28.904-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>Dynamic libraries in NetBeans</title><content type="html">&lt;iframe align="left" frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?t=notesandother-20&amp;amp;o=1&amp;amp;p=8&amp;amp;l=bpl&amp;amp;asins=0321356683&amp;amp;fc1=000000&amp;amp;IS2=1&amp;amp;lt1=_blank&amp;amp;m=amazon&amp;amp;lc1=0000FF&amp;amp;bc1=000000&amp;amp;bg1=FFFFFF&amp;amp;f=ifr" style="height: 245px; padding-right: 10px; padding-top: 5px; width: 131px;"&gt;&lt;/iframe&gt;I hear often that NetBeans is not as configurable as Eclipse (as a sample). Don't want to start a religious blind war, you'll find nothing like that here. &lt;br /&gt;
&lt;br /&gt;
Regarding this problem my answer is that NetBeans is configurable, but not in a ways as you would expect at the first glance. NetBeans for some things offers a limited GUI to manage things. As a sample, when you create a library. You have a GUI which gives you the possibility to create one. You can build that library only in one way: by selecting individual jars and folders for classes, sources and javadocs (I talk about Java SE libraries). If you want to create a customized library, there's no other GUI possibility.&lt;br /&gt;
&lt;br /&gt;
But you have programming. By offering a friendly and stable API you can extend the platform and IDE as you like. If you know Emacs and Lisp you know what I mean. Is the same philosophy as in Unix/Linux world. No need of GUIs with thousands of screens full of usually unused information. A text file well commented is more than enough. In NetBeans is translated: "You have a very well documented API, stable, samples, why do you need a GUI?".&lt;br /&gt;
&lt;br /&gt;
I will give a 10 minute way to create dynamic libraries in NetBeans. In 10 minutes spent you can do much more than with the best GUI ever.&lt;br /&gt;
&lt;br /&gt;
First, what do I mean by dynamic library. I library which can change in time by your own rules. As a sample, you could want to upgrade the jar files without selecting the new jar files according to the new versions. Or, you would like to have your libraries in different folders (one for development, other for testing machine). Or simply, you know somehow where are your libraries, you have some piece of code to get this information, but you don't want to spent you vacation selecting dozens of jars. You imagination is your limit. With this very simple method you can achieve that in minutes.&lt;br /&gt;
&lt;br /&gt;
First you need to create a NetBeans module project. Call it how do you like, is not important. You do that by &lt;i&gt;File -&amp;gt; New Project -&amp;gt; NetBeans Modules -&amp;gt; Module&lt;/i&gt;. After &lt;i&gt;Next&lt;/i&gt;, you give a name to your module and can choose &lt;i&gt;Standalone Module&lt;/i&gt;. After another next you give the base package, a code name and you have it.&lt;br /&gt;
First we will create a class which extends &lt;i&gt;ModuleInstall&lt;/i&gt;. This class will be called when the module is started up. In order to do this, we have to add an manifest entry like:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;OpenIDE-Module-Install: com/my/package/MyModuleInstall.class
&lt;/pre&gt;&lt;br /&gt;
This class has a method called restored(). This method is called when the module is restored during startup. Here we will put our code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public class ModuleHook extends ModuleInstall {

&amp;nbsp;&amp;nbsp;&amp;nbsp; public void restored() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Map&amp;lt;String, List&amp;lt;URL&amp;gt;&amp;gt; map = new HashMap&amp;lt;String, List&amp;lt;URL&amp;gt;&amp;gt;();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;URL&amp;gt; classpath = new ArrayList&amp;lt;URL&amp;gt;();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; map.put("classpath", classpath);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;URL&amp;gt; javadoc = new ArrayList&amp;lt;URL&amp;gt;();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; map.put("javadoc", javadoc);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // fill the URL map as you like, with jars, sources and javadocs
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // .....
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // by the way, you can use FileUtil.urlForArchiveOrDir(File file)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // to easy get an URL from a File
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Library library = libraryManager.getDefault().getLibrary(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "MyLibrary");
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (library != null) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // remove it if is an old version there
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LibraryManager.getDefault().removeLibrary(library);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LibraryManager.getDefault().createLibrary("j2se", "MyLibrary", map);
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}
&lt;/pre&gt;&lt;br /&gt;
And that is all. One thing though. You need to add dependencies to some Platform Libraries. In the contextual menu of the project action &lt;i&gt;Properties -&amp;gt; Libraries -&amp;gt; Add&lt;/i&gt;. If you don't know what dependency you need simply put the class name in filter field and you will find what you search for.&lt;br /&gt;
&lt;br /&gt;
I consider that NetBeans is a tool for programmers. And programmers don't fear coding. That is why this the best tool to configure your environment. Much flexible and better that a GUI.&lt;br /&gt;
&lt;br /&gt;
Hope you like it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-3195200457697145612?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/T-MPs8SGDvmnZAKrkr2QRuWz4kw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/T-MPs8SGDvmnZAKrkr2QRuWz4kw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/T-MPs8SGDvmnZAKrkr2QRuWz4kw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/T-MPs8SGDvmnZAKrkr2QRuWz4kw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/-e3ECMPcPso" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/3195200457697145612/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/10/dynamic-libraries-in-netbeans.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/3195200457697145612?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/3195200457697145612?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/-e3ECMPcPso/dynamic-libraries-in-netbeans.html" title="Dynamic libraries in NetBeans" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/10/dynamic-libraries-in-netbeans.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYAQXw7cCp7ImA9WxBUFk0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-8288332282686855792</id><published>2009-09-29T14:52:00.000-07:00</published><updated>2010-03-02T23:59:00.208-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-02T23:59:00.208-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Perforce" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>NetBeans Platform: Implement Perforce client - part III</title><content type="html">&lt;b&gt;Switch to P4JAPI, annotate and basic actions&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
All the Netbeans Plugins which tried to implement the Perforce client uses p4 command line tool. This is somehow difficult, because you have to manage the input and output of a command line. A lot of effort with no benefit. Because the perforce team put on place what is called P4Java, the &lt;i&gt;Perforce Java API&lt;/i&gt;. You can find the release notes here (last version) &lt;a href="http://www.perforce.com/perforce/doc.091/user/p4javanotes.txt"&gt;http://www.perforce.com/perforce/doc.091/user/p4javanotes.txt&lt;/a&gt;. Download it from &lt;a href="ftp://ftp.perforce.com/perforce/"&gt;here&lt;/a&gt;. The main benefits are the fact that you work with objects, don't have to parse things, and to manage external processes. Thought, also, it is faster than its command line brother. Since this is not an NetBeans Platform thing, I will not insist on that too much.&lt;br /&gt;
&lt;br /&gt;
As mentioned in a previous article, the presentation of versioning information is implemented in a class based on &lt;i&gt;VCSAnnotator&lt;/i&gt;. In our case, this class is called &lt;i&gt;PerforceAnnotator&lt;/i&gt;. There are some aspects which need to be explained. First is the fact that this class is a listener on some specific property change. That is done using the following code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public class PerforceAnnotator extends VCSAnnotator {
&amp;nbsp;&amp;nbsp;&amp;nbsp; /**
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Fired when textual annotations and badges have changed.&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * The NEW value is Set&amp;lt;File&amp;gt; of files that changed or NULL
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * if all annotaions changed.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */
&amp;nbsp;&amp;nbsp;&amp;nbsp; public static final String PROP_ANNOTATIONS_CHANGED = "annotationsChanged";
&amp;nbsp;&amp;nbsp;&amp;nbsp; private final PropertyChangeSupport support = new PropertyChangeSupport(this);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void addPropertyChangeListener(PropertyChangeListener listener) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; support.addPropertyChangeListener(listener);
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; public void removePropertyChangeListener(PropertyChangeListener listener) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; support.removePropertyChangeListener(listener);
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
The PerforceAnnotator has two methods related to property change events: &lt;i&gt;addPropertyChangeListener &lt;/i&gt;and &lt;i&gt;removePropertyChangeListener&lt;/i&gt;. How it works? We define a logical property, named "&lt;i&gt;annotationChanged&lt;/i&gt;". Any listener added will be notified if this property have been changed. This code works together with another piece from &lt;i&gt;PerforceVS &lt;/i&gt;and another one from &lt;i&gt;FileStatusCache&lt;/i&gt;. Practically, through this logical properties and wire of listeners we send messages from a component to another. They remain&amp;nbsp;loosely&amp;nbsp;coupled. As a sample, when the status of a file has been changed (from perforce point of view), the instance of &lt;i&gt;FileStatusCache &lt;/i&gt;(which manages these statuses) notify &lt;i&gt;PerforceVS &lt;/i&gt;that something on a file has been changed. &lt;i&gt;PerforceVS &lt;/i&gt;than will notify the &lt;i&gt;PerforceAnnotator &lt;/i&gt;about that change and the annotator will change also the status in UI (labels, colors, versioning info). The property change method is a very important concept. It is used very ofted to put UI things together, so take a closer lok on that, whenever you have some time.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;PerforceAnnotator &lt;/i&gt;show some UI information about the status of files. The icon from explorer view is modified and the name and color of the file element is modified. These is done with the following code.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public Image annotateIcon(Image oldImage, VCSContext context) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileStatusCache cache = PerforceSystem.getCache();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int x = 12;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int y = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (cache.containsStatus(context, FileStatus.STATUS_VERSIONED_EDIT)) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ImageUtilities.mergeImages(oldImage, ImageRoot.DECORATION_EDIT, x, y);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(cache.containsStatus(context, FileStatus.STATUS_VERSIONED_ADD)) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ImageUtilities.mergeImages(oldImage, ImageRoot.DECORATION_ADD, x, y);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(cache.containsStatus(context, FileStatus.STATUS_VERSIONED_UPTODATE)) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return super.annotateIcon(oldImage, context);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return super.annotateIcon(oldImage, context);
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public String annotateName(String name, VCSContext ctx) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FileStatusCache cache = PerforceSystem.getCache();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int version;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;FileInformation&amp;gt; files;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; files = cache.listFiles(ctx, FileStatus.STATUS_VERSIONED_EDIT);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (files.size() &amp;gt; 0) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; version = files.get(0).getVersion();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return markName(name, "#0B610B", "#" + version + " [edit]");
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; files = cache.listFiles(ctx, FileStatus.STATUS_VERSIONED_ADD);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (files.size() &amp;gt; 0) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; version = files.get(0).getVersion();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return markName(name, "#084B8A", "#" + version + " [add]");
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; files = cache.listFiles(ctx, FileStatus.STATUS_VERSIONED_UPTODATE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (files.size() &amp;gt; 0) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; version = files.get(0).getVersion();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return markName(name, null, "#" + version);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; files = cache.listFiles(ctx, FileStatus.STATUS_UNKNOWN);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (files.size() &amp;gt; 0) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return super.annotateName(name, ctx);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (name.equalsIgnoreCase("&amp;lt;default package&amp;gt;")) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return "&amp;amp;lt;default package&amp;amp;gt;";
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return super.annotateName(name, ctx);
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; private String markName(String name, String color, String label) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; boolean extra = VersioningSupport.getPreferences().getBoolean(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VersioningSupport.PREF_BOOLEAN_TEXT_ANNOTATIONS_VISIBLE, false);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (color == null) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return name + (extra ? label : "");
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return "&amp;lt;font color=\"" + color + "\"&amp;gt;" + name + "&amp;lt;/font&amp;gt;" +
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (extra ? "&amp;nbsp; &amp;lt;font color=\"" + color + "\"&amp;gt;" + label + "&amp;lt;/font&amp;gt;" : "");
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;br /&gt;
How it works? Depending on the status of the file, we modify the actual icon or label of the file from explorer view. To find the status of the file we ask the &lt;i&gt;FileStatusCache&lt;/i&gt;, this class manages the &lt;i&gt;FileInformation &lt;/i&gt;related to every managed file. The &lt;i&gt;VCSContext &lt;/i&gt;represents the selection of files on which we should show information. Note that is possible to have multiple files in a context. In order to keep things simple, I considered that context have only one file and if there are many, I take into consideration only the first one. In time this should be changed. The same scenario happens for labels. On labels we use HTML tags because the view allow that to modify the aspect of a label.&lt;br /&gt;
&lt;br /&gt;
One small tip to know. ImageUtilities class offers some very useful methods in managing images. We can use that class to merge two images, as is the case with &lt;i&gt;PerforceAnnotator &lt;/i&gt;(we put a small Perforce icon over the original NetBeans file icon). We can load an image giving only a location in class path and we can transform with easy from an image into an icon and viceversa. &lt;br /&gt;
&lt;br /&gt;
Let's take a look on the results of our work until now.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_jVuxYCl05pw/SsJ5iaGdeyI/AAAAAAAAB5I/rCehVGQjxJs/s1600-h/nb2a.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_jVuxYCl05pw/SsJ5iaGdeyI/AAAAAAAAB5I/rCehVGQjxJs/s400/nb2a.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_jVuxYCl05pw/SsJ5iaGdeyI/AAAAAAAAB5I/rCehVGQjxJs/s1600-h/nb2a.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;/a&gt;&lt;/div&gt;Another thing which &lt;i&gt;PerfoceAnnotator &lt;/i&gt;do is to wire up some actions. It does this by implementing the method getActions. This method receives two parameters as input. The first one is the &lt;i&gt;VCSContext&lt;/i&gt;. As noted before, the context gives information about the selected files for which the user wants to show actions. I repeat that is important to be aware that the context can represent more than one file, so behave accordingly. The second parameter is &lt;i&gt;ActionDestination&lt;/i&gt;. This is an enum which tells us if the IDE wants the actions to be inserted on the main menu or on the contextual menu. In the sample code below the complexity of building available actions is wrapped into another class, called &lt;i&gt;FileStatusManager&lt;/i&gt;.&amp;nbsp;An action is a standard swing action. My actions usually calls the perforce client and do something with that.&amp;nbsp;Since this is not a NetBeans Platform I will not talk about that, as usual, I invite you to take a look on the sources and give at least a feedback (you are welcomed anytime to submit). &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;@Override
&amp;nbsp;&amp;nbsp; &amp;nbsp;public Action[] getActions(VCSContext ctx, ActionDestination destination) {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;List&amp;lt;Action&amp;gt; actions = new ArrayList&amp;lt;Action&amp;gt;();
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;FileStatusManager manager = FileStatusManager.getInstance();
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;switch (destination) {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;case MainMenu:
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;actions.addAll(manager.getAvailableActionsOnMainMenu(ctx));
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;break;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;case PopupMenu:
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;actions.addAll(manager.getAvailableActionsOnPopup(ctx));
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;break;
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return actions.toArray(new Action[actions.size()]);
&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/pre&gt;&lt;br /&gt;
One more cookie, thought. To create a progress notification which will be displayed on status bar in a dedicated section, you can use &lt;i&gt;ProgressHandle&lt;/i&gt;. Like in the sample below taken form &lt;i&gt;FileStatusCache&lt;/i&gt;.&lt;i&gt;reloadCacheOnThread&lt;/i&gt;.&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;pre class="prettyprint"&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;final ProgressHandle progress =


&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;ProgressHandleFactory.createHandle("Perforce refresh..");


&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;progress.start();


&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.....


&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;progress.finish();


&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/pre&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/div&gt;&lt;div&gt;I mention this simple thing because a lot of things in NetBeans are very simple and straightforward to implement or use. That is the meaning of &amp;nbsp;strong API. The simplest form possible, intuitive and elegant. I think NetBeans Platform has a lot of those.&lt;br /&gt;
&lt;br /&gt;
Untill the next time, see changes on&amp;nbsp;&lt;a href="http://kenai.com/projects/perforcenb"&gt;http://kenai.com/projects/perforcenb&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-8288332282686855792?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/iMlaf91lh_KAqdpT8iriccYvm7o/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/iMlaf91lh_KAqdpT8iriccYvm7o/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/iMlaf91lh_KAqdpT8iriccYvm7o/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/iMlaf91lh_KAqdpT8iriccYvm7o/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/KALW52ZcjYY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/8288332282686855792/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/09/netbeans-platform-implement-perforce_29.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/8288332282686855792?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/8288332282686855792?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/KALW52ZcjYY/netbeans-platform-implement-perforce_29.html" title="NetBeans Platform: Implement Perforce client - part III" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_jVuxYCl05pw/SsJ5iaGdeyI/AAAAAAAAB5I/rCehVGQjxJs/s72-c/nb2a.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/09/netbeans-platform-implement-perforce_29.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYARH4-eCp7ImA9WxBUFk0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-6766318781151664106</id><published>2009-09-08T04:23:00.000-07:00</published><updated>2010-03-02T23:59:05.050-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-02T23:59:05.050-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Perforce" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>NetBeans Platform: Implement Perforce client - part II</title><content type="html">&lt;b&gt;Module preferences for PerforceNB. &lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Usually options for NetBeans modules are handled via option panel. For that we can use a specialized wizard. You can start the wizard from the contextual menu of the project, where we fire the &lt;i&gt;New&lt;/i&gt; - &lt;i&gt;Other&lt;/i&gt; - &lt;i&gt;Module Development&lt;/i&gt; - &lt;i&gt;Options Panel.&lt;/i&gt; In this way we can create primary or secondary panels for options.&lt;br /&gt;
&lt;br /&gt;
This is not our case. That is because for versioning system options, NetBeans has created a panel already. You can find that panel from the main menu by &lt;i&gt;Tools&lt;/i&gt; - &lt;i&gt;Options&lt;/i&gt; - &lt;i&gt;Miscellaneous&lt;/i&gt; - &lt;i&gt;Versioning&lt;/i&gt;. Take a look on the dialog box and see what comes next. Our job is to insert another item in the list of versioning systems, handling preferences for Perforce.&lt;br /&gt;
&lt;br /&gt;
We achieve that by extending &lt;i&gt;org.netbeans.spi.options.AdvancedOption&lt;/i&gt;. This class represents an advanced interface element for options dialog. We create a new class which extends &lt;i&gt;AdvancedOption&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
After that we must configure the layout.xml to inject in the interface this element. The programmatic way is to modify by hand the &lt;i&gt;layout.xml&lt;/i&gt; file. This file will look like below:&lt;br /&gt;
&lt;filesystem&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;=""&gt;&lt;/filesystem&amp;gt;&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;filesystem&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;=""&gt;&amp;lt;filesystem&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;folder name="VersioningOptionsDialog"&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;file name="PerforceOptions.instance"&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;attr name="instanceClass" stringvalue="org.padreati.perforcenb.ui.PerforceOptions"/&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/file&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/folder&amp;gt;&lt;br /&gt;
&amp;lt;/filesystem&amp;gt;&lt;/filesystem&amp;gt;&gt;&lt;/div&gt;&lt;filesystem&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;=""&gt;&lt;br /&gt;
&lt;/filesystem&amp;gt;&gt;&lt;br /&gt;
&lt;filesystem&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;=""&gt;Another option to generate this content is to find in the IDE the layer GUI editor. Use &lt;i&gt;&amp;lt;this layer in context&amp;gt;&lt;/i&gt; representation. Find &lt;i&gt;VersioningOptionsDialog&lt;/i&gt; folder. There use context menu to create a new file called &lt;i&gt;PerforceOptions.instance&lt;/i&gt; and so on.&lt;/filesystem&amp;gt;&gt;&lt;br /&gt;
&lt;filesystem&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;=""&gt;&lt;br /&gt;
&lt;/filesystem&amp;gt;&gt;&lt;br /&gt;
&lt;filesystem&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;=""&gt;Now we injected our UI element in NetBeans IDE. We implement the class to provide appropriate values. I implemented &lt;i&gt;AdvancedOption&lt;/i&gt; in class &lt;i&gt;PerforceOptions&lt;/i&gt;.&lt;br /&gt;
&lt;/filesystem&amp;gt;&gt;&lt;br /&gt;
&lt;pre class="prettyprint"&gt;&lt;filesystem&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;=""&gt;
&lt;/filesystem&amp;gt;&gt;&lt;filesystem&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;=""&gt;public class PerforceOptions extends AdvancedOption {
&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public String getDisplayName() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return NbBundle.getMessage(PerforceVS.class, "CTL_Perforce_DisplayName");
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public String getTooltip() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return NbBundle.getMessage(PerforceVS.class, "CTL_Perforce_OptionsTooltip");
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public OptionsPanelController create() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new PerforceOptionsPanelController();
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}&lt;/filesystem&amp;gt;&gt;&lt;filesystem&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;=""&gt;&lt;/filesystem&amp;gt;&gt;
&lt;filesystem&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;=""&gt;
&lt;/filesystem&amp;gt;&gt;&lt;/pre&gt;The listing is clear, we provide a display name and a tooltip for the UI element. I used resources for that. The main method here is &lt;i&gt;create()&lt;/i&gt; which returns an instance of &lt;i&gt;PerforceOptionsPanelController&lt;/i&gt;.An &lt;i&gt;OptionPanelController&lt;/i&gt; is the controller behind UI for managing options (MVC sounds familiar? that's one reason why I love NetBeans and Swing). The controller handles operations of managing data. Here is the listing:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public class PerforceOptionsPanelController extends OptionsPanelController {
&amp;nbsp;&amp;nbsp;&amp;nbsp; private PerforceOptionsPanel panel;

&amp;nbsp;&amp;nbsp;&amp;nbsp; public PerforceOptionsPanelController() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; panel = new PerforceOptionsPanel();
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void update() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PerforceModuleConfig config = PerforceModuleConfig.getInstance();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.reload();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; panel.setPath(config.getP4Path());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; panel.setDefaultPort(config.getP4DefaultPort());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; panel.setDefaultWorkspace(config.getP4DefaultWorkspace());
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void applyChanges() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PerforceModuleConfig config = PerforceModuleConfig.getInstance();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.setP4Path(panel.getPath());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.setP4DefaultPort(panel.getDefaultPort());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.setP4DefaultWorkspace(panel.getDefaultWorkspace());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config.store();
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void cancel() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PerforceModuleConfig.getInstance().reload();
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean isValid() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return true;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public boolean isChanged() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return panel.isDirty();
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public JComponent getComponent(Lookup masterLookup) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return panel;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public HelpCtx getHelpCtx() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new HelpCtx(PerforceOptionsPanel.class);
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void addPropertyChangeListener(PropertyChangeListener l) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; @Override
&amp;nbsp;&amp;nbsp;&amp;nbsp; public void removePropertyChangeListener(PropertyChangeListener l) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

}
&lt;/pre&gt;&lt;br /&gt;
There are only some methods which are really relevant. The &lt;i&gt;update&lt;/i&gt; method is called when IDE loads configuration data from storage, I update the interface at that moment. The &lt;i&gt;applyChanges&lt;/i&gt; is called when a save action is fired from interface. Use &lt;i&gt;isChanged&lt;/i&gt; to tell IDE if the configuration data was updated in UI. The UI is specified in &lt;i&gt;getComponent&lt;/i&gt; method. This method returns an instance of &lt;i&gt;PerforceOptionsPanel&lt;/i&gt;, a class which extends &lt;i&gt;JPanel&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
This is the interface. Here is how it looks:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_jVuxYCl05pw/SqY8rhGe-DI/AAAAAAAAB4I/jMwAelHjchs/s1600-h/Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_jVuxYCl05pw/SqY8rhGe-DI/AAAAAAAAB4I/jMwAelHjchs/s400/Screenshot.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
For managing the preferences of the module I created a class called &lt;i&gt;PerforceModuleConfig&lt;/i&gt;. This is a singleton which calls &lt;i&gt;NbPreferences&lt;/i&gt; to persist it's properties. This class I will use in our module to see which are the options for PerforceNB module. Here is a listing:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public final class PerforceModuleConfig {
&amp;nbsp;&amp;nbsp;&amp;nbsp; private static PerforceModuleConfig instance;

&amp;nbsp;&amp;nbsp;&amp;nbsp; private final static String P4_PATH_KEY = "P4_PATH_KEY";
&amp;nbsp;&amp;nbsp;&amp;nbsp; private final static String P4_DEFAULT_PORT_KEY = "P4_DEFAULT_PORT_KEY";
&amp;nbsp;&amp;nbsp;&amp;nbsp; private final static String P4_DEFAULT_WORKSPACE_KEY = "P4_DEFAULT_WORKSPACE_KEY";

&amp;nbsp;&amp;nbsp;&amp;nbsp; private String p4Path;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private String p4DefaultPort;
&amp;nbsp;&amp;nbsp;&amp;nbsp; private String p4DefaultWorkspace;

&amp;nbsp;&amp;nbsp;&amp;nbsp; private PerforceModuleConfig() {
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; public static PerforceModuleConfig getInstance() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(instance==null) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance = new PerforceModuleConfig();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return instance;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; public String getP4Path() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return p4Path;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; public void setP4Path(String p4Path) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.p4Path = p4Path;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; public String getP4DefaultPort() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return p4DefaultPort;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; public void setP4DefaultPort(String p4DefaultPort) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.p4DefaultPort = p4DefaultPort;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; public String getP4DefaultWorkspace() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return p4DefaultWorkspace;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; public void setP4DefaultWorkspace(String p4DefaultWorkspace) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.p4DefaultWorkspace = p4DefaultWorkspace;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; public void reload() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Preferences pref = NbPreferences.forModule(PerforceModuleConfig.class);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String p4PathDefault = "p4";
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(System.getProperty("os.name").startsWith("Windows")) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p4PathDefault = "p4.exe";
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; setP4Path(pref.get(P4_PATH_KEY, p4PathDefault));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; setP4DefaultPort(pref.get(P4_DEFAULT_PORT_KEY, ""));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; setP4DefaultWorkspace(pref.get(P4_DEFAULT_WORKSPACE_KEY, ""));
&amp;nbsp;&amp;nbsp;&amp;nbsp; }

&amp;nbsp;&amp;nbsp;&amp;nbsp; public void store() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Preferences pref = NbPreferences.forModule(PerforceModuleConfig.class);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pref.put(P4_PATH_KEY, getP4Path());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pref.put(P4_DEFAULT_PORT_KEY, getP4DefaultPort());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pref.put(P4_DEFAULT_WORKSPACE_KEY, getP4DefaultWorkspace());
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}
&lt;/pre&gt;&lt;br /&gt;
The content is obvious. Only notice that I have used &lt;i&gt;NbPreferences&lt;/i&gt;, a utility class from &lt;i&gt;NetBeans Platform&lt;/i&gt; for persisting preferences. Very useful one. Here is the result of my work from this episode.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_jVuxYCl05pw/SqY-ZwMMUhI/AAAAAAAAB4Q/sHtj9YLwZqM/s1600-h/Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_jVuxYCl05pw/SqY-ZwMMUhI/AAAAAAAAB4Q/sHtj9YLwZqM/s320/Screenshot.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
As usual, you can see the whole project and code from the kenai project page at &lt;a href="http://kenai.com/projects/perforcenb"&gt;http://kenai.com/projects/perforcenb&lt;/a&gt;. See you on the next episode.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-6766318781151664106?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/g0sYcNPivSe3ofgEvEdPNY4HT5I/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/g0sYcNPivSe3ofgEvEdPNY4HT5I/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/g0sYcNPivSe3ofgEvEdPNY4HT5I/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/g0sYcNPivSe3ofgEvEdPNY4HT5I/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/zp44UaV2qYA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/6766318781151664106/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/09/netbeans-platform-implement-perforce_08.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/6766318781151664106?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/6766318781151664106?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/zp44UaV2qYA/netbeans-platform-implement-perforce_08.html" title="NetBeans Platform: Implement Perforce client - part II" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_jVuxYCl05pw/SqY8rhGe-DI/AAAAAAAAB4I/jMwAelHjchs/s72-c/Screenshot.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/09/netbeans-platform-implement-perforce_08.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYBQX09fip7ImA9WxBUFk0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-139685956855457380</id><published>2009-09-06T17:30:00.000-07:00</published><updated>2010-03-02T23:59:10.366-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-02T23:59:10.366-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Perforce" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>NetBeans Platform: Implement Perforce client - part I</title><content type="html">NetBeans and NetBeans Platform were always the tools for the heart. Unfortunately, my usual job duties did not included enough time spent with them. So, I tool my chanses to spent some nights on these. Since I have to use Perforce versioning system and because NetBeans has not (yet!) a client for this system, I decided to implement such a client. Hope I can give something back to the community in this way, a humble little piece compared to the things I received. You will see project details here &lt;a href="http://kenai.com/projects/perforcenb"&gt;http://kenai.com/projects/perforcenb&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
So, a versioning control system. If you want to know more about Perforce, you can go to their site&amp;nbsp;&lt;a href="http://www.perforce.com/perforce/products.html"&gt;www.perforce.com&lt;/a&gt;.&amp;nbsp;It should be enought to say that I know at least two very big companies which use it as a main VCS.&lt;br /&gt;
&lt;br /&gt;
NetBeans Platform gives us an API which can be used to integrate a client for a versioning system into the IDE. A nice side effect of this is the fact that all the versioning control system clients will behave in a similar way. We will implement our Perforce client as a NetBeans module. In this way we can use it on our daily basis usual tasks.&lt;br /&gt;
&lt;br /&gt;
First thing to create is a NetBeans module project. We can do that by using &lt;i&gt;New&lt;/i&gt; -&amp;gt; &lt;i&gt;Project &lt;/i&gt;from NetBeans IDE. (I use 6.7.1, thought you should use a recent version too). We chose then &lt;i&gt;NetBeans Modules&lt;/i&gt; -&amp;gt; &lt;i&gt;Module&lt;/i&gt; for the project type and hit &lt;i&gt;Next&lt;/i&gt; button.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_jVuxYCl05pw/SqRFDCI77tI/AAAAAAAAB3w/PtwHYCP4Lpw/s1600-h/nb1a.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="271" src="http://2.bp.blogspot.com/_jVuxYCl05pw/SqRFDCI77tI/AAAAAAAAB3w/PtwHYCP4Lpw/s400/nb1a.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;In the next dialog box we insert information about the project. Like project name, location and so. You can see the data I enetered from the image. Afer that, hit the &lt;i&gt;Next&lt;/i&gt; button again.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_jVuxYCl05pw/SqRHt8J4TaI/AAAAAAAAB34/uj7BYOKQ-sQ/s1600-h/nb1b.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_jVuxYCl05pw/SqRHt8J4TaI/AAAAAAAAB34/uj7BYOKQ-sQ/s400/nb1b.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;
&lt;/div&gt;In the next dialog box we insert some information useful for code generation. Base package can be configured here, title of the plugin and layer. The will be important in the next parts of this story. For the moment just be sure you select it. To generate the code for the project you should use action &lt;i&gt;Finish&lt;/i&gt; button. &lt;br /&gt;
&lt;br /&gt;
So, we have now a module project which does nothing for the moment. We want to implement a versioning system client in it, so the starting point should be extending the&amp;nbsp;VersioningSystem class. But, to be able to use that class, we must do another preparation step. Importing the NetBeans modules which we will base our module on. For the beginning we will add two dependencies at the project. For that, action the contextual menu of the project. From there, action &lt;i&gt;Properties&lt;/i&gt; -&amp;gt; &lt;i&gt;Libraries&lt;/i&gt;. In the dialog box fire&amp;nbsp;&lt;i&gt;Add&lt;/i&gt; button which will gives us a search screen.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_jVuxYCl05pw/SqRKrT9VKjI/AAAAAAAAB4A/LyWk4hkDipA/s1600-h/nb1c.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_jVuxYCl05pw/SqRKrT9VKjI/AAAAAAAAB4A/LyWk4hkDipA/s400/nb1c.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
The interesting thing in this screen is that you can use it in two ways. First you know already which module you should import, so you can roll over the Module list and select modules you like to use it. The second way is to use search Filter. The nice thing here is that you can search for an exposed class. So, if you don't know which module to import in order to use a specific class or interface, you filter module by that class or interface and you will have listed all the modules which offer that name. Nice trick when you are lost somehow.&lt;br /&gt;
&lt;br /&gt;
So, we need to add dependencies to the following modules: Versioning and Utiities API. The last because we use an utility class for getting the resources (look for NbBundle to see what I mean).&lt;br /&gt;
&lt;br /&gt;
The next stept is to let the NetBeans IDE "know" that I just implemented a new versioning client for him.We do this by extending&amp;nbsp;&lt;i&gt;org.netbeans.modules.versioning.spi.VersioningSystem&lt;/i&gt; in a service provider interface way. So we create a derived class, PerforceVS which extends VersioningSystem. We create &lt;i&gt;META-INF&lt;/i&gt; folder into the source root. In &lt;i&gt;META-INF&lt;/i&gt; we create a folder called &lt;i&gt;services&lt;/i&gt;. In &lt;i&gt;META-INF/services&lt;/i&gt; we create an empty text file. That file will be called&amp;nbsp;org.netbeans.modules.versioning.spi.VersioningSystem and will have one line only:&amp;nbsp;org.padreati.perforcenb.PerforceVS. This is the name of the class which extends VersioningSystem. For a broader view of Service Provider Interface you can take a look &lt;a href="http://javasign.blogspot.com/2009/08/powered-by-service-provider-interface.html"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;package org.padreati.perforcenb;

import java.io.File;
import org.netbeans.modules.versioning.spi.VCSAnnotator;
import org.netbeans.modules.versioning.spi.VersioningSystem;
import org.openide.util.NbBundle;
import org.padreati.perforcenb.wrapper.PerforceSystem;

/**
&amp;nbsp;*
&amp;nbsp;* @author padreati
&amp;nbsp;*/
public class PerforceVS extends VersioningSystem {

&amp;nbsp;&amp;nbsp; &amp;nbsp;public PerforceVS() {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;putProperty(PROP_DISPLAY_NAME, NbBundle.getMessage(
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;PerforceVS.class, "CTL_Perforce_DisplayName")); // NOI18N
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;putProperty(PROP_MENU_LABEL, NbBundle.getMessage(
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;PerforceVS.class, "CTL_Perforce_MainMenu")); // NOI18N
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;@Override
&amp;nbsp;&amp;nbsp; &amp;nbsp;public File getTopmostManagedAncestor(File file) {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// TODO for the moment all will be considered under
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// Perforce just for testing
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return new File("/");
&amp;nbsp;&amp;nbsp; &amp;nbsp;}

&amp;nbsp;&amp;nbsp; &amp;nbsp;@Override
&amp;nbsp;&amp;nbsp; &amp;nbsp;public VCSAnnotator getVCSAnnotator() {
&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return PerforceSystem.getSystem().getAnnotator();
&amp;nbsp;&amp;nbsp; &amp;nbsp;}
}
&lt;/pre&gt;&lt;div&gt;&lt;/div&gt;&lt;br /&gt;
This class is in the very basic form. We do the following:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;In constructor we set values for menu labels. In order to work I have inserted entries into resource (properties) files for&amp;nbsp;CTL_Perforce_DisplayName and&amp;nbsp;CTL_Perforce_MainMenu.&lt;/li&gt;
&lt;li&gt;I implemented getVCSAnnotator just to return the instance of annotator we will use (details a little bit latter).&lt;/li&gt;
&lt;li&gt;implement getTopmostManagedAncestor. If this method returns a value, it means that the file/folder receicved as parameter is managed by our versioning system. If not, we return null.&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;One important aspect is the design of versioning system in NetBeans. It is considered that one resource from disk (either file or folder) can be in two states only. Either is managed by one versioning system (only one versioning system can own the resource in the same time) or is not managed at all. The versioning API consider also that if a folder is managed by a versioning system, all of the folders and files should be managed by that version control. So, to find for a folder if it is managed by a versioning control, we should tell to the versioning API that the specified files resides under a managed folder. We do that by implementing&amp;nbsp;getTopmostManagedAncestor. This method should return the topmost managed folder where resides the file received as parameter.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;In my sample I simply return root folder. Why, would you ask. Just for the testing purposes. Returning the root folder of the file system (this is similar to C:\ folder on Windows) I specify that all files are managed by Perforce. Obviously this is not true. We do it for now just to see where we go.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Also, I created a singleton class to hold all the references of the Perforce versioning system. For the moment we hold only annotator instance. But what is an annotator?&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;&lt;div&gt;&lt;div&gt;package org.padreati.perforcenb.impl;
&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;import java.awt.Image;
&lt;/div&gt;&lt;div&gt;import java.util.ArrayList;
&lt;/div&gt;&lt;div&gt;import java.util.List;
&lt;/div&gt;&lt;div&gt;import javax.swing.Action;
&lt;/div&gt;&lt;div&gt;import org.netbeans.modules.versioning.spi.VCSAnnotator;
&lt;/div&gt;&lt;div&gt;import org.netbeans.modules.versioning.spi.VCSContext;
&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;/**
&lt;/div&gt;&lt;div&gt;&amp;nbsp;*
&lt;/div&gt;&lt;div&gt;&amp;nbsp;* @author padreati
&lt;/div&gt;&lt;div&gt;&amp;nbsp;*/
&lt;/div&gt;&lt;div&gt;public class PerforceAnnotator extends VCSAnnotator {
&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;@Override
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public Image annotateIcon(Image arg0, VCSContext arg1) {
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return super.annotateIcon(arg0, arg1);
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}
&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;@Override
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public String annotateName(String name, VCSContext ctx) {
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return name + " [PERFORCE]";
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}
&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;@Override
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;public Action[] getActions(VCSContext ctx, ActionDestination destination) {
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// TODO complete actions, for the moment only an empty
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;// menu as a sample
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;List&lt;action&gt; actions = new ArrayList&lt;action&gt;();&lt;/action&gt;&lt;/action&gt;
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (destination == VCSAnnotator.ActionDestination.MainMenu) {
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;actions.add(null);
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return actions.toArray(new Action[actions.size()]);
&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}
&lt;/div&gt;&lt;div&gt;}
&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;An VCS Annotator is the class which implements the decoration in IDE of the code elements controlled by a versioning system. In our case, all the files managed by Perforce should be specified in a way that is visible into interface. Just because we signaled that all files are managed by Perforce (we know that is not true), all the files will be decorated by this annotator.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;annotateName&lt;/i&gt; will decorate the name of the resource, and &lt;i&gt;annotateIcon &lt;/i&gt;will decorate the icon. These methods receives VSContext. This class encapsulates a selection of objects, so we can multiple annotate the resources. In our sample implementation we only append the [PERFORCE] string at the name of resource.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;The method&amp;nbsp;&lt;i&gt;getActions &lt;/i&gt;deserves also a lot of attention. Bu on that in another next chapter. For the moment just remember that this is a way to provide actions to main or contextual menus. For the moment we give an empty menu.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Until the next episode, just give it a try. Run the module. It will open the IDE with our module enabled. Open &amp;nbsp; a project in IDE and watch for names, You will the the appended text for all the resources. Like it would be managed by Perforce.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;On the next things in the following episode. Follow it! NetBeans Platform deserves it!&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-139685956855457380?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/WidrJkpvTZeC_SOs6Uz_gSGwlGw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WidrJkpvTZeC_SOs6Uz_gSGwlGw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/WidrJkpvTZeC_SOs6Uz_gSGwlGw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WidrJkpvTZeC_SOs6Uz_gSGwlGw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/-c_A85PyqMM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/139685956855457380/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/09/netbeans-platform-implement-perforce.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/139685956855457380?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/139685956855457380?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/-c_A85PyqMM/netbeans-platform-implement-perforce.html" title="NetBeans Platform: Implement Perforce client - part I" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_jVuxYCl05pw/SqRFDCI77tI/AAAAAAAAB3w/PtwHYCP4Lpw/s72-c/nb1a.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/09/netbeans-platform-implement-perforce.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4BR3o5eCp7ImA9WxNSF00.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-5895838824460496441</id><published>2009-08-31T01:39:00.000-07:00</published><updated>2009-08-31T01:39:16.420-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-31T01:39:16.420-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Reviews" /><title>Powered by Service Provider Interface</title><content type="html">In my previous post I used an annotation processor to enrich the usage of annotations. I stated that to configure an annotation processor you should use a compiler time parameter. In Java 6 you can do more. You have Service Provider Interface API which lets you configure the same processor in a more elegant manner. But what is SPI (Service Provider Interface)?&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Brief on SPI&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
The official java doc is &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html"&gt;here&lt;/a&gt;. A &lt;i&gt;service&lt;/i&gt; is an interface or abstract class which defines a contract for a specific functionality. A &lt;i&gt;service provider&lt;/i&gt; is an implementation of that service. Java 6 provides a loader for services based on a &lt;i&gt;provider-configuration file&lt;/i&gt;. Just as simple.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Steps to put on jobs&lt;/b&gt; &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;You define an interface or use an existing one which defines the contract of your service. &lt;/li&gt;
&lt;li&gt;You define and implement one or more implementing classes. This classes should have an empty constructor, that is the only requirement.&lt;/li&gt;
&lt;li&gt;You create META-INF/services folder in you jar archive. In that folder you create a file named with the canonical class name of the interface. (as a sample: your.packages.MyInterface). That is the provider-configuration file.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;In the new created file you insert the canonical names of the implementing classes. These classes are the service providers. If you have more implementations, you put them on separate lines. The syntax of this file is the syntax of properties file (put comments prefixed with # for clarity).&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;That's all. The runtime will parse the provider-configuration files and provides service loaders for these services, which you can use.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;What are the usages?&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Insert providers for existent services&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
JDK provides some usefull SPIs already, which you can use them. Going back to the beggining of my article, the java annotation processor is such a SPI service. So, in place of putting "-processor org.aap.processor.AAPProcessor" as a compiler option, we can skip that. Instead, we create META-INF/services folder. In that folder we create a file called "javax.annotation.processing.Processor". In that provider-configuration file we put "org.aap.processor.AAPProcessor". Now it works. For the article go &lt;a href="http://javasign.blogspot.com/2009/08/annotation-checking-at-compile-time.html"&gt;here&lt;/a&gt;. Simply by providing this, the runtime at the moment of loading the jar library, will parse providers and use them. Nice and clean.&lt;br /&gt;
&lt;br /&gt;
Obviously we can provide implementation services for other SPIs as well. I mention here just a few like: &lt;a href="http://72.5.124.55/javase/6/docs/api/javax/security/auth/spi/LoginModule.html"&gt;LoginModule&lt;/a&gt; for authentication, &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/javax/sound/sampled/spi/package-tree.html"&gt;sound sample API&lt;/a&gt; or better &lt;a href="http://v1.dione.zcu.cz/java/docs/tutorial/sound/SPI-intro.html"&gt;here&lt;/a&gt;, &lt;a href="http://java.sun.com/javase/6/docs/api/index.html?javax/sound/sampled/spi/AudioFileReader.html"&gt;java text spi API&lt;/a&gt; (by the way, nice feature), and others.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Usage of service providers in an Observer Pattern manner&lt;/b&gt;&lt;br /&gt;
Implement your own interface for observable (eventually by extending java.util.Observer). Don't need to handle yourself contributions, service loader is here for that. And can handle contributions from the whole class path.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Usage of service providers in a Factory pattern manner&lt;/b&gt;&lt;br /&gt;
Implement an interface with a getter to discriminate between implementations. On execution time, use service loader to iterate through implementations and find which provider to use.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;
That's only a starting point for service provider. I found a nice feature brought by Java 6. In fact not only nice, but almost fabulous. An option to extending platform.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-5895838824460496441?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pkllHISanZ7n8UEMaCEECQfa0lk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pkllHISanZ7n8UEMaCEECQfa0lk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pkllHISanZ7n8UEMaCEECQfa0lk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pkllHISanZ7n8UEMaCEECQfa0lk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/jplQSBFwggA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/5895838824460496441/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/powered-by-service-provider-interface.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/5895838824460496441?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/5895838824460496441?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/jplQSBFwggA/powered-by-service-provider-interface.html" title="Powered by Service Provider Interface" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/powered-by-service-provider-interface.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcAQHo7eyp7ImA9WxNSF0w.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-2981324563008334873</id><published>2009-08-27T04:48:00.000-07:00</published><updated>2009-08-31T04:10:41.403-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-31T04:10:41.403-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Reviews" /><title>Annotation checking at compile time with Java Annotation Processor</title><content type="html">Some weeks ago I implemented a feature which collects some information on runtime from some classes. I preferred using annotations against interfaces for flexibility. Practically the task could be described like: decorate with meta information some classes, parse annotations and get information to be stored.&lt;br /&gt;
&lt;br /&gt;
As a sample a had a annotation like:&lt;br /&gt;
&lt;pre class="prettyprint"&gt;@Retention( RetentionPolicy.RUNTIME )
@Target( ElementType.METHOD )
public @interface Description 
{
}
&lt;/pre&gt;&lt;br /&gt;
As you can see, annotation syntax allows me to specify to store for runtime the annotation and that the annotation to be used for methods. That was frustrating for my job, because I would expect to have more flexibility on that. In my specific case, I would like to allow the meta decoration only on methods which returns strings.&lt;br /&gt;
&lt;br /&gt;
I was thinking to document the annotation and specify that if the annotation is not on a method which returns string, the annotation will be ignored. Said and done. But there is a better and fairly simple method to do the task. This is Java Annotation Processor. This feature is documented in &lt;a href="http://jcp.org/en/jsr/detail?id=269"&gt;JSR 269: Pluggable Annotation Processing API&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The code I wrote is more complex, but for this post I wrote a sample to show the usage of this API.&lt;br /&gt;
&lt;br /&gt;
The JSR 269 states that you can implement a plug-in for the compiler which can handle the annotations. This plug-in can be given as parameter at compile time, so your code will be called when one of your annotation appears in source code.&lt;br /&gt;
&lt;br /&gt;
First step is to create a annotation processor. This can be done by implementing interface javax.annotation.processing.Processor or by extending the class AbstractProcessor from the same package. I used the second way being much easier.&lt;br /&gt;
&lt;pre class="prettyprint"&gt;@SupportedAnnotationTypes(value = {"mypackage.LiveDescription"})
@SupportedSourceVersion(SourceVersion.RELEASE_5)
public class AAPProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set annotations, RoundEnvironment roundEnv) 
    {
        for (TypeElement typeElement : annotations) 
        {
            Set elements = roundEnv.getElementsAnnotatedWith(typeElement);
            for (Element element : elements) 
            {
                // we have only one annotation on methods
                processElement((ExecutableElement) element);
            }
        }
        return true;
    }

    private void processElement(ExecutableElement element) 
    {
        String elementTypeStr = element.getReturnType().toString();
        if (!"java.lang.String".equals(elementTypeStr)) 
        {
            processingEnv.getMessager().printMessage(
                Kind.ERROR, 
                "Method does not return a String", 
                element);
        }
    }
}
&lt;/pre&gt;Some things need to be explained:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;SupportedAnnotationTypes specify one specific annotation. You can use * and package names also.&lt;/li&gt;
&lt;li&gt;SupportedSourceVersion specify the Java version. That's OK because we did not had annotations on prior versions of Java language.&lt;/li&gt;
&lt;li&gt;the process method iterates though annotations and for every one give the code elements annotated with (in my case only methods); after that calls processElement for any annotated element.&lt;/li&gt;
&lt;li&gt;processElement&amp;nbsp; verify get the returned type of the method; if the returned type is not java.lang.String that use the message service to signal a syntax error&lt;/li&gt;
&lt;/ul&gt;That's all about processor. As you can see, is quite obvious and simple to implement that. Of course, your implementation will be more flexible (not harcoded) and complicated.&lt;br /&gt;
&lt;br /&gt;
The final step is to give that to the compiler. I used NetBeans (my beloved IDE) for that, but is simple enough in any IDE. You have only to give the compiler a hint about your plug-in. For that you have to:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;put on compiler options "-processor org.aap.processor.AAPProcessor", aka the -processor option with the fully qualified name of your class. In NetBeans you go on Project Properties-&amp;gt;Build-&amp;gt;Compiling and put that in "Addidtional Compiler Options" text box.&lt;/li&gt;
&lt;li&gt;put the class on compiler class path; as I created a jar file containing my annotation processor, you have only to add that to the compiler path. In NetBeans is also trivial. You have to go to Project Properties-&amp;gt;Libraries-&amp;gt;Compile and add your jar there&lt;/li&gt;
&lt;/ul&gt;That's all. The tested code was:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="prettyprint"&gt;public class AnnotatedTest {

    @Description
    public String getName() {
        return "String";
    }

    @Description
    public int getAge() {
        return 10;
    }
}&lt;/pre&gt;I bet that the second method will fail at compile time. Do you?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-2981324563008334873?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/_QEi31M2O-_3Ib9pbfwjuqxlsDk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_QEi31M2O-_3Ib9pbfwjuqxlsDk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/_QEi31M2O-_3Ib9pbfwjuqxlsDk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_QEi31M2O-_3Ib9pbfwjuqxlsDk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/rh42XT9Az-s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/2981324563008334873/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/annotation-checking-at-compile-time.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/2981324563008334873?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/2981324563008334873?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/rh42XT9Az-s/annotation-checking-at-compile-time.html" title="Annotation checking at compile time with Java Annotation Processor" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>3</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/annotation-checking-at-compile-time.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08BQn07fip7ImA9WxNSEU0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-2008593278704489592</id><published>2009-08-20T14:30:00.000-07:00</published><updated>2009-08-24T03:30:53.306-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-24T03:30:53.306-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Thoughts for monday morning" /><title>Concerned about JBoss Seam? Don't worry, it will be better</title><content type="html">I am a big fun of Java EE. Don't ask me why, if it's not obvious I will explain in another post. Even of the fact that I like Java EE that much, that does not mean I consider it perfect. In fact is not perfect at all.&lt;br /&gt;There is place for a lot of improvements, a lot of them are on the road to be included in the next versions of standards, others not yet. So, working with Java EE alone, sometimes could be a pain. That's why I put in place Seam Framework. Seam Framework is a perfect match for Java EE on server side. It gives you a lot of things which the standard has not. You have Seam components and Seam contexts, which is a big progress. I don't mention the whole features of Seam here, even those have a great weight. If you want to see details on that you can see on &lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;a href="http://seamframework.org/"&gt; http://seamframework.org/&lt;/a&gt;. I worked with Seam on three medium/big applications and had a lot of reasons to be happy.&lt;br /&gt;But in these days I had some black thoughts on that. I was wondering what will happen with Seam. You could honestly ask yourself why, if everything was so fine? Just because of WebBeans, the new standard. Here is the story.&lt;br /&gt;O lot of good people of JBoss and Seam were working on the new proposals from JSR. They provided a lot of work and results for EJB3 and JPA. Now they are ready to publish the new &lt;a href="http://jcp.org/en/jsr/detail?id=299"&gt;JSR-299 Java Context and Dependency Injection ( aka. WebBeans )&lt;/a&gt;. That is a great JSR and I am waiting to work with. The WebBeans comes to provide a standard for the main lack of Java EE applications. The poor integration between EJB components and JSF components ( aka. managed beans ). That was the core job of Seam Framework. Now WebBeans put these two layers together, by allowing EJB components to act as JSF components. We will have more multiuser secured acces and transactions on the components beneath JSF, and that's really cool. In fact WebBeans have knowledge from Seam Framework, Struts Shale, Oracle ADF and Google Guice inside.&lt;br /&gt;So what will happen with Seam in this context? The JBoss will renounce at Seam in favor of WebBeans? I was thinking on that until I read a very clear statement from JBoss. You can find it &lt;a href="http://seamframework.org/WebBeans/WebBeansOverview#H-HowDoesSeamRelateToWebBeans"&gt;here&lt;/a&gt;. It explains how Seam Framework relates with WebBeans.&lt;br /&gt;WebBeans implementation form JBoss will be the core on which Seam will be based. All the good things from Seam related to components and contexts will be based on that and that. Seam Framework continues, it will be alive. And most probably, it will give you in the future also, a lot of reasons to stay sticked your business and use EJB in a painless way.&lt;br /&gt;The good thing here is that we could use WebBeans implementations from another providers together with Seam Framework, it's a standard, isn't it?&lt;br /&gt;If you didn't give a try to Seam Framework, you should start to do it right now. EJB and Seam is a winner bet. Thanks to all guys who works on that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-2008593278704489592?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/sjInm9qR23y3RmYukqSpaZLbCh0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sjInm9qR23y3RmYukqSpaZLbCh0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/sjInm9qR23y3RmYukqSpaZLbCh0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sjInm9qR23y3RmYukqSpaZLbCh0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/NNlGhFO-PBo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/2008593278704489592/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/concerned-about-jboss-seam-dont-worry.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/2008593278704489592?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/2008593278704489592?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/NNlGhFO-PBo/concerned-about-jboss-seam-dont-worry.html" title="Concerned about JBoss Seam? Don't worry, it will be better" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/concerned-about-jboss-seam-dont-worry.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQDSX45eCp7ImA9WxNTFU0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-8018965989510906416</id><published>2009-08-17T02:07:00.002-07:00</published><updated>2009-08-17T02:12:58.020-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-17T02:12:58.020-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Thoughts for monday morning" /><title>Slow death by technical debt</title><content type="html">&lt;p&gt;Did you here the words "can't have time now, implement that quickly" or "we need a.s.a.p. that for a presentation"? If you did that, you should know that you are in the middle of the battle. Invisible bullets go near your ears and you and your team are living on the edge. That's not bad in itself, but can became as bad as can be soon, if you can't handle. I'll explain why.&lt;/p&gt; &lt;p&gt;When you have to implement something, either is a new feature or a solution for a bug, you face one common problem. You can take main scenario, fix what it should do and go further. That's called quick and dirt. That is because the code resulted from that is really dirt. The second and best approach is to face to problem for today and tomorrow. Think hard and implement the optimum solution, use a good design. As I said, there are times when quick and dirt saves you from something. Is like in management, the difference between important and urgent. The urgent sometimes is more useful than important. But this has a trade off.&lt;/p&gt; &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Ward_Cunningham" mce_href="http://en.wikipedia.org/wiki/Ward_Cunningham"&gt;Ward Cunningham&lt;/a&gt; invented a metaphor for that, which fits well in understanding the implications. This metaphor is called Technical Debt. Technical debt is similar to financial debt. When your business needs something urgent and you don't have enough money, you borrow some from the bank and do your job. After that you have to pay interests and principal to return the debt. Same in software, but here you deal with quality in place of money. Sometimes to get a good deal, to touch a milestone or to give something with few resources you can accept quick and dirty. After the deal is done you can decide if you live with that or you refactor it, using a good design this time.But you must have always in mind the working on poor code means paying more interests. And if you pay too more interests your deals could became a bad one. So, for your health, refactor as soon as possible. That is called paying the principal and eliminate the technical debt.&lt;/p&gt; &lt;p&gt;Quality in software means resources. You have to spent more resources to have better quality. As Martin Fowler said &lt;a href="http://martinfowler.com/bliki/TechnicalDebt.html" mce_href="http://martinfowler.com/bliki/TechnicalDebt.html"&gt;here&lt;/a&gt;, technical debts hurts performance. And the performance &lt;a href="http://martinfowler.com/bliki/CannotMeasureProductivity.html" mce_href="http://martinfowler.com/bliki/CannotMeasureProductivity.html"&gt;is almost unmeasurable in software&lt;/a&gt;. You have to manage a proper balance in your technical debts. If you hear the magical words which leads to quick and dirty, open your ears. If you don't hear soon about refactoring tasks, you should put your questions. If these things come again and again then you could go into a swamp with your projects. Everything begins with parts of code which is considered ugly and unmanageable. These become to stink. The project can go to the slowly path of death by technical debt suffocation.&lt;/p&gt; &lt;p&gt;How to handle technical debts?&lt;/p&gt; &lt;p&gt;There no standardized solutions. That's because is hard to measure and because managers like Excel too much. They like to see numbers, that give them the sensation of control. But numbers are not so bad. They really don't show the things how they are (don't let the managers know that!), but the process of getting these numbers enforce some processes which could help in handling technical debts.&lt;/p&gt; &lt;p&gt;A good individual exercise which I practice is using of IDE meta comments like TODO, FIXME or somebody else from the family. When I begun to implement something which is complex somehow I use TODO comments. I use them as bookmarks to remind me that I should complete something. These marks will be removed until I submit. So they exists only to remind to my poor memory that I did not finished the job. Before submit I check to see if everything is like I want by verifying and removing these comments.I call them Transient Technical Debts. Transient because these technical debts are not persisted into version control system.&lt;/p&gt; &lt;p&gt;A similar approach could be followed for the persistent technical debts or the normal technical debts. You can you a marker like FIXME. Maybe a FIXME and a date. Better is to have also a system for controlling them. A good approach is to put an effort in the next iteration of your software and eliminate them. So all the technical debts you accumulated on the current iteration will be paid in the next one. Just to keep things in control.&lt;/p&gt; &lt;p&gt;Another approach is to keep that ledger in the bug and task tracking management system. You can have some attributes on tasks and bugs which tells us if the job was done quick and dirty or not. If we have to spent more effort to put a good implementation in place of a poor one. A mixing solution is to have code comments linked to that kind of a system.&lt;/p&gt; &lt;p&gt;These kinds of ledgers are good because they can give you numbers also. It forces you to have a health quality of the software and keeps you manages happy. They have the input for nice charts and reasons for raise your salary. Anyway, keep your ears tuned and don't go int the technical debts swamp.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-8018965989510906416?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-0wR6T26D1zZ00wxxkMawtDiWPo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-0wR6T26D1zZ00wxxkMawtDiWPo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-0wR6T26D1zZ00wxxkMawtDiWPo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-0wR6T26D1zZ00wxxkMawtDiWPo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/LwOuq46SYcg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/8018965989510906416/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/slow-death-by-technical-debt.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/8018965989510906416?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/8018965989510906416?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/LwOuq46SYcg/slow-death-by-technical-debt.html" title="Slow death by technical debt" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/slow-death-by-technical-debt.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEDRXwyeSp7ImA9WxBTE0s.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-6936470613895993299</id><published>2009-08-17T02:07:00.001-07:00</published><updated>2009-12-09T04:44:34.291-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-09T04:44:34.291-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="News" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>NetBeans 6.7.1 with JavaFX</title><content type="html">&lt;a href="http://www.netbeans.org/" mce_href="http://www.netbeans.org/"&gt;NetBeans&lt;/a&gt; soon after 6.7 had launched another version of its IDE. That's 6.7.1 with JavaFX. As its name states, this version is an update version of the previous one containing few adiitional things:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Support for JavaFX 1.2&lt;/li&gt;
&lt;li&gt;Update of GlassFish v3 Prelude&lt;/li&gt;
&lt;li&gt;Important bux fixes requested by users&lt;/li&gt;
&lt;/ul&gt;You should give it a try, even if you don't use actually JavaFX. Bring it from &lt;a href="http://www.netbeans.org/downloads/index.html" mce_href="http://www.netbeans.org/downloads/index.html"&gt;here&lt;/a&gt; and have fun.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-6936470613895993299?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7L2CkPelFX1iX5IZfWYNlOPX9HU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7L2CkPelFX1iX5IZfWYNlOPX9HU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7L2CkPelFX1iX5IZfWYNlOPX9HU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7L2CkPelFX1iX5IZfWYNlOPX9HU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/3s7TxIQePDU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/6936470613895993299/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/netbeans-671-with-javafx.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/6936470613895993299?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/6936470613895993299?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/3s7TxIQePDU/netbeans-671-with-javafx.html" title="NetBeans 6.7.1 with JavaFX" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/netbeans-671-with-javafx.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMHQHg_eSp7ImA9WxNTFU0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-1467300138035692836</id><published>2009-08-17T02:06:00.004-07:00</published><updated>2009-08-17T02:13:51.641-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-17T02:13:51.641-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Reviews" /><title>JarSearch.com</title><content type="html">&lt;p&gt;&lt;a href="http://jarsearch.com/" mce_href="http://jarsearch.com"&gt;JarSearch.com&lt;/a&gt; is the tool of choice for software developers and software engineers searching for the jar file of a missing class. This is the first sentence which tells everything you need to know about that tool.&lt;/p&gt; &lt;p&gt;During time spent with Java programming there are a lot of cases when a class or more are missing from the path. The worst situation is when you don't even know where the class is defined. I mean which jar contains the class definition.&lt;/p&gt; &lt;p&gt;This site helps you with identifing that jars. It gives you all possible jars (most of the possible solutions, or course). It gives you also the jar version.&lt;/p&gt; &lt;p&gt;I found useful sometimes, so hope you will have too. Enjoy &lt;a href="http://jarsearch.com/" mce_href="http://jarsearch.com/"&gt;it&lt;/a&gt;!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-1467300138035692836?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Jquv1DK6wOrcoW9GsPhzh9zef3Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jquv1DK6wOrcoW9GsPhzh9zef3Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Jquv1DK6wOrcoW9GsPhzh9zef3Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Jquv1DK6wOrcoW9GsPhzh9zef3Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/T30oIK_WdGo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/1467300138035692836/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/jarsearchcom.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/1467300138035692836?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/1467300138035692836?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/T30oIK_WdGo/jarsearchcom.html" title="JarSearch.com" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/jarsearchcom.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMMR30-fip7ImA9WxNTFU0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-6823255576580700984</id><published>2009-08-17T02:06:00.003-07:00</published><updated>2009-08-17T02:14:46.356-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-17T02:14:46.356-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Reviews" /><title>Scannotation - java annotation scanner</title><content type="html">&lt;p&gt;Bill Burke a JBoss old timer, Red Hatter, and successful open source entrepreneur, as he calls himself &lt;a href="http://bill.burkecentral.com/" mce_href="http://bill.burkecentral.com/"&gt;here&lt;/a&gt; is one of the good people I read. He created in the past a very interesting and useful small tool. That tool is called Scannotation. You can find more on that from it's own place on web in the big house of sourceforge at this address &lt;a href="http://scannotation.sourceforge.net/" mce_href="http://scannotation.sourceforge.net/"&gt;http://scannotation.sourceforge.net/&lt;/a&gt;. The idea at least, if not the final code, which started Scannotation was the fact that Bill worked on JBoss EJB container and needed to know more about the annotated code.&lt;/p&gt; &lt;p&gt;There are two often seen scenarios on annotation usage. You can have classes or instances loaded by class loaders and you want to know which annotations provides these classes. That's the first scenario. The second one is when you want to know annotations used by classes before the class loader loads the definition of classes. Scannotation give you the second scenario.&lt;/p&gt; &lt;p&gt;You can have jars on classpath or even the bits of a class from a stream and you can use Scannotation to load annotations. You can also find annotations from a war type archive (Java EE web application module). The trick is that you don't need to load and spent a lot of processing time and memory to load classes just to know what annotations have. Scannotation parse the bits from the class definition and gives you annotations.&lt;/p&gt; &lt;p&gt;After you know what to parse you can parse and store annotation usages into a AnnotationDB object. That is not a real database. It contains only two maps. The first one gives you each class which have annotations and for each one the used ones. The second map gives you all annotations, and for each one the classes which uses them. You refine the class search by adding ignored packages. There are already some ignored packages by default, also. You can refine the search by setting to collect only some specific annotation place like annotations on classes, methods, parameters or fields.&lt;/p&gt; &lt;p&gt;The usage is really simple, and for that I will give you an excerpt from their own tests:&lt;/p&gt; &lt;pre&gt;          &lt;span&gt;URL&lt;/span&gt; url &lt;span&gt;=&lt;/span&gt; ClasspathUrlFinder&lt;span&gt;.&lt;/span&gt;&lt;span&gt;findClassBase&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;TestSmoke&lt;span&gt;.&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;/span&gt;      AnnotationDB db &lt;span&gt;=&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; &lt;span&gt;AnnotationDB&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;/span&gt;      db&lt;span&gt;.&lt;/span&gt;&lt;span&gt;scanArchives&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;url&lt;span&gt;);&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span&gt;   &lt;/span&gt;       &lt;span&gt;Map&lt;/span&gt;&lt;span&gt;&lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;Set&lt;/span&gt;&lt;span&gt;&lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&gt;&gt;&lt;/span&gt; annotationIndex &lt;span&gt;=&lt;/span&gt; db&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getAnnotationIndex&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;/span&gt;      &lt;span&gt;Set&lt;/span&gt;&lt;span&gt;&lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt; simpleClasses &lt;span&gt;=&lt;/span&gt; annotationIndex&lt;span&gt;.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;br /&gt;                       SimpleAnnotation&lt;span&gt;.&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getName&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;/span&gt;      Assert&lt;span&gt;.&lt;/span&gt;&lt;span&gt;assertTrue&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;simpleClasses&lt;span&gt;.&lt;/span&gt;&lt;span&gt;contains&lt;/span&gt;&lt;span&gt;(&lt;br /&gt;                       &lt;/span&gt;ClassWithFieldAnnotation&lt;span&gt;.&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getName&lt;/span&gt;&lt;span&gt;()));&lt;/span&gt;&lt;br /&gt;       &lt;span&gt; &lt;/span&gt;Assert&lt;span&gt;.&lt;/span&gt;&lt;span&gt;assertTrue&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;simpleClasses&lt;span&gt;.&lt;/span&gt;&lt;span&gt;contains&lt;/span&gt;&lt;span&gt;(&lt;br /&gt;                       &lt;/span&gt;InterfaceWithParameterAnnotations&lt;span&gt;.&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getName&lt;/span&gt;&lt;span&gt;()));&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;/span&gt;      &lt;span&gt;Set&lt;/span&gt;&lt;span&gt;&lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt; simpleAnnotations &lt;span&gt;=&lt;/span&gt; db&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getClassIndex&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;br /&gt;                       &lt;/span&gt;ClassWithFieldAnnotation&lt;span&gt;.&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getName&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;/span&gt;      Assert&lt;span&gt;.&lt;/span&gt;&lt;span&gt;assertTrue&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;simpleAnnotations&lt;span&gt;.&lt;/span&gt;&lt;span&gt;contains&lt;/span&gt;&lt;span&gt;(&lt;br /&gt;                       &lt;/span&gt;SimpleAnnotation&lt;span&gt;.&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getName&lt;/span&gt;&lt;span&gt;()));&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;/span&gt;      simpleAnnotations &lt;span&gt;=&lt;/span&gt; db&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getClassIndex&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;br /&gt;                       InterfaceWithParameterAnnotations&lt;span&gt;.&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getName&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;br /&gt;&lt;span&gt;    &lt;/span&gt;      Assert&lt;span&gt;.&lt;/span&gt;&lt;span&gt;assertTrue&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;simpleAnnotations&lt;span&gt;.&lt;/span&gt;&lt;span&gt;contains&lt;/span&gt;&lt;span&gt;(&lt;br /&gt;                       &lt;/span&gt;SimpleAnnotation&lt;span&gt;.&lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getName&lt;/span&gt;&lt;span&gt;()));&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt; &lt;p&gt;&lt;span&gt;As you can see you feed the AnnoationDB instances with URLs. These URLs can be obtained using Scannotation tools. After that you use the two provided indexes.&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;span&gt;Scannotation is small, fast and if you like, you can modify for you needs it it does not fit well. It's Open Source licensed with Apache License v2.0.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-6823255576580700984?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/siJsx0yjfbZd_26R-W62qli1dt0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/siJsx0yjfbZd_26R-W62qli1dt0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/siJsx0yjfbZd_26R-W62qli1dt0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/siJsx0yjfbZd_26R-W62qli1dt0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/0pOC7QyVoTk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/6823255576580700984/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/scannotation-java-annotation-scanner.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/6823255576580700984?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/6823255576580700984?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/0pOC7QyVoTk/scannotation-java-annotation-scanner.html" title="Scannotation - java annotation scanner" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/scannotation-java-annotation-scanner.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIEQXk7fip7ImA9WxNTFU0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-1553687181597124452</id><published>2009-08-17T02:06:00.001-07:00</published><updated>2009-08-17T02:15:00.706-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-17T02:15:00.706-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Thoughts for monday morning" /><title>Java EE is just Java</title><content type="html">&lt;p&gt;I write Java EE applications for about some years. During those years I learn some things and give some cents to others. But most productive things which were happen were the discussions on that topic. When you talk with somebody on a subject where both have some knowledge, you find usually nice points of view. Also I noticed that in the same the same time, the same problems are bypassed.&lt;/p&gt; &lt;p&gt;A lot of discussions on this subject happens having in mind that Java Enterprise applications are applications made from distributed components. That's true. Java Enterprise applications some standard services provided by EJB and web container. That is also true. Java Enterprise are build only from EJB layers ( entity beans - now JPA, session beans, message beans, etc) and presentation layers. That is not true. There is something missing here. Java Enterprise applications are still Java applications. What is the meaning of this note? The fact that Java Enterprise applications are still Java applications is an aspect which is often forgotten or simply not took into consideration. When you build a Java Enterprise application you don't loose the possibility to do the same things as you would do in a normal Java application.&lt;/p&gt; &lt;p&gt;When you debug a Java Enterprise application, as a matter of fact you debug a Java application. The debugging feature is something which happen on the virtual machine and class loader level (more on that on a future article). You debug in the same way a Java EE application as you would do with a desktop application, even local or remote, even through shared memory or TCP port.&lt;/p&gt; &lt;p&gt;You can have static or singletons or factories as would you have with normal Java application. I remember a discussion on a forum when somebody put the following problem. Every client is represented by a stateful session bean. How you would implement a communication between those clients? A saw a lot of responses, more that 15 on that topic. All of them stating more or less that you cannot avoid to use persistence layer to store information to be used by different clients. Nobody thought at a simple solution. A singleton which would hold information send by every client and requested by others (was a IM problem). Don't say that the singleton is the best solution. I state only that developing Java EE solutions sometime makes you think that the only things that you can do are EJB components. That's not true. You can however do everything you want.&lt;/p&gt; &lt;p&gt;The only differences between a Java application and a Java Enterprise are:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;The Java Enterprise application is loaded and started by a special piece of code called container (EJB/web), the normal Java application does not need to be started by something else, could have it's own main entry point&lt;/li&gt;&lt;li&gt;Java Enterprise applications are packaged in a specific way to achieve the third difference, while normal Java applications don't have this constraint&lt;/li&gt;&lt;li&gt;Java Enterprise applications can use services provided by EJB and web container, while normal Java applications can't (only if you you an embedded environment)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;An that's all. In every other aspect these applications are the same: Java applications.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-1553687181597124452?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dg-q7EFQHoEBgWbtEPm4HL7eN04/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dg-q7EFQHoEBgWbtEPm4HL7eN04/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dg-q7EFQHoEBgWbtEPm4HL7eN04/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dg-q7EFQHoEBgWbtEPm4HL7eN04/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/bsUug9iGwM8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/1553687181597124452/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/java-ee-is-just-java.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/1553687181597124452?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/1553687181597124452?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/bsUug9iGwM8/java-ee-is-just-java.html" title="Java EE is just Java" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/java-ee-is-just-java.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEEMQX06fSp7ImA9WxBTE0s.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-3781507107756881896</id><published>2009-08-17T02:00:00.000-07:00</published><updated>2009-12-09T04:44:40.315-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-12-09T04:44:40.315-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="News" /><category scheme="http://www.blogger.com/atom/ns#" term="NetBeans" /><title>NetBeans 6.7 was launched, what brings with him?</title><content type="html">&lt;a href="http://4.bp.blogspot.com/_jVuxYCl05pw/SokdYRx7KhI/AAAAAAAAB3M/warJqMJYJjw/s1600-h/nb67.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5370856333542894098" src="http://4.bp.blogspot.com/_jVuxYCl05pw/SokdYRx7KhI/AAAAAAAAB3M/warJqMJYJjw/s400/nb67.png" style="cursor: pointer; float: left; height: 193px; margin: 0pt 10px 10px 0pt; width: 400px;" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class="mceTemp"&gt;&lt;br /&gt;
&lt;dl class="wp-caption alignleft" id="attachment_63" style="width: 510px;"&gt;&lt;dt class="wp-caption-dt"&gt;&lt;br /&gt;
&lt;/dt&gt;
&lt;dd class="wp-caption-dd"&gt;NetBeans 6.7
&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;On June 2009 Netbeans released the final version of 6.7. You can find more about &lt;a href="http://www.netbeans.org/community/releases/67/" mce_href="http://www.netbeans.org/community/releases/67/"&gt;here&lt;/a&gt;, on their release page. You can download it &lt;a href="http://download.netbeans.org/netbeans/6.7/final/" mce_href="http://download.netbeans.org/netbeans/6.7/final/"&gt;here&lt;/a&gt;.&lt;br /&gt;
From the beginning I must say that I am a big fun of NetBeans. I used since it was named Forte for Java version 2. I appreciate also Eclipse, but don't start here a flame on why I consider Netbeans superior.&lt;br /&gt;
From the release page we can see major topics on the improvements of new features brought to us by this version. You can read yourself about them. Here is my only humble opinion on this release.&lt;b&gt; &lt;/b&gt;&lt;br /&gt;
&lt;b&gt;Overview.&lt;/b&gt; The first impression is that is faster than its predecessors. The difference is visible in usage. Also, they added a feature to enable/disable features with you don't work.&lt;br /&gt;
&lt;b&gt;Other languages than Java&lt;/b&gt;. Since I don't work too much with either of them I can't provide a full coverage. Still I am happy that I can have in the same IDE some tools for managing this kind of projects. That's cool. I tried PHP support, which I found quite good. Comparing with dedicated tools on that, it manages good. I found it fine for may needs. All that languages were supported before. Thought new valuable features were added for all of them. I would call here the sql editing and PHPUnit in php scripts, remote debugging for Ruby, code complettion on Groovy, profiling and QT libraries support for C/C++. Just to name few of them which are really consistent.&lt;br /&gt;
&lt;b&gt;GlassFish&lt;/b&gt;. Nice that v3 is supported now. You have code completion, there is also a nice plug-in called GlassFish v3 enabler, quite usefull. You have also v2 version support.&lt;br /&gt;
&lt;b&gt;Maven. &lt;/b&gt;That's really a very good thing. Maven support is much better now. You have a viewer for dependency graphs, you can configure a lot of your settings through UI. Also, you have  archetypes for Java EE projects. The most appealing thing on that is that you can easily use your NetBeans project in another IDE. Practically nothing need to be done to do that. That's impressive. For the ones who want to know more on Maven they should take a look &lt;a href="http://maven.apache.org/what-is-maven.html" mce_href="http://maven.apache.org/what-is-maven.html"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;b&gt;Kenai. &lt;/b&gt;The most appealing to me. Kenai is a community similar to sourceforge, I think. But the best thing is that is fully integrated with NetBeans. For start up project is increddible. You have almost everything you can wish: bug tracking, wiki, dedicated place for a site, IM chats, etc. Take a loot at &lt;a href="http://kenai.com/" mce_href="http://kenai.com/"&gt;kenai.com&lt;/a&gt;. It worths the effort.&lt;br /&gt;
&lt;b&gt;Conclusion. &lt;/b&gt;This release means "get into community" to my. Kenai is very apealing. In the same time they did not lost focus on continuous improvements. I believe everybody can found a new good reason to use NetBeans.&lt;br /&gt;
PS: for Eclipse developers now there's a button called "Synchronize editor with views" ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-3781507107756881896?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-aH_Wtp7nYv2iBXyao9jvF7Cyyw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-aH_Wtp7nYv2iBXyao9jvF7Cyyw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-aH_Wtp7nYv2iBXyao9jvF7Cyyw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-aH_Wtp7nYv2iBXyao9jvF7Cyyw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/r2sPMoEJFt4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/3781507107756881896/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/netbeans-67-was-launched-what-brings.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/3781507107756881896?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/3781507107756881896?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/r2sPMoEJFt4/netbeans-67-was-launched-what-brings.html" title="NetBeans 6.7 was launched, what brings with him?" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_jVuxYCl05pw/SokdYRx7KhI/AAAAAAAAB3M/warJqMJYJjw/s72-c/nb67.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/netbeans-67-was-launched-what-brings.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIGRXc6eyp7ImA9WxNTFU0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-8948464365200226278</id><published>2009-08-17T01:59:00.000-07:00</published><updated>2009-08-17T02:15:24.913-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-17T02:15:24.913-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Thoughts for monday morning" /><title>Interface vs Annotations</title><content type="html">&lt;p&gt;When I think about OOP languages, my 2 cents goes into choosing a good contract between the components of your code. I never liked "smart" solutions which tries to steal a little time from here, a little from there and so on. Don't say that there are no good solutions of that type. When you accommodate a generic solution to a specific problem, you might be find that your code is much better. But, to be in that position, you have to have first the best design possible. That gives good solutions in every day practice. And a good OOP design implies healthy contracts between components.&lt;/p&gt; &lt;p&gt;Interfaces apart from classes can define a contract without implementation. &lt;i&gt;&lt;b&gt;Interfaces exists only as pure contracts.&lt;/b&gt; &lt;/i&gt;And interfaces are firm contracts. If a class implements an interface you can be sure that it will respond to you on the contract terms. Of course, nobody saves you from a bad implementation behind, we should live with that possibility.&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;Interfaces solves somehow the multiple inheritance problem. Can't agree on that&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;When we think a contract we have in mind classes which consume services stated by interface and other classes, behind interface, who provide the service. In this way &lt;i&gt;&lt;b&gt;interface acts as an indirection between two classes&lt;/b&gt;&lt;/i&gt;. You can change always the consumer or the provider of that service, things will go on. There was said that interfaces solves somehow the multiple inheritance problem. Can't agree on that. Interfaces does not provides behavior. The classes which implements multiple interfaces provides the behavior. Still, the implementation classes can't be considered as multiroot inherited. The main difference is that the class which implements multiple interfaces doesn't inherit behavior. And that is the main purpose of multiple inheritance.&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;Multiple inheritance is a bit clumsy and error prone&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I always considered multiple inheritance as a bit clumsy and error prone. When a class inherits two behaviors we live on the edge. If the behaviors are small than there is a possibility to handle things in a logical way. If the behaviors are rich in features, that we are already doomed. That is the worst form of dependency. But even if we are in the best situation possible that an be on short term only. In time things can roll on in a bad way. Considering that the maintenance of the code is the biggest stage of a software component, there will be usually a lot of occasions or opportunities to "improve" and "enrich" the behavior of a component. If a class inherits multiple behavior, these kind of improvements is a curse.&lt;/p&gt; &lt;p&gt;Thanks to James Gosling and others that they don't allowed that in Java. But there are problems which still need to be solved.&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;Interfaces define how a component should look to be albe to be used by others&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Interfaces can define the form of a class. That's why they are called interfaces, right? The interface defines how a component should look to be albe to be used by others. We can have marker interfaces or interfaces with content. Our clases can be less or more polluted by methods implemented from many interfaces. For that we allways have the addapter solution. When we have a class which needs to address many targets we always can split the class in many pieces. The main piece will retain the original goal of the class. The other classes will adapt the main class to othe target, of course, by providing appropriate interface implementations. That address well the mltiple inheritance gap. But can be better, and here comes annotations.&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;Annotations don't enforce types, don't enforce method signatures or exceptions, like interface does&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Annotations are like interfaces, but there are suble differences.Interfaces defines a contract on a whole class. Annotations defines contracts for a class, method, field and others. Like interfaces annotations does not provide behavior. Still, the interfaces defines the form of a possible behavior in a complete way. Annotations don't imply these kind of restrictions. The consumer of annotations will have to handle evenrithing in a more generic manner. Annotations don't enforce types, don't enforce method signatures or exceptions, like interface does. That's way provider classes should alter their code to include the contract of it's implemented interfaces. Annotations don't pollute business code. Don't pollute contract of a class. They just decorate the class.&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;Annotations can be considered more like a part of the consumer which relies on the provider&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Let's take the simplest case for the moment. The marker interfaces. A marker interface is an interface which don't have a body. The are used only to "mark" a component. Just to know at runtime that a class "is a" kind of something. You can't use a marker interface to call methods. A classic example of marker interface is java.io.Serializable. When a class implements Serializable, we know that this class is allowed to be persisted. The interface is only a semantic to serialization. The same effect could be achieved using an annotation on class level. We know that on serialization problem, because of the fact that annotations were not invented at that time. Considering that, the interface solution is a normal solution. Still, if we had to design serialization now, when we have all, what should we choose? I would still choose interface. Both annotations and interfaces are ment to adapt a class to a specific usage. Thought, the interfaces are more a part of a class, more dependent to a class than annotations. Annotations can be considered more like a part of the consumer which relies on the provider. That's why they are more dependent of consumer class than interfaces. If on marker interface teh case is not very clear, we go further.&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;The only discriminator to choose interface or annotations is the degree of business cognation or similarity&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;When we want that a consumer class to use another one we usually need that the provider class to tell somethings about that. We can do that using an interface to be implemented by provider class or by using annotations. When we provide information to the consumer we have to fight against code pollution. Even if the provided information is in small or big quantity the problem is still there. &lt;i&gt;&lt;b&gt;The only discriminator to choose interface or annotations is the degree of business cognation or similarity&lt;/b&gt;&lt;/i&gt;. If we want our class to provide a functionality closer to its bussiness purpose, the most appropriate is interface. If we want our class to be used in a completely different way, apart from it's original scope we should use annotations. Finally, if both ways conduct to a lot of work to adapt, we are probably on a wrong way. We should give a call to adapter or it's cousins to help us because in most of the cases our problem can't be handled by our class. We take a look on two examples for clarifying purpose.&lt;/p&gt; &lt;p&gt;We have a BusinessProcess class which handles information about a process of our business. This class is a java bean, so all properties have setters and getters. Nice simple class. This class provides some methods to run a process, to stop it while is runnings and to collect output data as results.&lt;/p&gt; &lt;p&gt;We have to implement a GUI interface which shows us a log with running events, when tasks have started or stopped. A simple GUI list and that's all. We decide that the model behind the GUI to be a class which handle running business execution events. Because announcing when a process has started or stopped fits very well with our class, we can define an interface for Observer pattern. That interface can have as a sample onStart and onStop methods, with process name as a parameter. So our GUI model will implement our ProcessNotifierListener interface. Our BusinessProcess class will have methods to add or remove listeners of that type, and will call them when any event appeared.&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;Our classes should not be aware of the problems which don't relates to it's business&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Second task is to provide a way to specify the level of logging information for each type of process. The purpose is to show full logs for processes related to security transactions. The other type of processes will have only regular logs saved. We can do that by enforcing and interface with a method. But more appropriate is to use a custom annotation with a property defined. Like @LogLevel(LogLevel.FULL). At runtime we can read the annotation and action appropriate. Why is better to use annotations in this case? Because the logging activity is not even a secondary business purpose of our class. Our classes should not be aware of the problems which don't relates to it's business.&lt;/p&gt; &lt;p&gt;The discussion is never ending. For sure there are not rule appliable everywhere. And you always should reevaluate the case on using interface or annotations. That's whay good programmers are valuable. Thought, at least some of the questions, if not answers, will raise in your mind after reading that. Happy choosing!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-8948464365200226278?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/gnhr0iB2dmQZTHbBqBkJYLEu1po/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gnhr0iB2dmQZTHbBqBkJYLEu1po/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/gnhr0iB2dmQZTHbBqBkJYLEu1po/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/gnhr0iB2dmQZTHbBqBkJYLEu1po/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/6Wid3C4W_6Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/8948464365200226278/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/interface-vs-annotations.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/8948464365200226278?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/8948464365200226278?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/6Wid3C4W_6Y/interface-vs-annotations.html" title="Interface vs Annotations" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/interface-vs-annotations.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIMR306cSp7ImA9WxNTFU0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-6858533532492060981</id><published>2009-08-17T01:58:00.001-07:00</published><updated>2009-08-17T02:16:26.319-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-17T02:16:26.319-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Reviews" /><title>How to debug Java EE on JBossAS</title><content type="html">&lt;p&gt;A week ago I noticed a problem with a strange behavior of an EJB component.&lt;/p&gt; &lt;p&gt;Source code inspecting was not enough to understand what was happening. So I had to debug the component. In that moment I remembered what I felt the first time when I had to do a debug on such kind of application. I supposed that should be a complicated process behind, that I was needed some sophisticated tool for that. In reality the task is very easy to accomplish. Even the title of this article is misleading. You will understand why.&lt;/p&gt; &lt;p&gt;Java virtual machine gives us the everything to do a remote debug on any kind of Java application. Simply, as long as we have the source code, we can debug anything on the local computer or on the network. JBossAS is a Java application itself, like any other. Ok, not like any other, but from this point of view there is not difference.&lt;/p&gt; &lt;p&gt;Taking thisn into consideration, all we have to do is to configure the virtual machine on which the JBossAS is running. We have to enable a TCP connection for remote debugging, to enable the required port in firewall and to connect our IDE to that port. We need to have an IDE which is able to do a remote debugging, but virtually all the IDEs on the market implement that feature.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Configuring JBossAS&lt;/b&gt;&lt;/p&gt; &lt;p&gt;JBossAS make things simpler, from this point of view. If you use Linux, you should modify run.conf, if on Windows, you should modify directly run.bat (don't have any clue why on Windows they don't use run.conf). Here are the lines which should be modified.&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;# Sample JPDA settings for remote socket debuging&lt;br /&gt;#JAVA_OPTS="$JAVA_OPTS -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;If have only to remove the comment sign on the second line. We can change the port as we wish (TCP is used). Default value for that is 8787. The suspend deserves a closer look. If we change the value to y, that, the debugged process will wait for the client to make a remote connection and after that will continue to run. This is very useful if we have to debug something in the initializing code of the target application. Now is not useful.&lt;/p&gt; &lt;p&gt;I repeat, this kind of debugging can be enabled on any Java process. In that case this options are give in the command line to the java runtime.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Network configuration &lt;/b&gt;&lt;/p&gt; &lt;p&gt;If the target process is executed on another computer we should be able to connect on that machine. In order to be able to do this the specified port should not be blocked by firewall, if we have something like this enable. If the target system is not in our network or we don't have direct acces on that, than we have to create a path to that port. We do that using routing and port forwarding. Eventually from computer to computer until we found one which we can connect to.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Starting a remote debug session from Eclipse&lt;/b&gt;&lt;/p&gt; &lt;p&gt;In Ecplise we use menu item Run -&gt; Debug Configurations .. It will open a dialog box with execution configuration. We create a configuration for Remote Java Application. There we specify the project which contains the sources we want to debug, the host name or ip of the target system and the port, also.&lt;/p&gt; &lt;p&gt;Eventually we configure the breakpoints we want and .. happy debugging!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-6858533532492060981?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bFmAf-wopXprZ8h0BikFODrM1uE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bFmAf-wopXprZ8h0BikFODrM1uE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bFmAf-wopXprZ8h0BikFODrM1uE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bFmAf-wopXprZ8h0BikFODrM1uE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/BZAZ7iUI9Jo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/6858533532492060981/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/how-to-debug-java-ee-on-jbossas.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/6858533532492060981?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/6858533532492060981?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/BZAZ7iUI9Jo/how-to-debug-java-ee-on-jbossas.html" title="How to debug Java EE on JBossAS" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/how-to-debug-java-ee-on-jbossas.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEESHwyeCp7ImA9WxNTFU0.&quot;"><id>tag:blogger.com,1999:blog-1794241333858687434.post-7474080735704736823</id><published>2009-08-17T01:57:00.002-07:00</published><updated>2009-08-17T02:16:49.290-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-17T02:16:49.290-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Reviews" /><title>Two ways to start with Seam Framework</title><content type="html">&lt;p&gt;Seam is an Open Source framework for building Web Java EE.&lt;/p&gt; &lt;p&gt;Main functionalities includes:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;building managed beans on the fly for web modules&lt;/li&gt;&lt;li&gt;building EJB components in contexts richer that the three standard contexts for web apps (application, session and request)&lt;/li&gt;&lt;li&gt;useful JSF elements&lt;/li&gt;&lt;li&gt;many many other functionalities, but I wil not still from you the pleasure to discover these reading the official reference guide, which worths every minute spent&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;When we want to create a project structure for a Seam Java EE application we have two options: generate application using seam-gen or create that using JBossTools, an Eclipse plugin published by JBoss. I will not introduce you to the details of these processes, but I will insist on the consequences and what you can expect.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Create application with JBossTools&lt;/b&gt;&lt;/p&gt; &lt;p&gt;JBossTools is an Eclipse plug-in dedicated to manage this kind of application. More precisely, it offers a wizard which can be used to generate Seam Web applications. In the dialog boxes of this wizard you should specify all the start up information, including project names and modules, package names and persistence configuration. Using dialog boxes the process of creating the application becomes almost trivial.&lt;/p&gt; &lt;p&gt;JBossTools also offers a lot of functionalities which can be used after the project generation. It contains complex editors for web pages and for specific configuration files. In the same time, using additional wizards, we can add new components to the application. Yopu can generate entities from relational databases, creating web pages for generated entities, add new EJB or client modules and many others.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Generate application using seam-gen&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Seam Framework contains in its distribution a tool to generate Seam Java EE projects. Unlike JBossTools, this is a command line tool. It is based on Ant, so is executed in a similar way like a regular Ant taks. In order to generate the application, seam-gen needs also some information. They are the almost the same as in the case of JBossTools.&lt;/p&gt; &lt;p&gt;After you configure and execute seam-gen tool, the result will be produced in the form of a folder in which you will find everything required to build a Seam Web application. seam-gen will generate projects for Eclipse and NetBeans.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Strong/weak points&lt;br /&gt;&lt;/b&gt;&lt;/p&gt; &lt;p&gt;The two folder structures are not identical at all. JBossTools uses a project for every module of the Java EE application. seam-gen, on the contrary, uses a single project, containing a folder structure having everything you need to build and deploy all the application mdoules. JBossTools has an advantage on that, having a separate structure for every module helps to have an image about the project more closer to the final product.&lt;/p&gt; &lt;p&gt;JBossTool allows fast project configurations, using dialog boxes to set up every property of the projects. On the other hand, seam-gen uses for building and deploying an Ant build script. Using the Ant script is, of course, more harder to manage than a dialog box. Still, the build script is more flexible, practically we can take and implement any decision we like. For begginers the Ant script can seem intimidant, first choise would be JBossTools way. For the advanced ones, the complete control and flexibility makes the seam-gen variant be the first choice. If we count also the possibility of finding bugs in JBossTools (experience confirmed me that), the configuration can become a real nightmare.&lt;/p&gt; &lt;p&gt;The possibility to add with ease new modules brings again JBossTools in front. Modules having separate projects and the UI manipulation of settings is a real advantage. Although, the more experienced programmers know that the structure of a Java EE aplication module is very clear and easy to build. That's why the building of these modules using Ant script is realy easy after you understand basics.&lt;/p&gt; &lt;p&gt;JBossTools is integrated in Eclipse. It uses a lot from Web Tools Platform, a functionality set for Java EE. The advanced editors are often very useful. I name here the JBossTools editor for facelets web pages, which have an autocomplet feature for Seam EL and page preview. If you want another IDE or deploy to another kind of server, other than JBoss (Glassfish), than seam-gen is your choice. You have a generated project ready for NetBeans, but, because we have a project based on An, practically you can use the project with any other IDE. In the same time, using seam-gen you can choose to use various techonlogies for generating web pages (Apache Wicket, just to name one).&lt;/p&gt; &lt;p&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/p&gt; &lt;p&gt;For the beginners in working with Seam Web Java EE, probably JBossTools fits well. The more advanced users will apreciate the flexibility and portability of the structure generated by seam-gen, and also the control offered by Ant build script. Even for beginners, learning Ant (not complicated at all) will give good thing on long term. We should not forget the advanced features offered by JBossTools.&lt;/p&gt; &lt;p&gt;My proposal is a simple one. Use the best things from both. Use seam-gen for generating the project structure. In time you can manipulate Ant build scriptwithout difficulties. In the same time, use Eclipse and JBossTools for editing web resources, is priceles very often.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1794241333858687434-7474080735704736823?l=javasign.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2Sf0bPg27ZO_q8y61wPHtfGKcnc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2Sf0bPg27ZO_q8y61wPHtfGKcnc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2Sf0bPg27ZO_q8y61wPHtfGKcnc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2Sf0bPg27ZO_q8y61wPHtfGKcnc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Javasign/~4/wMmszCESdN0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://javasign.blogspot.com/feeds/7474080735704736823/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://javasign.blogspot.com/2009/08/two-ways-to-start-with-seam-framework.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/7474080735704736823?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1794241333858687434/posts/default/7474080735704736823?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Javasign/~3/wMmszCESdN0/two-ways-to-start-with-seam-framework.html" title="Two ways to start with Seam Framework" /><author><name>padreati</name><uri>http://www.blogger.com/profile/18131484115197304887</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://javasign.blogspot.com/2009/08/two-ways-to-start-with-seam-framework.html</feedburner:origLink></entry></feed>

