<?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-6643071316318130698</id><updated>2011-12-09T03:14:01.001-08:00</updated><category term='Personal'/><category term='CAPS'/><category term='Sun'/><category term='Oracle'/><category term='Java'/><category term='JavaOne'/><category term='Google'/><category term='GlassFish'/><category term='OpenESB'/><title type='text'>Frank Kieviet's Engineering Notebook</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>23</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-7299344194846275511</id><published>2010-07-31T22:02:00.001-07:00</published><updated>2010-08-18T21:12:38.529-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GlassFish'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='CAPS'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>GlassFish Security</title><content type='html'>&lt;p&gt;&lt;a href="http://www.packtpub.com/"&gt;Pact Publishing&lt;/a&gt; was kind enough to send me a copy of &lt;a href="http://www.packtpub.com/glassfish-security-with-java-ee/book?utm_source=frankkieviet.blogspot.com&amp;amp;utm_medium=bookrev&amp;amp;utm_content=blog&amp;amp;utm_campaign=mdb_003506"&gt;the book "GlassFish Security"&lt;/a&gt; that was released very recently. &lt;/p&gt; &lt;p&gt;&lt;a title="GlassFish Security" href="http://www.packtpub.com/glassfish-security-with-java-ee/book?utm_source=frankkieviet.blogspot.com&amp;amp;utm_medium=bookrev&amp;amp;utm_content=blog&amp;amp;utm_campaign=mdb_003506"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_k73ELjWNXV8/TGyumsR6hTI/AAAAAAAAB2k/VpBsLKa3d-4/image%5B1%5D.png?imgmax=800" width="125" height="152"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;It's tough to find the time to read a book cover to cover. In fact, it's been a while since I've read a book from beginning to end. Typically I'm only interested in a few chapters which I then read. Later, when the need arises, I may get back to other chapter. It's like treating a book like an encyclopedia or a dictionary. I bet that most people read technical books that way nowadays. So it's important that a book lends itself to be read that way.&lt;/p&gt; &lt;p&gt;Security is a very broad field with many many different topics, e.g. user authentication and authorization in web applications, integration with an external security server, web services security, and so on. Fortunately, very few people will have to deal with all these aspects at the same time. GlassFish Security covers many if not all of those aspects, and that's another reason why it should be possible to read this book like an encyclopedia.&lt;/p&gt; &lt;p&gt;I went back in time and tried to remember all the times that I have had anything to do with security in GlassFish and checked what the book had to say about it. For instance, to start simple, there's the issue of configuring realms and users. There's the time I tried to get JSPWiki to work on GlassFish using declarative authentication and authorization, something that goes through server.policy. More advanced, there's the time we tried to integrate GlassFish with AccessManager. On all these topics, the book delivers. There are many other topics (e.g. integration with OpenSSO, securing JMX, etc), all described in detail without wasting much space on repetition or endless code or XML listings. The book would have saved me a lot of time had I had it at the time when I needed it.&lt;/p&gt; &lt;p&gt;If you're using GlassFish, this book belongs on your bookshelf!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-7299344194846275511?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/7299344194846275511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=7299344194846275511' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/7299344194846275511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/7299344194846275511'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2010/07/glassfish-security.html' title='GlassFish Security'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_k73ELjWNXV8/TGyumsR6hTI/AAAAAAAAB2k/VpBsLKa3d-4/s72-c/image%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-8744160616985820614</id><published>2010-04-28T08:44:00.001-07:00</published><updated>2010-04-28T08:44:10.559-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Personal'/><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><title type='text'>Google TV Ads</title><content type='html'>&lt;p&gt;On Tuesday I went to the Google office to talk about what I might be working on. It's likely going to be Google TV Ads. What is that? Here is a 3 minute video that explains it.&lt;/p&gt; &lt;div style="width: 620px; height: 395px; overflow: hidden" id="video_player_mask"&gt;&lt;object id="SlateVPlayer" width="975" height="380" type="application/x-shockwave-flash" data="http://www.slatev.com/media/swfs/SlateVPlayer.swf"&gt;&lt;param name="movie" value="http://www.slatev.com/media/swfs/SlateVPlayer.swf"&gt;&lt;param name="flashVars" value="disableAd=true&amp;amp;autoPlay=false&amp;amp;videoId=72546547001&amp;amp;channel=arts-and-life&amp;amp;videoUrl=http://www.slatev.com/video/how-i-ran-ad-fox-news"&gt;&lt;param name="wmode" value="transparent"&gt;&lt;param name="base" value="http://admin.brightcove.com"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowScriptAcess" value="always"&gt;&lt;param name="seamlesstabbing" value="false"&gt;&lt;param name="swLiveConnect" value="true"&gt;&lt;/object&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-8744160616985820614?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/8744160616985820614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=8744160616985820614' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/8744160616985820614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/8744160616985820614'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2010/04/google-tv-ads.html' title='Google TV Ads'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-9010097631717925888</id><published>2010-04-26T14:58:00.001-07:00</published><updated>2010-04-29T15:06:29.766-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GlassFish'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='Oracle'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>Working with java.net: tips and tricks for project owners</title><content type='html'>&lt;p&gt;In the past two years I've managed the OpenESB open source project. This project is hosted on java.net. In this post I outline a number of tips and tricks I've learned while managing this project on java.net. This is useful information for my successor, but it also may be useful to other people who are managing projects on java.net.&lt;/p&gt; &lt;h4&gt;Web presence&lt;/h4&gt; &lt;p&gt;An important factor in the success of an open source project is its web presence: it will be the first point of contact between a potential new user and the project.&lt;/p&gt; &lt;p&gt;New visitors will want to see answers to these four items immediately:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;What is it?  &lt;li&gt;License?  &lt;li&gt;Getting started  &lt;li&gt;Downloads&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;It is important that the links to these pages are static, i.e. that they do not change. That is because a new visitor may enter the site through a link on a different site or through a search engine. For this very reason, it is especially important to keep a single downloads page rather than a page per version, so that users do end up immediately on the latest version, rather than a previous (old) version.&lt;/p&gt; &lt;p&gt;Looking at the front page of OpenESB, these four items are immediately apparent, and the links are permanent. Two more items are important: a visitor will judge a project for it being&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Alive  &lt;ul&gt; &lt;li&gt;Active mailing list  &lt;li&gt;Recent/frequent announcements&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Professional  &lt;ul&gt; &lt;li&gt;Well organized, thought through  &lt;li&gt;Documentation easily found and comprehensive&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Inviting  &lt;ul&gt; &lt;li&gt;New users should feel welcome to not just use the product, but also to participate in the community.  &lt;p&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You be the judge how well these goals have been met. Let's look at the mechanics of java.net now.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_k73ELjWNXV8/S9YMaDw0WXI/AAAAAAAAAEc/fFNCXXU1Zn8/s1600-h/openesbsite%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="openesbsite" border="0" alt="openesbsite" src="http://lh3.ggpht.com/_k73ELjWNXV8/S9YMbHu8jGI/AAAAAAAAAEg/WClalxPi2m0/openesbsite_thumb%5B3%5D.jpg?imgmax=800" width="576" height="484"&gt;&lt;/a&gt;&lt;/p&gt; &lt;h4&gt;java.net project web site&lt;/h4&gt; &lt;h5&gt;How java.net processes HTML files&lt;/h5&gt; &lt;p&gt;The HTML files for a project's web site are stored in the project's VCS system in a directory called www. There's a big twist here: although the HTML files are ordinary HTML files, i.e. with an &amp;lt;HTML&amp;gt;, &amp;lt;HEAD&amp;gt; and &amp;lt;BODY&amp;gt; tag, the java.net web server reads the HTML files and does a number of substitutions on the file before it writes the resulting file to the client.&lt;/p&gt; &lt;p&gt;Conceptually, there is a java.net template HTML file which has its own &amp;lt;HEAD&amp;gt; element, its own &amp;lt;BODY&amp;gt; element with static content, and some placeholders in these two elements for:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;some elements of &amp;lt;HEAD&amp;gt; element of the user defined HTML file, e.g. &amp;lt;TITLE&amp;gt;  &lt;li&gt;the contents of the project_tools.html file  &lt;li&gt;the contents of the &amp;lt;BODY&amp;gt; element from the user defined HTML file&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;As such, the project owner has to perform special tricks to have the page displayed in other ways than the standard java.net way.&lt;/p&gt; &lt;p&gt;In OpenESB we have several java.net projects. All of them should have the same look and feel, i.e. the OpenESB "brand" and a common navigation. The same goes for the OpenESB wiki.&lt;/p&gt; &lt;h5&gt;How OpenESB organizes HTML files&lt;/h5&gt; &lt;p&gt;Each project has the same project_tools.html file. This file takes care of the following:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;It includes custom CSS files. These files override the java.net styles.  &lt;li&gt;It hides the standard java.net navigation bar. For admins, the navbar display can be turned on: the state is maintained in a cookie. The value in the cookie can be toggled by loading the admin.html file in OpenESB: &lt;a title="https://open-esb.dev.java.net/admin.html" href="https://open-esb.dev.java.net/admin.html"&gt;https://open-esb.dev.java.net/admin.html&lt;/a&gt;.  &lt;li&gt;Loads the menu. The menu is defined in a separate JavaScript file.  &lt;li&gt;Displays the search box  &lt;li&gt;Sets an event handler that is invoked when the page's loading is complete. The event handler manipulates the layout of the page and invokes Google Analytics.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;As a result, the other HTML files in OpenESB or any of its sub projects don't have to bother with the common look and feel, the menu, etc. All of that is taken care of by project_tools.html, which as mentioned should be duplicated to all the OpenESB projects.&lt;/p&gt; &lt;p&gt;Some or if you will, many, HTML files in OpenESB have another common style element: a right hand side bar that displays common advertising for downloading GlassFish ESB, the wealth of components, and the a partner highlight. This right side bar is taken care of a separate JavaScript file. Files that should display this right hand side bar should explicitly be formatted to do so: it should contain a table in which the right column loads the JavaScript of the right hand side bar.&lt;/p&gt; &lt;h5&gt;Previewing HTML&lt;/h5&gt; &lt;p&gt;The fact that the look and feel of an HTML file is now defined in project_tools.html makes it difficult to see what a file will actually look like when deployed (i.e. checked in into the project's VCS) on java.net. There is a workaround: I created a directory that when deployed on a web server, emulates the java.net environment. To edit a file with the ability to preview it without checking in the file, follow this procedure:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Load the file in your browser through java.net's web server, e.g. &lt;a title="https://open-esb.dev.java.net/Downloads.html" href="https://open-esb.dev.java.net/Downloads.html"&gt;https://open-esb.dev.java.net/Downloads.html&lt;/a&gt;.  &lt;li&gt;Save this file to the emulation directory, e.g. Tomcat/webapps/ROOT/Downloads.html  &lt;li&gt;Now load the file into your browser through your local web server, e.g. &lt;a title="https://open-esb.dev.java.net/Downloads.html" href="http://localhost:9080/Downloads.html"&gt;http://localhost:9080/Downloads.html&lt;/a&gt;. This should look identical to what was loaded from java.net.  &lt;li&gt;Locate the text in the file to be edited. Change the text and save the file. Reload the file in your browser. Repeat this step until the file looks OK.  &lt;li&gt;Do a diff using a tool like Araxis Merge, or Beyond Compare between the local file and the file that was checked in into VCS, e.g. diff Tomcat/webapps/ROOT/Downloads.html and open-esb/www/Downloads.html.  &lt;li&gt;Merge the changes into the VCS file, i.e. open-esb/www/Downloads.html. Save and check in into VCS.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Here is the &lt;a href="http://mediacast.sun.com/users/Frank.Kieviet/media/ROOT.zip"&gt;directory for Tomcat&lt;/a&gt;. If you use it for projects other than OpenESB, you can remove many of the files. Make sure to leave branding and css directories in tact. If you intend to reuse project_tools.html, don't forget to change the Google Analytics account ID.&lt;/p&gt; &lt;h5&gt;SSL&lt;/h5&gt; &lt;p&gt;Unfortunately, java.net uses SSL for all its files. This is unfortunate for two reasons:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Files do not get cached in the browser: every time a user opens his browser and goes to OpenESB, all the images, style sheets, etc are reloaded again.  &lt;li&gt;To avoid security warnings in Internet Explorer, files that are included in an HTML file also should come through SSL. This rule is violated on the OpenESB main page (of all places!) where it loads a dynamic list of news item from a non-https server.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;There's no workaround for this. Collabnet promised a long time ago that SSL would be removed but this still has not happened.&lt;/p&gt; &lt;h5&gt;Changing the menu&lt;/h5&gt; &lt;p&gt;The menu is defined in a json like format in a file called menu.js. This file is duplicated in the wiki. See below. Make sure to use absolute URLs because the file is used from different projects, i.e. different roots.&lt;/p&gt; &lt;h4&gt;Wiki (not on java.net)&lt;/h4&gt; &lt;p&gt;OpenESB is not using the java.net wiki infrastructure. I don't recall why this decision was made. New projects should probably evaluate the java.net wiki infrastructure before considering setting up a wiki elsewhere.&lt;/p&gt; &lt;p&gt;The OpenESB wiki is hosted on a machine hosted at Sun/Oracle, not at Collab net. It is collocated with other wikis, e.g. GlassFish, UpdateCenter, etc. The wiki engine is JSP wiki. The templates have been adapted to look and feel like the java.net OpenESB web site.&lt;/p&gt; &lt;p&gt;Since java.net has / used to have a lot of downtime, and to avoid having this downtime impact the wiki, the menu.js file is duplicated on the wiki. That java.net uses ssl is another reason to duplicate the file. For the same reason, the icons displayed in the menu are also duplicated on the wiki server.&lt;/p&gt; &lt;p&gt;Users are managed separately from java.net. User management / restrictions are necessary to avoid spam. Spam has been a been big problem on the OpenESB wiki and the other wikis collocated with it. Cleaning up spam can be done by directly manipulating the text files that make up the wiki page.&lt;/p&gt; &lt;p&gt;JSPWiki security is configured to use JAAS. This fact is important if the wiki needs to be setup on a different GlassFish server. In that case make sure to update the server.policy file of GlassFish. The policy file specifies that only "validated" users can edit pages. Users are stored in a user database and a group database. The latter specifies group membership, of which the "validated" group is important. Both files are in the etc directory of the wiki directory.&lt;/p&gt; &lt;p&gt;To add a user, the group database needs to be updated. This can be done through the web interface, &lt;a title="http://wiki.open-esb.java.net/EditGroup.jsp?group=Validated" href="http://wiki.open-esb.java.net/EditGroup.jsp?group=Validated"&gt;http://wiki.open-esb.java.net/EditGroup.jsp?group=Validated&lt;/a&gt; or can be done by editing the group file directly.&lt;/p&gt; &lt;p&gt;The raw data files and user management files of the wiki can be accessed through SSH.&lt;/p&gt; &lt;p&gt;Since the user management of the wiki is separate from java.net, users can choose a different userid on the wiki than they do on java.net. Allowing this is a mistake in retrospect: editing the wiki requires a SCA (Sun Contributor Agreement) or employment in Sun/Oracle, and having to manage/audit two sets of users instead of one is a waste of time. Again, in retrospect.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_k73ELjWNXV8/S9YMbndCchI/AAAAAAAAAEk/G4ntBSEwOZE/s1600-h/openesbwiki%5B7%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="openesbwiki" border="0" alt="openesbwiki" src="http://lh3.ggpht.com/_k73ELjWNXV8/S9YMeOF85dI/AAAAAAAAAEo/Bwapwmfn23c/openesbwiki_thumb%5B5%5D.jpg?imgmax=800" width="576" height="484"&gt;&lt;/a&gt; &lt;/p&gt; &lt;h4&gt;java.net user management&lt;/h4&gt; &lt;p&gt;Anybody on java.net can request developer privileges. When that happens, an email is sent by java.net to the project owner. An automated process is setup that replies automatically to the user list asking the applicant for his motivation, background, etc. This reply is specified in role-approval.policy in the www directory.&lt;/p&gt; &lt;p&gt;For some reason, many people ask for developer privileges. They are not known, have not contributed or communicated before, and are never heard from again.&lt;/p&gt; &lt;p&gt;Consequently, this automated process sounds nice, but is useless in practice. A better process is that someone first communicates on the mailing list, proves he/she is serious and able to contribute, after which the project owner grants privileges. Before privileges are granted, a signed SCA needs to be on file. &lt;a href="https://open-esb.dev.java.net/ContributionProcess.html"&gt;This process is documented&lt;/a&gt; on the OpenESB web site.&lt;/p&gt; &lt;p&gt;The link to the membership management page is displayed in the java.net nav bar. Recall that the nav bar is hidden. To toggle display of the nav bar, load &lt;a title="https://open-esb.dev.java.net/admin.html" href="https://open-esb.dev.java.net/admin.html"&gt;https://open-esb.dev.java.net/admin.html&lt;/a&gt;. Alternatively, jump to the page directly: &lt;a title="https://open-esb.dev.java.net/servlets/ProjectMemberList" href="https://open-esb.dev.java.net/servlets/ProjectMemberList"&gt;https://open-esb.dev.java.net/servlets/ProjectMemberList&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;When a user is granted commit privileges to a project, he/she also automatically gets commit privileges to the code repositories of the sub projects. E.g. granting commit privileges to open-esb also gives commit privileges to open-jbi-components, a sub project of open-esb. This is only the case if the VCS of the child project is of the same type as the parent project. Since open-jbi-components and open-esb both use CVS, open-esb committers have access to open-jbi-components. However, if the VCS system is different, e.g. openesb-builds uses SVN, separate access to this project needs to be granted next to open-esb.&lt;/p&gt; &lt;h4&gt;java.net email management&lt;/h4&gt; &lt;p&gt;Email lists are managed by an email list manager running in java.net. This email list manager is only partially integrated in java.net. Users can click on a button on the java.net site to subscribe to an email list. What effectively happens is that it will register the email address that is associated with that user &lt;em&gt;at that moment&lt;/em&gt; in the list server. Similarly, a user can unsubscribe through a button, which will remove the email list associated with that user &lt;em&gt;at that moment. &lt;/em&gt;Where this knowledge comes in handy? There is confusion if the user changes his email address associated with his java.net id between subscribing and unsubscribing. Sometimes users get so confused that they'll need help unsubscribing from the list. After all the last thing you want is repeated posts of "how do I unsubscribe from this list?".&lt;/p&gt; &lt;p&gt;Here is another task with respect to email: spam. Protecting the list to spam is very important. Therefore lists should be setup as "discuss" or "moderated". A setting of "discuss" means that only "subscribed" or "allowed" posters can post. If someone posts a message who is not in the "subscribed" or "allowed" list, the message will be forwarded to the list owner(s) for review. Replying to that message will allow the message to be posted. To avoid getting too many of these "review messages", frequent posters can be added to the "allowed" list. The "allowed" list is accessible from the email management page.&lt;/p&gt; &lt;p&gt;The link to the email list management page is displayed in the java.net nav bar. Recall that the nav bar is hidden. To toggle display of the nav bar, load &lt;a title="https://open-esb.dev.java.net/admin.html" href="https://open-esb.dev.java.net/admin.html"&gt;https://open-esb.dev.java.net/admin.html&lt;/a&gt;. Alternatively, jump to the page directly: &lt;a title="https://open-esb.dev.java.net/servlets/ProjectMailingListList" href="https://open-esb.dev.java.net/servlets/ProjectMailingListList"&gt;https://open-esb.dev.java.net/servlets/ProjectMailingListList&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Nabble is a view on the mailing list. OpenESB has &lt;a href="https://open-esb.dev.java.net/MailingLists.html"&gt;integrated&lt;/a&gt; it on the web site. Note that posters are identified by their "from" email address only, but posters on Nabble somehow do not need to be in the "allowed" of "subscribed" list. This is fortunate, but puzzling from a technical point of view.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_k73ELjWNXV8/S9YMfGyDwYI/AAAAAAAAAEs/0KLWvykA_BE/s1600-h/openesbemail%5B3%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="openesbemail" border="0" alt="openesbemail" src="http://lh6.ggpht.com/_k73ELjWNXV8/S9YMf_lAhrI/AAAAAAAAAEw/QGBTy6GwuVw/openesbemail_thumb%5B1%5D.png?imgmax=800" width="576" height="484"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This brings me to one more email list related tasks: once in a while, someone posts an email that he/she wants to revoke. For example, someone could accidentally send a private email to the list, or include confidential (customer information for example) information in an email.&lt;/p&gt; &lt;p&gt;Of course there's no such thing as undoing the sending of an email. Subscribed users will have received the email by the time that the sender notices the mistake. However, there is an option to remove the email from Nabble and from the java.net mail browser. Note that there are two places where the email needs to be removed: both Nabble and java.net. Removing the mail there at least makes the mistake less visible and will make it harder for the mistaken email to be picked up by search engines.&lt;/p&gt; &lt;h4&gt;java.net automation&lt;/h4&gt; &lt;p&gt;Some of the management tasks on java.net can be automated. Kohsuke has developed an extensive set of tools that provide a Java api to java.net web interface: &lt;a title="https://javanettasks.dev.java.net/" href="https://javanettasks.dev.java.net/"&gt;https://javanettasks.dev.java.net/&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;I've written a few tools to make community management easier. One such tool is used to make an inventory of all the users in the community with commit privileges. Everybody in this list should either be a Sun/Oracle employee, or should have signed an SCA. The tool loads and parses the list of signatories (from &lt;a href="https://sca.dev.java.net/CA_signatories.htm"&gt;https://sca.dev.java.net/CA_signatories.htm&lt;/a&gt;) and compares this list with the one extracted from java.net. Discrepancies are people who are currently or have been Sun/Oracle employees. Since it is difficult to track who is no longer an employee (especially with the layoffs that used to happen every now and then), the tool can email all "discrepancies" and ask them to either submit an SCA or to verify employment by clicking a link pointing to an internal server. These tools are available on &lt;a href="https://open-esb-build.dev.java.net/svn/open-esb-build/trunk/community-mgt/"&gt;https://open-esb-build.dev.java.net/svn/open-esb-build/trunk/community-mgt/&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/6643071316318130698-9010097631717925888?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/9010097631717925888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=9010097631717925888' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/9010097631717925888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/9010097631717925888'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2010/04/working-with-javanet-tips-and-tricks.html' title='Working with java.net: tips and tricks for project owners'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_k73ELjWNXV8/S9YMbHu8jGI/AAAAAAAAAEg/WClalxPi2m0/s72-c/openesbsite_thumb%5B3%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-3314056709796796246</id><published>2010-04-21T13:52:00.001-07:00</published><updated>2010-04-21T13:52:02.882-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CAPS'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>OpenESB under Oracle</title><content type='html'>&lt;p&gt;It's been a few months since Oracle acquired Sun. At the time there were a lot of questions about what Oracle would do with OpenESB. On Feb 15, I posted &lt;a href="http://n2.nabble.com/News-update-on-OpenESB-and-Oracle-tp4578158p4578158.html"&gt;a plan to the users mailing list&lt;/a&gt;. What was the plan? And how is the plan coming together? How is OpenESB doing a few months after the acquisition? What will the future hold for OpenESB?&lt;/p&gt; &lt;p&gt;First, let's try to understand Oracle's perspective. Oracle already has an integration product: the SOA Suite. Through the BEA acquisition it got another one, and through the Sun acquisition it got yet two more: CAPS and OpenESB. Of course there's no sense in keeping high levels of investments in &lt;em&gt;all&lt;/em&gt; these products; it makes much more sense to focus on one product. What is this strategic product? Oracle is very clear about that: Oracle's strategic SOA middleware platform is the Oracle SOA Suite. Consequently, Oracle has reduced the level of investment in OpenESB.  &lt;p&gt;That was the bad news. Now for the good news. Oracle could have just pulled out from OpenESB and let it fall into a black hole. Or worse, it could have taken the site down, removed the downloads, or put other obstacles in place. It did not. It did quite the contrary.  &lt;p&gt;Although Sun was the main sponsor behind OpenESB, Oracle recognized that a lot of&amp;nbsp; people made investments into OpenESB, either in the community or into their own company by &lt;em&gt;using&lt;/em&gt; OpenESB, and with a feeling of responsibility and fairness, Oracle decided to help the community to find a way to stand on its own, so that all these investments would bear fruit for as long a time as possible.  &lt;p&gt;Did you invest in OpenESB? Let's look at what will change for you depending on the kind of investment you made.  &lt;h5&gt;What will change for you&lt;/h5&gt; &lt;p&gt;What will change for you if you bought GlassFish ESB support? Nothing will change: you are still fully supported. The same Sun SOA Support department is still available to help on issues. Should patches be created to address issues, the full Sun SOA Sustaining department is still there to create patches.  &lt;p&gt;Are you using GlassFish ESB but did not buy support? Unlike Sun, Oracle is no longer trying to sell GlassFish ESB licenses to new customers. Instead, you may rely on community support, or commercial support provided by one of the OpenESB community partners. The user mailing list is nowadays less frequented by Sun/Oracle engineers, but other community members have stepped up and are keeping the mailing list responsive. More about that below.  &lt;p&gt;Are you investing in OpenESB by contributing code or other artifacts, or are considering to do so? You will find that it has become easier to contribute. I've put together a &lt;a title="OpenESB governance" href="https://open-esb.dev.java.net/Governance.html"&gt;new governance document&lt;/a&gt; that gives greater freedom to community contributors. Oracle can still exert influence, but that is intended to keep the peace in the community should that be necessary. Overall, you will find it easier to propose and implement new changes, to commit code, and last but not least, to influence the roadmap. This brings us to the future of OpenESB.  &lt;h5&gt;The future of OpenESB&lt;/h5&gt; &lt;p&gt;The future of OpenESB revolves around OpenESB becoming an open source community that can stand on its own, i.e. without Sun or Oracle as the single major sponsor. That transformation will of course not happen overnight, and Oracle is committed to help with this transformation. For instance, Oracle will do periodic builds and post these on the downloads site. Another commitment is that Oracle will merge patches that it makes for customers, back into the open source repository.  &lt;p&gt;What did Oracle do so far? Next to the governance document I already mentioned, the sources of GlassFish ESB v2.2 can now be found in the open source repository. The HL7 BC and the WLM SE are also back in the open source repository, and the binaries can be downloaded from the downloads page. The process of an automatic periodic build has incurred some delays due to technical issues, but is well on its way.  &lt;h5&gt;OpenESB today&lt;/h5&gt; &lt;p&gt;How is OpenESB doing today? Let's look at the users mailing list. From &lt;a href="http://markmail.org/search/?q=open-esb#query:open-esb%20list%3Anet.java.dev.open-esb.users+page:1+state:facets"&gt;the Users mailing list on Markmail&lt;/a&gt;, it can be seen that the list activity has declined a bit, but is not much below the activity of that of a year ago.  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_k73ELjWNXV8/S89las_aguI/AAAAAAAAAEE/Sk80c1O-ZVA/s1600-h/emailactivity3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="emailactivity" border="0" alt="emailactivity" src="http://lh4.ggpht.com/_k73ELjWNXV8/S89la5HpC7I/AAAAAAAAAEI/VyGz1wQHBA8/emailactivity_thumb1.png?imgmax=800" width="422" height="195"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;What we also can learn from Markmail is that community members who are not on the Oracle payroll are stepping up. For example, here are &lt;a href="http://markmail.org/search/?q=open-esb+list%3Anet.java.dev.open-esb.users+date%3A200801-201003+#query:open-esb%20list%3Anet.java.dev.open-esb.users%20date%3A201003%20+page:1+state:facets"&gt;the most active posters for March&lt;/a&gt;:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_k73ELjWNXV8/S89lbE26nCI/AAAAAAAAAEM/Byn8tssVN2s/s1600-h/emailactivity23.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="emailactivity2" border="0" alt="emailactivity2" src="http://lh3.ggpht.com/_k73ELjWNXV8/S89lbo6JLII/AAAAAAAAAEQ/iY5txdZhQgc/emailactivity2_thumb1.png?imgmax=800" width="226" height="289"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Another metric that we can look at is the number of users. In GlassFish ESB v2.1 we introduced a feature in which NetBeans checks for updates upon startup. By looking at the traffic to the updates-server, we can estimate how many users there are of GlassFish ESB. I defined the number of users as the number of NetBeans installations that ping the server at least three times in a time window greater than five days. As can be seen, the number of users is going up.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_k73ELjWNXV8/S89lbyDR8PI/AAAAAAAAAEU/WoDhL5iCPkI/s1600-h/useractivty3.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="useractivty" border="0" alt="useractivty" src="http://lh4.ggpht.com/_k73ELjWNXV8/S89lcXqjqhI/AAAAAAAAAEY/7U2oBNrbd_4/useractivty_thumb1.png?imgmax=800" width="451" height="263"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;In terms of a roadmap there are no concrete proposals from the community yet, but several members have expressed interest in continuing with Fuji.  &lt;p&gt;More good news: a few new committers have joined the project and are contributing code.    &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-3314056709796796246?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/3314056709796796246/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=3314056709796796246' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/3314056709796796246'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/3314056709796796246'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2010/04/openesb-under-oracle.html' title='OpenESB under Oracle'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_k73ELjWNXV8/S89la5HpC7I/AAAAAAAAAEI/VyGz1wQHBA8/s72-c/emailactivity_thumb1.png?imgmax=800' height='72' width='72'/><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-8811092210429817415</id><published>2010-04-21T13:50:00.001-07:00</published><updated>2010-04-26T20:46:41.901-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GlassFish'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='CAPS'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>Moving on… next stop: Google</title><content type='html'>&lt;p&gt;I've decided it's time to move on. Yesterday I put in my resignation at Oracle. I'll be starting at Google in two weeks.&lt;/p&gt; &lt;p&gt;Why? Was Oracle such a bad place to work? Was it such a culture shock for a Sun employee that it just could not work? Could I not stand my manager? Could I not get along with my new co-workers? &lt;/p&gt; &lt;p&gt;If you're expecting a bitching session about big-bad-Oracle, I have to disappoint you. In the months that I've been at Oracle, I've come to the conclusion that it is a pretty decent company to work for. I like my manager, my co-workers are intelligent and pleasant, and the culture at Oracle is very similar as it was at Sun. So, honestly, no complaints there.&lt;/p&gt; &lt;p&gt;The reason for my leaving is that I've been doing SOA for 7+ years now. I've been involved in the complete lifecycle of two products: CAPS and OpenESB. Now, with my transition into Oracle, I was about to commit to a third SOA product. Before I dove into that, I did some soul searching, and realized that I ready for something new, something in a different field.&lt;/p&gt; &lt;p&gt;As I was looking for a change, I looked at what interesting companies there are here in Orange County. Google and Amazon came to mind. Google is said to be the engineering Valhalla, so I submitted my resume there. And surprise, surprise, I got an offer.&lt;/p&gt; &lt;p&gt;It's a big jump. It's starting from the bottom again… jumping into something brand new. Will I like the change? I'm eager to find out!&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/_k73ELjWNXV8/S9ZeHezeNsI/AAAAAAAAAE0/xxMv59WPUlU/s1600-h/feelinglucky%5B4%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="feelinglucky" border="0" alt="feelinglucky" src="http://lh6.ggpht.com/_k73ELjWNXV8/S9ZeHj5debI/AAAAAAAAAE4/5Tz_fcTIOh0/feelinglucky_thumb%5B2%5D.png?imgmax=800" width="146" height="35"&gt;&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/6643071316318130698-8811092210429817415?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/8811092210429817415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=8811092210429817415' title='20 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/8811092210429817415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/8811092210429817415'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2010/04/moving-on-next-stop-google.html' title='Moving on… next stop: Google'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_k73ELjWNXV8/S9ZeHj5debI/AAAAAAAAAE4/5Tz_fcTIOh0/s72-c/feelinglucky_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>20</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-1483937513895585347</id><published>2010-02-25T11:28:00.001-08:00</published><updated>2010-03-03T08:44:01.231-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='CAPS'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>I got a patent</title><content type='html'>&lt;p&gt;Today I got a pleasant surprise when I got into the office: I found a big box on my desk. It turns out it was a nice engraved plaque of my patent on "Protected Concurrent FIFO" message processing.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_k73ELjWNXV8/S46RylzA_YI/AAAAAAAAAD4/S7rHimL8GuE/s1600-h/Image1%5B3%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Image1" border="0" alt="Image1" src="http://lh6.ggpht.com/_k73ELjWNXV8/S46R0OI3XUI/AAAAAAAAAD8/odu_tJ0KlrY/Image1_thumb%5B1%5D.jpg?imgmax=800" width="408" height="527"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The funny thing is that I didn't even know that the patent was awarded. After the patent application in 2004 or 2005, I don't even remember when it was, I lost track of its status. Emails to the patent lawyer went unanswered.&lt;/p&gt; &lt;p&gt;I googled for the text of &lt;a href="http://mediacast.sun.com/users/Frank.Kieviet/media/Patent-US7644197.pdf"&gt;the actual patent (US7644197 Queue management by multiple processors)&lt;/a&gt; and found a PDF which I copied to Mediacast.&lt;/p&gt; &lt;p&gt;A thank-you to Jerry Waldorf (my boss during the SeeBeyond days and co-applicant of the patent) for asking me to work on this subject, and a thank-you to Sun for the plaque!&lt;/p&gt; &lt;p&gt;By the way, I have often said that almost all software patents are nonsense and inhibit progress rather than promote it. I still feel this way. Does that make me a hypocrite? Not necessarily: companies are forced to submit patents applications so that they can defend themselves against patent litigation from competitors. In that sense I'm happy that Sun got another patent. And that I'm happy that my name is on it: well, yes, I guess that's an ego-thing.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-1483937513895585347?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/1483937513895585347/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=1483937513895585347' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/1483937513895585347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/1483937513895585347'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2010/02/i-got-patent.html' title='I got a patent'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_k73ELjWNXV8/S46R0OI3XUI/AAAAAAAAAD8/odu_tJ0KlrY/s72-c/Image1_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-3076913094443088079</id><published>2010-01-15T10:41:00.001-08:00</published><updated>2010-01-15T10:41:01.017-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GlassFish'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>How to enlist and delist XA resources: trial and error</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;Once in a while a problem pops up with how a middleware stack supports XA. The problem I'm discussing here is the one of how to exactly enlist and delist &lt;code&gt;XAResource-&lt;/code&gt;s with &lt;code&gt;isSameRM()&lt;/code&gt;returning &lt;font face="Courier New"&gt;true&lt;/font&gt;. The XA spec is vague on this very topic, so this warrants some exploration.&lt;/p&gt; &lt;p&gt;First of all, what do I mean with "enlist and delist &lt;code&gt;XAResource-&lt;/code&gt;s with &lt;code&gt;isSameRM()&lt;/code&gt;returning &lt;font face="Courier New"&gt;true&lt;/font&gt;?" &lt;/p&gt; &lt;h4&gt;Enlisting and delisting&lt;/h4&gt; &lt;p&gt;When using an XA capable system, the connection needs to be enlisted in the transaction before it is used. A typical sequence on the &lt;font face="Courier New"&gt;XAResource&lt;/font&gt;, let's call it &lt;tt&gt;r1&lt;/tt&gt;, is:&lt;/p&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt;   1:&lt;/span&gt; r1.start(xid, TMNOFLAGS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt;   2:&lt;/span&gt; ... &lt;span style="color: #008000"&gt;// use (r1)&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt;   3:&lt;/span&gt; r1.end(xid, TMSUCCESS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt;   4:&lt;/span&gt; r1.commit(xid, true);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;With a second resource in the mix, the call sequence may become:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt;   1:&lt;/span&gt; r1.start(xid1, TMNOFLAGS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt;   2:&lt;/span&gt; ... &lt;span style="color: #008000"&gt;// use r1&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt;   3:&lt;/span&gt; r2.start(xid2, TMNOFLAGS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt;   4:&lt;/span&gt; ... &lt;span style="color: #008000"&gt;// use r2&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt;   5:&lt;/span&gt; r2.end(xid2, TMSUCCESS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt;   6:&lt;/span&gt; r1.end(xid1, TMSUCCESS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt;   7:&lt;/span&gt; r1.prepare(xid1);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum8" style="color: #606060"&gt;   8:&lt;/span&gt; r2.prepare(xid2);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum9" style="color: #606060"&gt;   9:&lt;/span&gt; p1.commit(xid1, false);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum10" style="color: #606060"&gt;  10:&lt;/span&gt; p2.commit(xid2, false);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The transaction is now escalated to a full two-phase transaction. But if &lt;tt&gt;r1 &lt;/tt&gt;and &lt;tt&gt;r2&lt;/tt&gt; represent the same resource manager, a shortcut can be taken: one resource can "piggy back ride" on the other resource. The &lt;font face="Courier New"&gt;isSameRM()&lt;/font&gt; method can be used to check if this should be attempted. If it returns true, the sequence may become:&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;// MULTIPLE ACTIVE&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt;   2:&lt;/span&gt; r1.start(xid, TMNOFLAGS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt;   3:&lt;/span&gt; r1.isSameRM(r2); &lt;span style="color: #008000"&gt;// returns true&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt;   4:&lt;/span&gt; r2.start(xid, TMJOIN);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt;   5:&lt;/span&gt; r2.end(xid, TMSUCCESS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt;   6:&lt;/span&gt; r1.end(xid, TMSUCCESS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt;   7:&lt;/span&gt; r1.commit(xid, true);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The transaction now again is a single-phase transaction, and the performance difference with the two-phase commit case is usually very significant. &lt;/p&gt;
&lt;p&gt;This sequence doesn't work for a number of popular systems, e.g. MQSeries and Oracle. Unfortunately the XA specification, but that specification is not quite clear at all about what resource managers should be able to do, so there is to some extent some trial and error involved. &lt;/p&gt;
&lt;h4&gt;Trial and error&lt;/h4&gt;
&lt;p&gt;How should &lt;font face="Courier New"&gt;isSameRM() &lt;/font&gt;&lt;font face="Verdana"&gt;be used then? By testing a number of different systems, it turns out &lt;strong&gt;that for some systems, there can be only one enlisted &lt;font face="Courier New"&gt;XAResource&lt;/font&gt; &lt;em&gt;active&lt;/em&gt; in the transaction&lt;/strong&gt;. If a second &lt;font face="Courier New"&gt;XAResource&lt;/font&gt; joins the transaction, the first one should be deactivated. Here is an example:&lt;/font&gt;&lt;/p&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;// SINGLE ACTIVE 1&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt;   2:&lt;/span&gt; r1.start(xid, TMNOFLAGS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt;   3:&lt;/span&gt; r1.isSameRM(r2); &lt;span style="color: #008000"&gt;// should return true&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt;   4:&lt;/span&gt; ... &lt;span style="color: #008000"&gt;// use r1&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt;   5:&lt;/span&gt; r1.end(xid, TMSUSPEND);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt;   7:&lt;/span&gt; r2.start(xid, TMJOIN);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum8" style="color: #606060"&gt;   8:&lt;/span&gt; ... &lt;span style="color: #008000"&gt;// use r2&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum9" style="color: #606060"&gt;   9:&lt;/span&gt; r2.end(xid, TMSUCCESS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum10" style="color: #606060"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum11" style="color: #606060"&gt;  11:&lt;/span&gt; r1.start(xid, TMRESUME);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum12" style="color: #606060"&gt;  12:&lt;/span&gt; ... &lt;span style="color: #008000"&gt;// use r1 again&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum13" style="color: #606060"&gt;  13:&lt;/span&gt; r1.end(xid, TMSUCESS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum14" style="color: #606060"&gt;  14:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum15" style="color: #606060"&gt;  15:&lt;/span&gt; r1.commit(xid, true);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;A variation of this is calling &lt;font face="Courier New"&gt;TMSUCCESS&lt;/font&gt; instead of &lt;font face="Courier New"&gt;TMSUSPEND&lt;/font&gt;. In that case &lt;font face="Courier New"&gt;TMJOIN&lt;/font&gt; should be called instead of &lt;font face="Courier New"&gt;TMRESUME&lt;/font&gt;:&lt;/div&gt;
&lt;div id="codeSnippetWrapper"&gt;
&lt;div id="codeSnippet" style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum1" style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #008000"&gt;// SINGLE ACTIVE 2&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum2" style="color: #606060"&gt;   2:&lt;/span&gt; r1.start(xid, TMNOFLAGS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum3" style="color: #606060"&gt;   3:&lt;/span&gt; r1.isSameRM(r2); &lt;span style="color: #008000"&gt;// should return true&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum4" style="color: #606060"&gt;   4:&lt;/span&gt; ... &lt;span style="color: #008000"&gt;// use r1&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum5" style="color: #606060"&gt;   5:&lt;/span&gt; r1.end(xid, TMSUCCESS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum6" style="color: #606060"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum7" style="color: #606060"&gt;   7:&lt;/span&gt; r2.start(xid, TMJOIN);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum8" style="color: #606060"&gt;   8:&lt;/span&gt; ... &lt;span style="color: #008000"&gt;// use r2&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum9" style="color: #606060"&gt;   9:&lt;/span&gt; r2.end(xid, TMSUCCESS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum10" style="color: #606060"&gt;  10:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum11" style="color: #606060"&gt;  11:&lt;/span&gt; r1.start(xid, TMJOIN);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum12" style="color: #606060"&gt;  12:&lt;/span&gt; ... &lt;span style="color: #008000"&gt;// use r1 again&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum13" style="color: #606060"&gt;  13:&lt;/span&gt; r1.end(xid, TMSUCESS);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum14" style="color: #606060"&gt;  14:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; direction: ltr; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; text-align: left; border-bottom-style: none"&gt;&lt;span id="lnum15" style="color: #606060"&gt;  15:&lt;/span&gt; r1.commit(xid, true);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div&gt;I ran these tests on a number of systems, and here is what I found:&lt;/div&gt;
&lt;table cellspacing="0" cellpadding="2" width="573" border="1"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="137"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td valign="top" width="100"&gt;&lt;tt&gt;isSameRM()&lt;/tt&gt;&lt;/td&gt;
&lt;td valign="top" width="113"&gt;Test: multiple active&lt;/td&gt;
&lt;td valign="top" width="121"&gt;Test: single active 1&lt;/td&gt;
&lt;td valign="top" width="100"&gt;Test: single active 2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="143"&gt;STCMS&lt;/td&gt;
&lt;td valign="top" width="105"&gt;yes&lt;/td&gt;
&lt;td valign="top" width="116"&gt;yes&lt;/td&gt;
&lt;td valign="top" width="122"&gt;yes&lt;/td&gt;
&lt;td valign="top" width="103"&gt;yes&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="146"&gt;JMQ&lt;/td&gt;
&lt;td valign="top" width="107"&gt;as of 4.4&lt;/td&gt;
&lt;td valign="top" width="116"&gt;yes&lt;/td&gt;
&lt;td valign="top" width="121"&gt;no: throws on line 7&lt;/td&gt;
&lt;td valign="top" width="104"&gt;yes&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="147"&gt;WebSphereMQ 6&lt;/td&gt;
&lt;td valign="top" width="109"&gt;yes&lt;/td&gt;
&lt;td valign="top" width="115"&gt;no: blocks on line 4&lt;/td&gt;
&lt;td valign="top" width="120"&gt;no: blocks on line 7&lt;/td&gt;
&lt;td valign="top" width="104"&gt;yes&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="149"&gt;Derby 10.5.3.0&lt;/td&gt;
&lt;td valign="top" width="110"&gt;yes&lt;/td&gt;
&lt;td valign="top" width="115"&gt;no: blocks on line 4 &lt;/td&gt;
&lt;td valign="top" width="120"&gt;yes&lt;/td&gt;
&lt;td valign="top" width="104"&gt;yes&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="148"&gt;Oracle 11.1.0.6&lt;/td&gt;
&lt;td valign="top" width="111"&gt;yes&lt;/td&gt;
&lt;td valign="top" width="115"&gt;no: blocks on line 4&lt;/td&gt;
&lt;td valign="top" width="119"&gt;yes&lt;/td&gt;
&lt;td valign="top" width="103"&gt;yes&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="150"&gt;MySQL 5.1&lt;/td&gt;
&lt;td valign="top" width="111"&gt;yes&lt;/td&gt;
&lt;td valign="top" width="114"&gt;no: throws on line 4&lt;/td&gt;
&lt;td valign="top" width="119"&gt;no: throws on line 5&lt;/td&gt;
&lt;td valign="top" width="103"&gt;no: throws on line 7&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;As can be seen, the &lt;font face="Courier New"&gt;SINGLE ACTIVE 2&lt;/font&gt; code sequence works best.&lt;/p&gt;
&lt;p&gt;As a side note, MySQL is showing surprising behavior: &lt;tt&gt;TMJOIN&lt;/tt&gt; and &lt;font face="Courier New"&gt;TMSUSPEND &lt;/font&gt;are not supported (as documented in the &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/xa-restrictions.html"&gt;MySQL documentation&lt;/a&gt;), so why does it bother to return true on &lt;font face="Courier New"&gt;isSameRM()&lt;/font&gt;? Behavior like this makes it difficult to write portable code: a container now has to provide a wrapper around the DataSource that corrects for this. It would have been much better if it simply had returned &lt;font face="Courier New"&gt;false&lt;/font&gt; on &lt;font face="Courier New"&gt;isSameRM()&lt;/font&gt;.&lt;/p&gt;
&lt;p&gt;How does this relate to what application code can do in for instance a Java EE container? That's the topic of a different blog post.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-3076913094443088079?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/3076913094443088079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=3076913094443088079' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/3076913094443088079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/3076913094443088079'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2010/01/how-to-enlist-and-delist-xa-resources.html' title='How to enlist and delist XA resources: trial and error'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-2642064350041003595</id><published>2010-01-12T17:46:00.001-08:00</published><updated>2010-01-12T17:46:58.534-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><title type='text'>Regex editor now on code.google.com</title><content type='html'>&lt;p&gt;By popular demand, the sources of the Regular Expression Editor I discussed &lt;a href="http://frankkieviet.blogspot.com/2009/01/interactive-regular-expression-editor.html"&gt;in a previous post&lt;/a&gt;, is now &lt;a href="http://code.google.com/p/regexeditor/"&gt;available on code.google.com&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/6643071316318130698-2642064350041003595?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/2642064350041003595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=2642064350041003595' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/2642064350041003595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/2642064350041003595'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2010/01/regex-editor-now-on-codegooglecom.html' title='Regex editor now on code.google.com'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-7853479210555118252</id><published>2010-01-12T11:59:00.001-08:00</published><updated>2010-01-12T11:59:37.860-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>Book "SOA with Java": Rough cut now online</title><content type='html'>&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_k73ELjWNXV8/S0zUpl4GP4I/AAAAAAAAAC8/xtZn7HmBSoQ/s1600-h/image%5B2%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="244" alt="image" src="http://lh3.ggpht.com/_k73ELjWNXV8/S0zUqN_OsGI/AAAAAAAAADA/TToB7hQ6fMo/image_thumb.png?imgmax=800" width="244" border="0"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;A few months ago I got a request from Satadru Roy, one of the authors of the book "SOA with Java", to write a section on Open Source ESBs for this book.&lt;/p&gt; &lt;p&gt;This was a good opportunity to advertise OpenESB, so I eagerly said yes. Satadru suggested that a practical example should be the core of the chapter, so I sat down with two of my colleagues, Murali Pottlapelli and Sujit Biswas, to discuss how the example would look like.&lt;/p&gt; &lt;p&gt;The result is a 17 page chapter that gives an overview of OpenESB. The book is now available for &lt;a href="http://my.safaribooksonline.com/9780137045914/ch13lev1sec6"&gt;review on Safari&lt;/a&gt;. This link will probably be invalidated when the review period ends, but perhaps the &lt;a href="http://my.safaribooksonline.com/9780137045914"&gt;link to the book itself&lt;/a&gt; is more permanent (the &lt;a href="http://www.amazon.com/Service-Oriented-Architecture-J2EE-Thomas-Erl/dp/0132435896/ref=sr_1_1?ie=UTF8&amp;amp;qid=1263326145&amp;amp;sr=8-1"&gt;book is also on Amazon&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/6643071316318130698-7853479210555118252?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/7853479210555118252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=7853479210555118252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/7853479210555118252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/7853479210555118252'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2010/01/book-with-java-rough-cut-now-online.html' title='Book &amp;quot;SOA with Java&amp;quot;: Rough cut now online'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_k73ELjWNXV8/S0zUqN_OsGI/AAAAAAAAADA/TToB7hQ6fMo/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-8528431035269153592</id><published>2009-11-06T17:53:00.001-08:00</published><updated>2009-11-06T17:53:37.346-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Remote learning, graduate projects, and open source</title><content type='html'>&lt;p&gt;Last week, an ex-colleague asked me if I could be a reviewer on a graduation project at &lt;a href="http://www.nu.edu/"&gt;National University&lt;/a&gt; where he is now a professor. Flattered, and finding myself with a little bit more time on my hands than usual, I accepted.&lt;/p&gt; &lt;p&gt;The goal of the project was to let a team of seven students build a real-life application as a learning experience about how software development is done in the industry, for a "real" customer. The task was to develop a tracking application for the Boys &amp;amp; Girls Clubs of the Sequoias.&lt;/p&gt; &lt;p&gt;There were several interesting aspects of this project: first of all, the end result was a working application that in quality and functionality exceeds a good portion of similar applications built by IT departments. Key to this was the use of off-the-shelf frameworks such as Spring MVC, Hibernate, BIRT, and jQuery. I'm glad that students are using frameworks like these rather than reinventing their own, although that might have been even more fun.&lt;/p&gt; &lt;p&gt;Another interesting aspect was that the project was done as &lt;a href="http://code.google.com/p/nucsc480project/"&gt;an open source project on&lt;/a&gt; &lt;a href="http://code.google.com/p/nucsc480project/"&gt;code.google.com&lt;/a&gt;. The practical advantages are the infrastructure is provided completely ready by the code forge (in this case code.google.com), so that little time needs to be spent on setting up an infrastructure. This is especially important for students that are remote and hence don't have a shared work environment (e.g. office). Of course there's a lot more work to be done to make it a successful open source project, but that's not important in the scope of the project. I'm glad universities expose students to an open source way of development.&lt;/p&gt; &lt;p&gt;Lastly, the presentation of the project was done using a tool called &lt;a href="http://www.elluminate.com/"&gt;ClassLive Pro&lt;/a&gt;. This is a JNLP application that provides similar functionality to WebEx. Although I've developed a few JNLP applications myself, and I'm convinced of its great utility, I haven't encountered any other JNLP applications so I was glad I ran into this application.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-8528431035269153592?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/8528431035269153592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=8528431035269153592' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/8528431035269153592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/8528431035269153592'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/11/remote-learning-graduate-projects-and.html' title='Remote learning, graduate projects, and open source'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-8422433391848577998</id><published>2009-09-22T14:29:00.001-07:00</published><updated>2009-09-22T14:29:36.929-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><title type='text'>A SEED certificate</title><content type='html'>&lt;p&gt;With the Oracle acquisition looming on the horizon, and the uncertainty that comes with it, it feels like many organizations within Sun are bringing projects in a state in which they can be &lt;em&gt;transitioned i&lt;/em&gt;n a clean way. &lt;em&gt;Transitioned&lt;/em&gt; meaning adopted or abandoned.&lt;/p&gt; &lt;p&gt;I also find myself doing this: for instance I'm trying to put the finishing touches on JMSJCA, and trying to put Hulp in a state where other people can use it, etc.&lt;/p&gt; &lt;p&gt;Maybe it was in that light that a few days ago, I got a certificate from the SEED organization within Sun. SEED is a mentoring program within Sun in which I had the good fortune to participate. I also was a SEED mentor. Or perhaps I should let the speak for itself.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_k73ELjWNXV8/SrlBvRLpXvI/AAAAAAAAACc/kT-KVHiq5Zs/s1600-h/image%5B7%5D.png"&gt;&lt;img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="842" alt="image" src="http://lh6.ggpht.com/_k73ELjWNXV8/SrlBwP9QULI/AAAAAAAAACg/mE2YF3h43Y4/image_thumb%5B5%5D.png?imgmax=800" width="643" border="0"&gt;&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/6643071316318130698-8422433391848577998?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/8422433391848577998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=8422433391848577998' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/8422433391848577998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/8422433391848577998'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/09/seed-certificate.html' title='A SEED certificate'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_k73ELjWNXV8/SrlBwP9QULI/AAAAAAAAACg/mE2YF3h43Y4/s72-c/image_thumb%5B5%5D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-5256869402000288378</id><published>2009-09-21T13:54:00.001-07:00</published><updated>2009-09-21T13:54:45.301-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GlassFish'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>Lessons of an interesting deadlock problem</title><content type='html'>&lt;p&gt;Two years ago I wrote a &lt;a href="http://blogs.sun.com/fkieviet/entry/using_nested_diagnostics_contexts_in"&gt;blog entry about Nested Diagnostics Contexts&lt;/a&gt; in GlassFish. The approach was based on custom &lt;tt&gt;Logger&lt;/tt&gt; objects. Now, two years later when running GlassFish on AIX, an issue with that turned up: a deadlock. Digging into it, there are two lessons I'd like to share: one about deadlocks, and the other one about workarounds.&lt;/p&gt; &lt;h3&gt;Deadlock in the JDK&lt;/h3&gt; &lt;p&gt;At the time of my writing the NDC facility, calling &lt;tt&gt;addLogger()&lt;/tt&gt; and &lt;tt&gt;getLogger()&lt;/tt&gt; from different threads may cause a deadlock in the JDK classes. Why is this?&lt;/p&gt; &lt;p&gt;This is how the code in the Sun JDK was:&lt;/p&gt;&lt;pre&gt;public class Logger {
...
    public &lt;b&gt;static synchronized&lt;/b&gt; Logger getLogger(String name) {
	LogManager manager = LogManager.getLogManager();
	Logger result = manager.getLogger(name);
	if (result == null) {
	    result = new Logger(name, null);
	    manager.addLogger(result);
	    result = manager.getLogger(name);
	}
	return result;
    }
}
&lt;/pre&gt;&lt;pre&gt;public class LogManager {
...
    public &lt;b&gt;synchronized&lt;/b&gt; boolean addLogger(Logger logger) {
...
        Logger plogger = Logger.getLogger(pname);
    }
...
}
&lt;/pre&gt;
&lt;p&gt;There is a problem if there are two threads calling these two methods. Say Thread 1 calls &lt;tt&gt;Logger.getLogger()&lt;/tt&gt; in its application code, e.g.&lt;/p&gt;&lt;pre&gt;public void doSomething() {
  Logger.getLogger("com.stc.test").info("doSomething!");
}
&lt;/pre&gt;
&lt;p&gt;Now let's consider another thread Thread 2 tries to register a custom logger using &lt;tt&gt;addLogger()&lt;/tt&gt;, e.g.&lt;/p&gt;&lt;pre&gt;LogManager.getLogManager().addLogger(new Logger() {
...
});
&lt;/pre&gt;
&lt;p&gt;There are two locks that come into the picture: one is the lock on &lt;tt&gt;Logger.class&lt;/tt&gt;, and the other one on &lt;tt&gt;LogManager.getLogManager()&lt;/tt&gt;. Thread 1 simply calls &lt;tt&gt;Logger.getLogger()&lt;/tt&gt; which first locks &lt;tt&gt;Logger.class&lt;/tt&gt;, and while having this lock, will call &lt;tt&gt;LogManager.addLogger()&lt;/tt&gt;. This call will get a lock on &lt;tt&gt;LogManager.getLogManager()&lt;/tt&gt;. This will try to lock &lt;tt&gt;Logger.class&lt;/tt&gt; again, which is no problem because it already had the lock on that. Now consider Thread 2: it will first lock &lt;tt&gt;LogManager.getLogManager()&lt;/tt&gt; through its call to &lt;tt&gt;addLogger()&lt;/tt&gt;, and while having this lock, it will try to lock &lt;tt&gt;Logger.class&lt;/tt&gt; through its call to &lt;tt&gt;Logger.getLogger()&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;So Thread 1 will lock first A and then B, while Thread 2 will first lock B and then A. A classical deadlock situation.&lt;/p&gt;
&lt;p&gt;This is clearly a bug in the JDK. With the knowledge of this bug, as the developer of the custom logger, we can use a simple workaround for this problem. Before calling &lt;tt&gt;addLogger()&lt;/tt&gt;, first lock &lt;tt&gt;Logger.class&lt;/tt&gt;. By doing that, we can guarantee that the locks are called in the same order: first &lt;tt&gt;Logger.class&lt;/tt&gt; and then &lt;tt&gt;LogManager.getLogManager()&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;This bug was actually reported by a customer, see &lt;a href="http://bugs.sun.com/view_bug.do?bug_id=6487638"&gt;bug report&lt;/a&gt;, and was fixed in 6u11 and 5.0u18. The LogManager now no longer calls &lt;tt&gt;Logger.getLogger()&lt;/tt&gt;, so there's no locking of &lt;tt&gt;Logger.class&lt;/tt&gt; anymore.&lt;/p&gt;
&lt;h3&gt;Deadlock in GlassFish&lt;/h3&gt;
&lt;p&gt;GlassFish installs its own &lt;tt&gt;LogManager&lt;/tt&gt;, and there's some locking going on there too. It has an internal lock which it locks in &lt;tt&gt;addLogger()&lt;/tt&gt;:&lt;/p&gt;&lt;pre&gt;    public boolean addLogger(Logger logger) {
...
    super.addLogger(logger);
...
    synchronized (_unInitializedLoggers) {
...
        doInitializeLogger(logger);
    }
}
&lt;/pre&gt;
&lt;p&gt;And this calls &lt;tt&gt;Logger.getLogger()&lt;/tt&gt; again.&lt;/p&gt;&lt;pre&gt;    protected void doInitializeLogger(Logger logger) {
...
    Logger newLogger =
        Logger.getLogger(logger.getName(), 
            getLoggerResourceBundleName(logger.getName()));
...
    }
&lt;/pre&gt;
&lt;p&gt;As a developer of the custom logger, we can still use the same fix: first lock &lt;tt&gt;Logger.class&lt;/tt&gt; before calling &lt;tt&gt;addLogger()&lt;/tt&gt; so that the locking sequence becomes: &lt;tt&gt;Logger.class&lt;/tt&gt;, transient lock on &lt;tt&gt;LogManager.getLogManager()&lt;/tt&gt; followed by a lock on &lt;tt&gt;_unInitializedLoggers&lt;/tt&gt;, lock on &lt;tt&gt;Logger.class()&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;A fix in GlassFish would simply make &lt;tt&gt;addLogger()&lt;/tt&gt; synchronized. An alternative fix is to make the &lt;tt&gt;synchronized&lt;/tt&gt; block smaller: it should not extend over &lt;tt&gt;doInitializeLogger()&lt;/tt&gt;.&lt;/p&gt;
&lt;h3&gt;Deadlock with the IBM JDK&lt;/h3&gt;
&lt;p&gt;All was well until this was run on the IBM JDK. As it turns out, &lt;tt&gt;Logger.getLogger()&lt;/tt&gt; doesn't lock &lt;tt&gt;Logger.class&lt;/tt&gt;, it locks &lt;tt&gt;LogManager.getLogManager()&lt;/tt&gt;. Now there is a new deadlock: Thread 1 calls &lt;tt&gt;Logger.getLogger()&lt;/tt&gt; and by doing so, locks &lt;tt&gt;LogManager.getLogManager()&lt;/tt&gt;, and then tries to lock &lt;tt&gt;_unInitializedLoggers&lt;/tt&gt; and later tries to lock &lt;tt&gt;LogManager.getLogManager()&lt;/tt&gt; again. Thread 2 calls &lt;tt&gt;addLogger()&lt;/tt&gt; and by doing so locks first &lt;tt&gt;_unInitializedLoggers&lt;/tt&gt; which later tries to lock &lt;tt&gt;LogManager.getLogManager()&lt;/tt&gt;. The problem is back: the sequence of locking is reversed.&lt;/p&gt;
&lt;h3&gt;Lessons learned&lt;/h3&gt;
&lt;p&gt;The first lesson is that of the deadlock itself: one should be extremely careful when locking an object, and then calling into another object, especially if that object is meant to be a baseclass in a public API. Both &lt;tt&gt;Logger&lt;/tt&gt; and &lt;tt&gt;LogManager&lt;/tt&gt; may be overridden, and are clearly very public.&lt;/p&gt;
&lt;p&gt;The second lesson is that instead of building workarounds, try to get a fix the original bug. Or at least try to have the original issue addressed while adding a workaround. In my case, I never filed a ticket against the JDK or against GlassFish. I should have known better.&lt;/p&gt;
&lt;h3&gt;... or not?&lt;/h3&gt;
&lt;p&gt;At this very moment, GlassFish v2.1.1 is about to be shipped, and we need GlassFish v2.1.1 on AIX for the upcoming CAPS release. A bug fix in GlassFish v2.1.1 is probably not going to get in. So I'm making yet another workaround: don't use a custom logger at all as to avoid the whole &lt;tt&gt;addLogger()&lt;/tt&gt; problem. Instead, use standard &lt;tt&gt;Logger&lt;/tt&gt; objects, but provide a custom filter that manipulates the log record. This will work on both unpatched versions of GlassFish, and also on unpatched versions of the JDK. Still, I hope the GlassFish problem will be fixed.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-5256869402000288378?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/5256869402000288378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=5256869402000288378' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/5256869402000288378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/5256869402000288378'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/09/lessons-of-interesting-deadlock-problem.html' title='Lessons of an interesting deadlock problem'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-8252411750262836708</id><published>2009-08-28T12:48:00.001-07:00</published><updated>2009-08-28T12:48:15.093-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaOne'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>JavaOne 2009 TS-5341: Rethinking the ESB: lessons learned challenging the limitations and pitfalls – audio recording uploaded</title><content type='html'>&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_k73ELjWNXV8/Spg0fQneNzI/AAAAAAAAACU/6MWCSbd2vVE/s1600-h/image%5B2%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="92" alt="image" src="http://lh5.ggpht.com/_k73ELjWNXV8/Spg0freaeFI/AAAAAAAAACY/NbyiDeau_a4/image_thumb.png?imgmax=800" width="104" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;At JavaOne 2009 I gave a number of presentations. One was "Rethinking the ESB: lessons learned challenging the limitations and pitfalls" which I did with Andi Egloff. JavaOne sessions were not recorded this year, that is not by the JavaOne Organization. But I used an mp3 player to record the sessions I was involved in. I finally processed the audio and uploaded it. I also uploaded a PDF of the presentation:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://mediacast.sun.com/users/Frank.Kieviet/media/TS-5341.pdf"&gt;Presentation (PDF) of TS-5341 Rethinking the ESB: lessons learned challenging the limitations and pitfalls&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://mediacast.sun.com/users/Frank.Kieviet/media/JavaOne2009-LessonsLearned/details"&gt;Audio recording (mp3) of TS-5341 Rethinking the ESB: lessons learned challenging the limitations and pitfalls&lt;/a&gt;&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/6643071316318130698-8252411750262836708?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/8252411750262836708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=8252411750262836708' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/8252411750262836708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/8252411750262836708'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/08/javaone-2009-ts-5341-rethinking-esb.html' title='JavaOne 2009 TS-5341: Rethinking the ESB: lessons learned challenging the limitations and pitfalls – audio recording uploaded'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_k73ELjWNXV8/Spg0freaeFI/AAAAAAAAACY/NbyiDeau_a4/s72-c/image_thumb.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-669353453491867504</id><published>2009-08-06T10:08:00.001-07:00</published><updated>2009-08-06T10:10:20.194-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>Message interceptors with JMS</title><content type='html'>&lt;p&gt;Interceptors are a way to add behavior to a system without directly invoking this behavior in from code. The typical anti-example is that if you would want to log the entry and exit of methods on a class, you could do that of course by adding log statements in each and every method. The downside is that you would have to change each and every method, and that all these methods now have repetitive code in there. With the interceptor approach on the other hand, you could do that by adding an interceptor that is invoked before and after the method is invoked. In the code of the interceptor you would then add the log statement. The advantage is that the existing methods are not changed, that repetitive code is avoided, and that the logging &lt;em&gt;concern&lt;/em&gt; is concentrated in one part of the code base rather than spread all over.&lt;/p&gt; &lt;p&gt;I think that this logging example is pretty dumb, but I guess it drives home the message of adding behavior non-invasively, and a separation of concerns. I'll discuss some more interesting examples in a minute.&lt;/p&gt; &lt;h4&gt;Interceptors in EE&lt;/h4&gt; &lt;p&gt;Interceptors have long been the domain of AOP (Aspect Oriented Programming) packages that add interceptors through byte code manipulation, either at runtime or as a post-compile step. For EE developers, things changed with the advent of EE5 in which interceptors were added to EJBs.&lt;/p&gt; &lt;p&gt;An interceptor can be added to all the methods or individual methods of an EJB by adding an annotation to either the class or to individual methods. In the following example, the &lt;tt&gt;NoConcurrency&lt;/tt&gt; interceptor is invoked when the &lt;tt&gt;getUnclaimedAccounts()&lt;/tt&gt; method is called.&lt;/p&gt;&lt;pre&gt;@Interceptors(NoConcurrency.class)&lt;br&gt;public void getUnclaimedAccounts(String category) {...&lt;/pre&gt;
&lt;p&gt;The interceptor class is a simple Java class that has to have a method with the following signature:&lt;/p&gt;&lt;pre&gt;@AroundInvoke&lt;br&gt;Object &amp;lt;METHOD&amp;gt;(javax.interceptor.InvocationContext) throws Exception&lt;/pre&gt;
&lt;p&gt;The interceptor method is called when a client calls an EJB method. The interceptor typically calls &lt;tt&gt;InvocationContext.proceed()&lt;/tt&gt;. This will call into the EJB method (or the next interceptor, should there be one).&lt;/p&gt;
&lt;p&gt;Interceptor classes are typically packaged as part of an EAR file: they are part of the application.&lt;/p&gt;
&lt;p&gt;Interceptors are referenced in an EJB using the &lt;tt&gt;@Interceptors&lt;/tt&gt; annotation. They can also be referenced from the EJB's deployment descriptor. In either case, &lt;strong&gt;the application needs to be modified to specify interceptors&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Another limitation of EJB interceptors is that they &lt;strong&gt;only work on EJB methods&lt;/strong&gt;. When common behavior needs to be added to other interactions, for instance if an EJB invokes something like an outbound resource adapter, a different mechanism must be used.&lt;/p&gt;
&lt;h4&gt;Interceptors in CAPS&lt;/h4&gt;
&lt;p&gt;A Java CAPS customer had an interesting case for using interceptors. The customer had hundreds of integration applications that all received and sent JMS messages. If a message cannot be processed, the message is sent to an error handling system using JMSJCA's dead letter queue facility. An operator will monitor the dead letter queue, and may resubmit the message. If a resubmitted message is processed successfully, the error handling system needs to be notified of that fact. One way of adding this behavior would be to add a chunk of code to all MDBs. That would of course lead to a lot of duplicated code. It also leads to mixing this system level behavior with the business logic in the integration applications. This is clearly undesirable.&lt;/p&gt;
&lt;p&gt;Because Repository based projects in Java CAPS generate all the MDB code and assembles the applications, it is difficult to make use of EJB interceptors. What is needed is to specify the use of interceptors on a global basis, that is outside of the applications, and preferably for all applications at the same time.&lt;/p&gt;
&lt;p&gt;Another requirement is that the customer wanted to add common behavior not just when messages are received, but also when messages were sent from an EJB. Upon sending a message, payload validation should happen. Since EJB interceptors can only be used for EJB methods, this was another reason that EJB interceptors could not be used.&lt;/p&gt;
&lt;p&gt;The solution was to add a new feature to JMSJCA to support interceptors.&lt;/p&gt;
&lt;h4&gt;Interceptors in JMSCA&lt;/h4&gt;
&lt;p&gt;Interceptors in JMSJCA are invoked not only before / after a message is delivered to the MDB, but also any time a message is sent.&lt;/p&gt;
&lt;p&gt;Rather than introducing a new Java interface, which would bring with it the complication of compile time dependencies on JMSJCA jars, the JMSJCA interceptors use the same annotations as in EJB3: any class with a method with the right signature and the &lt;tt&gt;@AroundInvoke&lt;/tt&gt; annotation can serve as an interceptor.&lt;/p&gt;
&lt;p&gt;Which classes will JMSJCA consider as interceptors? For this, it uses the service locator mechanism from JDK 6. This is done without introducing dependencies on JDK 6 by the way. With the service locator mechanism, a jar that holds the interceptor should have a special manifest file that lists the class names of the interceptors. The name of this manifest should be &lt;tt&gt;META-INF/services/myinterceptor&lt;/tt&gt; where &lt;tt&gt;myinterceptor&lt;/tt&gt; is the name of the interceptor. This name needs to be specified in the JMSJCA configuration. If no name is specified, the default name &lt;tt&gt;jmsjca.interceptor&lt;/tt&gt; is used. This means that interceptors using the service name &lt;tt&gt;jmsjca.interceptor&lt;/tt&gt; are automatically loaded and invoked if not overridden in the JMSJCA configuration.&lt;/p&gt;
&lt;p&gt;With this, it's easy to add interceptors to all applications running in the application server, whenever they send or receive messages through JMSJCA, without having to change any application.&lt;/p&gt;
&lt;p&gt;For more information, see &lt;a href="http://jmsjca.dev.java.net/"&gt;http://jmsjca.dev.java.net/&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/6643071316318130698-669353453491867504?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/669353453491867504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=669353453491867504' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/669353453491867504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/669353453491867504'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/08/message-interceptors-with-jms.html' title='Message interceptors with JMS'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-4556305305961095850</id><published>2009-05-31T19:46:00.001-07:00</published><updated>2009-05-31T19:46:34.072-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaOne'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>JavaOne 2009</title><content type='html'>&lt;p&gt;I'm writing this on my way to JavaOne 2009. San Francisco airport was fogged in so my flight was cancelled. I have some time to burn: I'm waiting for a train to take me from Santa Clara to San Francisco.&lt;/p&gt; &lt;p&gt;As usual it has been immensely busy in the two months before JavaOne. &lt;/p&gt; &lt;p&gt;For this JavaOne, I'm the lead of the SOA/Services track. A track lead is responsible for assembling a program of sessions and BOFs. Or in more practical terms, going through the proposals with the other volunteers that make up the selection committee, and picking the proposals so that not only the quality but also the variety of the track is optimal. The selection committee consists of subject matter experts. There are three from Sun and four from other companies: RedHat, Cap Gemini, Adobe.&lt;/p&gt; &lt;p&gt;This year there again were many hundreds of proposals for sessions and BOFs. Going through them to make a first cut took a lot of time. Refining the first cut to the final selection is difficult: there were many good and interesting proposals. But in the end only 22 sessions could prevail. Getting consensus on the selections, scheduling them, ensuring that presentations are ready, reviewing the presentations, the inevitable change requests, etc. took a lot more time than I expected. But I think these efforts have paid off: I think we have a very interesting lineup of presentations.&lt;/p&gt; &lt;p&gt;My second JavaOne activity is presenting at Java University, the day before JavaOne. Like last year, Joe Boulenouar invited me to present a few hours on SOA and integration middleware. The course title is "Using Java EE and SOA to Help Architect and Design Robust Enterprise Applications." Last year there were four hundred or so people in attendance. I haven't heard yet how many people there will be this year. Perhaps fewer on account of the poor the economy.&lt;/p&gt; &lt;p&gt;Thirdly, I'm presenting a session titled "Glassfish ESB: get your apps on the bus". The original plan was that Keith Babo would pull that wagon, but unfortunately he had to pull out. I'm now doing that session with Sujit Biswas. In this session I'm making a case for ESBs or integration middleware in general. This has led me to some more thoughts on how we can widen the applicability of ESBs. More about that in a future post.&lt;/p&gt; &lt;p&gt;I'm also doing a session titled "Rethinking the ESB: lessons learned challenging the limitations and pitfalls". Andi Egloff is co-presenter. The idea of this session is to show a number of things that went wrong in previous product releases and how we changed that in subsequent releases. The interesting part for the audience is that it gives a set of requirements or "things to avoid" in middleware products.&lt;/p&gt; &lt;p&gt;The fifth activity I'm involved in is the OpenESB community BOF. The idea of this BOF is to discuss experiences with OpenESB and discuss what's on the wish list for OpenESB.&lt;/p&gt; &lt;p&gt;So, yes, it was busy running up to JavaOne. I'm sure that JavaOne itself will also be very busy: not only will there be the presentations I need to give, others I have to be in attendance for, but there will also be the numerous customer meetings. &lt;/p&gt; &lt;p&gt;I think I'll need a break after JavaOne!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-4556305305961095850?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/4556305305961095850/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=4556305305961095850' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/4556305305961095850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/4556305305961095850'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/05/javaone-2009.html' title='JavaOne 2009'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-7253626682855273103</id><published>2009-03-22T12:50:00.001-07:00</published><updated>2009-03-22T12:50:12.590-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>The java.lang.LinkageError: loader constraint violation" demystified</title><content type='html'>&lt;p&gt;My colleague Murali Pottlapelli ran into an interesting problem the other day. He added Rhino to his BPEL Service Engine, and saw this error happen:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;tt&gt;java.lang.LinkageError: loader constraint violation: loader (instance of &amp;lt;bootloader&amp;gt;) previously initiated loading for a different type with name "org/w3c/dom/UserDataHandler"&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The weird thing was that this exception was thrown from a call to &lt;font face="Courier New"&gt;Class.getMethods()&lt;/font&gt; on a class shipped with the JVM!&lt;/p&gt; &lt;p&gt;Googling this problem revealed that there are a lot of people running into this issue, often when using OSGi. Most search results referred to email lists postings where people ran into this problem. None of the web pages properly explained what the problem was. Intuitively I felt we could solve our problem by moving a jar to a different classloader, but was that merely &lt;em&gt;hiding&lt;/em&gt; the problem? As with my post on "&lt;a href="http://blogs.sun.com/fkieviet/entry/classloader_leaks_the_dreaded_java"&gt;How to fix the dreaded "java.lang.OutOfMemoryError: PermGen space" exception (classloader leaks)&lt;/a&gt;", I was convinced that &lt;em&gt;understanding the problem&lt;/em&gt; is key. So Murali and I set out to dig in this problem deeper until we completely grasped it.&lt;/p&gt; &lt;p&gt;As it turns out, there are some aspects about this problem that make it very confusing:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;In a dynamic component system, a change in one component may cause the other components to fail in areas that used to work properly before. At the same time, the changed component appears to be working properly.  &lt;li&gt;The order in which components are activated determines where and how the problem shows up.  &lt;li&gt;The effects of the problem may show up in innocuous and seemingly unrelated calls such as &lt;font face="Courier New"&gt;Class.getMethods()&lt;/font&gt;.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;In the following sections I'll first illustrate the problem, and then explain in detail what's causing the problem.&lt;/p&gt; &lt;h4&gt;The problem&lt;/h4&gt; &lt;p&gt;Let's look at a model example. In stead of looking at an OSGi example or a JBI example, let's look at EE because it will be more familiar. Imagine we have an EAR file with an EJB and two WAR files. The WAR files are identical, and have a servlet that uses an EJB to log in. As such we have three classes:&lt;/p&gt; &lt;p style="margin-bottom: 0in" align="left"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; User {&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in" align="left"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in" align="left"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; LoginEJB {&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;&lt;font color="#000000"&gt;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; {&lt;br&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font color="#000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;System.&lt;/font&gt;&lt;font color="#0000c0"&gt;&lt;i&gt;out&lt;/i&gt;&lt;/font&gt;&lt;font color="#000000"&gt;.println(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"LoginEJB loaded"&lt;/font&gt;&lt;font color="#000000"&gt;);&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;}&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt; &lt;p style="margin-bottom: 0in" align="left"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;&lt;font color="#000000"&gt;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; login(User u) {&lt;br&gt;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;}&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in" align="left"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in" align="left"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; Servlet {&lt;br&gt;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; doGet() {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;User u = &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt; User();&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;System.&lt;/font&gt;&lt;font color="#0000c0"&gt;&lt;i&gt;out&lt;/i&gt;&lt;/font&gt;&lt;font color="#000000"&gt;.println(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"User in "&lt;/font&gt;&lt;font color="#000000"&gt; + u.getClass().getClassLoader());&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;LoginEJB.&lt;i&gt;login&lt;/i&gt;(u);&lt;br&gt;&amp;nbsp; &lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;}&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;}&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;Let's say that one WAR is configured with a self-first classloader, and the other one uses the default parent-first class loading model.&lt;br&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_k73ELjWNXV8/ScaWbxppC4I/AAAAAAAAAB0/xf-ceLc-NmA/s1600-h/image%5B4%5D.png"&gt;&lt;img title="image" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="374" alt="image" src="http://lh4.ggpht.com/_k73ELjWNXV8/ScaWcqV_WtI/AAAAAAAAAB4/LvQ9L4LBzCw/image_thumb%5B2%5D.png?imgmax=800" width="223" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Now consider these three scenarios:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;We log in using the parent-first servlet, and then inspect the EJB with &lt;font face="Courier New"&gt;Class.getMethods()&lt;/font&gt;. Everything works as expected, but when we then try to login on the second servlet, we see the linkage error.  &lt;li&gt;We log in using the self-first servlet. Then when we call &lt;font face="Courier New"&gt;Class.getMethods()&lt;/font&gt; on the EJB, this fails. Also, we can no longer log in on the parent-first servlet!  &lt;li&gt;We first call &lt;font face="Courier New"&gt;Class.getMethods()&lt;/font&gt; on the EJB. We can no longer login using the self-first servlet, but the parent-first servlet still works. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;What is going on? To explain, let's first revisit some classloader basics. If parent-first and self-first is in your daily vocabulary, feel free to skip the next section.&lt;/p&gt; &lt;h4&gt;Self-first versus parent-first delegation&lt;/h4&gt; &lt;p&gt;What is meant with self-first delegating classloaders? Here's the skinny on classloaders. In Java you can create your own classloader for two reasons: this allows multiple versions of the same class to co-exist in memory, as is often found in OSGi. It also allows classes to be unloaded, as is found in application servers. A classloader typically represents a set of jars that make up the module, the component, or the application. Each classloader must have a parent classloader. Hence, classloaders form a tree with the bootstrap classloader as the root. See the picture above.&lt;/p&gt; &lt;p&gt;When a classloader is asked to load a class, it can first ask its parent to load the class. If the parent fails to load the class, that classloader will then try to load the class. In this scheme, called &lt;strong&gt;parent-first&lt;/strong&gt; class loading, common classes are &lt;em&gt;always &lt;/em&gt;loaded by the parent classloader. This allows one application or module to talk to another application or module in the same VM.&lt;/p&gt; &lt;p&gt;Instead of asking the parent classloader first, a classloader can also try to find a class itself first, and only if it cannot find the class would it ask the parent classloader to find the class. A &lt;strong&gt;self-first&lt;/strong&gt; classloader allows for an application to have a different version of a class than found in the parent classloader.&lt;/p&gt; &lt;h4&gt;Classloader lab&lt;/h4&gt; &lt;p&gt;To show what's going on, I've developed a small demo that emulates the scenario with the two WARs and the EJB. Key in this demo is a custom classloader. The constructor takes a list of classes that should be &lt;em&gt;defined&lt;/em&gt; by that classloader, i.e. the classloader behaves as self-first for those classes, and delegates to the parent classloader for the other classes. The custom classloader is listed in the code at the bottom of this post.&lt;/p&gt; &lt;p&gt;This is how the system is setup: a classloader for the EJB that loads the &lt;font face="Courier New"&gt;LoginEJB&lt;/font&gt; and the &lt;font face="Courier New"&gt;User&lt;/font&gt; class. A classloader for the parent-first WAR that loads the &lt;font face="Courier New"&gt;Servlet&lt;/font&gt; only, and a self-first classloader that loads the &lt;font face="Courier New"&gt;Servlet&lt;/font&gt; and the &lt;font face="Courier New"&gt;User&lt;/font&gt; class.&lt;/p&gt;&lt;!-- =============================== --&gt;&lt;pre&gt;CustomCL ejbCL = &lt;span class="keyword-directive"&gt;new&lt;/span&gt; CustomCL(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;EJB  &lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, Demo.&lt;span class="keyword-directive"&gt;class&lt;/span&gt;.getClassLoader(), &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$User&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$LoginEJB&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;
CustomCL pfWebCL = &lt;span class="keyword-directive"&gt;new&lt;/span&gt; CustomCL(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;PFWeb&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, ejbCL, &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$Servlet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;
CustomCL sfWebCL = &lt;span class="keyword-directive"&gt;new&lt;/span&gt; CustomCL(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;SFWeb&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, ejbCL, &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$User&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$Servlet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;/pre&gt;&lt;!-- =============================== --&gt;
&lt;p&gt;The custom classloader prints all class loading requests so it can be easily seen what's happening. &lt;/p&gt;
&lt;h4&gt;Classloading eagerness&lt;/h4&gt;
&lt;p&gt;What exactly happens when the &lt;font face="Courier New"&gt;LoginEJB&lt;/font&gt; class is loaded? In the demo program, the following line causes the following output:&lt;/p&gt;&lt;font face="Courier New"&gt;ejbCL.loadClass(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$LoginEJB&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="keyword-directive"&gt;true&lt;/span&gt;).newInstance();&lt;br&gt;&lt;/font&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;EJB&amp;nbsp; : Loading com.stc.Demo$LoginEJB in custom classloader&lt;br&gt;EJB&amp;nbsp; : super.loadclass(java.lang.Object)&lt;br&gt;EJB&amp;nbsp; : super.loadclass(java.lang.System)&lt;br&gt;EJB&amp;nbsp; : super.loadclass(java.io.PrintStream)&lt;br&gt;LoginEJB loaded&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;When the JVM loads the &lt;font face="Courier New"&gt;LoginEJB&lt;/font&gt; class, it goes over references in the class and loads those classes too: the &lt;font face="Courier New"&gt;java.lang.Object&lt;/font&gt; class because it's the super class of the EJB, and the &lt;font face="Courier New"&gt;java.lang.System&lt;/font&gt; and &lt;font face="Courier New"&gt;java.io.PrintStream&lt;/font&gt; class because they are used in the static block. That these "JVM" classes are loaded is in itself remarkable and shows an interesting aspect of how classloading works. "JVM" classes are not treated specially, and it is not relevant that they are already loaded in the bootstrap classloader and are used all over the place.&lt;/p&gt;
&lt;p&gt;When the EJB classloader receives the request to load these "JVM" classes, that classloader &lt;em&gt;of course&lt;/em&gt; delegates those requests to the parent classloader. In fact, it's a &lt;em&gt;requirement&lt;/em&gt; to delegate all class load requests to the parent classloader for all classes that are in &lt;font face="Courier New"&gt;java.*&lt;/font&gt; and &lt;font face="Courier New"&gt;javax.*&lt;/font&gt;.&lt;/p&gt;
&lt;p&gt;Something also remarkable is what is &lt;em&gt;not&lt;/em&gt; loaded: the &lt;font face="Courier New"&gt;User&lt;/font&gt; class. Apparently, the fact that this class is used in a method is not enough to cause this class to be loaded when the EJB class is loaded. It is difficult to predict what classes are loaded as the result of loading a particular class. I think the spec leaves a lot of room to implementers to decide when to do so.&lt;/p&gt;
&lt;p&gt;It's important to realize that when the EJB class is loaded, the &lt;font face="Courier New"&gt;User&lt;/font&gt; class is &lt;em&gt;not&lt;/em&gt; loaded yet.&lt;/p&gt;
&lt;h4&gt;Linking classes&lt;/h4&gt;
&lt;p&gt;Next, let's use the parent-first Servlet to log in:&lt;/p&gt;&lt;font face="Courier New"&gt;pfWebCL.loadClass(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$Servlet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="keyword-directive"&gt;false&lt;/span&gt;).getMethod(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;doGet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;).invoke(&lt;span class="keyword-directive"&gt;null&lt;/span&gt;);&lt;br&gt;&lt;/font&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;PFWeb: Loading com.stc.Demo$Servlet in custom classloader&lt;br&gt;PFWeb: super.loadclass(java.lang.Object)&lt;br&gt;EJB&amp;nbsp; : already loaded(java.lang.Object)&lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;PFWeb: super.loadclass(com.stc.Demo$User)&lt;br&gt;EJB&amp;nbsp; : Loading com.stc.Demo$User in custom classloader&lt;br&gt;&lt;/strong&gt;PFWeb: super.loadclass(java.lang.System)&lt;br&gt;EJB&amp;nbsp; : already loaded(java.lang.System)&lt;br&gt;...&lt;br&gt;Logging in with User loaded in EJB&lt;br&gt;PFWeb: super.loadclass(com.stc.Demo$LoginEJB)&lt;br&gt;EJB&amp;nbsp; : already loaded(com.stc.Demo$LoginEJB)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Ignoring the "JVM" classes, it can be seen that the Servlet causes the User class to be loaded, and that that class is loaded in the EJB classloader. Nothing unexpected here.&lt;/p&gt;
&lt;p&gt;If &lt;em&gt;subsequently&lt;/em&gt; the self-first Servlet gets a go, the following happens:&lt;/p&gt;&lt;font face="Courier New"&gt;sfWebCL.loadClass(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$Servlet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="keyword-directive"&gt;false&lt;/span&gt;).getMethod(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;doGet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;).invoke(&lt;span class="keyword-directive"&gt;null&lt;/span&gt;);&lt;br&gt;&lt;/font&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;SFWeb: Loading com.stc.Demo$Servlet in custom classloader&lt;br&gt;SFWeb: super.loadclass(java.lang.Object)&lt;br&gt;EJB&amp;nbsp; : already loaded(java.lang.Object)&lt;br&gt;&lt;strong&gt;SFWeb: Loading com.stc.Demo$User in custom classloader&lt;br&gt;&lt;/strong&gt;SFWeb: super.loadclass(java.lang.System)&lt;br&gt;...&lt;br&gt;Logging in with User loaded in SFWeb&lt;br&gt;SFWeb: super.loadclass(com.stc.Demo$LoginEJB)&lt;br&gt;EJB&amp;nbsp; : already loaded(com.stc.Demo$LoginEJB)&lt;br&gt;&lt;strong&gt;java.lang.reflect.InvocationTargetException&lt;br&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)&lt;br&gt;...&lt;br&gt;&lt;strong&gt;Caused by: java.lang.LinkageError: loader constraints violated when linking com/stc/Demo$User class&lt;br&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at com.stc.Demo$Servlet.doGet(Demo.java:82)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ... 6 more&lt;/font&gt;&lt;font face="Courier New"&gt;&lt;br&gt;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The &lt;font face="Courier New"&gt;User&lt;/font&gt; class is loaded and defined in the self-first WAR classloader, and when the &lt;font face="Courier New"&gt;login()&lt;/font&gt; method is called, an instance of &lt;em&gt;that class&lt;/em&gt; is passed to the EJB. Why does the linkage error happen?&lt;/p&gt;
&lt;p&gt;When the parent-first servlet invoked the EJB, it passed in a &lt;font face="Courier New"&gt;User&lt;/font&gt; object. At that moment, the JVM links the reference to &lt;font face="Courier New"&gt;com.stc.Demo$User&lt;/font&gt; to a class instance. A class instance is identified using the fully qualified name &lt;em&gt;and&lt;/em&gt; the classloader instance in which it was loaded. Upon invocation of &lt;font face="Courier New"&gt;login(User)&lt;/font&gt;, the JVM will check that the class object of the &lt;font face="Courier New"&gt;User&lt;/font&gt; passed in, matches the class object that was linked to &lt;font face="Courier New"&gt;com.stc.Demo$User&lt;/font&gt;. If they don't match, the JVM will throw a &lt;font face="Courier New"&gt;LinkageError&lt;/font&gt;.&lt;/p&gt;
&lt;p&gt;This linking happened on the first invocation. We can also force the linking to happen by calling &lt;font face="Courier New"&gt;LoginEJB.class.getMethods()&lt;/font&gt;. I can illustrate that by changing the test program to fist inspect the EJB class, and then make the self-first servlet to login.&lt;/p&gt;&lt;font face="Courier New"&gt;
&lt;p style="margin-bottom: 0in"&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;System.&lt;font color="#0000c0"&gt;&lt;i&gt;out&lt;/i&gt;&lt;/font&gt;&lt;font color="#000000"&gt;.println(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"Loading EJB"&lt;/font&gt;&lt;font color="#000000"&gt;);&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;ejbCL.loadClass(&lt;font color="#2a00ff"&gt;"com.stc.Demo$LoginEJB"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;true&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;).newInstance();&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;System.&lt;font color="#0000c0"&gt;&lt;i&gt;out&lt;/i&gt;&lt;/font&gt;&lt;font color="#000000"&gt;.println(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"Examining methods of LoginEJB"&lt;/font&gt;&lt;font color="#000000"&gt;);&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;ejbCL.loadClass(&lt;font color="#2a00ff"&gt;"com.stc.Demo$LoginEJB"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;false&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;).getMethods();&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;System.&lt;font color="#0000c0"&gt;&lt;i&gt;out&lt;/i&gt;&lt;/font&gt;&lt;font color="#000000"&gt;.println(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"Logging in, self-first"&lt;/font&gt;&lt;font color="#000000"&gt;);&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;sfWebCL.loadClass(&lt;font color="#2a00ff"&gt;"com.stc.Demo$Servlet"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;false&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;).getMethod(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"doGet"&lt;/font&gt;&lt;font color="#000000"&gt;).invoke(&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;null&lt;/b&gt;&lt;/font&gt;);&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;/font&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;Loading EJB&lt;br&gt;EJB&amp;nbsp; : Loading com.stc.Demo$LoginEJB in custom classloader&lt;br&gt;LoginEJB loaded&lt;br&gt;Examining methods of LoginEJB&lt;br&gt;EJB&amp;nbsp; : already loaded(com.stc.Demo$LoginEJB)&lt;br&gt;&lt;strong&gt;EJB&amp;nbsp; : Loading com.stc.Demo$User in custom classloader&lt;br&gt;&lt;/strong&gt;Logging in&lt;br&gt;SFWeb: Loading com.stc.Demo$Servlet in custom classloader&lt;br&gt;&lt;strong&gt;SFWeb: Loading com.stc.Demo$User in custom classloader&lt;br&gt;&lt;/strong&gt;Logging in with User loaded in SFWeb&lt;br&gt;SFWeb: super.loadclass(com.stc.Demo$LoginEJB)&lt;br&gt;EJB&amp;nbsp; : already loaded(com.stc.Demo$LoginEJB)&lt;br&gt;&lt;strong&gt;java.lang.reflect.InvocationTargetException&lt;br&gt;Caused by: java.lang.LinkageError: loader constraints violated when linking com/stc/Demo$User class&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The login fails because the &lt;font face="Courier New"&gt;LoginEJB.class.getMethods() &lt;/font&gt;invocation causes the &lt;font face="Courier New"&gt;com.stc.Demo$User&lt;/font&gt; reference to be linked with the &lt;font face="Courier New"&gt;User&lt;/font&gt; class loaded in the EJB classloader. When the self-first servlet invokes the method, the two class objects don't match, causing the Error to be thrown.&lt;/p&gt;
&lt;h4&gt;Small mistake results in "poisoning" a shared class&lt;/h4&gt;
&lt;p&gt;By now it should be obvious that the User class should not have been packaged in the self-first WAR. What may not be obvious yet, is that this small mistake has big consequences. If a login happens on the self-first servlet before anything else, the linking happens with the erroneous &lt;font face="Courier New"&gt;User&lt;/font&gt; class object from the self-first classloader. This will cause the login of the parent-first WAR to fail. It will also cause the &lt;font face="Courier New"&gt;LoginEJB.class.getMethods() &lt;/font&gt;invocation to fail. &lt;/p&gt;&lt;!-- ============================================= --&gt;
&lt;style type="text/css"&gt;
&lt;!--
body {color: #000000; background-color: #ffffff; font-family: monospaced}
table {color: #000000; background-color: #e9e8e2; font-family: monospaced}
.comment {color: #969696}
.character {color: #ce7b00}
.keyword-directive {color: #0000e6}
body pre { overflow:auto; }
}
--&gt;
&lt;/style&gt;
&lt;font face="Courier New"&gt;
&lt;p style="margin-bottom: 0in"&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;System.&lt;/font&gt;&lt;font color="#0000c0"&gt;&lt;i&gt;out&lt;/i&gt;&lt;/font&gt;&lt;font color="#000000"&gt;.println(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"Loading EJB"&lt;/font&gt;&lt;font color="#000000"&gt;);&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;ejbCL.loadClass(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"com.stc.Demo$LoginEJB"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;true&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;).newInstance();&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;System.&lt;/font&gt;&lt;font color="#0000c0"&gt;&lt;i&gt;out&lt;/i&gt;&lt;/font&gt;&lt;font color="#000000"&gt;.println(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"Logging in, self-first"&lt;/font&gt;&lt;font color="#000000"&gt;);&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;sfWebCL.loadClass(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"com.stc.Demo$Servlet"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;false&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;).getMethod(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"doGet"&lt;/font&gt;&lt;font color="#000000"&gt;).invoke(&lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;null&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;);&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;System.&lt;/font&gt;&lt;font color="#0000c0"&gt;&lt;i&gt;out&lt;/i&gt;&lt;/font&gt;&lt;font color="#000000"&gt;.println(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"Examining methods of LoginEJB"&lt;/font&gt;&lt;font color="#000000"&gt;);&lt;br&gt;&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&lt;font face="Courier New, monospace"&gt;&lt;font size="2"&gt;ejbCL.loadClass(&lt;/font&gt;&lt;font color="#2a00ff"&gt;"com.stc.Demo$LoginEJB"&lt;/font&gt;&lt;font color="#000000"&gt;, &lt;/font&gt;&lt;font color="#7f0055"&gt;&lt;b&gt;false&lt;/b&gt;&lt;/font&gt;&lt;font color="#000000"&gt;).getMethods();&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;br&gt;&lt;/p&gt;&lt;/font&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;font face="Courier New"&gt;Loading EJB&lt;br&gt;EJB&amp;nbsp; : Loading com.stc.Demo$LoginEJB in custom classloader&lt;br&gt;LoginEJB loaded&lt;br&gt;Logging in, self-first&lt;br&gt;SFWeb: Loading com.stc.Demo$Servlet in custom classloader&lt;br&gt;&lt;strong&gt;SFWeb: Loading com.stc.Demo$User in custom classloader&lt;br&gt;&lt;/strong&gt;Logging in with User loaded in SFWeb&lt;br&gt;SFWeb: super.loadclass(com.stc.Demo$LoginEJB)&lt;br&gt;EJB&amp;nbsp; : already loaded(com.stc.Demo$LoginEJB)&lt;br&gt;Examining methods of LoginEJB&lt;br&gt;EJB&amp;nbsp; : already loaded(com.stc.Demo$LoginEJB)&lt;br&gt;&lt;strong&gt;EJB&amp;nbsp; : Loading com.stc.Demo$User in custom classloader&lt;br&gt;java.lang.LinkageError: Class com/stc/Demo$User violates loader constraints&lt;br&gt;&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at java.lang.ClassLoader.defineClass1(Native Method)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at java.lang.ClassLoader.defineClass(ClassLoader.java:620)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at java.lang.ClassLoader.defineClass(ClassLoader.java:465)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at com.stc.Demo$CustomCL.findClass(Demo.java:36)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at com.stc.Demo$CustomCL.loadClass(Demo.java:54)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at java.lang.ClassLoader.loadClass(ClassLoader.java:251)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at java.lang.Class.getDeclaredMethods0(Native Method)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at java.lang.Class.privateGetDeclaredMethods(Class.java:2395)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at java.lang.Class.privateGetPublicMethods(Class.java:2519)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at java.lang.Class.getMethods(Class.java:1406)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at com.stc.Demo.test1(Demo.java:98)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; at com.stc.Demo.main(Demo.java:111)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The first login with the self-first WAR has effectively poisoned the EJB, making it unusable. In everyday life, the problem is likely not so clear cut. For instance, a developer adds a jar to a component, or changes the classloading delegation model of a component, and all tests with that component may succeed. The problem may only show up in next day's build when integration tests are run. And as the example above shows, the stacktrace does not tell much about where the real cause of the error is.&lt;/p&gt;
&lt;h4&gt;Formalization and references&lt;/h4&gt;
&lt;p&gt;A formal description of loading constraints can be found in detail in section 5.3.4 of The Java Virtual Machine Specification (online available at &lt;a title="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html" href="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html"&gt;http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html&lt;/a&gt;). In simple words, a linkage error can occur if two different classes interact with each other, and in this interaction the classes refer to types with the same symbolic name but with different class objects. In the example,&amp;nbsp; the self-first servlet referred to &lt;font face="Courier New"&gt;EJB:LoginEJB.login(sfWeb:User)&lt;/font&gt;, but the EJB's representation was &lt;font face="Courier New"&gt;EJB:loginEJB(EJB:User)&lt;/font&gt;.&lt;/p&gt;
&lt;p&gt;Other places where linkage errors may occur are in class hierarchies. If class &lt;font face="Courier New"&gt;Derived&lt;/font&gt; overrides a method &lt;font face="Courier New"&gt;f(A a, B b)&lt;/font&gt; in class &lt;font face="Courier New"&gt;Super&lt;/font&gt;, &lt;font face="Courier New"&gt;A&lt;/font&gt; and &lt;font face="Courier New"&gt;B&lt;/font&gt; as seen from &lt;font face="Courier New"&gt;Super&lt;/font&gt; must be the same &lt;font face="Courier New"&gt;A&lt;/font&gt; and &lt;font face="Courier New"&gt;B&lt;/font&gt; as seen from &lt;font face="Courier New"&gt;Derived&lt;/font&gt;. References to static variables are another example.&lt;/p&gt;
&lt;p&gt;More information can also be found in the book &lt;a href="http://www.amazon.com/Inside-Java-Virtual-Machine-Venners/dp/0071350934/ref=sr_1_2?ie=UTF8&amp;amp;s=books&amp;amp;qid=1237178714&amp;amp;sr=1-2"&gt;Inside the Java Virtual Machine&lt;/a&gt; by Bill Venners. Chapters from this book are also available at &lt;a href="http://www.artima.com/insidejvm/ed2/linkmod.html"&gt;Artima&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Classloader lab&lt;/h4&gt;
&lt;p&gt;If you like to experiment, here's the source of the Demo program. (&lt;a onclick="return toggledisplay('gfnbldoc');" href="javascript:none"&gt;click to expand&lt;/a&gt;)&lt;/p&gt;&lt;script&gt;
function toggledisplay(id) {
  var totoggle = document.getElementById(id);
  if (!totoggle.style.display || totoggle.style.display == 'none')  {
    totoggle.style.display = 'block'
  } else {
    totoggle.style.display = 'none'
  }
}
&lt;/script&gt;
&lt;div id="gfnbldoc" style="border-top-width: 1px; display: none; border-left-width: 1px; border-bottom-width: 1px; border-right-width: 1px"&gt;&lt;pre&gt;&lt;br&gt;
&lt;span class="keyword-directive"&gt;package&lt;/span&gt; com.stc;&lt;br&gt; &lt;br&gt; &lt;span class="keyword-directive"&gt;import&lt;/span&gt; java.io.InputStream;&lt;br&gt; &lt;span class="keyword-directive"&gt;import&lt;/span&gt; java.util.Arrays;&lt;br&gt; &lt;span class="keyword-directive"&gt;import&lt;/span&gt; java.util.HashSet;&lt;br&gt; &lt;span class="keyword-directive"&gt;import&lt;/span&gt; java.util.Set;&lt;br&gt; &lt;br&gt; &lt;span class="comment"&gt;/**&lt;/span&gt;&lt;br&gt; &lt;span class="comment"&gt; * &lt;/span&gt;&lt;span class="comment"&gt;Demonstrates&lt;/span&gt; &lt;span class="comment"&gt;Linkeage&lt;/span&gt; &lt;span class="comment"&gt;errors&lt;/span&gt;&lt;br&gt; &lt;span class="comment"&gt; * &lt;/span&gt;&lt;br&gt; &lt;span class="comment"&gt; * &lt;/span&gt;&lt;span class="ST0"&gt;@author&lt;/span&gt; &lt;span class="comment"&gt;fkieviet&lt;/span&gt;&lt;br&gt;  &lt;span class="comment"&gt;*/&lt;/span&gt;&lt;br&gt; &lt;span class="keyword-directive"&gt;public&lt;/span&gt; &lt;span class="keyword-directive"&gt;class&lt;/span&gt; Demo {&lt;br&gt;     &lt;span class="comment"&gt;/**&lt;/span&gt;&lt;br&gt; &lt;span class="comment"&gt;     * &lt;/span&gt;&lt;span class="comment"&gt;A&lt;/span&gt; &lt;span class="comment"&gt;self&lt;/span&gt;&lt;span class="comment"&gt;-&lt;/span&gt;&lt;span class="comment"&gt;first&lt;/span&gt; &lt;span class="comment"&gt;delegating&lt;/span&gt; &lt;span class="comment"&gt;classloader&lt;/span&gt;&lt;span class="comment"&gt;.&lt;/span&gt; &lt;span class="comment"&gt;It&lt;/span&gt; &lt;span class="comment"&gt;only&lt;/span&gt; &lt;span class="comment"&gt;loads&lt;/span&gt; &lt;span class="comment"&gt;specified&lt;/span&gt; &lt;span class="comment"&gt;classes&lt;/span&gt; &lt;span class="comment"&gt;self&lt;/span&gt;&lt;span class="comment"&gt;-&lt;/span&gt;&lt;span class="comment"&gt;first&lt;/span&gt;&lt;span class="comment"&gt;;&lt;/span&gt;&lt;br&gt; &lt;span class="comment"&gt;     * &lt;/span&gt;&lt;span class="comment"&gt;other&lt;/span&gt; &lt;span class="comment"&gt;classes&lt;/span&gt; &lt;span class="comment"&gt;are&lt;/span&gt; &lt;span class="comment"&gt;loaded&lt;/span&gt; &lt;span class="comment"&gt;from&lt;/span&gt; &lt;span class="comment"&gt;the&lt;/span&gt; &lt;span class="comment"&gt;parent&lt;/span&gt;&lt;span class="comment"&gt;.&lt;/span&gt; &lt;br&gt;      &lt;span class="comment"&gt;*/&lt;/span&gt;&lt;br&gt;     &lt;span class="keyword-directive"&gt;private&lt;/span&gt; &lt;span class="keyword-directive"&gt;static&lt;/span&gt; &lt;span class="keyword-directive"&gt;class&lt;/span&gt; CustomCL &lt;span class="keyword-directive"&gt;extends&lt;/span&gt; ClassLoader {&lt;br&gt;         &lt;span class="keyword-directive"&gt;private&lt;/span&gt; Set&amp;lt;String&amp;gt; selfFirstClasses;&lt;br&gt;         &lt;span class="keyword-directive"&gt;private&lt;/span&gt; String label;&lt;br&gt; &lt;br&gt;         &lt;span class="keyword-directive"&gt;public&lt;/span&gt; CustomCL(String name, ClassLoader parent, String... selfFirsNames) {&lt;br&gt;             &lt;span class="keyword-directive"&gt;super&lt;/span&gt;(parent);&lt;br&gt;             &lt;span class="keyword-directive"&gt;this&lt;/span&gt;.label = name;&lt;br&gt;             &lt;span class="keyword-directive"&gt;this&lt;/span&gt;.selfFirstClasses = &lt;span class="keyword-directive"&gt;new&lt;/span&gt; HashSet&amp;lt;String&amp;gt;(Arrays.asList(selfFirsNames));&lt;br&gt;         }&lt;br&gt; &lt;br&gt;         &lt;span class="keyword-directive"&gt;public&lt;/span&gt; Class&amp;lt;?&amp;gt; findClass(String name) &lt;span class="keyword-directive"&gt;throws&lt;/span&gt; ClassNotFoundException {&lt;br&gt;             &lt;span class="keyword-directive"&gt;if&lt;/span&gt; (selfFirstClasses.contains(name)) {&lt;br&gt;                 &lt;span class="keyword-directive"&gt;try&lt;/span&gt; {&lt;br&gt;                     &lt;span class="keyword-directive"&gt;byte&lt;/span&gt;[] buf = &lt;span class="keyword-directive"&gt;new&lt;/span&gt; &lt;span class="keyword-directive"&gt;byte&lt;/span&gt;[100000];&lt;br&gt;                     String loc = name.replace(&lt;span class="character"&gt;'.'&lt;/span&gt;, &lt;span class="character"&gt;'/'&lt;/span&gt;) + &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;.class&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;;&lt;br&gt;                     InputStream inp = Demo.&lt;span class="keyword-directive"&gt;class&lt;/span&gt;.getClassLoader().getResourceAsStream(loc);&lt;br&gt;                     &lt;span class="keyword-directive"&gt;int&lt;/span&gt; n = inp.read(buf);&lt;br&gt;                     inp.close();&lt;br&gt;                     System.out.println(label + &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;: Loading &lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt; + name + &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt; in custom classloader&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;                     &lt;span class="keyword-directive"&gt;return&lt;/span&gt; defineClass(name, buf, 0, n);&lt;br&gt;                 } &lt;span class="keyword-directive"&gt;catch&lt;/span&gt; (Exception e) {&lt;br&gt;                     &lt;span class="keyword-directive"&gt;throw&lt;/span&gt; &lt;span class="keyword-directive"&gt;new&lt;/span&gt; ClassNotFoundException(name, e);&lt;br&gt;                 }&lt;br&gt;             }&lt;br&gt; &lt;br&gt;             &lt;span class="comment"&gt;// Is never executed in this test&lt;/span&gt;&lt;br&gt;             &lt;span class="keyword-directive"&gt;throw&lt;/span&gt; &lt;span class="keyword-directive"&gt;new&lt;/span&gt; ClassNotFoundException(name);&lt;br&gt;         }&lt;br&gt; &lt;br&gt;         &lt;span class="keyword-directive"&gt;public&lt;/span&gt; Class&amp;lt;?&amp;gt; loadClass(String name, &lt;span class="keyword-directive"&gt;boolean&lt;/span&gt; resolve) &lt;span class="keyword-directive"&gt;throws&lt;/span&gt; ClassNotFoundException {&lt;br&gt;             &lt;span class="keyword-directive"&gt;if&lt;/span&gt; (findLoadedClass(name) != &lt;span class="keyword-directive"&gt;null&lt;/span&gt;) {&lt;br&gt;                 System.out.println(label + &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;: already loaded(&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt; + name + &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;)&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;                 &lt;span class="keyword-directive"&gt;return&lt;/span&gt; findLoadedClass(name);&lt;br&gt;             }&lt;br&gt; &lt;br&gt;             &lt;span class="comment"&gt;// Override parent-first behavior into self-first only for specified classes&lt;/span&gt;&lt;br&gt;             &lt;span class="keyword-directive"&gt;if&lt;/span&gt; (selfFirstClasses.contains(name)) {&lt;br&gt;                 &lt;span class="keyword-directive"&gt;return&lt;/span&gt; findClass(name);&lt;br&gt;             } &lt;span class="keyword-directive"&gt;else&lt;/span&gt; {&lt;br&gt;                 System.out.println(label + &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;: super.loadclass(&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt; + name + &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;)&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;                 &lt;span class="keyword-directive"&gt;return&lt;/span&gt; &lt;span class="keyword-directive"&gt;super&lt;/span&gt;.loadClass(name, resolve);&lt;br&gt;             }&lt;br&gt;         }&lt;br&gt; &lt;br&gt;         &lt;span class="keyword-directive"&gt;public&lt;/span&gt; String toString() {&lt;br&gt;             &lt;span class="keyword-directive"&gt;return&lt;/span&gt; label;&lt;br&gt;         }&lt;br&gt;     }&lt;br&gt; &lt;br&gt; &lt;br&gt;     &lt;span class="keyword-directive"&gt;public&lt;/span&gt; &lt;span class="keyword-directive"&gt;static&lt;/span&gt; &lt;span class="keyword-directive"&gt;class&lt;/span&gt; User {&lt;br&gt;     }&lt;br&gt;     &lt;br&gt;     &lt;span class="keyword-directive"&gt;public&lt;/span&gt; &lt;span class="keyword-directive"&gt;static&lt;/span&gt; &lt;span class="keyword-directive"&gt;class&lt;/span&gt; LoginEJB {&lt;br&gt;         &lt;span class="keyword-directive"&gt;static&lt;/span&gt; {&lt;br&gt;             System.out.println(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;LoginEJB loaded&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;         }&lt;br&gt;         &lt;span class="keyword-directive"&gt;public&lt;/span&gt; &lt;span class="keyword-directive"&gt;static&lt;/span&gt; &lt;span class="keyword-directive"&gt;void&lt;/span&gt; login(User u) {&lt;br&gt;         }&lt;br&gt;     }&lt;br&gt;     &lt;br&gt;     &lt;span class="keyword-directive"&gt;public&lt;/span&gt; &lt;span class="keyword-directive"&gt;static&lt;/span&gt; &lt;span class="keyword-directive"&gt;class&lt;/span&gt; Servlet {&lt;br&gt;         &lt;span class="keyword-directive"&gt;public&lt;/span&gt; &lt;span class="keyword-directive"&gt;static&lt;/span&gt; &lt;span class="keyword-directive"&gt;void&lt;/span&gt; doGet() {&lt;br&gt;             User u = &lt;span class="keyword-directive"&gt;new&lt;/span&gt; User();&lt;br&gt;             System.out.println(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;Logging in with User loaded in &lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt; + u.getClass().getClassLoader());&lt;br&gt;             LoginEJB.login(u);&lt;br&gt;         }&lt;br&gt;     }&lt;br&gt;     &lt;br&gt;     &lt;span class="keyword-directive"&gt;public&lt;/span&gt; &lt;span class="keyword-directive"&gt;static&lt;/span&gt; &lt;span class="keyword-directive"&gt;void&lt;/span&gt; test1() &lt;span class="keyword-directive"&gt;throws&lt;/span&gt; Exception {&lt;br&gt;         CustomCL ejbCL = &lt;span class="keyword-directive"&gt;new&lt;/span&gt; CustomCL(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;EJB  &lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, Demo.&lt;span class="keyword-directive"&gt;class&lt;/span&gt;.getClassLoader(), &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$User&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$LoginEJB&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;         CustomCL pfWebCL = &lt;span class="keyword-directive"&gt;new&lt;/span&gt; CustomCL(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;PFWeb&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, ejbCL, &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$Servlet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;         CustomCL sfWebCL = &lt;span class="keyword-directive"&gt;new&lt;/span&gt; CustomCL(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;SFWeb&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, ejbCL, &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$User&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$Servlet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt; &lt;br&gt;         System.out.println(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;Loading EJB&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;         ejbCL.loadClass(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$LoginEJB&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="keyword-directive"&gt;true&lt;/span&gt;).newInstance();&lt;br&gt;         &lt;br&gt;         System.out.println(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;Logging in, self-first&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;         sfWebCL.loadClass(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$Servlet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="keyword-directive"&gt;false&lt;/span&gt;).getMethod(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;doGet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;).invoke(&lt;span class="keyword-directive"&gt;null&lt;/span&gt;);&lt;br&gt;         &lt;br&gt;         System.out.println(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;Examining methods of LoginEJB&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;         ejbCL.loadClass(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$LoginEJB&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="keyword-directive"&gt;false&lt;/span&gt;).getMethods();&lt;br&gt; &lt;br&gt;         System.out.println(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;Logging in&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;);&lt;br&gt;         pfWebCL.loadClass(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;com.stc.Demo$Servlet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;, &lt;span class="keyword-directive"&gt;false&lt;/span&gt;).getMethod(&lt;span class="character"&gt;"&lt;/span&gt;&lt;span class="character"&gt;doGet&lt;/span&gt;&lt;span class="character"&gt;"&lt;/span&gt;).invoke(&lt;span class="keyword-directive"&gt;null&lt;/span&gt;);&lt;br&gt;     }&lt;br&gt;     &lt;br&gt;     &lt;span class="keyword-directive"&gt;public&lt;/span&gt; &lt;span class="keyword-directive"&gt;static&lt;/span&gt; &lt;span class="keyword-directive"&gt;void&lt;/span&gt; main(String[] args) {&lt;br&gt;         &lt;span class="keyword-directive"&gt;try&lt;/span&gt; {&lt;br&gt;             test1();&lt;br&gt;         } &lt;span class="keyword-directive"&gt;catch&lt;/span&gt; (Throwable e) {&lt;br&gt;             e.printStackTrace(System.out);&lt;br&gt;         }&lt;br&gt;     }&lt;br&gt; }&lt;br&gt; &lt;/pre&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-7253626682855273103?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/7253626682855273103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=7253626682855273103' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/7253626682855273103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/7253626682855273103'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/03/javalanglinkageerror-loader-constraint.html' title='The java.lang.LinkageError: loader constraint violation&amp;quot; demystified'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_k73ELjWNXV8/ScaWcqV_WtI/AAAAAAAAAB4/LvQ9L4LBzCw/s72-c/image_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-261878745237716211</id><published>2009-03-19T13:20:00.001-07:00</published><updated>2009-03-19T13:20:02.866-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><title type='text'>Time running backwards in Microsoft's Hyper-V</title><content type='html'>&lt;p&gt;You would think that subsequent calls to &lt;tt&gt;System.nanoTime()&lt;/tt&gt; would return ever increasing values. After all, time cannot run backwards. However, when you run a JVM on the Hyper-V virtualization platform, it turns out that time may actually run backwards.&lt;/p&gt; &lt;p&gt;Hence, if you use this timer to measure time differences, you need to account for negative differences. This was a problem that I had not accounted for in the Hulp Measuring package.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-261878745237716211?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/261878745237716211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=261878745237716211' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/261878745237716211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/261878745237716211'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/03/time-running-backwards-in-microsoft.html' title='Time running backwards in Microsoft&amp;#39;s Hyper-V'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-3132265615451206927</id><published>2009-03-17T10:06:00.001-07:00</published><updated>2009-03-17T10:06:58.916-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>Interview with DZone</title><content type='html'>&lt;p&gt;Last week &lt;a href="http://soa.dzone.com/users/Kalali"&gt;Masoud Kalali&lt;/a&gt; asked me for an interview about OpenESB. Today the &lt;a href="http://soa.dzone.com/articles/qa-interview-frank-kieviet"&gt;interview was published&lt;/a&gt;. Nothing new for those that already known OpenESB and Java CAPS, but for people who look at it for the first time it may provide some useful background information.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-3132265615451206927?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/3132265615451206927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=3132265615451206927' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/3132265615451206927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/3132265615451206927'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/03/interview-with-dzone.html' title='Interview with DZone'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-7769846897030575713</id><published>2009-01-20T15:27:00.001-08:00</published><updated>2009-01-20T15:36:24.057-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>An interactive Regular Expression Editor</title><content type='html'>&lt;p&gt;The other day I had to filter an HTTP access log. I figured I could write a dozen or two lines of Java code to do the job, to be written with a dozen or so test-fix cycles. But I also knew that it could be done in just a few lines when using a regular expression. The things that I don't like about using regular expressions in Java code is the fact that the regular expression becomes difficult to edit because the backslash and quote characters need to be escaped with an extra backslash, and secondly I typically need even more test-fix cycles to get the expression right. Thirdly, a non-trivial regular expression becomes difficult to read. &lt;br&gt;&lt;/p&gt; &lt;p&gt;It occurred to me that much of my reservations could be eliminated with an interactive editor that would allow me to edit the regular expression in plain text, and that would show me the results immediately. Since I've been wanting to look at NetBeans' Matisse editor, I thought I'd be able to whip out an editor in less than half an hour, and by doing so, save time not just for the project I was working on, but also for whenever I need to edit a regular expression in the future.&lt;/p&gt; &lt;p&gt;The Matisse editor in NetBeans is as easy as advertised. It took me only minutes to put together a basic editor. To my satisfaction, the time savings in editing regular expressions immediately proved to be enormous!&lt;/p&gt; &lt;p&gt;That was a few weeks ago. This week I was on vacation, and to kill time in the airplane, I've been upgrading this editor further. What I've added is the ability to convert the regular expression in the editor and convert it into Java. That is, the tool now takes care of escaping special characters such as backslashes. The tool is now sort of a code generator. But how about round-trip engineering? I also threw in an option to take a snippet of Java code with a regular expression, and remove the escaping characters. This makes it easy when you later need to revisit a regular expression: you copy the expression from the Java code, paste it into the editor, hit &lt;em&gt;convert&lt;/em&gt; and you can edit the plain text regular expression. When done, generate the expression to Java code, paste it back in the Java source file.&lt;/p&gt; &lt;p&gt;Sounds easy, no? What else could you wish for? Of course the whole thing could be integrated into NetBeans and / or Eclipse. Maybe an exercise for another plain trip.&lt;/p&gt; &lt;h3&gt;Use the Interactive Regular Expression Editor!&lt;/h3&gt; &lt;p&gt;I’ve made the application into a JNLP application, so you can launch it from the browser.&lt;/p&gt; &lt;p&gt;&lt;a href="http://mediacast.sun.com/users/Frank.Kieviet/media/regex.jnlp"&gt;Launch Interactive Regular Expression Editor&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://mediacast.sun.com/users/Frank.Kieviet/media/regex.jnlp"&gt;&lt;img title="Sample screenshot. Click to launch the editor" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="596" alt="Sample screenshot. Click to launch the editor" src="http://lh4.ggpht.com/_k73ELjWNXV8/SXZd1HDJAzI/AAAAAAAAABo/-cEEQNn9o28/image4.png?imgmax=800" width="670" border="0"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;How do you use the editor? The screen consists of three edit panes. The middle editor is where you edit the regular expression. Any time that you change the expression, the sample input in the top pane is evaluated, and the results are displayed in the bottom edit pane. When you're done editing the expression, click the "generate" button, and Java code will appear in the bottom pane. Copy that code and use it in your Java programs. If you later on need to edit the expression again, simply paste the Pattern definition in the regular expression pane, and hit the "extract" button. The code in the middle pane will be replaced with the clear text version.&lt;/p&gt; &lt;h3&gt;Tips for working with Regular Expressions&lt;/h3&gt; &lt;p&gt;Here are some tips for working with regular expressions: use the &lt;tt&gt;Pattern.COMMENTS&lt;/tt&gt; flag:&amp;nbsp; it allows you to&amp;nbsp; break up your regular expression into multiple lines. Doing so makes it possible to document the parts that the regular expression consists of. This leads me to the second tip: document the parts of your expression so that you'll make it a lot easier on yourself if you later have to revisit the expression. Commenting is easy: use the # sign just like you would use // in Java. Whitespace in the expression is ignored, so if you want to insert a literal space, escape it with a backslash. &lt;br&gt;&lt;/p&gt; &lt;h3&gt;Parsing text with regular expressions&lt;/h3&gt; &lt;p&gt;I knew that regular expressions are great for &lt;em&gt;matching&lt;/em&gt; text, but now that I have the interactive regular expression editor, I also came to appreciate the regular expressions to &lt;em&gt;parse&lt;/em&gt; strings -- I mean to extract fragments out of a string. It surely is a lot easier than finding positions in a string and then using String.subString(). &lt;br&gt;&lt;/p&gt; &lt;p&gt;For example, here is a regular expression with capturing groups to parse the GlassFish log file:&lt;/p&gt;&lt;pre&gt;# Begin marker
\[\#

# Date and time
\|&amp;nbsp; (\d\d\d\d-\d\d-\d\d)\D(\d\d:\d\d:\d\d\.\d\d\d\D\d\d\d\d)

# Level
\|&amp;nbsp; (.+?)

# Product
\|&amp;nbsp; (.+?)

# Category
\|&amp;nbsp; (.+?)

# Key-value pairs
\|&amp;nbsp; (.+)?

# Msg text
\|&amp;nbsp; (.+?)

# Optional stack trace
(^\t at \s \p{javaLowerCase} .*&amp;nbsp; \.java .*)?

# End marker
\|\#\]&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This will result in 8 groups. This looks like a difficult expression, but with the Interactive regular expression editor, it's pretty simple to write this expression.And showing off the Interactive regular expression editor, this is what Java code it produces: &lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;pre&gt;public static Pattern REGEX = Pattern.compile("# Begin marker\r\n" + 
  "\\[\\#\r\n" + 
  "\r\n" + 
  "# Date and time\r\n" + 
  "\\|  (\\d\\d\\d\\d-\\d\\d-\\d\\d)\\D(\\d\\d:\\d\\d:\\d\\d\\.\\d\\d\\d\\D\\d\\d\\d\\d)\r\n" + 
  "\r\n" + 
  "# Level\r\n" + 
  "\\|  (.+?)\r\n" + 
  "\r\n" + 
  "# Product\r\n" + 
  "\\|  (.+?)\r\n" + 
  "\r\n" + 
  "# Category\r\n" + 
  "\\|  (.+?)\r\n" + 
  "\r\n" + 
  "# Key-value pairs\r\n" + 
  "\\|  (.+)?\r\n" + 
  "\r\n" + 
  "# Msg text\r\n" + 
  "\\|  (.+?)\r\n" + 
  "\r\n" + 
  "# Optional stack trace\r\n" + 
  "(^\\t at \\s \\p{javaLowerCase} .*  \\.java .*)?\r\n" + 
  "\r\n" + 
  "# End marker\r\n" + 
  "\\|\\#\\]", 0 | Pattern.COMMENTS | Pattern.DOTALL | Pattern.MULTILINE);&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-7769846897030575713?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/7769846897030575713/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=7769846897030575713' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/7769846897030575713'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/7769846897030575713'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/01/interactive-regular-expression-editor.html' title='An interactive Regular Expression Editor'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_k73ELjWNXV8/SXZd1HDJAzI/AAAAAAAAABo/-cEEQNn9o28/s72-c/image4.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-3017695440114150887</id><published>2009-01-20T13:01:00.001-08:00</published><updated>2009-01-20T13:01:33.705-08:00</updated><title type='text'>Blogger.com works after all</title><content type='html'>&lt;p&gt;I had this issue with blogspot where it would insert a great number of line breaks just before a table.&amp;nbsp; As I found out&amp;nbsp; (thanks to &lt;a href="http://blogs.sun.com/edwardchou/"&gt;Edward Chou&lt;/a&gt;), this behavior can be turned off in the settings page of Blogspot.&lt;/p&gt; &lt;p&gt;I also found out how to create Atom feeds from labels. The help text on Google is incorrect, and I found out to reference a category like Sun, the corresponding URL is: &lt;a href="http://frankkieviet.blogspot.com/feeds/posts/default/-/Sun"&gt;http://frankkieviet.blogspot.com/feeds/posts/default/-/Sun&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Now I’m wondering if I should stick with Blogspot or with Wordpress…&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-3017695440114150887?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/3017695440114150887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=3017695440114150887' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/3017695440114150887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/3017695440114150887'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2009/01/bloggercom-works-after-all.html' title='Blogger.com works after all'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-52619768817878233</id><published>2008-12-21T17:12:00.001-08:00</published><updated>2008-12-21T17:12:25.445-08:00</updated><title type='text'>Blogger.com not a success</title><content type='html'>&lt;p&gt;I’ve had great trouble to make the previous entry to appear properly.&amp;#160; I’m using raw HTML, but somehow when I publish, the server adds a lot of &amp;lt;br/&amp;gt; tags in my text.&lt;/p&gt;  &lt;p&gt;I think I’ll switch to wordpress.com (&lt;a href="http://fkieviet.wordpress.com"&gt;http://fkieviet.wordpress.com&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/6643071316318130698-52619768817878233?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/52619768817878233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=52619768817878233' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/52619768817878233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/52619768817878233'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2008/12/bloggercom-not-success.html' title='Blogger.com not a success'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-6403654904312436821</id><published>2008-12-21T16:36:00.001-08:00</published><updated>2008-12-21T16:36:08.856-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Sun'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenESB'/><title type='text'>The size of Java objects</title><content type='html'>&lt;p&gt;Here's a blog entry / research note / note-to-self that I wrote months ago, but never found the time to publish.    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;At JavaOne there was an interesting BOF about &lt;span style="font-style: italic"&gt;Efficient XML&lt;/span&gt;. It made me wonder about how efficiently the use of DOM in Java is. To find out, I wrote a small program to find out how many bytes of RAM a Java object uses. The program counts how many objects it can allocate before it runs out of memory. Here's the class:&lt;/p&gt;  &lt;pre&gt;    public static class H {&lt;br /&gt;        public H next;&lt;br /&gt;        byte[] b = new byte[8];&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;By changing the size of the byte array and running the program again, the size of an H instance can be calculated, as well as the total memory space available for object allocation in the test program. This number can be used in subsequent runs. Running the program on this trivial class on a Windows machine yielded a size of 16 bytes for each allocation.&lt;/p&gt;

&lt;pre&gt;    public static class H {&lt;br /&gt;        public H next;&lt;br /&gt;    }&lt;br /&gt;16 bytes&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;The VM apparently uses 8 byte alignment, because when another reference is added to the class above, the size does not increase, but it does increase in steps of 8 bytes when more members are added:&lt;/p&gt;

&lt;pre&gt;    public static class H {&lt;br /&gt;        public H next;&lt;br /&gt;        public H next1;&lt;br /&gt;    }&lt;br /&gt;16 bytes&lt;br /&gt;&lt;br /&gt;    public static class H {&lt;br /&gt;        public H next;&lt;br /&gt;        public H next1;&lt;br /&gt;        public H next2;&lt;br /&gt;    }&lt;br /&gt;24 bytes&lt;br /&gt;&lt;br /&gt;    public static class H {&lt;br /&gt;        public H next;&lt;br /&gt;        public H next1;&lt;br /&gt;        public H next2;&lt;br /&gt;        public H next3;&lt;br /&gt;    }&lt;br /&gt;24 bytes&lt;br /&gt;&lt;br /&gt;    public static class H {&lt;br /&gt;        public H next;&lt;br /&gt;        public H next1;&lt;br /&gt;        public H next2;&lt;br /&gt;        public H next3;&lt;br /&gt;        public H next4;&lt;br /&gt;    }&lt;br /&gt;32 bytes&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;Hence an empty class takes 8 bytes, and each object references takes 4 bytes. This is &lt;span style="font-style: italic"&gt;much&lt;/span&gt; better than what I intuitively expected: underneath there should be at least a pointer to a virtual method table (4 bytes), there should be a pointer to this object from some VM list of objects for memory management. I'd expected that list to be a linked list, and I'd expected that there perhaps would be some additional flags for garbage collection, etc. Clearly the VM does it much more efficiently than I would have done.&lt;/p&gt;

&lt;p&gt;Similarly, the size of arrays can be measured. A char[] comes down to 12 bytes plus two times the number of characters, rounded up to an 8 byte boundary. The size of a String object is more interesting: it is 32 bytes plus two times the number of characters; the minimum size is 40 bytes. Hence, a string of 3 characters is 48 bytes, and an eight character string is 56 bytes.&lt;/p&gt;

&lt;p&gt;Now let's take a look at XML, a DOM structure to be exact. How much does an element with a text node take, as in this XML snippet?&lt;/p&gt;

&lt;pre&gt;&amp;lt;root&amp;gt;&lt;br /&gt;  &amp;lt;ElementName&amp;gt;1000000&amp;lt;/ElementName&amp;gt;&lt;br /&gt;  &amp;lt;ElementName&amp;gt;1000001&amp;lt;/ElementName&amp;gt;&lt;br /&gt;  &amp;lt;ElementName&amp;gt;1000002&amp;lt;/ElementName&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;(line breaks and indentation added for clarity; &amp;quot;ElementName&amp;quot; is a string constant)&lt;/p&gt;

&lt;p&gt;Measuring this yields 144 bytes per node. Let's add another child element:&lt;/p&gt;

&lt;pre&gt;&amp;lt;root&amp;gt;&lt;br /&gt;  &amp;lt;ElementName&amp;gt;&lt;br /&gt;    &amp;lt;SubEl&amp;gt;1000000&amp;lt;/SubEl&amp;gt;&lt;br /&gt;  &amp;lt;/ElementName&amp;gt;&lt;br /&gt;  &amp;lt;ElementName&amp;gt;&lt;br /&gt;    &amp;lt;SubEl&amp;gt;1000001&amp;lt;/SubEl&amp;gt;&lt;br /&gt;  &amp;lt;/ElementName&amp;gt;&lt;br /&gt;  &amp;lt;ElementName&amp;gt;&lt;br /&gt;    &amp;lt;SubEl&amp;gt;1000002&amp;lt;/SubEl&amp;gt;&lt;br /&gt;  &amp;lt;/ElementName&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;Measuring this yields 200 bytes per repeating element. When we add an attribute the size increases again:&lt;/p&gt;

&lt;pre&gt;&amp;lt;root&amp;gt;&lt;br /&gt;  &amp;lt;ElementName&amp;gt;&lt;br /&gt;    &amp;lt;SubEl last=&amp;quot;false&amp;quot;&amp;gt;1000000&amp;lt;/SubEl&amp;gt;&lt;br /&gt;  &amp;lt;/ElementName&amp;gt;&lt;br /&gt;  &amp;lt;ElementName last=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;SubEl&amp;gt;1000001&amp;lt;/SubEl&amp;gt;&lt;br /&gt;  &amp;lt;/ElementName&amp;gt;&lt;br /&gt;  &amp;lt;ElementName last=&amp;quot;false&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;SubEl&amp;gt;1000002&amp;lt;/SubEl&amp;gt;&lt;br /&gt;  &amp;lt;/ElementName&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;This increases the size to 312 bytes per repeating element&lt;/p&gt;

&lt;p&gt;Summarizing the results:&lt;/p&gt;

&lt;table style="text-align: left" cellspacing="2" cellpadding="2" border="1"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;new Object() 
        &lt;br /&gt;&lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;8 bytes 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;&amp;quot;&amp;quot; 
        &lt;br /&gt;&lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;40 bytes 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;&amp;quot;123&amp;quot; 
        &lt;br /&gt;&lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;48 bytes 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;&amp;quot;12345678&amp;quot; 
        &lt;br /&gt;&lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;56 bytes 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;int data member 
        &lt;br /&gt;&lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;4 bytes 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;byte data member 
        &lt;br /&gt;&lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;1 byte 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;Object reference data member 
        &lt;br /&gt;&lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;4 bytes 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;char[n] 
        &lt;br /&gt;&lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;12 + 2*n 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;
        &lt;pre&gt;&amp;lt;ElementName&amp;gt;1234567&amp;lt;/ElementName&amp;gt;&lt;/pre&gt;
      &lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;144 bytes 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;
        &lt;pre&gt;&amp;lt;ElementName&amp;gt;&lt;br /&gt;    &amp;lt;SubEl&amp;gt;1234567&amp;lt;/SubEl&amp;gt;&lt;br /&gt;&amp;lt;/ElementName&amp;gt;&lt;/pre&gt;
      &lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;200 bytes 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td style="vertical-align: top"&gt;
        &lt;pre&gt;&amp;lt;ElementName&amp;gt;&lt;br /&gt;    &amp;lt;SubEl last=&amp;quot;false&amp;quot;&amp;gt;1234567&amp;lt;/SubEl&amp;gt;&lt;br /&gt;&amp;lt;/ElementName&amp;gt;&lt;br /&gt;&lt;/pre&gt;
      &lt;/td&gt;

      &lt;td style="vertical-align: top"&gt;312 bytes 
        &lt;br /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;br /&gt;

&lt;p&gt;Indeed, DOM is not very efficient with respect to memory usage. The last XML snippet was only 62 single byte characters. The information content is actual a lot less: since &lt;span style="font-family: monospace"&gt;ElementName&lt;/span&gt;, &lt;span style="font-family: monospace"&gt;SubEl&lt;/span&gt;, and &lt;span style="font-family: monospace"&gt;last&lt;/span&gt; are constant, they could be replaced with a reference. Without using schema information, the information content can be encoded with about 25 bytes. With JAXB it can be done with 88 bytes.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-6403654904312436821?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/6403654904312436821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=6403654904312436821' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/6403654904312436821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/6403654904312436821'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2008/12/size-of-java-objects.html' title='The size of Java objects'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6643071316318130698.post-1305746087559837511</id><published>2008-12-21T15:52:00.000-08:00</published><updated>2008-12-21T16:00:35.991-08:00</updated><title type='text'>Hello world</title><content type='html'>This is my first blog entry on blogger.com. It's really a continuation of my other blog, the one that I started at &lt;a href="http://blogs.sun.com/fkieviet"&gt;http://blogs.sun.com/fkieviet&lt;/a&gt;. Why did I start a new blog? Blogs at blogs.sun.com are tied to Sun Microsystems, my employer. With the world in economic turmoil, Sun included, I felt it was a good idea to have a blog not tied to my employer.

A few words about me: I'm a software engineer. Building software has been my hobby since the Commodore 64. I'm glad that I've been able to turn this hobby into a full time profession. I currently work as a Senior Staff Engineer at Sun Microsystems. There I work as a lead in the SOA/Business Integration group, and am a contributor to OpenESB, an open source platform for Integration and SOA.
&lt;p&gt;It's been a long time since my last blog entry on blogs.sun.com. Been busy -- work has been piling up, and it's difficult to justify taking time to write a blog when people are waiting on me for work to be finished. (And that's another reason to start this blog instead of continuing on blogs.sun.com.) How I find the time to write this then? I'm on vacation this week!
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6643071316318130698-1305746087559837511?l=frankkieviet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://frankkieviet.blogspot.com/feeds/1305746087559837511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6643071316318130698&amp;postID=1305746087559837511' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/1305746087559837511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6643071316318130698/posts/default/1305746087559837511'/><link rel='alternate' type='text/html' href='http://frankkieviet.blogspot.com/2008/12/hello-world.html' title='Hello world'/><author><name>Frank Kieviet</name><uri>http://www.blogger.com/profile/07479805042474878714</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_k73ELjWNXV8/SXZcwK-hhmI/AAAAAAAAAAM/x6-5GO8JNC4/S220/fkieviet-241x241.jpg'/></author><thr:total>0</thr:total></entry></feed>
