<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4700787238821257876</id><updated>2011-12-03T13:34:55.287-08:00</updated><category term='document generation'/><category term='JODReports'/><category term='star-schema'/><category term='Scala'/><category term='GWT'/><category term='jaxb hibernate import export'/><category term='java zip ZipInputStream'/><category term='java date'/><category term='XP'/><category term='Maven'/><category term='anti-pattern'/><category term='BI'/><category term='ODT'/><category term='Hibernate'/><category term='UML code generation'/><category term='webdav tomcat XP JackRabbit'/><category term='GWT XSTM'/><category term='svn ignore multiple folders directories'/><category term='document automation programming'/><category term='Java'/><category term='Open Office'/><title type='text'>TradeOffz</title><subtitle type='html'>Challenges facing Software Engineering</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>46</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-1483428919829108962</id><published>2009-08-12T14:21:00.000-07:00</published><updated>2009-08-12T14:22:53.959-07:00</updated><title type='text'>To Be Continued</title><content type='html'>see &lt;a href="http://www.trade-offs.nl/blog/"&gt;http://www.trade-offs.nl/blog/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-1483428919829108962?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/1483428919829108962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=1483428919829108962' title='41 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/1483428919829108962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/1483428919829108962'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2009/08/to-be-continued.html' title='To Be Continued'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>41</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-2636505158827488525</id><published>2008-11-18T06:15:00.000-08:00</published><updated>2008-11-18T06:19:00.925-08:00</updated><title type='text'>Web application configuration on Tomcat using Spring</title><content type='html'>In order to get two sets of independent configuration (property) files, one for development and one for production, one can do the following:&lt;br /&gt;&lt;br /&gt;In the web-inf folder place a property file, e.g. act.properties&lt;br /&gt;In the applicationContext.xml define:&lt;br /&gt;&lt;br /&gt;    &lt;bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;&lt;br /&gt;        &lt;property name="locations"&gt;&lt;br /&gt;             &lt;list&gt;&lt;br /&gt;                 &lt;value&gt;WEB-INF/act.properties&lt;/value&gt;&lt;br /&gt;                 &lt;value&gt;file:///${CATALINA_HOME}/act.properties&lt;/value&gt;&lt;br /&gt;             &lt;/list&gt;&lt;br /&gt;         &lt;/property&gt;&lt;br /&gt;        &lt;property name="ignoreResourceNotFound" value="true"&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-2636505158827488525?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/2636505158827488525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=2636505158827488525' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/2636505158827488525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/2636505158827488525'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/11/web-application-configuration-on-tomcat.html' title='Web application configuration on Tomcat using Spring'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-2388882379038900786</id><published>2008-11-06T00:30:00.000-08:00</published><updated>2008-11-06T00:37:15.146-08:00</updated><title type='text'>Birt versus Jasper Reports</title><content type='html'>My experiences as a new user with Birt and Jasper.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Birt&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A report grouped by week done within a one - two hours&lt;/li&gt;&lt;li&gt;Built-in support for group-by week (special function)&lt;/li&gt;&lt;li&gt;Adding JDBC drivers is easy&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Jasper&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I get hopelessly lost in the NetBeans based IDE. I do not understand how to use the query builder and the report builder.&lt;/li&gt;&lt;li&gt;Trying to build a report with group-by week is hard. No built-in support for weeks, just the standard java.util.timestamp functions. Trying to build an expression using day() results in weird validation errors (cannot cast from int to Integer()). With 1.5 you should not get this error anyway.  Adding cast does not help. Bottom-line I do not understand the problem and the tool is not helping me to solve it.&lt;/li&gt;&lt;li&gt;NetBeans based IDE looks a lot sharper as the 3.0 classic IDE.&lt;/li&gt;&lt;li&gt;Selecting a SQL Server JDBC driver from dropdown result in classnotfound exception, you can select the driver, but it is not delivered with the product. You need to add your own drivers. Very confusing&lt;/li&gt;&lt;li&gt;A report needs to get compiled. Makes it harder to work with. Probably results in better performance but should be optional.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-2388882379038900786?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/2388882379038900786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=2388882379038900786' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/2388882379038900786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/2388882379038900786'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/11/birt-versus-jasper-reports.html' title='Birt versus Jasper Reports'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-2684990604775555431</id><published>2008-09-11T12:05:00.000-07:00</published><updated>2008-09-11T12:20:07.594-07:00</updated><title type='text'>VB6 &amp; REST</title><content type='html'>I want to call a REST service from my VB6 Macro. This &lt;a href="http://www.freevbcode.com/ShowCode.asp?ID=7611"&gt;page&lt;/a&gt; describes how to do this using IE 6 COM objects, instead of needing to install the MS SOAP Toolkit (if it is still available)&lt;br /&gt;&lt;br /&gt;It will probably also work for IE 7 since the difference between the two is small. Anyway something to verify.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In case the original page gets lost:&lt;br /&gt;&lt;br /&gt;' Create objects to DOMDocument and XMLHTTP&lt;br /&gt;Set objDom = CreateObject("MSXML2.DOMDocument")&lt;br /&gt;Set objXmlHttp = CreateObject("MSXML2.XMLHTTP")&lt;br /&gt;&lt;br /&gt;' Load XML&lt;br /&gt;objDom.async = False&lt;br /&gt;objDom.loadXML XmlBody&lt;br /&gt;&lt;br /&gt;objXmlHttp.open "POST", AsmxUrl, False&lt;br /&gt;&lt;br /&gt;objXmlHttp.setRequestHeader "Content-Type", "text/xml; charset=utf-8"&lt;br /&gt;objXmlHttp.setRequestHeader "SOAPAction", SoapActionUrl&lt;br /&gt;&lt;br /&gt;objXmlHttp.send objDom.xml&lt;br /&gt;&lt;br /&gt;strRet = objXmlHttp.responseText&lt;br /&gt;&lt;br /&gt;Set objXmlHttp = Nothing&lt;br /&gt;&lt;br /&gt;' strRet contains result&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-2684990604775555431?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/2684990604775555431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=2684990604775555431' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/2684990604775555431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/2684990604775555431'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/09/vb6-rest.html' title='VB6 &amp; REST'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-3038042347508788010</id><published>2008-08-13T06:58:00.000-07:00</published><updated>2008-08-13T09:42:12.663-07:00</updated><title type='text'>Evaluation criteria Java Library</title><content type='html'>Evaluation criteria I suggest:&lt;br /&gt;-    maturity of the product; years in service,&lt;br /&gt;-    size of the community, popularity among developers, documentation&lt;br /&gt;-    feature set and what is missing&lt;br /&gt;-    how easy to extend&lt;br /&gt;-    rate of new releases&lt;br /&gt;-    stability, performance, scalability&lt;br /&gt;-    integration with other 3rd party libs (e.g. Spring, Hibernate, ActiveMQ, GWT, etc)&lt;br /&gt;-    (commercial) support&lt;br /&gt;- license&lt;br /&gt;-    Readability / ease of use of the configuration files&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-3038042347508788010?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/3038042347508788010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=3038042347508788010' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3038042347508788010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3038042347508788010'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/08/evaluation-criteria-java-library.html' title='Evaluation criteria Java Library'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-9178294166146893313</id><published>2008-07-03T13:19:00.000-07:00</published><updated>2008-07-03T13:26:05.697-07:00</updated><title type='text'>Partitioning</title><content type='html'>Partitioning is a very import aspect of software development; you need to partition the application into several parts; modules, classes, units, whatsoever. Dividing the work among people is also partitioning. Choosing the right partitioning is about trade-offs.&lt;br /&gt;&lt;br /&gt;It stroke me during my vacation that a landmass like Europe is also partitioned; it is divided into countries. It took a couple of thousand of years and a lot of fights, but finally we have a stable partitioning of land. In a way it is a self organizing system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-9178294166146893313?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/9178294166146893313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=9178294166146893313' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/9178294166146893313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/9178294166146893313'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/07/partitioning.html' title='Partitioning'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-5019168803979201065</id><published>2008-04-03T08:06:00.000-07:00</published><updated>2008-04-03T08:08:58.748-07:00</updated><title type='text'>RBAC versus ACL</title><content type='html'>&lt;a href="http://en.wikipedia.org/wiki/Role-based_access_control"&gt;RBAC&lt;/a&gt; stands for role-based access control&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Access_control_list"&gt;ACL&lt;/a&gt; stands for access control list&lt;br /&gt;&lt;br /&gt;RBAC adds an indirection level - role.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-5019168803979201065?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/5019168803979201065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=5019168803979201065' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5019168803979201065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5019168803979201065'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/04/rbac-versus-acl.html' title='RBAC versus ACL'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-3766779299954898203</id><published>2008-03-27T09:22:00.001-07:00</published><updated>2008-03-27T09:23:06.647-07:00</updated><title type='text'>Perfection</title><content type='html'>Perfection kills innovation&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-3766779299954898203?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/3766779299954898203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=3766779299954898203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3766779299954898203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3766779299954898203'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/03/perfection.html' title='Perfection'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-962985132667659397</id><published>2008-03-16T05:18:00.001-07:00</published><updated>2008-03-16T05:33:07.574-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='star-schema'/><category scheme='http://www.blogger.com/atom/ns#' term='BI'/><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Hibernate and BI</title><content type='html'>Business Intelligence (BI) requires a star schema for efficient analytics. (the difference between analytics and reporting is that reporting requires you to know up front what you want to report and analytics allows you to do ad-hoc reporting). BI operates in most cases from a data warehouse based on star schemas to allow fast and time-based (historical) reporting. Reporting from the operational data sources would jeopardize the transactional/operational systems and in most cases does not allow for historical reports.&lt;br /&gt;&lt;br /&gt;An ordinary application based on a persistence engine like Hibernate uses obviously an operational schema - making analytics hard. It would be nice to let Hibernate also update a data warehouse - similar to updating the indexes for text based retrieval.&lt;br /&gt;&lt;br /&gt;So when a transaction is comitted, a message (asynchronously) is send to a component that updates the data warehouse. Each operation has a time stamp - allowing time based reporting. You could even use the data warehouse as a kind of trash bucket to restore data that has been deleted inadvertently.&lt;br /&gt;&lt;br /&gt;To summarize; the application has three data sources; operational, warehouse and text-indexes.&lt;br /&gt;An application in this way allows for text based search and analytics reports.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-962985132667659397?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/962985132667659397/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=962985132667659397' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/962985132667659397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/962985132667659397'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/03/hibernate-and-bi.html' title='Hibernate and BI'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-748789325107014823</id><published>2008-03-05T06:44:00.000-08:00</published><updated>2008-03-05T07:26:54.682-08:00</updated><title type='text'>Tomcat as Windows Service</title><content type='html'>To install Tomcat5 as a service follow the &lt;a href="http://tomcat.apache.org/tomcat-5.5-doc/windows-service-howto.html"&gt;"Windows service HOW-TO" instructions&lt;/a&gt; on the Apache Tomcat side.&lt;br /&gt;&lt;br /&gt;Calling &lt;span style="font-family:courier new;"&gt;Tomcat5 //IS//MyServiceName blabla&lt;/span&gt; will create an entry in the Windows registry located at:&lt;br /&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyServiceName&lt;br /&gt;&lt;br /&gt;The new installed service when started does a call back to tomcat5.exe specifying the service name and the start parameter.&lt;br /&gt;&lt;br /&gt;With &lt;span style="font-family:courier new;"&gt;tomcat5w //ES//MyServiceName&lt;/span&gt; you can monitor the service. Bit similar to the Windows Services application, but it has more functionality like specifying the log level and log location.&lt;br /&gt;&lt;br /&gt;In my case the service did not start and I had an error in the log:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[2008-03-05 15:55:24] [443 javajni.c] [error] FindClass org/apache/catalina/startup/Bootstrap failed&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[2008-03-05 15:55:24] [997 prunsrv.c] [error] Failed loading main org/apache/catalina/startup/Bootstrap class &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[2008-03-05 15:55:24] [1260 prunsrv.c] [error] ServiceStart returned 3&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So a classpath problem. I re-read the instructions and I noticed that the remark " If using tomcat5.exe, " put me on the wrong foot. I thought service.bat applied to versions prior 5. Appearently this is not the case because running service.bat worked fine. Looking into the content of service.bat I noticed that there is some classpath manipulation and after installing the service, the service is also updated with JVM options so this way is superior as to the excerpt installing Tomcat5. (In hindsight I completely misinterpreted this)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Deleting the service using &lt;span style="font-family:courier new;"&gt;//DS&lt;/span&gt; removes the entry from the registry.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-748789325107014823?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/748789325107014823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=748789325107014823' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/748789325107014823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/748789325107014823'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/03/tomcat-as-windows-service.html' title='Tomcat as Windows Service'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-9200404948698206988</id><published>2008-02-29T00:29:00.000-08:00</published><updated>2008-02-29T02:05:22.382-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GWT XSTM'/><title type='text'>GWT &amp; object serialization</title><content type='html'>When writing GWT business applications you have the problem that the object graph resided at the server has to be partially send to the browser/client, (perhaps) updated and send back.&lt;br /&gt;&lt;br /&gt;A though problem to crack is how to break the graph in pieces. After all, we do not want to send the entire database from the server to the client. This is similar to the problem that Hibernate solves when communicating with the database. Hibernate will load on-demand needed objects from the database. Hibernate will also optimize the updates to the database.&lt;br /&gt;&lt;br /&gt;I think it is key to have something similar to Hibernate for the GWT arena. Instead of manually loading additional objects a framework should handle this.&lt;br /&gt;&lt;br /&gt;A key difference is that (in most cases) the Hibernate instance is a singleton, thus allowing caching techniques. Caching at the browser is tricky since other clients can have updated the data.&lt;br /&gt;&lt;br /&gt;My hope was that a framework like &lt;a href="http://www.xstm.net/"&gt;XSTM &lt;/a&gt;would solve this problem. The sad things it that it uses code generation. I'm not in favor of code generation and especially not when it involves the domain objects. Reason is that it makes the usage of the library very intrusive through your entire application. Advantage of code generation in this case instead of byte code manipulation is of course that it runs in GWT.&lt;br /&gt;&lt;br /&gt;Anyway when I look at the sample the objects replicated are stored in a share, which is a generic container and thus requiring a lot of casting. My idea that you could retrieve objects with a query kind of language is not the case, you have to manually put in the share and get it out. So this solution will work well for games I suspect - but not for business applications with huge databases. In this case you have to write code at client side to notify the server which objects to put in the share. Again plumming that I hoped the framework would fix. Looks like that XSTM requires an additional layer of abstraction on top of it that will make it hide the clouds/shares and just work with regular objects.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-9200404948698206988?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/9200404948698206988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=9200404948698206988' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/9200404948698206988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/9200404948698206988'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/02/gwt-object-serialization.html' title='GWT &amp; object serialization'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-2037554857290743093</id><published>2008-02-18T03:50:00.000-08:00</published><updated>2008-02-18T03:52:58.008-08:00</updated><title type='text'>All problems in computer science can be solved by another level of indirection</title><content type='html'>Finally found the guy(s) whom the quote is from.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/"&gt;Butler Lampson&lt;/a&gt; and/or &lt;a href="http://en.wikipedia.org/wiki/David_Wheeler_%28computer_scientist%29"&gt;David Wheeler&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-2037554857290743093?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/2037554857290743093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=2037554857290743093' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/2037554857290743093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/2037554857290743093'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/02/all-problems-in-computer-science-can-be.html' title='All problems in computer science can be solved by another level of indirection'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-2511210393033870057</id><published>2008-02-16T13:44:00.000-08:00</published><updated>2008-02-16T14:13:45.965-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Cross-region software development</title><content type='html'>At my company we have been struggling finding out the optimal partitioning of the source tree of a product that is developed in three different countries (US, India and NL).&lt;br /&gt;&lt;br /&gt;Some people prefer to have a single source tree. Others (among myself) prefer to have a stricter separation between the teams in different locations and time zones. One of the major reasons is that if the build is broken or disfunctional caused by team A, it impacts the productivity of team B and C. The developers of team B or C enter in the morning and face a build in which they cannot check. First the failure has to be solved before continuing regular development. Admitted, this can be done by a single person, but still the broken build impacts all the developers of a team since they can't check-in and might have updated from source control before realizing something was wrong. Since a team performs optimal when it is running at constant speed - similar to a car's engine - you need to avoid peaks and breaks.&lt;br /&gt;&lt;br /&gt;Another reason for keeping sources separate is that you want to avoid mixing integration and regular development cross teams. Otherwise you cannot isolate external factors easily. It is much more efficient when you have accomplished your work of team development, all tests are passing and then integrate new releases of other teams or 3'rd party artifacts. If something fails, the cause is much easier to spot then when you also have changed your code.&lt;br /&gt;&lt;br /&gt;Lesson: separate daily development from integration. We effectuated this (or tried to)  by giving each team  and the application its own Maven artifact. Admitted, you need Maven mavens to get the whole thing working. (BTW we never got to the point where we could fully demonstrate this Maven approach to be more efficient, in the past we used branches)&lt;br /&gt;&lt;br /&gt;An often heard counter argument for having separate source trees is the price you have to pay for refactorings, especially renaming classes / methods. This can be solved in the following way: at the end of an iteration, the teams have released their artifacts and hopefully the product is working with all the parts integrated. So the start of the next iteration is an excellent time to get all the source code into a single view / project and refactor some elements. Yes, indeed you do have to wait. That is a small price to pay. However note that for really big products, getting all the source code into a single project probably makes the IDE too slow. This is something you do not want to work with the whole day. Besides renaming there is also a refactoring like changing the signature. The same can be accomplished with deprecating and introducing new methods.&lt;br /&gt;&lt;br /&gt;Another mistake often made is the focus on compilation - which can easily be accomplished with a single source tree. IF the code compiles together then we are OK. But compiling is only just a small part of creating the product, much more important is to have a stable product and you know what is in it. That the code compiles together, does not mean a thing. It gets much better if the artifacts have passed their unit tests, are released and composed into a new product - that should pass some automated acceptance test.&lt;br /&gt;&lt;br /&gt;There is much more to this discussion, I will have to add that another time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-2511210393033870057?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/2511210393033870057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=2511210393033870057' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/2511210393033870057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/2511210393033870057'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/02/cross-region-software-development.html' title='Cross-region software development'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-4260301788430147300</id><published>2008-02-16T03:50:00.000-08:00</published><updated>2008-02-16T14:14:38.157-08:00</updated><title type='text'>Panta rhei</title><content type='html'>Everything flows - Heraklitus.&lt;br /&gt;&lt;br /&gt;Well known fact; when you write down the specs, the world is changing. By the time you've finished the implementation the world is no longer the same. This why we all went agile.&lt;br /&gt;&lt;br /&gt;There is another side to this; with an agile approach you take shortcuts in the first iteration. Most simple thing you can do, blabla bla. However a couple of iterations down the road, you forgot you took some shortcuts. People start cursing the whacky implementation, forgetting that this was a deliberate choice and now the time has come to crank up the implementations.&lt;br /&gt;&lt;br /&gt;Iterations also pose a challenge for QA. In my experience they are still used to the waterfall process. It is hard for them; each iteration new functionality is delivered but still some things are not (yet) fully functional. The deliverable of each iteration has to be carefully defined to enable them to properly test the deliverable. However, how much time you are going to invest writing a detailed document that is obsolete after the next iteration? Worse, how are you going to get the full spec after all iteration are finished? How efficient are UI designers if they know that each iteration the UI will change? Do they start with a wizard or tab-based approach because they know the next iteration requires more widgets?&lt;br /&gt;&lt;br /&gt;There is some kind of impedance mismatch between the development process (iterative) and the product as itself. As usual a trade-off.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-4260301788430147300?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/4260301788430147300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=4260301788430147300' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/4260301788430147300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/4260301788430147300'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/02/panta-rhei.html' title='Panta rhei'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-1131796883227159679</id><published>2008-02-12T02:04:00.000-08:00</published><updated>2008-02-16T13:40:36.052-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><title type='text'>Scala</title><content type='html'>I've been reading the “Scala for Java Refugees” series. I'm amazed by the power of this language. Tuples,  closure, etc, everything that annoys me about Java is 'fixed'. The language itself is a bit overwhelming, reminds me of university with its magical and impressive calculus notations.&lt;br /&gt;&lt;br /&gt;Reading on the implicit type conversion in serie 6, I got similar feeling when reading on AOP for the first time. It might become complex to understand the code, especially in the case of Scala where a smart compiler can find paths the developer has not thought off.&lt;br /&gt;&lt;br /&gt;Probably the answer is the same as with AOP, use it scarce, wise and effective. In other words not all over the place, but where it pays off, eg security, transactions, all those clear cross cutting concerns.&lt;br /&gt;&lt;br /&gt;I'm impressed by the expressive power of the language. On &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=223156"&gt;ScalaTest&lt;/a&gt; the expect construct is close to natural language (ok, a bit exaggerated). The freedom it gives to clearly state the intent, is something you never get with Java.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-1131796883227159679?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/1131796883227159679/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=1131796883227159679' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/1131796883227159679'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/1131796883227159679'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/02/scala.html' title='Scala'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-8375299999342788364</id><published>2008-02-07T11:49:00.000-08:00</published><updated>2008-02-08T03:04:26.471-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JODReports'/><title type='text'>JODReports and MS-Word</title><content type='html'>I finally implemented my document generation application using &lt;a href="http://www.artofsolving.com/opensource/jodreports"&gt;JODReports&lt;/a&gt;. The basic idea is as follows; user creates a bunch of templates using the JODReports variable mechanism and stores them in a certain folder. My application picks the templates up, converts to OO format, merges it with the data from the database, converts it back to Word and writes the files to a certain folder.&lt;br /&gt;&lt;br /&gt;Works pretty good so far. A couple of issues I stumbled into:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Editing the Word document by pasting a variable name from  html (in my case the instructions page in the browser) gives weird Freemarker parse exceptions. Pasting as plain text workarounds the problem.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;In the supplied merge data the zip code field is separated by two spaces from the city name. However the final merged document contains one space. This is also the case if the data contains three spaces...&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Default error handling from Freemarker prints out to the console. There is documentation how to fix this, but requires more research.&lt;/li&gt;&lt;li&gt;JODReports code is not well maintained. The code of the converter and the report are out of sync (watch the package names). Luckily this does not pose a problem when using it.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;It is a bit of a pity that JODReports does not support callbacks. Now you have to pass in all data up front. It would be nicer if JODReports would do a callback asking for the value of a field. Reason is that I need to supply a couple of calculated fields. Now I have to supply them all up front, whilst perhaps none is used.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-8375299999342788364?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/8375299999342788364/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=8375299999342788364' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/8375299999342788364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/8375299999342788364'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/02/jodreports-and-ms-word.html' title='JODReports and MS-Word'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-4466609614629786691</id><published>2008-01-29T11:45:00.000-08:00</published><updated>2008-02-25T04:29:37.962-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java date'/><title type='text'>Java Bug Date equals?</title><content type='html'>Who would have thought that the following test would fail: &lt;span style="font-family:georgia;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;private Date getDate14April() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Calendar calendar = Calendar.getInstance();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;calendar.set(2007, 3, 14, 15, 30); // 14 april 15:30&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;return calendar.getTime();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;public void testCompareDate() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Date date = getDate14April();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;for (int i=0; i &amp;lt; 100; i++) {&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;assertEquals(getDate14April, date);&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Stacktrace (edited brackets):&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;junit.framework.AssertionFailedError: 60 expected: [Sat Apr 14 15:30:40 CEST 2007] but was:[Sat Apr 14 15:30:40 CEST 2007]&lt;br /&gt;at org.westen.act.document.TestTemplateManager.testCompareDate(TestTemplateManager.java:212)&lt;br /&gt;at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;JavaDoc of Date.equals:&lt;/span&gt;&lt;br /&gt;Compares two dates for equality.&lt;br /&gt;The result is true if and only if the argument is not null&gt; and is a Date object that represents the same point in time, to the millisecond, as this object.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;"&gt;Hmm, I would have though that the milliseconds would have been initialized to 0 when I create a date object.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-4466609614629786691?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/4466609614629786691/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=4466609614629786691' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/4466609614629786691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/4466609614629786691'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/01/bug-comparing-dates.html' title='Java Bug Date equals?'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-4371845336147393666</id><published>2008-01-29T07:47:00.000-08:00</published><updated>2008-01-29T13:19:37.911-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hibernate'/><title type='text'>Hibernate many-to-many &amp; inverse</title><content type='html'>I had the problem that two entities A and B had a many-to-many relation but deleting an object a resulted in a constraint violation because the object was used by an object b.&lt;br /&gt;&lt;br /&gt;To my surprise fiddling with the inverse="true", inverse="false" and cascade="none" fixed the problem.&lt;br /&gt;&lt;br /&gt;My understanding is that deleting an object always deletes the row from the join table. (cascade="none").  Setting cascade to "delete" will also force the deletion of the object(s) on the other side.&lt;br /&gt;&lt;br /&gt;However why inverse="true" and "false" make a difference I do not understand. You would assume that specifying one would be enough and imply the other. Apparently there is more to it than I understand.  Needs a follow up...&lt;br /&gt;&lt;br /&gt;So I'm not the first one to run into this. Found this blog "&lt;a href="http://blogs.warwick.ac.uk/colinyates/entry/hibernates_bizzare_interpretation/"&gt;Hibernates bizarre interpretation of inverse&lt;/a&gt;". He basically says that inverse tells Hibernate which side of the relation to ignore. Although this does make complete sense to me, it fits my problem.&lt;br /&gt;&lt;br /&gt;Hmmmm&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-4371845336147393666?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/4371845336147393666/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=4371845336147393666' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/4371845336147393666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/4371845336147393666'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/01/hibernate-many-to-many-cascase.html' title='Hibernate many-to-many &amp; inverse'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-3707820481995899942</id><published>2008-01-19T12:36:00.000-08:00</published><updated>2008-01-19T12:54:23.997-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GWT'/><title type='text'>GWT-EXT</title><content type='html'>The last few weeks i've been struggling with GWT-Ext 1. Conclusion: the lay-out capabilities of GWT-Ext 1 are poor.&lt;br /&gt;&lt;br /&gt;For example a table-layout is not possible. When using a form you can only place a limited number of widgets on it. Separate label widget is not present.&lt;br /&gt;&lt;br /&gt;Ext v2 has much richer lay-our support. So we have to wait for GWT-Ext 2....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-3707820481995899942?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/3707820481995899942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=3707820481995899942' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3707820481995899942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3707820481995899942'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2008/01/gwt-ext.html' title='GWT-EXT'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-8894092456183209572</id><published>2007-12-19T07:55:00.000-08:00</published><updated>2008-02-16T13:42:31.019-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ODT'/><category scheme='http://www.blogger.com/atom/ns#' term='JODReports'/><title type='text'>Writing a test to verify ODT content</title><content type='html'>Sample to test the content of an Open Office document containing three lines ('1234', empty line, 'description'):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;import javax.xml.parsers.DocumentBuilderFactory;&lt;br /&gt;...&lt;br /&gt;import com.artofsolving.jodconverter.DefaultDocumentFormatRegistry;&lt;br /&gt;import com.artofsolving.jodconverter.DocumentConverter;&lt;br /&gt;import org.w3c.dom.Document;&lt;br /&gt;import org.w3c.dom.Element;&lt;br /&gt;&lt;br /&gt;ByteArrayOutputStream output = templateManager.applyModelToTemplate(inputStream, map);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        String content = getZipEntry(new ByteArrayInputStream(output.toByteArray()), "content.xml");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        Document doc = dbf.newDocumentBuilder().parse(new ByteArrayInputStream(content.getBytes()));&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        Element docElement = doc.getDocumentElement();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        assertEquals("office:document-content", docElement.getTagName());&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        Element bodyElement = (Element) docElement.getElementsByTagName("text:p").item(0);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        assertEquals("1234", bodyElement.getTextContent());&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        // skip empty line&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        bodyElement = (Element) docElement.getElementsByTagName("text:p").item(2);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        assertEquals("description", bodyElement.getTextContent());&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-8894092456183209572?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/8894092456183209572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=8894092456183209572' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/8894092456183209572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/8894092456183209572'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/12/writing-test-to-verify-odt-content.html' title='Writing a test to verify ODT content'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-7481643089051645291</id><published>2007-12-13T09:01:00.000-08:00</published><updated>2007-12-18T04:32:01.358-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java zip ZipInputStream'/><title type='text'>Getting the entry from a ZipInputStream</title><content type='html'>Finally I found the code to get an entry from an InputStream that contains zipped data. For a ZipFileInputStream this is easy, but not for a regular input stream because the size of the entry can be unknown (-1) and there is no alternative then just go through the stream.&lt;br /&gt;&lt;br /&gt;sorry for the messy mark-up...&lt;br /&gt;&lt;br /&gt;disclaimer: code is not optimized!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; // based on http://java.sun.com/developer/technicalArticles/Programming/compression/&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;public static String unzipEntry(InputStream zippedInputStream, String entryName) throws Exception {&lt;br /&gt;    String result = null;&lt;br /&gt;    final int BUFFER = 2048;&lt;br /&gt;    BufferedOutputStream dest = null;&lt;br /&gt;    ZipInputStream zis = new ZipInputStream(new BufferedInputStream(zippedInputStream));&lt;br /&gt;    ZipEntry entry;&lt;br /&gt;    while((entry = zis.getNextEntry()) != null) {&lt;br /&gt;    int count;&lt;br /&gt;    byte data[] = new byte[BUFFER];&lt;br /&gt;    StringOutputStream fos = new StringOutputStream();&lt;br /&gt;    dest = new BufferedOutputStream(fos, BUFFER);&lt;br /&gt;    while ((count = zis.read(data, 0, BUFFER)) != -1) {&lt;br /&gt;    dest.write(data, 0, count);&lt;br /&gt;    }&lt;br /&gt;    dest.flush();&lt;br /&gt;    dest.close();&lt;br /&gt;    if (entryName.equals(entry.getName())) {&lt;br /&gt;    result = fos.toString();&lt;br /&gt;    }&lt;br /&gt;    }&lt;br /&gt;    zis.close();&lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class StringOutputStream extends OutputStream {&lt;br /&gt;&lt;br /&gt;    // This buffer will contain the stream&lt;br /&gt;    protected StringBuffer buf = new StringBuffer();&lt;br /&gt;&lt;br /&gt;    public StringOutputStream() {}&lt;br /&gt;&lt;br /&gt;    public void close() {}&lt;br /&gt;&lt;br /&gt;    public void flush() {}&lt;br /&gt;&lt;br /&gt;    public void write(byte[] b) {&lt;br /&gt;    String str = new String(b);&lt;br /&gt;    this.buf.append(str);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void write(byte[] b, int off, int len) {&lt;br /&gt;    String str = new String(b, off, len);&lt;br /&gt;    this.buf.append(str);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void write(int b) {&lt;br /&gt;    String str = Integer.toString(b);&lt;br /&gt;    this.buf.append(str);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String toString() {&lt;br /&gt;    return buf.toString();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public int contains(String string) {&lt;br /&gt;    return StringUtils.countOccurrencesOf(buf.toString(), string);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-7481643089051645291?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/7481643089051645291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=7481643089051645291' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7481643089051645291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7481643089051645291'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/12/getting-entry-from-zipped-inputstream.html' title='Getting the entry from a ZipInputStream'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-5931676617913377252</id><published>2007-12-13T00:32:00.000-08:00</published><updated>2007-12-13T00:37:45.163-08:00</updated><title type='text'>Pairs</title><content type='html'>While driving to work I realized something funny:&lt;br /&gt;&lt;br /&gt;If I have to work on something, for example produce an article, I will write it, put it away and pick it up a couple of days later to look at it with a fresh mind.&lt;br /&gt;&lt;br /&gt;Within our team we also (sometimes) practice pair programming. The idea is that two know and see more than one (the power of interdependence ;-).&lt;br /&gt;&lt;br /&gt;Effectively these two practices are one and the same; in the first case you use yourself as the second person. Time will make you a different person than you were. The two practices differ in their usage of the dimensions time and resource. Tradeoffzz..&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-5931676617913377252?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/5931676617913377252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=5931676617913377252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5931676617913377252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5931676617913377252'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/12/pairs.html' title='Pairs'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-491374076659786297</id><published>2007-12-10T02:50:00.001-08:00</published><updated>2007-12-10T02:58:41.072-08:00</updated><title type='text'>Red/green/refactor &amp; spikes</title><content type='html'>I've developed a new way of coding new functionality. In the past I distinguished between spikes and production code development. The spike was meant for prototype code, throwaway code.&lt;br /&gt;&lt;br /&gt;Today I do it like this:&lt;br /&gt;I start with a new test that has some basic code that will do the basics of the job i'm after. I can very easily run this test from my IDE (IntelliJ in my case). After a while the test(s) will succeed. This proves that I understand the basics of the code needed. Next step is to move some code to the main folder - to production level. I will use Extract methods refactoring to do this.&lt;br /&gt;&lt;br /&gt;This way I slowly, but steadily move from prototype to production without redoing work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-491374076659786297?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/491374076659786297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=491374076659786297' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/491374076659786297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/491374076659786297'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/12/redgreenrefactor-spikes.html' title='Red/green/refactor &amp; spikes'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-6674782182691653007</id><published>2007-12-07T01:00:00.000-08:00</published><updated>2007-12-07T01:07:31.994-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='anti-pattern'/><category scheme='http://www.blogger.com/atom/ns#' term='XP'/><title type='text'>The Inner-Platform Effect</title><content type='html'>The &lt;a href="http://worsethanfailure.com/Articles/The_Inner-Platform_Effect.aspx"&gt;Inner-Platform Effect&lt;/a&gt; anti-pattern is a nice description of what I try to avoid with document generation. The task of making a document template becomes so complicated that only an expert can use it.&lt;br /&gt;&lt;br /&gt;In a way it reminds me of XP (extreme programming); keep it as simple as possible. Wait till the latest moment adding flexibility till is really needed.&lt;br /&gt;&lt;br /&gt;Another analogy is the J2EE / EJB programming model; programmers should focus on writing business logic. However tying the whole thing together on an application server like WAS was a nightmare and required more expertise than solving the original business problem.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-6674782182691653007?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/6674782182691653007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=6674782182691653007' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/6674782182691653007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/6674782182691653007'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/12/inner-platform-effect.html' title='The Inner-Platform Effect'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-3033214245073533890</id><published>2007-12-06T08:15:00.000-08:00</published><updated>2007-12-07T01:06:20.982-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='document generation'/><category scheme='http://www.blogger.com/atom/ns#' term='Open Office'/><title type='text'>RTFTemplate</title><content type='html'>&lt;a href="http://rtftemplate.sourceforge.net/"&gt;RTFTemplate&lt;/a&gt; is the Java library that does what i was looking for; it allows replacing MS-Word mail merge fields by actual data on the server side. So users can still define their document in the traditional sense using mail merge, save it as RTF and the server use it as a template to generate new documents.&lt;br /&gt;&lt;br /&gt;The issue however is how scalable this solution is in the long term; for example how easy is to add pieces of text to documents? Converting to PDF, which is necessary in my case, is also still not solved. Using Open Office as a templating engine would solve this. However running OO as a (headless) service complicates things; it is an external process, i'm not sure about memory leaks and/or how robust it is.&lt;br /&gt;&lt;br /&gt;Another con of using OO is that - since Word will still remain the document editor for the user - the fields have to be typed in as regular test with some markers, for example ${lastname}. This makes it a little less robust, typos are easier made, deleted by mistake, control characters within the field.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-3033214245073533890?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/3033214245073533890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=3033214245073533890' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3033214245073533890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3033214245073533890'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/12/rtftemplate.html' title='RTFTemplate'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-7610990437265809528</id><published>2007-11-27T10:52:00.000-08:00</published><updated>2007-11-27T10:54:41.153-08:00</updated><title type='text'>OpenOffice API sample</title><content type='html'>A sample on how to use the OpenOffice is described on this &lt;a href="http://weblogs.java.net/blog/tchangu/archive/2005/12/open_office_jav_1.html"&gt;blog&lt;/a&gt;. It gives the impression that it is not headless (perhaps my mistake). I know OpenOffice can run headless.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-7610990437265809528?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/7610990437265809528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=7610990437265809528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7610990437265809528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7610990437265809528'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/11/openoffice-api-sample.html' title='OpenOffice API sample'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-7994096194696535990</id><published>2007-11-26T02:48:00.000-08:00</published><updated>2007-11-26T04:21:21.551-08:00</updated><title type='text'>PDF Export in Java</title><content type='html'>This &lt;a href="http://schmidt.devlib.org/java/libraries-pdf.html"&gt;site&lt;/a&gt; and &lt;a href="http://www.dmoz.org/Computers/Programming/Languages/Java/Class_Libraries/Data_Formats/PDF/"&gt;Open Directory site&lt;/a&gt; mention a list of available Java libraries for PDF export (commercial and open source).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.alfresco.com/"&gt;Alfresco &lt;/a&gt;uses &lt;a href="http://www.pdfbox.org/"&gt;PdfBox&lt;/a&gt;, &lt;a href="http://poi.apache.org/"&gt;POI&lt;/a&gt; and OpenOffice for its document mgt. (I suspect OpenOffice for the PDF conversion)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-7994096194696535990?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/7994096194696535990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=7994096194696535990' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7994096194696535990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7994096194696535990'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/11/pdf-export-in-java.html' title='PDF Export in Java'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-982969675007503078</id><published>2007-11-25T09:52:00.001-08:00</published><updated>2008-03-16T05:17:25.408-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='webdav tomcat XP JackRabbit'/><title type='text'>WebDav</title><content type='html'>I did not realize that you could mount a webdav folder as a drive on your computer. For example &lt;a href="http://www.download.com/3000-2160_4-10647142.html"&gt;WebDrive&lt;/a&gt; does this. According to this &lt;a href="http://smallvoid.com/article/winnt-webdav-network-drive.html"&gt;article&lt;/a&gt; even XP SP3 can do it out-of-the-box (SP2 has some issues, see &lt;a href="http://forum.joyent.com/viewtopic.php?pid=4869"&gt;here&lt;/a&gt;). This makes remote documents easy to understand for users. (In my pet applications the users are used to shared drive for all their documents.  Versioning? They use backup &amp;amp; restore ;-)&lt;br /&gt;&lt;br /&gt;I need a simple WebDav implementation that redirects to a folder on the server. This way I can easily link to files from my web application. My hope is that users can also save the files they open this way (should be the case). Perhaps I will use Tomcat's webdav sample application, although I need to direct the content to/from another folder as the web application's root - which is not that easy. According to this &lt;a href="http://codinginparadise.org/weblog/2004/08/i-added-webdav-to-open-source-wikiwiki.html"&gt;blog&lt;/a&gt; it is possible using a JNDI factory.&lt;br /&gt;&lt;br /&gt;Instead of Tomcat I could use a library like &lt;a href="http://jackrabbit.apache.org/"&gt;JackRabbit&lt;/a&gt; or an application like Alfresco, but they are too heavy. (btw in my experience you should be very careful integration another &lt;span style="font-style: italic;"&gt;application&lt;/span&gt; into your own). Missing using Tomcat's implementation would be a search engine - which is supported by the two above, although i'm not sure whether JackRabbit would index Word documents out of the box. (btw I do know that JspWiki can search through Word Documents using Lucene)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-982969675007503078?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/982969675007503078/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=982969675007503078' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/982969675007503078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/982969675007503078'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/11/webdav.html' title='WebDav'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-3734116514626942121</id><published>2007-11-23T13:06:00.000-08:00</published><updated>2007-11-23T13:27:54.527-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='UML code generation'/><title type='text'>Executive UML</title><content type='html'>I do not believe in UML that can be executed one day. Perhaps for a very small, well defined domain it might work - and then only for the first 20%, the rest, the tweaking, small UI enhancements will require manual coding. Hopefully in a language that is powerful enough and does not require tons of code. (Java is an example of how it not should be done, with the writers, outputstreams, etc. You have always to pay the price for flexibility, certainly not a good trade-off)&lt;br /&gt;&lt;br /&gt;Alternative:&lt;br /&gt;&lt;br /&gt;From the requirements you distill the concepts. For example a requirement could be: "as end-user I should be able to add a contact person". Contact person would be a concept.&lt;br /&gt;The requirements would be translated in automated acceptance tests in terms of these concepts. The automated acceptance test would talk to an API. (call addContactPerson and getAllContactPersons). Next step would be to translate these tests to UI level - probably requiring human interaction&lt;span style="font-style: italic;"&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Obvious benefit would be that you could change the implementation and still verify whether the requirements are met or not.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-3734116514626942121?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/3734116514626942121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=3734116514626942121' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3734116514626942121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3734116514626942121'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/11/executive-uml.html' title='Executive UML'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-7871150615109533974</id><published>2007-11-23T07:03:00.001-08:00</published><updated>2007-11-23T07:06:40.211-08:00</updated><title type='text'>Modern Times</title><content type='html'>Ain't it weird: we fear privacy intrusion, but everybody is writing blogs. We dislike traditions like female genital mutilation, but women these days do surgery on their body everywhere.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-7871150615109533974?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/7871150615109533974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=7871150615109533974' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7871150615109533974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7871150615109533974'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/11/modern-times.html' title='Modern Times'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-7678402481329450753</id><published>2007-11-23T06:01:00.000-08:00</published><updated>2007-11-23T07:15:10.348-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='document automation programming'/><title type='text'>Word 2003 docx format - mail merge</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_oWeAcsf-SaI/R0bdypURe0I/AAAAAAAAAAM/vt-sXOmvJy0/s1600-h/mailmerge-docx.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_oWeAcsf-SaI/R0bdypURe0I/AAAAAAAAAAM/vt-sXOmvJy0/s320/mailmerge-docx.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5136036287216712514" /&gt;&lt;/a&gt;&lt;br /&gt;Hopefully i'm doing something wrong, but look at the screenshot to the left that displays the document.xml of a docx when a mail merge field has been defined. Notice the use of &lt;span style="font-style:italic;"&gt;begin &lt;/span&gt;and &lt;span style="font-style:italic;"&gt;end &lt;/span&gt;instead of making use of the hierarchical nature of xml.&lt;br /&gt;&lt;br /&gt;But it gets even weirder; if you define a document in Word (i'm using 2003 with the docx plugin) with the mail merge fields and you do a preview before saving the document then the document.xml looks like this:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_oWeAcsf-SaI/R0bj_JURe1I/AAAAAAAAAAU/n7GWklhZZd4/s1600-h/mailmerge2-docx.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_oWeAcsf-SaI/R0bj_JURe1I/AAAAAAAAAAU/n7GWklhZZd4/s320/mailmerge2-docx.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5136043099034843986" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The xml hierarchy of the last one makes sense, but the first one definitely not. Why the two are completely different, i've no clue...&lt;br /&gt;&lt;br /&gt;After doing some research I found out that others have run into a similar issue. See the hyperlink discussion on this &lt;a href="http://www.snee.com/bobdc.blog/2006/11/word_2003_xml.html"&gt;blog&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-7678402481329450753?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/7678402481329450753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=7678402481329450753' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7678402481329450753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7678402481329450753'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/11/docx-format-mail-merge.html' title='Word 2003 docx format - mail merge'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_oWeAcsf-SaI/R0bdypURe0I/AAAAAAAAAAM/vt-sXOmvJy0/s72-c/mailmerge-docx.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-1030120924018908203</id><published>2007-11-20T04:57:00.000-08:00</published><updated>2007-11-20T05:13:49.633-08:00</updated><title type='text'>Partially copying XML using XSL</title><content type='html'>Subject: Sample xls that copies entire XML source tree, but skips an element as specified in the xls.&lt;br /&gt;&lt;br /&gt;Note: the indentation is messed up due to the xml characters used.&lt;br /&gt;&lt;br /&gt;The source xml file includes a link to the xsl for display purposes (xml and xls as stored in the same folder):&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="ISO-8859-1"?&amp;gt;&lt;br /&gt;&amp;lt;?xml-stylesheet type="text/xsl" href="display.xsl"?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;data&amp;gt;&lt;br /&gt; &amp;lt;employee id="100"&amp;gt;&lt;br /&gt;  &amp;lt;lastname fooAttr="123"&amp;gt;Basta&amp;lt;/lastname&amp;gt;&lt;br /&gt;  &amp;lt;insertion&amp;gt;van&amp;lt;/insertion&amp;gt;&lt;br /&gt;  &amp;lt;firstname&amp;gt;Marco&amp;lt;/firstname&amp;gt;&lt;br /&gt; &amp;lt;/employee&amp;gt;&lt;br /&gt; &lt;br /&gt; &amp;lt;employee id="102"&amp;gt;&lt;br /&gt;  &amp;lt;lastname fooAttr="123"&amp;gt;Kruif&amp;lt;/lastname&amp;gt;&lt;br /&gt;  &amp;lt;insertion&amp;gt;&amp;lt;/insertion&amp;gt;&lt;br /&gt;  &amp;lt;firstname&amp;gt;Jan&amp;lt;/firstname&amp;gt;&lt;br /&gt; &amp;lt;/employee&amp;gt;&lt;br /&gt; &lt;br /&gt;&amp;lt;/data&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The xsl file (called display.xsl), the employee entry with firstname 'Marco' is skipped:&lt;br /&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="ISO-8859-1"?&amp;gt;&lt;br /&gt;&amp;lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;xsl:template match="*"&amp;gt;&lt;br /&gt;  &amp;lt;xsl:copy&amp;gt; &amp;lt;xsl:apply-templates/&amp;gt; &amp;lt;/xsl:copy&amp;gt;&lt;br /&gt;&amp;lt;/xsl:template&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;xsl:template match="/data/employee[firstname='Marco']"/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/xsl:stylesheet&amp;gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-1030120924018908203?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/1030120924018908203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=1030120924018908203' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/1030120924018908203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/1030120924018908203'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/11/partially-copying-xml-using-xsl.html' title='Partially copying XML using XSL'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-1583884448797986566</id><published>2007-11-19T03:39:00.000-08:00</published><updated>2007-11-24T13:35:11.264-08:00</updated><title type='text'>Convert Word document to HTML</title><content type='html'>I've found two ways to convert a word document in docx format to HTML, both using XSLT.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Sharepoint's &lt;span style="font-family:Courier New;"&gt;DocX2Html.xsl, no idea if it is open source&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:Courier New;"&gt;&lt;a href="http://openxmldeveloper.org/articles/333.aspx"&gt;xslt on OpenXML&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;This would make it possible to do some kind of mail merge preview, replacing the mail merge fields and showing the output both using XSLT.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Similar topic, but different implementation (not open source) from &lt;a href="http://www.softinterface.com/index.htm"&gt;Softinterface.&lt;/a&gt; Not sure how they get this working without installing any additional software. (perhaps they use the OLE object's preview for images, but how about the entire Word document?).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-1583884448797986566?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/1583884448797986566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=1583884448797986566' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/1583884448797986566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/1583884448797986566'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/11/convert-word-document-to-html.html' title='Convert Word document to HTML'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-6144954073590945317</id><published>2007-10-31T01:23:00.000-07:00</published><updated>2007-10-31T01:48:33.004-07:00</updated><title type='text'>Architectural Quality Attributes</title><content type='html'>Two quality attributes to which an application architecture should adhere:&lt;br /&gt;&lt;br /&gt;I) It is important that an application architecture can accommodate new requirements without big changes in the implementation. Changes should be as local as possible, keeping the impact small. (not everything can be tested in an automated manner).&lt;br /&gt;&lt;br /&gt;This means that the delta in requirements should be linear towards the delta in implementation changes. I call this an architectural quality attribute. (see also book &lt;a href="http://www.amazon.com/Software-Architecture-Practice-2nd-Engineering/dp/0321154959/ref=pd_bbs_sr_1/103-8040072-6750261?ie=UTF8&amp;amp;s=books&amp;amp;qid=1193820322&amp;amp;sr=1-1"&gt;Software Architecture in Practice&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;II) An architecture should have one way of doing things and allow for exceptions.&lt;br /&gt;&lt;br /&gt;For example an architecture that has two different ways of sharing information, for example through a remote service call or storing information in a database, does not adhere to this quality attribute.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-6144954073590945317?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/6144954073590945317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=6144954073590945317' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/6144954073590945317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/6144954073590945317'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/10/architectural-quality-attributes.html' title='Architectural Quality Attributes'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-6948662796873397207</id><published>2007-10-17T11:19:00.000-07:00</published><updated>2007-10-17T11:35:01.604-07:00</updated><title type='text'>Using EasyMock2</title><content type='html'>The recording and playback phase of &lt;a href="http://www.easymock.org/"&gt;EasyMock&lt;/a&gt; has always drove me away from it, but I got sick of implementing mocks myself, so I gave it a try.&lt;br /&gt;&lt;br /&gt;The simplicity is appealing. The record and playback is not as annoying as I thought it would be. However what is a bit frustrating is that i'm not interested so much in the collaboration between the class-to-test and the mock, but just in the-test-to-class. If i'm not mistaken; I want to use the mock just as a stub.&lt;br /&gt;&lt;br /&gt;Example: i've a component that uses a dao. I want to mock the dao. For example return a fixed collection of items for a particular method. This is easily feasible with EasyMock.&lt;br /&gt;&lt;br /&gt;Other example: i've a component that uses a HttpServletResponse. My component sets the header, content-type and some other stuff. I'm only interested what is written to the response. So I do not want to implement the setContentType and other methods. However afaik you can't tell EasyMock just to ignore calls for all methods - except for the ones you have specified during recording.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-6948662796873397207?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/6948662796873397207/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=6948662796873397207' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/6948662796873397207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/6948662796873397207'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/10/using-easymock2.html' title='Using EasyMock2'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-3066917924762386410</id><published>2007-09-16T01:38:00.000-07:00</published><updated>2007-11-19T03:46:33.185-08:00</updated><title type='text'>Objects have identity, components don't</title><content type='html'>A couple of rules:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Objects have identity, components don't. &lt;/li&gt;&lt;li&gt;Components have an emphasis on behavior, objects on state.&lt;/li&gt;&lt;li&gt;Object can expose methods to expose state and validate state.&lt;/li&gt;&lt;li&gt;Components with state are considered harmful - but sometimes inevitable&lt;/li&gt;&lt;li&gt;Events in components should always make it explicit if they are before or after the fact occurred. To make it explicit in which state the component is and not in some kind of transition&lt;/li&gt;&lt;li&gt;Services are components designed for remote access. (coarse granular)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;To me, a service is instantiated and accessible at a certain physical location, however this does not match with the situation where a service is deployed in an embedded way. Mmmm.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-3066917924762386410?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/3066917924762386410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=3066917924762386410' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3066917924762386410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3066917924762386410'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/09/objects-have-identity-components-dont.html' title='Objects have identity, components don&apos;t'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-5379651174422038395</id><published>2007-09-16T01:22:00.001-07:00</published><updated>2007-09-16T01:37:46.771-07:00</updated><title type='text'>Data Duplication - Source of all Evil</title><content type='html'>Several disciplines in the software world have their means to deal with data duplication; database guys use normalization, programmers use refactorings like extract-method. The goal is to have the definition/specification in one place to reduce the maintenance burden.&lt;br /&gt;&lt;br /&gt;Other disciplines like data warehousing don't care about the data duplication because they do not have to update the data, only to add.&lt;br /&gt;&lt;br /&gt;The problem in programming is that it is hard to detect duplication. (especially when we span the dimensions; large &amp;amp; multiple teams + time). There are known algorithms to detect duplication (eg IntelliJ provides something like this). However I question; do we want to remove all duplication? If there is a single implementation in a large system; won't it become impossible to change the implementation just because doing the impact analysis will take a very long time?&lt;br /&gt;&lt;br /&gt;In this case of components it will be hard to prevent duplication. Take for example a simple method that replaces all double quotes with single quotes (one Java 1.5 call). This method occurs in two different components. The cost of extracting this (and thus introducing a new shared component) does not weigh up against living with the duplication.&lt;br /&gt;&lt;br /&gt;Another killer is of course 'semantics'; although the implementation is identical; are the semantics identical? Determining this won't be always easy - especially when another guy wrote the other component.&lt;br /&gt;&lt;br /&gt;Fact; we have to live with code duplication. It is inevitable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-5379651174422038395?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/5379651174422038395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=5379651174422038395' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5379651174422038395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5379651174422038395'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/09/data-duplication-source-of-all-evil.html' title='Data Duplication - Source of all Evil'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-5373238583476417838</id><published>2007-09-14T01:51:00.000-07:00</published><updated>2007-09-14T01:53:48.054-07:00</updated><title type='text'>Programming languages with build-in support for unit testing</title><content type='html'>How many times have you made a private method package local just for unit testing? Each time you have to add some comment 'package local for testing'. Annoyance!&lt;br /&gt;&lt;br /&gt;Java's successor must have some kind of access descriptor dedicated for unit testing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-5373238583476417838?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/5373238583476417838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=5373238583476417838' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5373238583476417838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5373238583476417838'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/09/programming-languages-with-build-in.html' title='Programming languages with build-in support for unit testing'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-5813413385755256355</id><published>2007-09-12T07:06:00.000-07:00</published><updated>2007-09-12T07:11:22.104-07:00</updated><title type='text'>'Class names in Plural' smell</title><content type='html'>Just ran into a piece of code where somebody was using a class that was in plural, like for example &lt;span style="font-family: courier new;"&gt;Computers&lt;/span&gt;. Well, that smells. If you have a collection/list/bag/set/whatever of computers, then use the appropriate collection class. Since this was not the case probably more is going on. This is a collection of items with a certain characteristic that they share. Probably a bunch of computers forming a domain with additional properties that rise above the collection level. I'm arguing that you should use a class name that reflects the item(s) in common - most likely in singular.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-5813413385755256355?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/5813413385755256355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=5813413385755256355' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5813413385755256355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5813413385755256355'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/09/class-names-in-plural-smell.html' title='&apos;Class names in Plural&apos; smell'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-3492077517986099609</id><published>2007-09-06T03:24:00.000-07:00</published><updated>2007-09-06T03:29:05.735-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='svn ignore multiple folders directories'/><title type='text'>svn ignore for multiple folder / directories</title><content type='html'>I was struggling with the svn:ignore property to specify multiple folders. This is how I solved it:&lt;br /&gt;&lt;br /&gt;set the environment variable EDITOR. I'm using ultra edit:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&gt;set EDITOR="C:\Program Files\UltraEdit\uedit32.exe"&lt;/span&gt;  (note the quotes)&lt;br /&gt;&lt;br /&gt;Type in (note the period at the end, indicating the current folder is the target)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&gt;svn propedit svn:ignore .&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This will open the editor, UltraEdit in my case.&lt;br /&gt;Enter the folder names separated on each line&lt;br /&gt;Save and exit the editor.&lt;br /&gt;&lt;br /&gt;That's it. Use svn status to see if indeed the folders are ignored.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-3492077517986099609?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/3492077517986099609/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=3492077517986099609' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3492077517986099609'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/3492077517986099609'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/09/svn-ignore-for-multiple-folder.html' title='svn ignore for multiple folder / directories'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-5626955795170844964</id><published>2007-09-05T06:35:00.000-07:00</published><updated>2008-01-29T13:36:04.241-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jaxb hibernate import export'/><title type='text'>Import / Export Database from / to XML</title><content type='html'>I'm using Hibernate to manage my database persistency and I wanted to add export/import to/from XML capabilities. Hibernate does support XML but the documentation is very limited. Next, it is not capable of generating a schema (xsd). XStream has the same problem. So that left only JAXB. Issue with JAXB is that it is very document (web service) oriented. The HyperJAXB - project uses the web services xml as a starting point. I want it the other way; my domain classes are the source of truth; they form the basis from which I want to persist and export/import.&lt;br /&gt;&lt;br /&gt;Since i'm neither a JAXB nor a Hibernate expert it has proven to be quite an exercise. Especially Hibernate's merge operation in combination with Spring's &lt;span style=";font-family:Arial;font-size:10;"  &gt;&lt;span style="font-family: georgia;font-size:100%;" &gt;IdTransferringMergeEventListener caused a lot of headache. I did not fix this properly, but replaced the merge() with saveOrUpdate().&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: georgia;font-size:100%;" &gt;&lt;br /&gt;Anyway the basic steps to export/import a database (aka repository) are as follows:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;  &lt;ul style="margin-top: 0cm;" type="disc"&gt;&lt;li class="MsoNormal" style=""&gt;Create      a container class that contains collections of the top-level domain classes.      My sample is based on two domain classes Person and FiledCase. The      class Repository contains two collections of these classes. The      collections are extensions of a special HibernateCollectionAdapter class.      This class takes care of loading from and persisting to the database for a      domain class. The container class is passed to JAXB for import or export&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;Annotate      the database id field in each domain class with @XmlTransient, we do not      use this field since it is not guaranteed to be unique across all      classes. (if it would be you could use this field as xml id)&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;Add      an xml id field to the domain classes that can be referred to. Annotate      the get method with @XmlID. The get method should return the fully      quantified classname appended with the database id. (to make the ID unique      across all classes)&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;Annotate      the classes that needs to be exported with @XmlRootElement&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;Mark      the get methods that refer to other objects that are not aggregated, but      have an association type of relationship with @XmlIDREF&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;Make      sure that the classes are exported in the order of least referenced, use      the annotation @XmlType with field proporder to specify the order of the      properties. This is very important during import. JAXB will patch references      of objects afterwards when they cannot be resolved immediately (because      the object is not yet imported). However when the object is already      persisted it will not reflect the updated references.&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;The HibernateCollectionAdapter class implements the Collection interface. In the add() method it will store() an object and in the contains() it delegates to a find() method. The store and find methods are overridden in the descended classes. There are a couple of other methods that should also be overriden.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Sample is uploaded, see comment below&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-5626955795170844964?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/5626955795170844964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=5626955795170844964' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5626955795170844964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/5626955795170844964'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/09/jaxb-hibernate-integration.html' title='Import / Export Database from / to XML'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-360156013088990472</id><published>2007-08-25T11:16:00.000-07:00</published><updated>2007-08-25T11:29:51.951-07:00</updated><title type='text'>Controlling Change Requests</title><content type='html'>One of the challenges facing the software delopment process is controlling the number of change requests (CR). You got tons of exotic enhancement requests that will never make it into the product. Next, you have enormous amounts of small bugs that should be fixed. Among those thousands CRs a bunch is already fixed and it is too expensive to find out which ones are fixed.&lt;br /&gt;&lt;br /&gt;I plead that enhancement requests older than 2 years (2 major versions) are removed. Apparently they are not important enough. If they are important, they will come back.&lt;br /&gt;&lt;br /&gt;Another recommendation: when doing triage (deciding if and when the CR will be fixed), the corresponding code should be annotated with the CR number. This will make it easier for the programmer to see which CRs are applicable to this part. He/she can decide to fix the CR as well, update the CR text, or perhaps even close the CR as already fixed.&lt;br /&gt;&lt;br /&gt;Today's bugtracking systems integrate with version control systems enabling you to see which CRs is fixed in which piece. This should be improved so you can see where future CRs reside. This will enable you to see which parts are the weakest.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-360156013088990472?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/360156013088990472/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=360156013088990472' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/360156013088990472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/360156013088990472'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/08/controlling-change-requests.html' title='Controlling Change Requests'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-4892517025119555437</id><published>2007-08-19T10:31:00.000-07:00</published><updated>2007-08-19T10:37:47.635-07:00</updated><title type='text'>Your own framework</title><content type='html'>Your own framework that is gonna solve all the problems. It is going to be faster, easier to understand, more robust and lightweight.&lt;br /&gt;&lt;br /&gt;There is one problem; it takes time. Probably about 3 major releases to get it right. And guess what happened after 3 years of hard work? A new technology has arisen making the existing technologies obsolete.&lt;br /&gt;&lt;br /&gt;Take Lucene - i've been told a very elegant framework. There is new major v5 on the horizon to get everything right. Problem however is that frameworks like GWT and J2S solve a core problem; easy way of writing client side code.&lt;br /&gt;&lt;br /&gt;Lesson: as a company don't write your own frameworks unless it is core business. Even then take into account that it is going to be out-dated in 5 years.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-4892517025119555437?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/4892517025119555437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=4892517025119555437' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/4892517025119555437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/4892517025119555437'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/08/your-own-framework.html' title='Your own framework'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-4350702891903763121</id><published>2007-08-14T11:14:00.001-07:00</published><updated>2007-08-14T11:23:38.946-07:00</updated><title type='text'>unit testing</title><content type='html'>Unit testing aka white box testing means you write a test that is aware of the implementation. It means that you can write fine grained tests specific to a set of requirements. Integration tests (or whatever you wanna call them) test multiple artifacts cooperating together. Theoretically a unit test tests the implementation of one method and nothing else. However this distinction is hard to make when the tests evolve.&lt;br /&gt;&lt;br /&gt;Suppose you start with two different test folders: unit-test and integration-test. First couple of days everything is working nicely. One day you decide to refactor a piece of code. Luckily you are disciplined enough to move the tests along with the code to the new packages. However one of the methods that was white box tested had a piece that was extracted to a new method (let's say within the same class). Now suddenly this test you had written is no longer testing solely one method. Hmmm.&lt;br /&gt;&lt;br /&gt;Thinking of this; if I write a unit test for a method and  this method calls a couple of JVM routines, is it a unit test or an integration test from the beginning?&lt;br /&gt;&lt;br /&gt;Point i'm trying to make is that if you want to be really strict about separating unit and integration tests it takes an enormous effort to keep it sound. With large teams - people come and go - in time it will be an impossible task.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-4350702891903763121?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/4350702891903763121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=4350702891903763121' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/4350702891903763121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/4350702891903763121'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/08/unit-testing_14.html' title='unit testing'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-8308202052164084907</id><published>2007-08-09T02:27:00.000-07:00</published><updated>2007-08-09T02:43:12.810-07:00</updated><title type='text'></title><content type='html'>In the last couple of years software code and architecture moved from being porcelain to rubber, but it still not fluid. We need fluidity; we need some kind of dynamic flow that will re-establish balance within the code. For example some packages or classes have become too large, obsolete code that needs to be removed. This is now all manual labor. Organism have something called homestase , a mechanism to restore the internal  equilibrium. The premise is already fulfilled; we have the metrics, we have refactorings.  Only some kind of automation is needed  to put it together. Might be a little be odd to come into the office in the morning and to find out  you're whole application is turned upside down.&lt;span style="font-size: 12pt; font-family: &amp;quot;Times New Roman&amp;quot;;" lang="NL"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-8308202052164084907?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/8308202052164084907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=8308202052164084907' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/8308202052164084907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/8308202052164084907'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/08/in-last-couple-of-years-software-code.html' title=''/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4700787238821257876.post-7320154696382122190</id><published>2007-08-06T11:14:00.000-07:00</published><updated>2007-08-06T11:26:24.298-07:00</updated><title type='text'>Unit testing</title><content type='html'>After a couple of years of unit testing I still haven't found an elegant way to make sure that a method calls another method. For example I want to test method x that calls method y. Method y ensures a business rule, for example it checks whether certain reserved characters are not present in a string that is passed as parameter. I can do some litmus tests against x, indirectly testing whether it calls y. However this gives not a 100% guarantee. In fact, it introduces an extra dependency. If the business rule change, y changes and i've to update some tests of x...&lt;br /&gt;Another approach is of course to use mocks. However this requires interfaces, factories/ioc, etc. A lot of overhead for a simple test.&lt;br /&gt;&lt;br /&gt;A futuristic alternative is to define an aspect that checks that at least one method called from x is y. Admittedly, I've no idea how to implement this, but it won't be easy / flexible to do in a TDD manner.&lt;br /&gt;&lt;br /&gt;Another desperate attempt; if y would throw an exception in case of failure, you could check the stacktrace. Obivously, still brittle.&lt;br /&gt;&lt;br /&gt;So the question remains how to solve this. It gives me an unpleasant feeling that such a basic problem is not yet solved. Perhaps someone else has a bright idea.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4700787238821257876-7320154696382122190?l=tradeoffz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tradeoffz.blogspot.com/feeds/7320154696382122190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4700787238821257876&amp;postID=7320154696382122190' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7320154696382122190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4700787238821257876/posts/default/7320154696382122190'/><link rel='alternate' type='text/html' href='http://tradeoffz.blogspot.com/2007/08/unit-testing.html' title='Unit testing'/><author><name>Stephan Westen</name><uri>http://www.blogger.com/profile/14524916792349427485</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>
