<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:georss="http://www.georss.org/georss"><id>tag:blogger.com,1999:blog-4396093936384561136</id><updated>2009-10-03T00:50:37.919-07:00</updated><title type="text">No milk in my coffee</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default?start-index=26&amp;max-results=25" /><author><name>French Fry</name><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>33</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/NoMilkInMyCoffee" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-3982363275851358243</id><published>2009-02-26T04:37:00.001-08:00</published><updated>2009-02-26T04:40:05.854-08:00</updated><title type="text">Introducing Unit Testing in Legacy code base</title><content type="html">In big companies, developing a green field project is a rare privilege&lt;br /&gt;... most of the time you will have to develop on a existing code base of&lt;br /&gt;versatile quality - Not due to the skill of the developer more likely to&lt;br /&gt;the history of the project, lack of code review and poor quality focus,&lt;br /&gt;short term vs. long term risk -.&lt;br /&gt;&lt;br /&gt;Anyway if you are not lucky you are facing a big spaghetti monster&lt;br /&gt;calling other pasta entities in ways ranging from CORBA, RV, rmi, EJB,&lt;br /&gt;ftp messaging ... Chances is that the code can't even run on your dev&lt;br /&gt;machine, making development laborious and non productive.&lt;br /&gt;&lt;br /&gt;There are 2 ways to deal with this problem&lt;br /&gt;&lt;br /&gt; 1 Status quo, self explanatory&lt;br /&gt; 2 Introducing unit test, mocking the internal and external monsters&lt;br /&gt;&lt;br /&gt;1 : simple solution, not very rewarding but if the cost of solution 2&lt;br /&gt;overcome the benefit that's the way to go&lt;br /&gt;2 : long term benefit in development and quality. But costly&lt;br /&gt;&lt;br /&gt;Though with a bit of method there are way to make 2 less costly, all you&lt;br /&gt;will need is :&lt;br /&gt;&lt;br /&gt; - A good refactoring dev environment, eclipse or idea&lt;br /&gt; - Junit, XmlUnit&lt;br /&gt; - XStream an xml serializer/desiralizer&lt;br /&gt; - an UAT/Dev environment that runs.&lt;br /&gt;&lt;br /&gt;1 - identify the part the function you need to test&lt;br /&gt;&lt;br /&gt;you won't be able to test all the code, it is important to test a small&lt;br /&gt;chain of the code lest that the mocking will be too complex.&lt;br /&gt;&lt;br /&gt;It's likely that you can identify the function that is the entry and&lt;br /&gt;exit point&lt;br /&gt;&lt;br /&gt;  Object f1(Object... args)&lt;br /&gt;&lt;br /&gt;It is that function that we will try to unit test.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2 - record samples&lt;br /&gt;&lt;br /&gt;your system is probably generating high complex object, based on high&lt;br /&gt;complex entry. Trying to reproduce the graph manually is laborious and&lt;br /&gt;sure to be incomplete. That's what we need to used XStream to record the&lt;br /&gt;args and the output of the function in a uat environment, getting that&lt;br /&gt;way real life object.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;// the new method that will delegate to the old&lt;br /&gt;// and dump in and out&lt;br /&gt;Object f1(Object... args)  {&lt;br /&gt;  dumpIn(args);&lt;br /&gt;&lt;br /&gt;  Object o  = _f1(args);&lt;br /&gt;&lt;br /&gt;  dumpOut(o);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// was the real&lt;br /&gt;Object _f1(Object args) {&lt;br /&gt;       ...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;3 - integrate your sample in your unit test&lt;br /&gt;&lt;br /&gt;Now that you have sample with your input parameters and your expected&lt;br /&gt;result you can start writing your unit test.&lt;br /&gt;&lt;br /&gt;4 - mock the external call&lt;br /&gt;&lt;br /&gt;It is likely that once you integrate the sample in the unit test, the&lt;br /&gt;code will need to code external or internal component. you will need to&lt;br /&gt;refactor that code in specific method that you will overwrite for your&lt;br /&gt;test.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;class F {&lt;br /&gt;       Object _f1(Object... args) {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;               // used to be inline&lt;br /&gt;               Object extInf = getExtInfo();&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;       Object getExtInfo() {&lt;br /&gt;        ....&lt;br /&gt;       }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class FTest extends F {&lt;br /&gt;&lt;br /&gt;       Object getExtInfo() {&lt;br /&gt;        return new MockObject();&lt;br /&gt;       }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If the object is to complex to Mock you can use the XStream to dump a&lt;br /&gt;sample in uat environment.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;5 - run the test !&lt;br /&gt;&lt;br /&gt;6 - how to improve the solution&lt;br /&gt;&lt;br /&gt;It is possible to create the list of test automatically by scanning the&lt;br /&gt;samples directory e.g.. Making it easier to add sample and extend the&lt;br /&gt;coverage of the test and behaviour.&lt;br /&gt;&lt;br /&gt;This is an iterative process, it is not possible to make everything&lt;br /&gt;testable in one go, take your time and surely step by step the quality&lt;br /&gt;of your code will improve.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-3982363275851358243?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/3982363275851358243/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=3982363275851358243" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/3982363275851358243" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/3982363275851358243" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2009/02/introducing-unit-testing-in-legacy-code.html" title="Introducing Unit Testing in Legacy code base" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-7191123513410010427</id><published>2008-07-25T05:38:00.000-07:00</published><updated>2008-07-25T05:39:16.763-07:00</updated><title type="text">Dr. Horrible's Sing-Along Lyrics</title><content type="html">&lt;a href="http://en.wikiquote.org/wiki/Dr._Horrible's_Sing-Along_Blog"&gt;Here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-7191123513410010427?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/7191123513410010427/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=7191123513410010427" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/7191123513410010427" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/7191123513410010427" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2008/07/dr-horribles-sing-along-lyrics.html" title="Dr. Horrible's Sing-Along Lyrics" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-2472990819758465934</id><published>2008-07-25T01:34:00.001-07:00</published><updated>2008-07-25T01:47:42.119-07:00</updated><title type="text">The Java Spirit</title><content type="html">- Composition is better than inheritance&lt;br /&gt;- Constructor are for initialization only&lt;br /&gt;- destructor/finalizer are for debugging only&lt;br /&gt;- Free resource explicitly&lt;br /&gt;- Declare the interface not the type ie List myList; not ArrayList myList&lt;br /&gt;- Optimize on metrics of a real system&lt;br /&gt;- Use a proper development environment&lt;br /&gt;- Don't believe the hype about closure, anonymous inner class cover 90% of the cases&lt;br /&gt;- Properties are private or protected.&lt;br /&gt;- Immutable is your friend.&lt;br /&gt;- Don't pool object, we are in the 21st century&lt;br /&gt;- Elegant code is code that is meaningful&lt;br /&gt;- the most useful api are : Collections, common-lang, java.text&lt;br /&gt;&lt;br /&gt;... To be continued&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-2472990819758465934?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/2472990819758465934/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=2472990819758465934" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/2472990819758465934" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/2472990819758465934" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2008/07/java-spirit.html" title="The Java Spirit" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-1317630858573894436</id><published>2008-06-11T07:04:00.000-07:00</published><updated>2008-06-11T07:08:45.399-07:00</updated><title type="text">Too many open file descriptors, leak detection</title><content type="html">In Java it is good practice to manually free the resources such as Streams, Connection. This is the consequence of the non deterministic property of the Garbage Collector. You object that is not reference might wait minutes before being process - or might even never -, so you can rely and the destructor - the finalize method - to do that - the finalizer make the collection of the object really costly-.&lt;br /&gt;&lt;br /&gt;So if you open a Stream you should ideally do that :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;InputStream is = null&lt;br /&gt;try {&lt;br /&gt;  is = new FileInputStream(...);&lt;br /&gt;  &lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;} finally {&lt;br /&gt;  if (is != null) {&lt;br /&gt;    try { is.close(); ) catch(Exception e) { // IGNORE }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's a lot of boiler plate code, and it's probably a good idea to use a Template pattern for that - look af Spring JDBCTemplate for example -.&lt;br /&gt;&lt;br /&gt;What happen if you don't do that? That depends on how many file you are gonna open.  It's really likely that the object is gonna get GC and FileInputStream as a finalizer where it closed itself.&lt;br /&gt;&lt;br /&gt;But if your application uses file intensively you might end up with "Too many open file descriptors" errors. If you're lucky you have few entry points where stream are open, so you can easily fix it. Otherwise you will need a way to take the part of the code that are erronous. &lt;br /&gt;&lt;br /&gt;What I propose under is to use &lt;a href="http://www.csg.is.titech.ac.jp/~chiba/javassist/"&gt;Javassist&lt;/a&gt; to instrument the FileInputStrean and FileOutputStream class.&lt;br /&gt;&lt;br /&gt;First we need a class that we would inject into the FileXStream to capture the states and detect the leaks.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package io;&lt;br /&gt;&lt;br /&gt;public class LeakDetector {&lt;br /&gt; &lt;br /&gt; private boolean closed;&lt;br /&gt; private Exception trace;&lt;br /&gt; &lt;br /&gt; &lt;br /&gt; public LeakDetector() {&lt;br /&gt;  trace = new Exception();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void close() {&lt;br /&gt;  this.closed = true;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; protected void finalize() {&lt;br /&gt;  if (! closed) {&lt;br /&gt;   printAlert();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private void printAlert() {&lt;br /&gt;  if (System.err != null) {&lt;br /&gt;   System.err.println("LeakDetector detected a leak from the object open at the following trace :");&lt;br /&gt;   trace.printStackTrace();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Then we need a class that instruments the FileXStreams&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package io;&lt;br /&gt;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.util.concurrent.Callable;&lt;br /&gt;&lt;br /&gt;import javassist.CannotCompileException;&lt;br /&gt;import javassist.ClassPool;&lt;br /&gt;import javassist.CtClass;&lt;br /&gt;import javassist.CtConstructor;&lt;br /&gt;import javassist.CtField;&lt;br /&gt;import javassist.CtMethod;&lt;br /&gt;import javassist.NotFoundException;&lt;br /&gt;&lt;br /&gt;public class Instrumenter implements Callable&amp;lt;Object&amp;gt; {&lt;br /&gt;&lt;br /&gt; private String[] clazzes;&lt;br /&gt; &lt;br /&gt; public Instrumenter(String[] args) {&lt;br /&gt;  this.clazzes = args;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) throws Exception {&lt;br /&gt;  &lt;br /&gt;  if (args == null || args.length == 0) {&lt;br /&gt;   args = new String[] { "java.io.FileInputStream", &lt;br /&gt;     "java.io.FileOutputStream" };&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  new Instrumenter(args).call();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public Object call() throws NotFoundException, CannotCompileException, IOException {&lt;br /&gt;  ClassPool pool = ClassPool.getDefault();&lt;br /&gt;  for(String clazz : clazzes) {&lt;br /&gt;   instrument(clazz, pool);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  return null;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private void instrument(String clazz, ClassPool pool) throws NotFoundException, CannotCompileException, IOException {&lt;br /&gt;  CtClass ctClass = pool.get(clazz);&lt;br /&gt;  &lt;br /&gt;  ctClass.addField(CtField.make("private io.LeakDetector __io_ld;", ctClass));&lt;br /&gt;  &lt;br /&gt;  for(CtConstructor cConst : ctClass.getConstructors()) {&lt;br /&gt;   cConst.insertBefore("__io_ld = new io.LeakDetector();");&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  for(CtMethod cMethod : ctClass.getMethods()) {&lt;br /&gt;   if (cMethod.getName().equals("close")) {&lt;br /&gt;    cMethod.insertBefore("__io_ld.close();");&lt;br /&gt;   } else if (cMethod.getName().equals("finalize")) {&lt;br /&gt;    cMethod.insertBefore("__io_ld._finalize();");&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  ctClass.writeFile("bin/java");&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This class write the new FileInputStream in the bin/java directory. We need do assemble the LeakDetector and the new FileInputStream, FileOutputStream under the same jar. all you need to next is to run your application with the "-Xbootclasspath/p:leakdetector.jar" on the command line.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Note: Applications that use this technique for the purpose of overriding a system class in rt.jar should not be deployed as doing so would contravene the Java 2 Runtime Environment binary code license.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you run the following code, with the bootclasspath set : &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import java.io.FileInputStream;&lt;br /&gt;import java.io.FileOutputStream;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class DodgyIOClass {&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) throws Exception {&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  new FileOutputStream("c:/test.txt");&lt;br /&gt;  &lt;br /&gt;  new FileInputStream("c:/test.txt");&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  Thread.sleep(3000);&lt;br /&gt;  System.gc();&lt;br /&gt;  Thread.sleep(3000);&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It should prints :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;LeakDetector detected a leak from the object open at the following trace :&lt;br /&gt;java.lang.Exception&lt;br /&gt; at io.LeakDetector.&amp;lt;init&amp;gt;(LeakDetector.java:11)&lt;br /&gt; at java.io.FileOutputStream.&amp;lt;init&amp;gt;(FileOutputStream.java)&lt;br /&gt; at java.io.FileOutputStream.&amp;lt;init&amp;gt;(FileOutputStream.java:70)&lt;br /&gt; at DodgyIOClass.main(DodgyIOClass.java:10)&lt;br /&gt;LeakDetector detected a leak from the object open at the following trace :&lt;br /&gt;java.lang.Exception&lt;br /&gt; at io.LeakDetector.&amp;lt;init&amp;gt;(LeakDetector.java:11)&lt;br /&gt; at java.io.FileInputStream.&amp;lt;init&amp;gt;(FileInputStream.java)&lt;br /&gt; at java.io.FileInputStream.&amp;lt;init&amp;gt;(FileInputStream.java:66)&lt;br /&gt; at DodgyIOClass.main(DodgyIOClass.java:12)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-1317630858573894436?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/1317630858573894436/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=1317630858573894436" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/1317630858573894436" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/1317630858573894436" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2008/06/too-many-open-file-descriptors-leak.html" title="Too many open file descriptors, leak detection" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-8167586886096063904</id><published>2008-04-02T08:10:00.000-07:00</published><updated>2008-04-02T08:12:39.834-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="/" /><title type="text">JSR 203 NIO 2 in Java 7</title><content type="html">&lt;a href="http://blogs.sun.com/rajendrag/entry/jsr_203_new_file_system" &gt;So it seems&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;That would be probably one of the most awaited fix, a well design file system api.&lt;br /&gt;&lt;br /&gt;no more &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;if (!file.delete())  {&lt;br /&gt; // delete did not work but I don't know why &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-8167586886096063904?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/8167586886096063904/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=8167586886096063904" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/8167586886096063904" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/8167586886096063904" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2008/04/jsr-203-nio-2-in-java-7.html" title="JSR 203 NIO 2 in Java 7" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-1029933802223540440</id><published>2008-03-28T09:22:00.000-07:00</published><updated>2008-03-28T09:23:46.913-07:00</updated><title type="text">Java performance improvements touted</title><content type="html">&lt;a href="http://www.infoworld.com/article/08/03/26/java-speed_1.html" &gt;&lt;i&gt;&lt;br /&gt;&lt;b&gt;Java is not the slowpoke of old days and performance now matches or exceeds applications developed in C&lt;/b&gt;, technologists stressed Wednesday during a presentation at TheServerSide Java Symposium in Las Vegas.&lt;br /&gt;&lt;/i&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;From : &lt;a href="http://www.dzone.com/links/rss/java_performance_improvements_touted_infoworld_ne.html"&gt;DZone&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Nice to see that written again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-1029933802223540440?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/1029933802223540440/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=1029933802223540440" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/1029933802223540440" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/1029933802223540440" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2008/03/java-performance-improvements-touted.html" title="Java performance improvements touted" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-973374902577386972</id><published>2008-03-14T03:01:00.000-07:00</published><updated>2008-03-14T03:03:07.904-07:00</updated><title type="text">IE 6 display = 'none' not working</title><content type="html">see &lt;a href="http://www.dynamicdrive.com/forums/showthread.php?t=6846"&gt;Here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Using &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  element.style.display = '' &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;instead solve the problem&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-973374902577386972?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/973374902577386972/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=973374902577386972" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/973374902577386972" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/973374902577386972" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2008/03/ie-6-display-none-not-working.html" title="IE 6 display = 'none' not working" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-7767979244056680102</id><published>2008-03-14T02:48:00.001-07:00</published><updated>2008-03-14T02:49:08.437-07:00</updated><title type="text">How to disable escaping in xslt</title><content type="html">&lt;pre&gt;&lt;br /&gt; &amp;lt;xsl:text disable-output-escaping="yes"&gt;&amp;lt;!--&amp;lt;/xsl:text&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-7767979244056680102?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/7767979244056680102/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=7767979244056680102" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/7767979244056680102" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/7767979244056680102" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2008/03/how-to-disble-escaping-in-xslt.html" title="How to disable escaping in xslt" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-1540466182070564831</id><published>2008-03-05T08:53:00.000-08:00</published><updated>2008-03-05T08:56:48.272-08:00</updated><title type="text">NIO / IO debates</title><content type="html">More NIO / IO benchmark or evidence &lt;br /&gt;&lt;br /&gt;&lt;a href="http://paultyma.blogspot.com/2008/03/writing-java-multithreaded-servers.html" &gt;Writing Java Multithreaded Servers - whats old is new (PDF Slides)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://morningcofee.blogspot.com/2007/12/micro-benchmark-channel-vs-inputstream_04.html" &gt;Micro benchmark Channel vs InputStream / 2&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-1540466182070564831?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/1540466182070564831/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=1540466182070564831" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/1540466182070564831" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/1540466182070564831" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2008/03/nio-io-debates.html" title="NIO / IO debates" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-5492759471938824099</id><published>2008-01-24T01:25:00.001-08:00</published><updated>2008-01-24T01:26:22.671-08:00</updated><title type="text">String sorting tip</title><content type="html">Good tip &lt;a href="http://blogs.sun.com/CoreJavaTechTips/entry/sorting_strings"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt; Collator esCollator =&lt;br /&gt;   Collator.getInstance(new Locale("es"));&lt;br /&gt; Collections.sort(list, esCollator);&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-5492759471938824099?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/5492759471938824099/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=5492759471938824099" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/5492759471938824099" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/5492759471938824099" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2008/01/string-sorting-tip.html" title="String sorting tip" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-491578277953767509</id><published>2008-01-05T04:13:00.000-08:00</published><updated>2008-04-30T06:04:03.066-07:00</updated><title type="text">Image Resizer for widescreen picture frame and the main color problem</title><content type="html">-- UPDate&lt;br /&gt;http://www.comesolvego.com/2008/04/29/resize-images-with-java-high-quality-and-working-solution/&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;For Xmas I receive a picture frame, unfortunately the image is expanded&lt;br /&gt;to the size of the frame without respecting the ratio.&lt;br /&gt;&lt;br /&gt;I try to find a batch solution to resize and fit the picture so that it&lt;br /&gt;would not be deformed.&lt;br /&gt;&lt;br /&gt;I did not find anything so I decided to try to write a small java&lt;br /&gt;program to do it.&lt;br /&gt;it would take the picture resize it so it fit in the frame and put it&lt;br /&gt;center in a image the size of the frame.&lt;br /&gt;&lt;br /&gt;It was relatively easy.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package org.srf;&lt;br /&gt;&lt;br /&gt;import java.awt.Color;&lt;br /&gt;import java.awt.Graphics2D;&lt;br /&gt;import java.awt.Rectangle;&lt;br /&gt;import java.awt.RenderingHints;&lt;br /&gt;import java.awt.image.BufferedImage;&lt;br /&gt;&lt;br /&gt;public class FitImage {&lt;br /&gt;&lt;br /&gt; public BufferedImage  scaleImage(BufferedImage image, int width, int height) throws Exception {&lt;br /&gt;&lt;br /&gt;  int originalHeight = image.getHeight();&lt;br /&gt;  int originalWidth = image.getWidth();&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  double scale = Math.min(&lt;br /&gt;    height/ (double)originalHeight,&lt;br /&gt;    originalWidth/ (double)originalWidth&lt;br /&gt;  );&lt;br /&gt;  &lt;br /&gt;  int newWidth = (int)Math.round(scale * originalWidth);&lt;br /&gt;  int newHeight = (int)Math.round(scale * originalHeight);&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  // Draw the scaled image&lt;br /&gt;  BufferedImage thumbImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);&lt;br /&gt;  &lt;br /&gt;  Graphics2D graphics2D = thumbImage.createGraphics();&lt;br /&gt;  graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,&lt;br /&gt;    RenderingHints.VALUE_INTERPOLATION_BILINEAR);&lt;br /&gt;  &lt;br /&gt;  graphics2D.drawImage(image, 0, 0, newWidth, newHeight,&lt;br /&gt;    null);&lt;br /&gt;&lt;br /&gt;  return thumbImage;&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public BufferedImage frameImage(BufferedImage image, int width, int height, Color backgroundColor) throws Exception {&lt;br /&gt;  &lt;br /&gt;  int paddingX = (width - image.getWidth()) / 2;&lt;br /&gt;  int paddingY = (height - image.getHeight()) / 2;&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;  // Draw the scaled image&lt;br /&gt;  BufferedImage thumbImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  Graphics2D graphics2D = thumbImage.createGraphics();&lt;br /&gt;  &lt;br /&gt;  graphics2D.setColor(backgroundColor);&lt;br /&gt;  &lt;br /&gt;  graphics2D.fill(new Rectangle(0, 0, width, height));&lt;br /&gt;  &lt;br /&gt;  graphics2D.drawImage(image, paddingX, paddingY, null);&lt;br /&gt;&lt;br /&gt;  return thumbImage;&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Then what color do I want to draw the border. The average color of the&lt;br /&gt;picture? does not seems right if you have a picture with blue and green&lt;br /&gt;you might end up with a yellow ...&lt;br /&gt;&lt;br /&gt;So what about the dominant colour ? the main colour of the picture ?&lt;br /&gt;That quite a fusy concept like that. The color are distributed in a 4&lt;br /&gt;dimension space (red, green, blue, alpha) what would that mean to be the&lt;br /&gt;dominant color? What would be an efficient algorythm to determine it.&lt;br /&gt;&lt;br /&gt;I came up with something that give relatively good result also not sure&lt;br /&gt;about the validity of it.&lt;br /&gt;&lt;br /&gt;It iteratively cut the spaces in 2^4 boxes and keep the one where there&lt;br /&gt;is most color.&lt;br /&gt;It does the same thing on this box reduce it a specific number of time.&lt;br /&gt;As the color are define by a number between 0-256, each iteration&lt;br /&gt;dividing the solution possibilite by to, in 8 iteration I arrived to a&lt;br /&gt;result. What does it mean not sure... but on test I did it seems to work&lt;br /&gt;fine.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package org.srf;&lt;br /&gt;&lt;br /&gt;import java.awt.Color;&lt;br /&gt;import java.awt.image.BufferedImage;&lt;br /&gt;&lt;br /&gt;public class ColorHelper {&lt;br /&gt; private boolean discardPixelOutOfTheBox = true;&lt;br /&gt; private boolean shiftRange = false;&lt;br /&gt; &lt;br /&gt; &lt;br /&gt; public void setDiscardPixelOutOfTheBox(boolean discardPixelOutOfTheBox) {&lt;br /&gt;  this.discardPixelOutOfTheBox = discardPixelOutOfTheBox;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; public void setShiftRange(boolean shiftRange) {&lt;br /&gt;  this.shiftRange = shiftRange;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; public Color getMainColor(BufferedImage image, int refineTo) {&lt;br /&gt;  Color c = null;&lt;br /&gt;  &lt;br /&gt;  int[] rgbs = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  int[][] colorRanges = new int[][]{ {0, 0xFF}, {0, 0xFF},{0, 0xFF}, {0, 0xFF}};&lt;br /&gt;  &lt;br /&gt;  for(int refine = 0; refine &lt; refineTo ; refine++) {&lt;br /&gt;   int[] colorSpace = new int[2 * 2 * 2 * 2];&lt;br /&gt;   for(int rgb : rgbs) {&lt;br /&gt;    int gi = calculateSpacePoint(colorRanges, rgb);&lt;br /&gt;    if (gi != -1 ) {&lt;br /&gt;     colorSpace[gi] ++;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   int ci = calculateSpacePointWinner(colorSpace);&lt;br /&gt;   &lt;br /&gt;   shrinkSpace(colorRanges, ci);&lt;br /&gt;   &lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  int[] crgbs = new int[4]; &lt;br /&gt;  // take middle of colorRange&lt;br /&gt;  for(int i = 0; i &lt; colorRanges.length; i++) {&lt;br /&gt;   int[] range = colorRanges[i];&lt;br /&gt;   crgbs[i] =  (range[0] +  range[1]) /2  ;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  c = new Color(crgbs[2],crgbs[1],crgbs[0],   crgbs[3]);&lt;br /&gt;  &lt;br /&gt;  return c;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; private int calculateSpacePointWinner(int[] colorSpace) {&lt;br /&gt;  int ci = 0;&lt;br /&gt;  int ciValue = 0;&lt;br /&gt;  for(int i = 0; i &lt; colorSpace.length; i++) {&lt;br /&gt;   if (colorSpace[i] &gt; ciValue) {&lt;br /&gt;    ci = i;&lt;br /&gt;    ciValue = colorSpace[i];&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  return ci;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; private int calculateSpacePoint(int[][] colorRanges, int rgb) {&lt;br /&gt;  int gi = 0;&lt;br /&gt;  for(int i = 0; gi != - 1 &amp;&amp; i &lt; 4; i++) {&lt;br /&gt;   int v  = (rgb &gt;&gt; (i * 8)) &amp; 0xFF;&lt;br /&gt;   &lt;br /&gt;   if (!discardPixelOutOfTheBox &lt;br /&gt;     || (v &gt;= colorRanges[i][0] &amp;&amp; v &lt;= colorRanges[i][1])) {&lt;br /&gt;    int rangeMiddle = (colorRanges[i][0] + colorRanges[i][1]) / 2;&lt;br /&gt;    &lt;br /&gt;    int vi = v &lt; rangeMiddle ? 0:1;&lt;br /&gt;    &lt;br /&gt;    gi |=  vi &lt;&lt; i;&lt;br /&gt;   } else {&lt;br /&gt;    gi = -1;&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;  }&lt;br /&gt;  return gi;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; private void shrinkSpace(int[][] colorRanges, int ci) {&lt;br /&gt;  // re-adjust colorRange&lt;br /&gt;  for(int i = 0; i &lt; colorRanges.length; i++) {&lt;br /&gt;   int[] range = colorRanges[i];&lt;br /&gt;   int cri = (ci &gt;&gt; i ) &amp; 0x1;&lt;br /&gt;   &lt;br /&gt;   shrinkDimension(range, cri);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; private void shrinkDimension(int[] range, int cri) {&lt;br /&gt;  int rangeShift = shiftRange  ? (range[1] - range[0]) /4 : 0;&lt;br /&gt;  int middleRange = (range[0] +  range[1]) /2;&lt;br /&gt;  if (cri == 0) {&lt;br /&gt;   range[1] =  middleRange + rangeShift ;&lt;br /&gt;  } else {&lt;br /&gt;   range[0] = middleRange - rangeShift;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-491578277953767509?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/491578277953767509/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=491578277953767509" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/491578277953767509" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/491578277953767509" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2008/01/mage-resizer-for-widescreen-picture.html" title="Image Resizer for widescreen picture frame and the main color problem" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-4110108514171027072</id><published>2007-12-11T01:38:00.000-08:00</published><updated>2007-12-11T01:39:24.889-08:00</updated><title type="text">XML/Castor notes 1</title><content type="html">Marshal to a document object&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt; Document serializeObject(Object o) throws Exception {&lt;br /&gt;&lt;br /&gt;  DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();&lt;br /&gt;  &lt;br /&gt;  Document document = documentBuilder.newDocument();&lt;br /&gt;  &lt;br /&gt;  Marshaller marshaller = new Marshaller(d);&lt;br /&gt;  &lt;br /&gt;  synchronized (mapping) {&lt;br /&gt;   marshaller.setMapping(mapping);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  marshaller.marshal(o);&lt;br /&gt;  &lt;br /&gt;  return document;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Write the Document to an xml file&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt; void write(Document doc, File f) throws Exception {&lt;br /&gt;  Transformer trans = TransformerFactory.newInstance().newTransformer();&lt;br /&gt;  &lt;br /&gt;  Source source = new DOMSource(doc);&lt;br /&gt;  Result result = new StreamResult(new FileOutputStream(f));&lt;br /&gt;  &lt;br /&gt;  trans.transform(source, result);&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-4110108514171027072?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/4110108514171027072/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=4110108514171027072" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/4110108514171027072" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/4110108514171027072" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/12/xmlcastor-notes-1.html" title="XML/Castor notes 1" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-8415037155275251110</id><published>2007-12-10T04:34:00.001-08:00</published><updated>2007-12-10T04:37:24.464-08:00</updated><title type="text">Acegi 2</title><content type="html">&lt;a href="http://blog.interface21.com/main/2007/12/06/whats-new-in-spring-security-2/" &gt;does not kill fairy by murder anymore.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-8415037155275251110?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/8415037155275251110/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=8415037155275251110" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/8415037155275251110" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/8415037155275251110" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/12/acegi-2.html" title="Acegi 2" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-5117738860226710451</id><published>2007-12-10T03:00:00.000-08:00</published><updated>2007-12-10T03:02:04.706-08:00</updated><title type="text">Map &amp; Reduce explained for dummies</title><content type="html">&lt;a href="http://www.joelonsoftware.com/items/2006/08/01.html" &gt;Can Your Programming Language Do This?&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Also I'm quite sure the cost of doing it in java is overrated - what about anonymous class, used in the common collection for example - ... This is a nice piece of explanation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-5117738860226710451?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/5117738860226710451/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=5117738860226710451" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/5117738860226710451" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/5117738860226710451" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/12/map-reduce-explained-for-dummies.html" title="Map &amp; Reduce explained for dummies" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-8606573300715465801</id><published>2007-12-06T07:34:00.001-08:00</published><updated>2007-12-06T07:39:50.763-08:00</updated><title type="text">Interruptible Call</title><content type="html">In the not so new concurrent api, a call - Executor.call(new Call()) can be cancel by the Future object return. &lt;br /&gt;&lt;br /&gt;Future.cancel(true) is gonna interrupt the thread. But does that mean that your code gonna stop automatically if it already started? Only if it's on a blocking call, which it's quite unlikely. So that your code is interruptible you need to test it the thread has been interrupted.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   while(test) {&lt;br /&gt;      if (Thread.interrupted()) {&lt;br /&gt;         throw new InterruptedException();&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This way your cancel is more reactive.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-8606573300715465801?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/8606573300715465801/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=8606573300715465801" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/8606573300715465801" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/8606573300715465801" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/12/interruptible-call.html" title="Interruptible Call" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-5640362653304895884</id><published>2007-12-04T07:40:00.000-08:00</published><updated>2007-12-04T07:45:17.295-08:00</updated><title type="text">Micro benchmark Channel vs InputStream / 2</title><content type="html">If you follow actually the samples like &lt;a href="http://java.sun.com/j2se/1.4.2/docs/guide/nio/example/Grep.java" &gt;Grep&lt;/a&gt;. Channel are slower than the BufferedReader&lt;br /&gt;&lt;br /&gt;On a directory with 16 files, with a total of 42 MB :&lt;br /&gt;nio direct=Time Taken: 3703ms,&lt;br /&gt;nio=Time Taken: 3781ms,&lt;br /&gt;io=Time Taken: 3063ms&lt;br /&gt;&lt;br /&gt;So ?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; public class NIOReader implements Reader {&lt;br /&gt;&lt;br /&gt;  private ByteBuffer byteBuffer;&lt;br /&gt;  &lt;br /&gt;  public NIOReader(int bufferSize, boolean direct) {&lt;br /&gt;   if (direct) {&lt;br /&gt;    this.byteBuffer = ByteBuffer.allocateDirect(bufferSize);&lt;br /&gt;     &lt;br /&gt;   } else {&lt;br /&gt;    this.byteBuffer = ByteBuffer.allocate(bufferSize);&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String readFile(File f) throws IOException {&lt;br /&gt;   FileInputStream fis = null;&lt;br /&gt;   FileChannel channel = null;&lt;br /&gt;   &lt;br /&gt;   try {&lt;br /&gt;    fis = new FileInputStream(f);&lt;br /&gt;    &lt;br /&gt;    channel = fis.getChannel();&lt;br /&gt;    &lt;br /&gt;    MappedByteBuffer buffer = channel.map(MapMode.READ_ONLY, 0, channel.size());&lt;br /&gt;    &lt;br /&gt;    CharBuffer charBuffer = Charset.defaultCharset().decode(buffer);&lt;br /&gt;&lt;br /&gt;    return charBuffer.toString();&lt;br /&gt;    &lt;br /&gt;   } finally {&lt;br /&gt;    if (fis != null)&lt;br /&gt;     fis.close();&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   &lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-5640362653304895884?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/5640362653304895884/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=5640362653304895884" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/5640362653304895884" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/5640362653304895884" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/12/micro-benchmark-channel-vs-inputstream_04.html" title="Micro benchmark Channel vs InputStream / 2" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-2106998711846491458</id><published>2007-12-04T02:27:00.000-08:00</published><updated>2007-12-04T02:40:20.267-08:00</updated><title type="text">Micro benchmark Channel vs InputStream</title><content type="html">I wrote a little non representative test to check is it was worth rewriting the IO, in an application that write and read a lot of data from the file system, using the not so new NIO api.&lt;br /&gt;&lt;br /&gt;On a directory with containing 8 305 files all around 1 to 4 KB the result are around :&lt;br /&gt;nio direct=Time Taken: 5610ms&lt;br /&gt;nio=Time Taken: 5766ms &lt;br /&gt;io=Time Taken: 5578ms&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;On a directory with 16 files, with a total of 42 MB :&lt;br /&gt;nio direct=Time Taken: 875ms&lt;br /&gt;nio=Time Taken: 906ms&lt;br /&gt;io=Time Taken: 3079ms&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So for big files it's definitly worth it, but not for small file. &lt;br /&gt;&lt;br /&gt;It's tested under windows XP, would the result be the same under a Unix OS? Don't know ...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;import java.io.File;&lt;br /&gt;import java.io.FileInputStream;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.nio.ByteBuffer;&lt;br /&gt;import java.nio.channels.FileChannel;&lt;br /&gt;import java.util.HashMap;&lt;br /&gt;import java.util.Map;&lt;br /&gt;&lt;br /&gt;import junit.framework.TestCase;&lt;br /&gt;&lt;br /&gt;import org.apache.log4j.Logger;&lt;br /&gt;&lt;br /&gt;public class NIOTest  extends TestCase {&lt;br /&gt; &lt;br /&gt; private static Logger  logger= Logger.getLogger(NIOTest.class);&lt;br /&gt; public class NIOReader implements Reader {&lt;br /&gt;&lt;br /&gt;  private ByteBuffer byteBuffer;&lt;br /&gt;  &lt;br /&gt;  public NIOReader(int bufferSize, boolean direct) {&lt;br /&gt;   if (direct) {&lt;br /&gt;    this.byteBuffer = ByteBuffer.allocateDirect(bufferSize);&lt;br /&gt;     &lt;br /&gt;   } else {&lt;br /&gt;    this.byteBuffer = ByteBuffer.allocate(bufferSize);&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String readFile(File f) throws IOException {&lt;br /&gt;   FileInputStream fis = null;&lt;br /&gt;   FileChannel channel = null;&lt;br /&gt;   StringBuilder sb = new StringBuilder((int)f.length());&lt;br /&gt;   &lt;br /&gt;   try {&lt;br /&gt;    fis = new FileInputStream(f);&lt;br /&gt;    &lt;br /&gt;    channel = fis.getChannel();&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;    while(channel.read(byteBuffer) != -1) {&lt;br /&gt;     byteBuffer.flip();&lt;br /&gt;     sb.append(byteBuffer.toString());&lt;br /&gt;     byteBuffer.clear();&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;   } finally {&lt;br /&gt;    if (fis != null)&lt;br /&gt;     fis.close();&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   &lt;br /&gt;   return sb.toString();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt; public class IOReader implements Reader {&lt;br /&gt;&lt;br /&gt;  private byte[] buffer;&lt;br /&gt;&lt;br /&gt;  public IOReader(int bufferSize) {&lt;br /&gt;   this.buffer = new byte[bufferSize];&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String readFile(File f) throws IOException {&lt;br /&gt;   FileInputStream fis = null;&lt;br /&gt;   &lt;br /&gt;   StringBuilder sb = new StringBuilder((int)f.length());&lt;br /&gt;   &lt;br /&gt;   try {&lt;br /&gt;    fis = new FileInputStream(f);&lt;br /&gt;    &lt;br /&gt;    int c = -1;&lt;br /&gt;    &lt;br /&gt;    while( (c = fis.read(buffer)) != -1) {&lt;br /&gt;     sb.append(new String(buffer, 0 , c));&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;   } finally {&lt;br /&gt;    if (fis != null)&lt;br /&gt;     fis.close();&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   &lt;br /&gt;   &lt;br /&gt;   &lt;br /&gt;   return sb.toString();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; File dir = new File ("C:\\my directory with files");&lt;br /&gt; &lt;br /&gt; int size = 3;&lt;br /&gt; int buffer = 4096;&lt;br /&gt; &lt;br /&gt; public void testIO() throws IOException {&lt;br /&gt;  for (int i = 0 ; i &lt; size; i++) {&lt;br /&gt;   Map&lt;String, StopWatch&gt; stopWatches = new HashMap&lt;String,StopWatch&gt;();&lt;br /&gt;   &lt;br /&gt;   logger.info("test io");&lt;br /&gt;   stopWatches.put("io", testLoop(size, new IOReader(buffer), dir));&lt;br /&gt;   logger.info("test nio");&lt;br /&gt;   stopWatches.put("nio", testLoop(size, new NIOReader(buffer, false), dir));&lt;br /&gt;   logger.info("test nio direct");&lt;br /&gt;   stopWatches.put("nio direct", testLoop(size, new NIOReader(buffer, true), dir));&lt;br /&gt;   &lt;br /&gt;   &lt;br /&gt;   logger.info(stopWatches.toString());&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public StopWatch testLoop(int size, Reader reader, File dir) throws IOException {&lt;br /&gt;  StopWatch stopWatch = new StopWatch();&lt;br /&gt;  &lt;br /&gt;  stopWatch.start();&lt;br /&gt;  &lt;br /&gt;  for(int i = 0; i &lt; size; i ++) {&lt;br /&gt;   test(reader, dir);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  stopWatch.stop();&lt;br /&gt;  &lt;br /&gt;  logger.info("end loop " +stopWatch);&lt;br /&gt;  return stopWatch;&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void test(Reader r, File dir) throws IOException {&lt;br /&gt;  for(File f: dir.listFiles()) {&lt;br /&gt;   if (f.isFile()) {&lt;br /&gt;    String str = r.readFile(f);&lt;br /&gt;    //logger.debug("read "+ str.length()+" in "+f);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; interface Reader {&lt;br /&gt;  String readFile(File f) throws IOException;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-2106998711846491458?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/2106998711846491458/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=2106998711846491458" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/2106998711846491458" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/2106998711846491458" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/12/micro-benchmark-channel-vs-inputstream.html" title="Micro benchmark Channel vs InputStream" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-5383540155554805674</id><published>2007-11-29T09:39:00.001-08:00</published><updated>2007-11-29T09:39:47.412-08:00</updated><title type="text">7.4 Preventing Castor from checking for a default constructor (since 0.9.5)</title><content type="html">Sometimes it's useful to prevent Castor from checking for a default constructor, such as when trying to write a mapping for an interface or type-safe enum. You can use the "undocumented" verify-constructable="false" attribute on the &lt;class&gt; element to prevent Castor from looking for the default constructor. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;been looking for this one ...&lt;br /&gt;&lt;a href="http://castor.codehaus.org/xml-mapping.html" &gt;See&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-5383540155554805674?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/5383540155554805674/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=5383540155554805674" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/5383540155554805674" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/5383540155554805674" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/11/74-preventing-castor-from-checking-for.html" title="7.4 Preventing Castor from checking for a default constructor (since 0.9.5)" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-991875526381644589</id><published>2007-11-28T01:36:00.000-08:00</published><updated>2007-11-28T01:37:04.337-08:00</updated><title type="text">Interesting post ab out Database Partitioning using Spring</title><content type="html">&lt;a href="http://www.jroller.com/kenwdelong/entry/horizontal_database_partitioning_with_spring" &gt;Horizontal Database Partitioning with Spring and Hibernate&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-991875526381644589?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/991875526381644589/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=991875526381644589" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/991875526381644589" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/991875526381644589" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/11/interesting-post-ab-out-database.html" title="Interesting post ab out Database Partitioning using Spring" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-1882850638841656570</id><published>2007-11-01T06:10:00.000-07:00</published><updated>2007-11-01T06:18:35.815-07:00</updated><title type="text">Castor elusive StackOverflowError</title><content type="html">On one of my project, I'm using Casor - 1.1.2.1 - to serialize an object tree to xml. At the beginning of the week I had a weird StackOverflowError when writing a big set of objects. I did not pay much attention do it, was not a priority. &lt;br /&gt;&lt;br /&gt;Today I had the same error, on a very reasonably size object tree. So I try to find where it was comming from - a cycling mapping maybe ... -. I putted my eclipse in debug mode, and add a breakpoint on the error. And then no more SOE ... but a error when setting the mapping in the Marshaller... weird ...&lt;br /&gt;&lt;br /&gt;What can it be? that looks like a multi thread issue... But the Marshaler are both distinct, the only common thing is the Mapping. Could it be ? &lt;br /&gt;So I replaced&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; Marshaller marshaller = new Marshaller(serializer&lt;br /&gt;   .asDocumentHandler());&lt;br /&gt; if (mapping != null) {&lt;br /&gt;     marshaller.setMapping(mapping);&lt;br /&gt; }&lt;br /&gt; marshaller.marshal(o);&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;with &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; Marshaller marshaller = new Marshaller(serializer&lt;br /&gt;   .asDocumentHandler());&lt;br /&gt; if (mapping != null) {&lt;br /&gt;  synchronized (mapping) {&lt;br /&gt;   marshaller.setMapping(mapping);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; marshaller.marshal(o);&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And it solve my problem.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;Castor Mapping object is not Thread Safe...&lt;br /&gt;&lt;br /&gt;How weird....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-1882850638841656570?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/1882850638841656570/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=1882850638841656570" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/1882850638841656570" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/1882850638841656570" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/11/castor-elusive-stackoverflowerror.html" title="Castor elusive StackOverflowError" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-406849925342735405</id><published>2007-09-27T02:11:00.001-07:00</published><updated>2007-09-27T03:33:04.511-07:00</updated><title type="text">Comparing double with relative precision</title><content type="html">&lt;pre&gt;&lt;br /&gt;  private static final int DOUBLE_PRECISION = Math.getExponent(0.00000000000001);&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;  public static boolean equalsDouble(double d1, double d2) {&lt;br /&gt;    double diff = Math.abs(d1 - d2);&lt;br /&gt;&lt;br /&gt;    if (diff == 0.0) {&lt;br /&gt;      return true;&lt;br /&gt;    }&lt;br /&gt;  &lt;br /&gt;    int minExp = Math.min(Math.getExponent(d1), Math.getExponent(d2));&lt;br /&gt;  &lt;br /&gt;    int diffExp = Math.getExponent(diff);&lt;br /&gt;  &lt;br /&gt;    int relExp = diffExp - minExp;&lt;br /&gt;  &lt;br /&gt;    return  relExp &lt;= DOUBLE_PRECISION;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt; &lt;br /&gt; The test :&lt;br /&gt;&lt;br /&gt;&lt;pre&gt; &lt;br /&gt;  public void testDoubleEquals() {&lt;br /&gt;    assertTrue( Utils.equalsDouble(0.0, 0.0));&lt;br /&gt;    assertTrue( Utils.equalsDouble(123.56, 123.56));&lt;br /&gt;    assertTrue( Utils.equalsDouble(15698965.23659898, 15698965.23659898));&lt;br /&gt;&lt;br /&gt;    assertTrue( Utils.equalsDouble(1.000000000000001, 1.000000000000000));&lt;br /&gt;    assertTrue( Utils.equalsDouble(1000000000000001d, 1000000000000000d));&lt;br /&gt;    assertTrue( Utils.equalsDouble(0.000000000000001000000000000001d, 0.000000000000001d));&lt;br /&gt;  &lt;br /&gt;    assertFalse( Utils.equalsDouble(1.00000000000011, 1.00000000000001));&lt;br /&gt;    assertFalse( Utils.equalsDouble(100000000000011d, 100000000000001d));&lt;br /&gt;    assertFalse( Utils.equalsDouble(0.00000000000000100000000000011d, 0.00000000000000100000000000001d));&lt;br /&gt;&lt;br /&gt;    assertFalse( Utils.equalsDouble(15d, 1d));&lt;br /&gt;    assertFalse( Utils.equalsDouble(15d, 15.6d));&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-406849925342735405?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/406849925342735405/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=406849925342735405" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/406849925342735405" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/406849925342735405" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/09/comparing-double-with-relative.html" title="Comparing double with relative precision" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-5287907882988105316</id><published>2007-09-20T02:24:00.000-07:00</published><updated>2007-09-20T02:26:11.171-07:00</updated><title type="text">Cursors random walks</title><content type="html">I was working on an existing database with a simple table like this&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE TABLE T (&lt;br /&gt; id int,&lt;br /&gt; name varcher(255),&lt;br /&gt; job_id int&lt;br /&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;there is about 400 rows in this table, and the DB design is quite poor.&lt;br /&gt;&lt;br /&gt;I decided to refactor a procedure that was going through the table T using a counter and assuming that it would match the id. It was working fine but it's kind of hard to imagine a weirder way of parcouring a table. &lt;br /&gt;&lt;br /&gt;It did look like this&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  select @insertRowCount = count(*) from T&lt;br /&gt;    &lt;br /&gt;  while @counter &lt; @insertRowCount&lt;br /&gt;  begin&lt;br /&gt;   select @name = name from T where id = @counter&lt;br /&gt;   &lt;br /&gt;   ...&lt;br /&gt;   &lt;br /&gt;   set @counter = @counter+1&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The most obvious modification was using a cursor instead of this counter thing.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  declare Tcursor cursor for &lt;br /&gt;   select  name , id&lt;br /&gt;   from T&lt;br /&gt;&lt;br /&gt;  open jobInfo&lt;br /&gt;&lt;br /&gt;  fetch jobInfo into  @name, @id&lt;br /&gt;&lt;br /&gt;  while(@@sqlstatus=0)&lt;br /&gt;  begin&lt;br /&gt;&lt;br /&gt;   fetch jobInfo into  @name, @id&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  close jobInfo&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Looks better, doesn't it?&lt;br /&gt;&lt;br /&gt;except that the cursor did not return all the row ... Kind of weird.&lt;br /&gt;&lt;br /&gt;After a bit of googling I find my answer, it need a unique index, which you've got normaly with a primary key...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  create unique index PK_T on T(id)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;PS: I do know such database is badly design...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-5287907882988105316?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/5287907882988105316/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=5287907882988105316" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/5287907882988105316" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/5287907882988105316" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/09/cursors-random-walks.html" title="Cursors random walks" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-310964634369494077</id><published>2007-08-24T05:17:00.000-07:00</published><updated>2007-08-24T05:23:49.615-07:00</updated><title type="text">Micro benchmark - Collection sorting</title><content type="html">What is the most efficient &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;    List&lt;Long&gt; list = new ArrayList&lt;Long&gt;();&lt;br /&gt;    &lt;br /&gt;    for(Long l : array) {&lt;br /&gt;     list.add(l);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    Collections.sort(list);  &lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Or &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;    TreeSet&lt;Long&gt; list = new TreeSet&lt;Long&gt;();&lt;br /&gt;&lt;br /&gt;    for(Long l : array) {&lt;br /&gt;     list.add(l);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;After a micro benchmark, on 1000 random arrays of 100 000 element &lt;br /&gt;&lt;br /&gt;&lt;table style="border: 1px solid black;" &gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Total Time (ms)&lt;/th&gt;&lt;th&gt;Average Time (ms)&lt;/th&gt;&lt;th&gt;Min Time (ms)&lt;/th&gt;&lt;th&gt;Max Time (ms)&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;Collections.sort&lt;/b&gt;&lt;/td&gt;&lt;td style="text-align:right;"&gt;81 893&lt;/td&gt;&lt;td style="text-align:right;"&gt;81&lt;/td&gt;&lt;td style="text-align:right;"&gt;62&lt;/td style="text-align:right;"&gt;&lt;td style="text-align:right;"&gt;125&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;b&gt;TreeSet&lt;/b&gt;&lt;/td&gt;&lt;td style="text-align:right;"&gt;187 578&lt;/td style="text-align:right;"&gt;&lt;td style="text-align:right;"&gt;187&lt;/td&gt;&lt;td style="text-align:right;"&gt;140&lt;/td&gt;&lt;td style="text-align:right;"&gt;281&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;    &lt;br /&gt;In the Benchmark the Collections.sort takes 43 % of the time that it takes using the Tree.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-310964634369494077?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/310964634369494077/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=310964634369494077" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/310964634369494077" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/310964634369494077" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/08/micro-benchmark-collection-sorting.html" title="Micro benchmark - Collection sorting" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-2787313727519811789</id><published>2007-08-16T01:33:00.001-07:00</published><updated>2007-08-16T01:33:54.962-07:00</updated><title type="text">Normalization under attack</title><content type="html">&lt;a href="http://www.infoq.com/news/2007/08/denormalization"&gt;Data normalization, is it really that good?&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-2787313727519811789?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/2787313727519811789/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=2787313727519811789" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/2787313727519811789" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/2787313727519811789" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/08/normalization-under-attack.html" title="Normalization under attack" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4396093936384561136.post-7338672429063097277</id><published>2007-07-02T06:48:00.000-07:00</published><updated>2007-07-02T09:29:21.375-07:00</updated><title type="text">Xalan-specific output properties nightmare</title><content type="html">At work we are using Xalan 2.7.0, it works fine except that for some reason we would like to modify a bit the html output method. This method strip the attribute value for readonly and disabled attribute. E.g :&lt;br /&gt;&lt;br /&gt;&lt;div&gt;   &lt;table style="color: rgb(0, 0, 0);" border="1" cellpadding="3" cellspacing="0" width="100%"&gt;     &lt;tbody&gt;     &lt;tr&gt;       &lt;td width="100%"&gt;         &lt;span style="font-family:Courier New;"&gt;&amp;lt;input readonly="readonly" type="checkbox"&amp;gt; &lt;/span&gt;       &lt;/td&gt;     &lt;/tr&gt;     &lt;/tbody&gt;   &lt;/table&gt; &lt;/div&gt; &lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;is output as&lt;br /&gt;&lt;br /&gt;&lt;div&gt;   &lt;table style="color: rgb(0, 0, 0);" border="1" cellpadding="3" cellspacing="0" width="100%"&gt;     &lt;tbody&gt;     &lt;tr&gt;       &lt;td width="100%"&gt;         &lt;span style="font-family:Courier New;"&gt;&amp;lt;input type="checkbox"&amp;gt; &lt;/span&gt;       &lt;/td&gt;     &lt;/tr&gt;     &lt;/tbody&gt;   &lt;/table&gt; &lt;/div&gt; &lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;that's fair enough but not the behaviour we need. So I start looking for a way to change that. I quicly found the way the method influence the Serializer. If you like in the output_html.properties you'll find&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;table style="color: rgb(0, 0, 0);" border="1" cellpadding="3" cellspacing="0" width="100%"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td width="100%"&gt;&lt;span style="font-family:Courier New;"&gt;# Xalan-specific output properties.  These can be overridden in the stylesheet&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;# assigning a xalan namespace.  For example:&lt;/span&gt;  &lt;span style="font-family:Courier New;"&gt;&lt;br /&gt;# &lt;xsl:stylesheet version="1.0"&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&lt;/span&gt;  &lt;span style="font-family:Courier New;"&gt;&lt;br /&gt;#          xmlns:xalan="http://xml.apache.org/xalan"&gt;&lt;/span&gt;  &lt;span style="font-family:Courier New;"&gt;&lt;br /&gt;# &lt;xsl:output method="html" encoding="UTF-8"&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#              xalan:content-handler="MyContentHandler"/&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#  ...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;# Note that the colon after the protocol needs to be escaped.&lt;/span&gt;&lt;/xsl:output&gt;&lt;/span&gt;&lt;/xsl:stylesheet&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;That was a great start. So how does the html content handler work ? Would it be possible to easily change its behaviour ? At first I thought so. The code interesting here is in the method protected void processAttribute(java.io.Writer writer, String name, String value, ElemDesc elemDesc) throws IOException&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px solid black" &gt;/**&lt;br /&gt;   * Process an attribute.&lt;br /&gt;   * @param   writer The writer to write the processed output to.&lt;br /&gt;   * @param   name   The name of the attribute.&lt;br /&gt;   * @param   value   The value of the attribute.&lt;br /&gt;   * @param   elemDesc The description of the HTML element&lt;br /&gt;   *           that has this attribute.&lt;br /&gt;   *&lt;br /&gt;   * @throws org.xml.sax.SAXException&lt;br /&gt;   */&lt;br /&gt;  protected void processAttribute(&lt;br /&gt;      java.io.Writer writer,&lt;br /&gt;      String name,&lt;br /&gt;      String value,&lt;br /&gt;      ElemDesc elemDesc)&lt;br /&gt;      throws IOException&lt;br /&gt;  {&lt;br /&gt;      writer.write(' ');&lt;br /&gt;&lt;br /&gt;      if (   ((value.length() == 0) || value.equalsIgnoreCase(name))&lt;br /&gt;          &amp;&amp;amp; elemDesc != null&lt;br /&gt;          &amp;&amp;amp; elemDesc.isAttrFlagSet(name, ElemDesc.ATTREMPTY))&lt;br /&gt;      {&lt;br /&gt;          writer.write(name);&lt;br /&gt;      }&lt;br /&gt;      else&lt;br /&gt;      {&lt;br /&gt;          // %REVIEW% %OPT%&lt;br /&gt;          // Two calls to single-char write may NOT&lt;br /&gt;          // be more efficient than one to string-write...&lt;br /&gt;          writer.write(name);&lt;br /&gt;          writer.write("=\"");&lt;br /&gt;          if (   elemDesc != null&lt;br /&gt;              &amp;&amp;amp; elemDesc.isAttrFlagSet(name, ElemDesc.ATTRURL))&lt;br /&gt;              writeAttrURI(writer, value, m_specialEscapeURLs);&lt;br /&gt;          else&lt;br /&gt;              writeAttrString(writer, value, this.getEncoding());&lt;br /&gt;          writer.write('"');&lt;br /&gt;&lt;br /&gt;      }&lt;br /&gt;  }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So when the ElemDesc which is defined in the ToHtmlStream got the attribute with the fllag ATTREMPTY it does that. Easy ! so we probably can extend this class and change the behaviour of processAttribute? No! Is there an easy way to change the ElemDesc? No! Maybe we can just copy and past the class? Not really without putting it in the jar, solution a bit to risky because the Xalan Jar is probably shared.&lt;br /&gt;&lt;br /&gt;So the solution? using reflexion to do a deep copy of the specific not very friendly Trie object - we want that only on the specified page -, and create an Handler that gonna delegate to the classic ToHtmlStream to which we are gonna change the root of the Trie object to point to the copy with the modified ElemDesc ... It does work but it's a nightmare of 200 lines of reflexion that used the name of private field of private inner class ...&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: 1px solid black"&gt;&lt;br /&gt;public class NewToHTMLStream implements SerializationHandler {&lt;br /&gt;&lt;br /&gt;    ToHTMLStream stream = null;&lt;br /&gt;&lt;br /&gt;    Object trieCopy = null;&lt;br /&gt;&lt;br /&gt;    static final Set&lt;String&gt; ATTRIBUTES = new HashSet&lt;String&gt;(Arrays.asList(new String[] { "READONLY", "DISABLED" }));&lt;br /&gt;&lt;br /&gt;    static final Object lock = new Object();&lt;br /&gt;&lt;br /&gt;    private static Field fieldm_htmlInfo;&lt;br /&gt;&lt;br /&gt;    private static Field field_trie_root;&lt;br /&gt;&lt;br /&gt;    private static Field field_trie_node_nodes;&lt;br /&gt;&lt;br /&gt;    private static Field field_trie_node_value;&lt;br /&gt;&lt;br /&gt;    private static Field field_m_elementFlags;&lt;br /&gt;&lt;br /&gt;    private static Field field_ElemDesc_m_attrs;&lt;br /&gt;&lt;br /&gt;    private static Field field_ElemDesc_m_Flags;&lt;br /&gt;&lt;br /&gt;    private static Method elementDesc_setAttr;&lt;br /&gt;&lt;br /&gt;    private static Constructor&lt;ElemDesc&gt; eltDescConstructor;&lt;br /&gt;&lt;br /&gt;    private static Constructor nodeConstructor;&lt;br /&gt;&lt;br /&gt;    private static Constructor constructorTrie;&lt;br /&gt;&lt;br /&gt;    private static Field fieldMMap;&lt;br /&gt;&lt;br /&gt;    private static Field fieldMValues;&lt;br /&gt;&lt;br /&gt;    private static Field fieldMFirstFree;&lt;br /&gt;&lt;br /&gt;    public NewToHTMLStream() throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException, SecurityException, NoSuchMethodException, InvocationTargetException, InstantiationException {&lt;br /&gt;&lt;br /&gt;        stream = new ToHTMLStream();&lt;br /&gt;&lt;br /&gt;        synchronized (lock) {&lt;br /&gt;            if (trieCopy == null) {&lt;br /&gt;                trieCopy = copyTrie();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;br /&gt;        Object htmlInfo = fieldm_htmlInfo.get(stream);&lt;br /&gt;        &lt;br /&gt;        field_trie_root.set(htmlInfo, field_trie_root.get(trieCopy));&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static Object copyTrie() throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchMethodException, InvocationTargetException, InstantiationException {&lt;br /&gt;        initReflexion();&lt;br /&gt;&lt;br /&gt;        Object m_elementFlags = field_m_elementFlags.get(ToHTMLStream.class);&lt;br /&gt;        Object newTrie = constructorTrie.newInstance(new Object[] { m_elementFlags });&lt;br /&gt;&lt;br /&gt;        Object root = (Object) field_trie_root.get(m_elementFlags);&lt;br /&gt;&lt;br /&gt;        Object newRoot = copyNode(root, newTrie);&lt;br /&gt;&lt;br /&gt;        field_trie_root.set(newTrie, newRoot);&lt;br /&gt;&lt;br /&gt;        return newTrie;&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static Object copyNode(Object root, Object trie) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {&lt;br /&gt;        Object copy = nodeConstructor.newInstance(new Object[] { trie });&lt;br /&gt;&lt;br /&gt;        field_trie_node_value.set(copy, copyElementDescription(field_trie_node_value.get(root)));&lt;br /&gt;&lt;br /&gt;        Object[] originalNodes = (Object[]) field_trie_node_nodes.get(root);&lt;br /&gt;        Object[] newNodes = (Object[]) field_trie_node_nodes.get(copy);&lt;br /&gt;&lt;br /&gt;        for (int i = 0; i &lt; originalNodes.length; i++) {&lt;br /&gt;            Object n = originalNodes[i];&lt;br /&gt;            if (n != null) {&lt;br /&gt;                newNodes[i] = copyNode(n, trie);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return copy;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static ElemDesc copyElementDescription(Object o) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {&lt;br /&gt;        if (o == null)&lt;br /&gt;            return null;&lt;br /&gt;&lt;br /&gt;        ElemDesc desc = (ElemDesc) o;&lt;br /&gt;&lt;br /&gt;        ElemDesc desc2 = eltDescConstructor.newInstance(new Object[] { field_ElemDesc_m_Flags.get(desc) });&lt;br /&gt;&lt;br /&gt;        /*&lt;br /&gt;         * m_attrs copy except ATTRIBUTES&lt;br /&gt;         */&lt;br /&gt;&lt;br /&gt;        StringToIntTable m_attrs = (StringToIntTable) field_ElemDesc_m_attrs.get(desc);&lt;br /&gt;&lt;br /&gt;        if (m_attrs != null) {&lt;br /&gt;            String[] m_map = (String[]) fieldMMap.get(m_attrs);&lt;br /&gt;            int[] m_values = (int[]) fieldMValues.get(m_attrs);&lt;br /&gt;            int m_firstFree = (Integer) fieldMFirstFree.get(m_attrs);&lt;br /&gt;&lt;br /&gt;            for (int j = 0; j &lt; m_firstFree; j++) {&lt;br /&gt;                int flag = 0;&lt;br /&gt;                String attributeName = m_map[j];&lt;br /&gt;                if (!ATTRIBUTES.contains(attributeName)) {&lt;br /&gt;                    flag = m_values[j];&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                elementDesc_setAttr.invoke(desc2, new Object[] { attributeName, flag });&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return desc2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static void initReflexion() throws NoSuchFieldException, NoSuchMethodException {&lt;br /&gt;        fieldm_htmlInfo = setAccessible("m_htmlInfo", ToHTMLStream.class);&lt;br /&gt;&lt;br /&gt;        field_m_elementFlags = setAccessible("m_elementFlags", ToHTMLStream.class);&lt;br /&gt;&lt;br /&gt;        constructorTrie = field_m_elementFlags.getType().getDeclaredConstructor(new Class[] { field_m_elementFlags.getType() });&lt;br /&gt;        constructorTrie.setAccessible(true);&lt;br /&gt;&lt;br /&gt;        field_trie_root = setAccessible("m_Root", field_m_elementFlags.getType());&lt;br /&gt;        field_trie_node_nodes = setAccessible("m_nextChar", field_trie_root.getType());&lt;br /&gt;        field_trie_node_value = setAccessible("m_Value", field_trie_root.getType());&lt;br /&gt;&lt;br /&gt;        nodeConstructor = field_trie_root.getType().getDeclaredConstructor(new Class[] { field_m_elementFlags.getType() });&lt;br /&gt;        nodeConstructor.setAccessible(true);&lt;br /&gt;&lt;br /&gt;        field_ElemDesc_m_attrs = setAccessible("m_attrs", ElemDesc.class);&lt;br /&gt;        field_ElemDesc_m_Flags = setAccessible("m_flags", ElemDesc.class);&lt;br /&gt;        elementDesc_setAttr = setAccessible("setAttr", new Class[] { String.class, Integer.TYPE }, ElemDesc.class);&lt;br /&gt;&lt;br /&gt;        eltDescConstructor = ElemDesc.class.getDeclaredConstructor(new Class[] { Integer.TYPE });&lt;br /&gt;        eltDescConstructor.setAccessible(true);&lt;br /&gt;&lt;br /&gt;        fieldMMap = setAccessible("m_map", StringToIntTable.class);&lt;br /&gt;        fieldMValues = setAccessible("m_values", StringToIntTable.class);&lt;br /&gt;        fieldMFirstFree = setAccessible("m_firstFree", StringToIntTable.class);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static Method setAccessible(String methodName, Class[] paramTypes, Class&lt;? extends Object&gt; clazz) throws SecurityException, NoSuchMethodException {&lt;br /&gt;        Method method = clazz.getDeclaredMethod(methodName, paramTypes);&lt;br /&gt;&lt;br /&gt;        method.setAccessible(true);&lt;br /&gt;        return method;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static Field setAccessible(String fieldName, Class&lt;? extends Object&gt; clazz) throws NoSuchFieldException {&lt;br /&gt;        Field fieldMAttrs = clazz.getDeclaredField(fieldName);&lt;br /&gt;&lt;br /&gt;        fieldMAttrs.setAccessible(true);&lt;br /&gt;        return fieldMAttrs;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * DELEGATE to stream ...&lt;br /&gt;     */&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4396093936384561136-7338672429063097277?l=morningcofee.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://morningcofee.blogspot.com/feeds/7338672429063097277/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4396093936384561136&amp;postID=7338672429063097277" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/7338672429063097277" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4396093936384561136/posts/default/7338672429063097277" /><link rel="alternate" type="text/html" href="http://morningcofee.blogspot.com/2007/07/xalan-specific-output-properties.html" title="Xalan-specific output properties nightmare" /><author><name>French Fry</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="14144473459078849693" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry></feed>
