<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1781855377895663590</id><updated>2011-08-15T09:31:24.875-07:00</updated><category term='programming singleton'/><title type='text'>Anton Tagunov</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://atagunov.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://atagunov.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Anton Tagunov</name><uri>http://www.blogger.com/profile/04903035827978774750</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>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1781855377895663590.post-6796729254588210551</id><published>2011-05-18T06:25:00.000-07:00</published><updated>2011-05-18T10:56:48.178-07:00</updated><title type='text'>I want spring's &lt;util:property-path path="..."/&gt; to become simply path="..."</title><content type='html'>Hi,&lt;br /&gt;&lt;br /&gt;I have recently discovered a great feature in Spring:&lt;br /&gt;&lt;pre&gt;    &amp;lt;property name="propertyToSet"&amp;gt;&lt;br /&gt;        &amp;lt;util:property-path path="aBean.aProperty"/&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;/pre&gt;This is much nicer in my opinion than&lt;br /&gt;&lt;pre&gt;    &amp;lt;property name="propertyToSet"&amp;gt;&lt;br /&gt;        &amp;lt;bean factory-bean="aBean" factory-method="getAProperty"/&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;/pre&gt;It is also more powerful because you can do things like&lt;br /&gt;&lt;pre&gt;    &amp;lt;property name="propertyToSet"&amp;gt;&lt;br /&gt;        &amp;lt;util:property-path path="aBean.aProperty.aNestedProperty"/&amp;gt;&lt;br /&gt;    &amp;lt;/property&amp;gt;&lt;/pre&gt;which otherwise would have been awkward.&lt;br /&gt;&lt;br /&gt;However I do want an improvement. I want a yet more concise syntax for this. Spring can already do this:&lt;br /&gt;&lt;pre&gt;    &amp;lt;property name="aPropertyToSet" value="true"/&amp;gt;&lt;br /&gt;    &amp;lt;property name="aPropertyToSet" ref="anotherBean"/&amp;gt;&lt;/pre&gt;So it would only be logical (and very-very nice!) if it could also do this:&lt;br /&gt;&lt;pre&gt;    &amp;lt;property name="propertyToSet" path="aBean.aProperty"/&amp;gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1781855377895663590-6796729254588210551?l=atagunov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://atagunov.blogspot.com/feeds/6796729254588210551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1781855377895663590&amp;postID=6796729254588210551' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/6796729254588210551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/6796729254588210551'/><link rel='alternate' type='text/html' href='http://atagunov.blogspot.com/2011/05/i-want-spring-path-to-become-simply.html' title='I want spring&apos;s &amp;lt;util:property-path path=&quot;...&quot;/&amp;gt; to become simply path=&quot;...&quot;'/><author><name>Anton Tagunov</name><uri>http://www.blogger.com/profile/04903035827978774750</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></entry><entry><id>tag:blogger.com,1999:blog-1781855377895663590.post-6545324576193628481</id><published>2010-11-17T14:47:00.001-08:00</published><updated>2010-11-17T15:19:28.874-08:00</updated><title type='text'>Political Action Needed For Net Neutrality In The UK</title><content type='html'>Government wants to &lt;a href="http://www.bbc.co.uk/news/uk-politics-11773574"&gt;abolish net neutrality&lt;/a&gt; in the UK. Not a piece of good news. I really like the way &lt;a href="http://www.sivacracy.net/archives/003114.html"&gt;Siva&lt;/a&gt; has &lt;a href="http://wiki.openrightsgroup.org/wiki/Net_Neutrality"&gt;said&lt;/a&gt; it:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;There are a couple of different ways to look at this. The romantic way is that we want to have the Internet as the wild frontier for entrepreneurship, and that's a strong case. There's also the liberal free speech argument, which says we want the Internet to be a level playing field so a variety of voices can enter the public sphere. That's a fairly strong argument. But then you've got the economic argument, which is those of us who write checks every month to these companies, we want to be able to know that we are getting decent service for what we're paying. If my broadband company next week starts dialing down my Skype speed so Skype doesn't work as well for me, I might not even know it or notice it for a long time, until Skype starts frustrating me, and out of frustration, I'm just going to pick up my old phone and dial India the old-fashioned way and just pay for it because I know the call's going to go through. That's the sort of frustration and opacity we might start seeing on the Internet. So it is a service question, a competition question, an economic development question, a consumer question.&lt;/blockquote&gt;&lt;br /&gt;I expect to see a political campaign started against this motion, similar to &lt;a href="http://www.no2id.net/"&gt;NO2ID&lt;/a&gt;. This I will wholeheartedly support.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1781855377895663590-6545324576193628481?l=atagunov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://atagunov.blogspot.com/feeds/6545324576193628481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1781855377895663590&amp;postID=6545324576193628481' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/6545324576193628481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/6545324576193628481'/><link rel='alternate' type='text/html' href='http://atagunov.blogspot.com/2010/11/political-action-needed-for-net.html' title='Political Action Needed For Net Neutrality In The UK'/><author><name>Anton Tagunov</name><uri>http://www.blogger.com/profile/04903035827978774750</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></entry><entry><id>tag:blogger.com,1999:blog-1781855377895663590.post-3293352471083731485</id><published>2010-08-07T14:56:00.000-07:00</published><updated>2010-08-07T17:29:09.431-07:00</updated><title type='text'>Hamcrest 1.1, AllOf, DSL, SuppressWarnings And Maven Central</title><content type='html'>Hi,&lt;br /&gt;&lt;br /&gt;I've never used &lt;a href="http://code.google.com/p/hamcrest/"&gt;Hamcrest&lt;/a&gt; before; today is my first day with it. And I have already had a lot of "fun" which I would like to share.&lt;br /&gt;&lt;br /&gt;My experiences today have been centred around the &lt;a href="http://code.google.com/p/hamcrest/source/browse/trunk/hamcrest-java/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java"&gt;AllOf&lt;/a&gt; matcher. Or rather around &lt;a href="http://code.google.com/p/hamcrest/source/browse/tags/hamcrest-java-1.1/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java"&gt;this version&lt;/a&gt; shipped with Hamcrest 1.1. This is the newest version you can find on &lt;a href="http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/"&gt;Maven central&lt;/a&gt;. It also seems to be built into the newest JUnit jar version 4.8.1.&lt;br /&gt;&lt;br /&gt;Imagine that in your test you've got variable &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;a&lt;/span&gt; of type &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;A&lt;/span&gt; and you want to check it against three matchers &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;m1&lt;/span&gt;, &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;m2&lt;/span&gt; and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;m3&lt;/span&gt; of type &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Matcher&amp;lt;A&amp;gt;&lt;/span&gt;. It was quite natural for me to write it like this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;import static org.hamcrest.core.AllOf.allOf;&lt;br /&gt;import static org.junit.Assert.assertThat;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;@Test&lt;br /&gt;public void testA() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(a, allOf(m1, m2, m3)); // here you get a warning&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;That works and looks nice. But you get a compiler warning: &lt;tt&gt;Type safety : A generic array of Matcher is created for a varargs parameter&lt;/tt&gt;. I have found this &lt;a href="http://james-iry.blogspot.com/2010/05/anatomy-of-annoyance.html"&gt;blog post&lt;/a&gt; to be very helpful in explaining the nature of this warning. The quickest solution is to write:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@Test&lt;br /&gt;@SuppressWarnings("unchecked")&lt;br /&gt;public void testA() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(a, allOf(m1, m2, m3));&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;However it would be nice if we could preserve full type checking in the test code. It took me a while to find an alternative solution:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@Test&lt;br /&gt;public void testA() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;List&amp;lt;Matcher&amp;lt;? extends A&amp;gt;&amp;gt; matchers&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;nbsp;= new LinkedList&amp;lt;Matcher&amp;lt;? extends A&amp;gt;&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;matchers.add(m1);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;matchers.add(m2);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;matchers.add(m3);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(a, allOf(matchers));&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;This is fully type checked. Unfortunately it is a bit more long-winded and we looses the DSL feeling. On a side note this code can not be shortened to just:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@Test&lt;br /&gt;public void testA() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// doesn't compile&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;List&amp;lt;Matcher&amp;lt;? extends A&amp;gt;&amp;gt; matchers = Arrays.asList(m1, m2, m3);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(a, allOf(matchers));&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;This sample deceptively looks as legit as the one above it. However it fails to compile because of a &lt;tt&gt;Type mismatch: cannot convert from List&amp;lt;Matcher&amp;lt;A&amp;gt;&amp;gt; to List&amp;lt;Matcher&amp;lt;? extends A&amp;gt;&amp;gt;&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;I've had to discovere all this the hard way because in Hamcrest 1.1 &lt;tt&gt;AllOf.allOf&lt;/tt&gt; is defined as:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public static &lt;t&gt; Matcher&lt;t&gt; allOf(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Matcher&amp;lt;? extends T&amp;gt;... matchers) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return allOf(Arrays.asList(matchers));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static &lt;t&gt; Matcher&lt;t&gt; allOf(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Iterable&amp;lt;Matcher&amp;lt;? extends T&amp;gt;&amp;gt; matchers) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return new AllOf&lt;t&gt;(matchers);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;My day would have been saved if I had switched to Hamcrest 1.2. Nat Pryce has fixed the issue in &lt;a href="http://code.google.com/p/hamcrest/source/diff?r=258&amp;amp;format=side&amp;amp;path=/trunk/hamcrest-java/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java"&gt;revision 258&lt;/a&gt;. We get explicit overloads of &lt;tt&gt;allOf&lt;/tt&gt; method for up to 6 matchers in one go. This makes my very first code sample compile and run without any warnings.&lt;br /&gt;&lt;br /&gt;It is also interesting to note that shortly before this commit another issue had been corrected in Hamcrest codebase: &lt;a href="http://code.google.com/p/hamcrest/source/diff?r=194&amp;amp;format=side&amp;amp;path=/trunk/hamcrest-java/hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java"&gt;revision 194&lt;/a&gt;. &lt;tt&gt;Matcher&amp;lt;? extends A&amp;gt;&lt;/tt&gt; has been replaced with &lt;tt&gt;Matcher&amp;lt;? super A&amp;gt;&lt;/tt&gt;. This is most reasonable: indeed we can apply a &lt;tt&gt;Matcher&amp;lt;Object&amp;gt;&lt;/tt&gt; to test a &lt;tt&gt;String&lt;/tt&gt;. On the other hand it is not very useful to apply a &lt;tt&gt;Matcher&amp;lt;SomeClassExtendingA&amp;gt;&lt;/tt&gt; when our object is known to be of class &lt;tt&gt;A&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;1.2 release of Hamcrest contains both fixes. Unfortunately it is only available on the &lt;a href="http://code.google.com/p/hamcrest/downloads/list"&gt;project website&lt;/a&gt; but not on &lt;a href="http://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/"&gt;Maven central&lt;/a&gt;. Having spent quite a bit of time on the investigation what do I do now? I see three options:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;use the long-winded version of code&lt;/li&gt;&lt;li&gt;wait for Hamcrest 1.2 to be uploaded to Maven central&lt;/li&gt;&lt;li&gt;copy-paste &lt;tt&gt;AllOf&lt;/tt&gt; into my own code base and backport these two fixes&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;I have chosen the last option. This is my temporary fix. It makes my test code look nice right now and I can easily take out my hack later when a newer Hamcrest appears on Maven central.&lt;br /&gt;&lt;br /&gt;Speaking of which: to use an updated version of Hamcrest I will need a version of JUnit which doesn't package hamcrest classes inside its own jar. Such a version exists, it is called &lt;tt&gt;junit-dep&lt;/tt&gt;. Unfortunately the latest version Maven central &lt;a href="http://repo1.maven.org/maven2/junit/junit-dep/"&gt;currently has&lt;/a&gt; is only 4.5. Does anybody know of any way to cause a newer version of &lt;tt&gt;junit-dep&lt;/tt&gt; to be uploaded? As far as I can tell there is just one person behind JUnit, Kent Beck. Is this right? Is there any chance to accomplish this with or without his help?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1781855377895663590-3293352471083731485?l=atagunov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://atagunov.blogspot.com/feeds/3293352471083731485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1781855377895663590&amp;postID=3293352471083731485' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/3293352471083731485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/3293352471083731485'/><link rel='alternate' type='text/html' href='http://atagunov.blogspot.com/2010/08/hamcrest-11-allof-dsl-suppresswarnings.html' title='Hamcrest 1.1, AllOf, DSL, SuppressWarnings And Maven Central'/><author><name>Anton Tagunov</name><uri>http://www.blogger.com/profile/04903035827978774750</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>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1781855377895663590.post-7970569482566743895</id><published>2009-08-02T07:27:00.000-07:00</published><updated>2009-08-02T08:26:30.750-07:00</updated><title type='text'>shoal/jxta - any good?</title><content type='html'>Hi,&lt;br /&gt;&lt;br /&gt;looking for re-usable code to drive a clustered java application.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://shoal.dev.java.net/"&gt;Shoal&lt;/a&gt; promises&lt;ul&gt;&lt;li&gt;peers discovery&lt;/li&gt;&lt;br /&gt;&lt;li&gt;group membership&lt;/li&gt;&lt;br /&gt;&lt;li&gt;group messaging&lt;/li&gt;&lt;br /&gt;&lt;li&gt;small replicated cache&lt;/li&gt;&lt;/ul&gt;About what I need. Used by &lt;a href="https://glassfish.dev.java.net/"&gt;Glassfish&lt;/a&gt; and seems to have &lt;a href="http://wikis.sun.com/display/shoal/Known+Shoal+Clustering+User+Companies+or+Projects"&gt;other uses too&lt;/a&gt;. There is recent activity on the project. GPL not ASL but I it's an in-house project only.&lt;br /&gt;&lt;br /&gt;Deal? Invest more effort? Hold on! Here's their &lt;a href="https://shoal.dev.java.net/issues/buglist.cgi?Submit+query=Submit+query&amp;amp;component=shoal&amp;amp;issue_status=UNCONFIRMED&amp;amp;issue_status=NEW&amp;amp;issue_status=STARTED&amp;amp;issue_status=REOPENED&amp;amp;version=current&amp;amp;email1=&amp;amp;emailtype1=exact&amp;amp;emailassigned_to1=1&amp;amp;email2=&amp;amp;emailtype2=exact&amp;amp;emailreporter2=1&amp;amp;issueidtype=include&amp;amp;issue_id=&amp;amp;changedin=&amp;amp;votes=&amp;amp;chfieldfrom=&amp;amp;chfieldto=Now&amp;amp;chfieldvalue=&amp;amp;short_desc=&amp;amp;short_desc_type=fulltext&amp;amp;long_desc=&amp;amp;long_desc_type=fulltext&amp;amp;issue_file_loc=&amp;amp;issue_file_loc_type=fulltext&amp;amp;status_whiteboard=&amp;amp;status_whiteboard_type=fulltext&amp;amp;field0-0-0=noop&amp;amp;type0-0-0=noop&amp;amp;value0-0-0=&amp;amp;cmdtype=doit&amp;amp;order=Issue+Number" style="text-decoration: none;"&gt;list of open bugs&lt;/a&gt;&lt;ul&gt;&lt;li&gt;(&lt;a href="https://shoal.dev.java.net/issues/show_bug.cgi?id=36"&gt;36&lt;/a&gt;) Messages received not in same order as when sent&lt;/li&gt;&lt;br /&gt;&lt;li&gt;(&lt;a href="https://shoal.dev.java.net/issues/show_bug.cgi?id=61"&gt;61&lt;/a&gt;) When members join the group concurrently, join notifications of some members are often duplicated or missed&lt;/li&gt;&lt;br /&gt;&lt;li&gt;(&lt;a href="https://shoal.dev.java.net/issues/show_bug.cgi?id=74"&gt;74&lt;/a&gt;) potential to miss FAILURE_NOTIFICATION when multiple instances killed at same time&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;(&lt;a href="https://shoal.dev.java.net/issues/show_bug.cgi?id=83"&gt;83&lt;/a&gt;) When group leader failed, any member couldn't receive FailureRecovery notification&lt;/li&gt;&lt;/ul&gt;Now, the've got versions 1.0 and 1.1.&lt;div&gt;1.1 &lt;a href="https://shoal.dev.java.net/downloadsindex.html"&gt;is said to be&lt;/a&gt; a "work in progress".&lt;/div&gt;&lt;div&gt;So is 1.0 okay? I don't know&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another oddity: a CVS commit message seems to imply (&lt;a href="https://shoal.dev.java.net/issues/show_bug.cgi?id=83"&gt;83&lt;/a&gt;) has been fixed.&lt;/div&gt;&lt;div&gt;But it's still open in the issue tracker&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="https://jxta.dev.java.net/"&gt;Jxta&lt;/a&gt; - the foundation of Shoal - is another unknown.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When I troubleshoot late at night I prefer to have an intimate knowledge of my whole stack.&lt;/div&gt;&lt;div&gt;Jxta is another big (?) thing to learn. Thankfully sources are available but still..&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Does it look easier just to write my clustering code from scratch?&lt;/div&gt;&lt;div&gt;Implement proper &lt;a href="http://research.microsoft.com/en-us/um/people/lamport/pubs/pubs.html#paxos-simple"&gt;Paxos&lt;/a&gt;?&lt;/div&gt;&lt;div&gt;Be less dependent on other people's bugs?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;P.S. I've had a look at &lt;a href="http://cwiki.apache.org/GMOxDEV/geronimo-clustering-with-gcache.html"&gt;Geronimo clustering&lt;/a&gt; as well. They allow Cache servers to be in separate jvm-s. Hmm.. Somehow my intuition doesn't immediately suggest integrating that code is an easy route either..&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;P.P.S. &lt;a href="http://hadoop.apache.org/zookeeper/"&gt;Zookeeper&lt;/a&gt; was another obvious candidate. What stops me here is that Zookeper seems to have a very hard dependency on disk. Every change is persisted. Node recovery is done by reading the transaction log. It's a mismatch for my goals. I need something blazingly fast living completely in RAM&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1781855377895663590-7970569482566743895?l=atagunov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://atagunov.blogspot.com/feeds/7970569482566743895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1781855377895663590&amp;postID=7970569482566743895' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/7970569482566743895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/7970569482566743895'/><link rel='alternate' type='text/html' href='http://atagunov.blogspot.com/2009/08/shoaljxta-any-good.html' title='shoal/jxta - any good?'/><author><name>Anton Tagunov</name><uri>http://www.blogger.com/profile/04903035827978774750</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></entry><entry><id>tag:blogger.com,1999:blog-1781855377895663590.post-7591561620529117520</id><published>2008-12-12T03:51:00.000-08:00</published><updated>2008-12-12T04:01:49.617-08:00</updated><title type='text'>eclipse -clean</title><content type='html'>Hi! I've got an irresistable urge to share this.&lt;br /&gt;&lt;br /&gt;eclipse -clean&lt;br /&gt;&lt;br /&gt;cleans eclipse caches and can make a very stubborn build error go away.&lt;br /&gt;&lt;br /&gt;I've had a "resource already exists on disk" in a m2eclipse driven project. Deleting the file manaully/refresh/clean/close-open-project did not help. workspace/.metadata/.log contained a lot of ClassCastException-s.&lt;br /&gt;&lt;br /&gt;But closing Eclipse and re-running it as "eclipse -clean" did help.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1781855377895663590-7591561620529117520?l=atagunov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://atagunov.blogspot.com/feeds/7591561620529117520/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1781855377895663590&amp;postID=7591561620529117520' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/7591561620529117520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/7591561620529117520'/><link rel='alternate' type='text/html' href='http://atagunov.blogspot.com/2008/12/eclipse-clean.html' title='eclipse -clean'/><author><name>Anton Tagunov</name><uri>http://www.blogger.com/profile/04903035827978774750</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></entry><entry><id>tag:blogger.com,1999:blog-1781855377895663590.post-6049600767730449691</id><published>2008-05-30T03:58:00.000-07:00</published><updated>2008-05-30T05:58:25.871-07:00</updated><title type='text'>SLF4J - Beyond Log4j</title><content type='html'>Just starting to work on a new project I've found a very encouraging surprise.&lt;br /&gt;This project uses &lt;a href="http://www.slf4j.org/"&gt;SLF4J&lt;/a&gt;/&lt;a href="http://logback.qos.ch/"&gt;Logback&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;Log4J is a good old fried. However it may benefit a bit of rework.&lt;br /&gt;SL4J is a fresh wind. Same spirit slimmer code.&lt;br /&gt;&lt;br /&gt;I really feel it can blow Log4J out of the water.&lt;br /&gt;If it chooses MIT license me thinks.&lt;br /&gt;&lt;br /&gt;Speaking of &lt;a href="http://www.qos.ch/pipermail/logback-user/2008-April/000433.html"&gt;license&lt;/a&gt; &lt;a href="http://www.qos.ch/pipermail/logback-user/2008-April/000419.html"&gt;choices&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;Ceki&gt; Do we want Big Iron (insert your least favorite IT company here)&lt;br /&gt;Ceki&gt; to legally pirate an open source project, say logback?&lt;br /&gt;&lt;br /&gt;Let's assume SLF4J gains in popularity.&lt;br /&gt;Then it will likely be perceived as same in kind to Log4J.&lt;br /&gt;However then Big Co-s would still hold on to the conveniently licensed alternative wouldn't they?&lt;br /&gt;&lt;br /&gt;I don't see how Log4J can be replaced this way.&lt;br /&gt;IMO SLF4J/Logback need MIT/ASL.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1781855377895663590-6049600767730449691?l=atagunov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://atagunov.blogspot.com/feeds/6049600767730449691/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1781855377895663590&amp;postID=6049600767730449691' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/6049600767730449691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/6049600767730449691'/><link rel='alternate' type='text/html' href='http://atagunov.blogspot.com/2008/05/slf4j-beyond-log4j.html' title='SLF4J - Beyond Log4j'/><author><name>Anton Tagunov</name><uri>http://www.blogger.com/profile/04903035827978774750</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></entry><entry><id>tag:blogger.com,1999:blog-1781855377895663590.post-4422524919478241256</id><published>2008-04-17T09:31:00.050-07:00</published><updated>2008-04-17T11:41:39.558-07:00</updated><title type='text'>ConcurrentLinkedQueue On A  Diet</title><content type='html'>News are coming very slowly on me I know. This &lt;a href="http://www.ibm.com/developerworks/java/library/j-jtp11234/"&gt;overview of atomic variables from IBM website&lt;/a&gt; is dated year 2004.&lt;br /&gt;&lt;br /&gt;The article implies that in the case when contention is high (multiple threads compete for access to the same data structures) we can save a lot of CPU cycles that the JVM would have otherwise spent on scheduling threads by using atomic variables instead of traditional synchronized locking.&lt;br /&gt;&lt;br /&gt;As I understand Java memory model each read/write to an atomic variable (as well as to a volatile one) introduces a memory barrier forcing the CPU-s to discard read caches/to flush write ones.&lt;br /&gt;&lt;br /&gt;Following this line of reasoning I have concluded that it would be beneficial not only to synchronize access to highly contended data structures with atomic variables but also to do as little synchronization as at all possible.&lt;br /&gt;&lt;br /&gt;Here's my mental experiment. Suppose we would like to optimize one particular use case. A number of threads put tasks into a queue. A single worker thread takes tasks from the queue and executes them. Apparently we need only one atomic variable to perform this task reliably. Here's the code&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;package org.apache.atagunov.mr.queue;&lt;br /&gt;&lt;br /&gt;public class MrLinked&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/** Managed exclusively by {@link MrQueue} */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;T first, next;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;package org.apache.atagunov.mr.queue;&lt;br /&gt;&lt;br /&gt;public interface MrInternalIterator&amp;lt;T&amp;gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void process(T t);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;package org.apache.atagunov.mr.queue;&lt;br /&gt;&lt;br /&gt;import java.util.concurrent.atomic.AtomicReference;&lt;br /&gt;&lt;br /&gt;import org.apache.log4j.Logger;&lt;br /&gt;&lt;br /&gt;public class MrQueue&amp;lt;T extends MrLinked&amp;lt;T&amp;gt;&amp;gt;&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private final AtomicReference&amp;lt;T&amp;gt; last = new AtomicReference&amp;lt;T&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Add &amp;lt;tt&amp;gt;item&amp;lt;/tt&amp;gt; to this queue&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * May be called from multiple threads.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * @return &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; if we have gone from empty to non-empty state&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public boolean add(final T item)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;item.next = null;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;T oldLast;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;do&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&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;nbsp;/* suppose queue is empty; then item will be the only element */&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;nbsp;item.first = item;&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;nbsp;do&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;nbsp;{&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (last.compareAndSet(null, item)) {&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return true;&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/* okay, queue wasn't empty during compareAndSet */&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;oldLast = last.get();&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;nbsp;}&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;nbsp;/* may have gone null by now */&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;nbsp;while (oldLast == null);&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;nbsp;&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;nbsp;/* suppose the queue doesn't change until next compareAndSet */&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;nbsp;oldLast.next = item;&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;nbsp;&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;nbsp;/* all items in the queue have same first */&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;nbsp;item.first = oldLast.first;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while (!last.compareAndSet(oldLast, item));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/* if we got here this means we have added item to non-empty queue */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private final Logger logger = Logger.getLogger(MrQueue.class);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Run &amp;lt;tt&amp;gt;ii&amp;lt;/tt&amp;gt; for every item in the queue then clear the queue.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Even if &amp;lt;tt&amp;gt;ii&amp;lt;/tt&amp;gt; throws an exception we consider the item as processed&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * Run from one thread at a time please!&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; * @return number of orders executed&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; */&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public int processAndClear(final MrInternalIterator&amp;lt;T&amp;gt; ii)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;T stopHere = last.get();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (stopHere == null) {&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;nbsp;/* don't expect this in context of MrUniverse */&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;nbsp;return 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int count = 0;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;T t = stopHere.first;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(;;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&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;nbsp;for(;;)&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;nbsp;{&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (t == null) {&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;logger.fatal("encountered null, queue discarded");&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/* sort of recovery - discard queue */&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;last.set(null);&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return count;&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;doProcess(t, ii);&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count++;&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (t == stopHere) {&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;t = t.next;&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;nbsp;}&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;nbsp;&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;nbsp;if (last.compareAndSet(stopHere, null))&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;nbsp;{&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/* done! */&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return count;&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;nbsp;}&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;nbsp;&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;nbsp;/* somebody must have added an item to the queue */&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;nbsp;stopHere = last.get();&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;nbsp;&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;nbsp;/* only read .next now after get() which has been a synch point */&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;nbsp;t = t.next;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private final void doProcess(final T t, final MrInternalIterator&amp;lt;T&amp;gt; ii)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&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;nbsp;ii.process(t);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;catch (Error e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&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;nbsp;/* sort of recoverty - discard queue */&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;nbsp;logger.fatal("Iterator thrown " + e.getClass().getName()&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ ", queue discarded");&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;nbsp;last.set(null);&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;nbsp;&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;nbsp;/* let it go through killing the thread maybe */&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;nbsp;throw e;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;catch (Throwable thr)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&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;nbsp;/* consider item as processed; more handling may be added later,&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;nbsp; * at least better logging */&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;nbsp;logger.error("Problem processing queued item", thr);&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;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Only one atomic variable per queue! Contrast this with ConcurrentLinkedQueue which uses atomic access for each "next" pointer in its backing linked list implementation. This is our win for coding specialized solution for a specific use case.&lt;br /&gt;&lt;br /&gt;I was also so concerned about performance that I've decided to unite backing linked list element implementation with actual data items. Sort of what we used to do in good old C days coding lists by hand. The actual class that needs to be stored in MrQueue has to extend MrQueue&amp;lt;its-own-type&amp;gt;. The gain here is that GC has to take care only about one object not about two.&lt;br /&gt;&lt;br /&gt;I have tested this little bit of code as part of a bigger application on a big multi-processor box. The tests have run fine and it appears that the code actually works as designed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1781855377895663590-4422524919478241256?l=atagunov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://atagunov.blogspot.com/feeds/4422524919478241256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1781855377895663590&amp;postID=4422524919478241256' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/4422524919478241256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/4422524919478241256'/><link rel='alternate' type='text/html' href='http://atagunov.blogspot.com/2008/04/concurrentlinkedqueue-on-diet.html' title='ConcurrentLinkedQueue On A  Diet'/><author><name>Anton Tagunov</name><uri>http://www.blogger.com/profile/04903035827978774750</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>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1781855377895663590.post-2132326365042390198</id><published>2008-03-21T06:32:00.050-07:00</published><updated>2008-03-21T14:35:15.389-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming singleton'/><title type='text'>Singleton Free JRE?</title><content type='html'>&lt;span style="color: rgb(0, 0, 0); font-weight: bold;font-size:130%;" &gt;Briefing&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Inversion_of_Control"&gt;IoC&lt;/a&gt; rocks.&lt;br /&gt;Singletons are the opposite of IoC.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://c2.com/cgi/wiki?TestDrivenDevelopment"&gt;TDD&lt;/a&gt;/&lt;a href="http://www.junit.org/"&gt;unit testing&lt;/a&gt;/&lt;a href="http://www.jmock.org/"&gt;mock objects&lt;/a&gt; rock.&lt;br /&gt;Singletons subvert unit testing.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;font-size:130%;" &gt;[Objective No. 1] Modularity&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'd like my application components (osgi bundles, ear-s, war-s or otherwise) to be truly separate from the rest of the system.&lt;br /&gt;&lt;br /&gt;So that a web container could provide its own implementation of file system, console, threading API to my webapp. And a different implementation to another guy's webapp.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;font-size:130%;" &gt;[Objective No. 2] Unit Testability&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'd like to &lt;a href="http://www.junit.org/"&gt;unit test&lt;/a&gt; every bit of code I write. For every unit I test I need to &lt;a href="http://www.jmock.org/"&gt;mock&lt;/a&gt; all it's external dependencies.&lt;br /&gt;&lt;br /&gt;I would also like to unit test 3rd party modules if need be.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;font-size:130%;" &gt;What Are The Evil Singletons?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These are the complex application entities that can not be mocked for testing&lt;br /&gt;&lt;ul&gt;&lt;li&gt;constructors, static methods, static variables (Java)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;functions (C)&lt;/li&gt;&lt;/ul&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;font-size:130%;" &gt;What Singletons Are Ok?&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Singletons so trivial that dependency on them does not violate modularity and we never need to mock them for testing either&lt;br /&gt;&lt;ul&gt;&lt;li&gt;constants (Boolean.TRUE, Enum values)&lt;/li&gt;&lt;li&gt;constructors of value types (java.lang.Integer(int))&lt;/li&gt;&lt;/ul&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;font-size:130%;" &gt;State Of Art&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.springframework.org/"&gt; Spring&lt;/a&gt;, &lt;a href="http://www.picocontainer.org/"&gt;PicoContainer&lt;/a&gt;, &lt;a href="http://felix.apache.org/"&gt;Felix&lt;/a&gt; (&lt;a href="http://www.osgi.org/"&gt;OSGI&lt;/a&gt;), &lt;a href="http://incubator.apache.org/projects/tuscany.html"&gt;Tuscany&lt;/a&gt;(&lt;a href="http://www.ibm.com/developerworks/library/specification/ws-sca/"&gt;SCA&lt;/a&gt;) all give us the blessing of &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_Control"&gt;IoC&lt;/a&gt;. J2EE also does a good job of abstracting inter-module and container services dependencies via interfaces. A small fault is that J2EE components still have to depend on &lt;a href="http://java.sun.com/j2se/1.3/docs/api/javax/naming/directory/InitialDirContext.html#InitialDirContext%28%29"&gt;certain&lt;/a&gt; &lt;a href="http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/xml/parsers/DocumentBuilderFactory.html#newInstance%28%29"&gt;singletons&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;J2SE is more troublesome. These are the prime examples of what I'd like to mock for testing but can not&lt;br /&gt;&lt;ul&gt;&lt;li&gt;System.currentTimeMillis()&lt;/li&gt;&lt;li&gt;new FileOutputStream()&lt;/li&gt;&lt;li&gt;new File("a").mkdir&lt;/li&gt;&lt;li&gt;all of Swing&lt;/li&gt;&lt;/ul&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;font-size:130%;" &gt;Dreams&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;I've long dreamed of writing alternative Java libraries. I don't have any exact design. Just an intuition of strict API/Impl separation + Spring/OSGI/Pico to tie modules together.&lt;br /&gt;&lt;br /&gt;Another dream is to have this supported at programming language level. Each application consists of module instances. Each module declares its dependencies. The module's instantiator provides them.&lt;br /&gt;&lt;br /&gt;Top level module instantiates and connects subordinate modules.&lt;br /&gt;Subordinate modules do it recursively.&lt;br /&gt;&lt;br /&gt;Only the top level module has access to &lt;span style="font-style: italic;"&gt;true&lt;/span&gt; &lt;span style="font-style: italic;"&gt;singletons&lt;/span&gt;. &lt;span style="font-style: italic;"&gt;True&lt;/span&gt; &lt;span style="font-style: italic;"&gt;singletons&lt;/span&gt; are operating system services like IO console thread management.&lt;br /&gt;&lt;br /&gt;Only the top level module can provide the &lt;span style="font-style: italic;"&gt;true singletons&lt;/span&gt; to subordinate modules. Subordinate modules have no way to know if they have been provided with real system services or fake ones.&lt;br /&gt;&lt;br /&gt;Perhaps some &lt;a href="http://factorcode.org/"&gt;young and daring&lt;/a&gt; programming language has a chance to get this right?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1781855377895663590-2132326365042390198?l=atagunov.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://atagunov.blogspot.com/feeds/2132326365042390198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1781855377895663590&amp;postID=2132326365042390198' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/2132326365042390198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1781855377895663590/posts/default/2132326365042390198'/><link rel='alternate' type='text/html' href='http://atagunov.blogspot.com/2008/03/singleton-free-jre.html' title='Singleton Free JRE?'/><author><name>Anton Tagunov</name><uri>http://www.blogger.com/profile/04903035827978774750</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></entry></feed>
