<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;A0AERHk-fyp7ImA9Wx5TE08.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933</id><updated>2010-07-28T12:08:25.757-03:00</updated><title>Zauber Code</title><subtitle type="html">This blog is written by &lt;a href="http://www.zauber.com.ar"&gt;Zauber's people&lt;/a&gt;, to spread new thoughts and ideas related with technologies we use</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.code.zauber.com.ar/" /><author><name>Damian Calderon</name><uri>http://www.blogger.com/profile/11694872055620690195</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ZauberCode" /><feedburner:info uri="zaubercode" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;A0AERHk9fip7ImA9Wx5TE08.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933.post-3308624771626772806</id><published>2010-07-28T11:45:00.006-03:00</published><updated>2010-07-28T12:08:25.766-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-28T12:08:25.766-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="usability" /><category scheme="http://www.blogger.com/atom/ns#" term="design process" /><category scheme="http://www.blogger.com/atom/ns#" term="user centered design" /><title>Getting started with Usability and User Centered Design - Part I</title><content type="html">Last week, we &lt;a href="http://blog.zauber.com.ar/2010/07/our-new-design-usability-area-at-zauber.html"&gt;officially launched&lt;/a&gt; our &lt;a href="http://www.zaubersoftware.com/en/services/design/"&gt;&lt;span style="font-weight:bold"&gt;User-Centered Design services&lt;/span&gt;&lt;/a&gt; area at Zauber, together with an internal presentation for the whole company.
Our presentation intended to tell developers why they all take part (consciously or not) of the design process, and how we can develop our design awareness and integrate it with &lt;a href="http://www.zaubersoftware.com/en/process/"&gt;our software development process&lt;/a&gt;.

&lt;dl&gt;
&lt;dt&gt;Why choosing User-Centered Design as a design framework?&lt;/dt&gt;

&lt;dd&gt;&lt;span style="font-weight: bold;"&gt;User-Centered Design&lt;/span&gt; is about &lt;span style="font-weight: bold;"&gt;optimizing a product&lt;/span&gt; by thinking in&lt;span style="font-weight: bold;"&gt; specific goals of an specific group of people in a specific context of use&lt;/span&gt;. It's at the same time a very rational philosophy about design and a set of very useful techniques (some of them really scientific). It makes sense to design for human beings, trying to know better their goals and problems. After all, we're building products for people, and if the product helps their purposes and they can understand it intuitively, their productivity and satisfaction by using it increases.
&lt;/dd&gt;

&lt;dt&gt;Getting started with User-Centered Design&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;Some UCD techniques require some effort to learn and integrate to a defined process, but some of them can be more easily adopted.&lt;/p&gt;

&lt;strong style="font-weight:bold"&gt;Iterate the design process&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_toYKT_ESrww/TFBD7vEJASI/AAAAAAAAACI/7-hSmkPOk1E/s1600/iterate.png"&gt;&lt;img style="cursor:pointer; cursor:hand;height:162px;width:590px;" src="http://2.bp.blogspot.com/_toYKT_ESrww/TFBD7vEJASI/AAAAAAAAACI/7-hSmkPOk1E/s600/iterate.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5498969838544552226" /&gt;&lt;/a&gt;
&lt;br /&gt;

&lt;p&gt;You shouldn't think about design as an activity that just takes place at the beginning or at the end of the development process. User-Centered Design is about finding solutions to interaction problems, thus the best way to solve a problem is by approaching it in an iterative way, in order to understand it better and find the most suitable solutions. The best way to make it work is to start working on the more crucial functions and then expand your key decisions to the rest of the features.&lt;/p&gt;

&lt;strong style="font-weight:bold"&gt;Make sketches and wireframes&lt;/strong&gt;
&lt;p&gt;Everytime you think about a screen or visual component, it's a good practice to begin with quick sketches trying to figure out which visual components will be more understandable for your potential users. It's really helpful to validate your work with your project partners and even with people who don't know about the project, previously explaining to them the main goal of the user facing that screen or component. This will also help you to iterate and go over your work.&lt;/p&gt;

&lt;strong style="font-weight:bold"&gt;Learn about some basic laws&lt;/strong&gt;
&lt;ul class="lista"&gt;
   &lt;li&gt;&lt;strong&gt;Fitts Law&lt;/strong&gt;: proximity to the mouse's cursor and size of page elements may increase or decrease the ability of a user to interact with it. In a nutshell, you have to make the clickable area bigger for main actions. To learn more, there's a &lt;a href="http://en.wikipedia.org/wiki/Fitts%27s_law"&gt;Wikipedia article about Fitts' Law&lt;/a&gt; and you can also check &lt;a href="http://www.usabilityfirst.com.foraker.com/glossary/fitts-law/"&gt;Usability First's definition&lt;/a&gt;.&lt;/li&gt;
   &lt;li&gt;&lt;strong&gt;Hick Law&lt;/strong&gt;: when the user is taking a decision, it's making a cognitive effort. The more options he has to consider, the harder it will be for him to make the choice. You've to keep a clear, default path of decisions and to make the rest of possibilities available but with less visual hierarchy. To learn more, you can check &lt;a href="http://www.usabilityfirst.com/glossary/hicks-law/"&gt;Usability First's definition about Hick's Law&lt;/a&gt;.&lt;/li&gt;
   &lt;li&gt;&lt;strong&gt;KLM-GOMS&lt;/strong&gt;: each operation we demand from the user implies a cognitive effort for him/her. KLM-GOMS is a model that quantifies basic operations with a computer, such us clicking, pressing a key, alternating between mouse and keyboard, etc. It's useful to optimize data input actions reducing the effort needed for each of them. &lt;a href="http://www.cs.umd.edu/class/fall2002/cmsc838s/tichi/printer/goms.html"&gt;To learn more about KLM-GOMS, you can check this article&lt;/a&gt; from The Department of Computer Science, University of Maryland.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;strong style="font-weight:bold"&gt;Use Interaction Design patterns&lt;/strong&gt;
&lt;p&gt;There are very useful libraries you can consider each time you're about to select interactive components for your screens. If you're a developer, you probably know the benefits of using Design Patterns. We recommend &lt;a href="http://www.welie.com/patterns/"&gt;http://www.welie.com/patterns/&lt;/a&gt; and &lt;a href="http://quince.infragistics.com/UX-Design-Patterns.aspx"&gt;http://quince.infragistics.com/UX-Design-Patterns.aspx&lt;/a&gt;.&lt;/p&gt;

&lt;strong style="font-weight:bold"&gt;Use Jakob Nielsen's Heuristic Guidelines&lt;/strong&gt;
&lt;p&gt;Heuristic guidelines are a set of important rules to have in mind when designing to increase intuitiveness, ease of use and consistency of your product. They can also help you to evaluate the application you are building and make new iterations over it once you are in an intermediate instance of the design. To learn in detail about these guidelines, you can &lt;a href="http://www.useit.com/papers/heuristic/heuristic_list.html"&gt;check the original article at useit.com&lt;/a&gt;. There's also a good list of examples of heuristic guidelines applied to web applications at &lt;a href="http://designingwebinterfaces.com/6-tips-for-a-great-flex-ux-part-5"&gt;http://designingwebinterfaces.com/6-tips-for-a-great-flex-ux-part-5&lt;/a&gt;&lt;/p&gt;
&lt;/dd&gt;

&lt;dt&gt;Next steps&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;
Next week we will be covering in detail different research techniques, books and more. Stay tuned and give us feedback!
&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7870515310189033933-3308624771626772806?l=blog.code.zauber.com.ar' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/3308624771626772806/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.code.zauber.com.ar/2010/07/getting-started-with-usability-and-user.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/3308624771626772806?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/3308624771626772806?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ZauberCode/~3/SqB-RQCFIE4/getting-started-with-usability-and-user.html" title="Getting started with Usability and User Centered Design - Part I" /><author><name>Damian Calderon</name><uri>http://www.blogger.com/profile/11694872055620690195</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09352563823751570984" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_toYKT_ESrww/TFBD7vEJASI/AAAAAAAAACI/7-hSmkPOk1E/s72-c/iterate.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.code.zauber.com.ar/2010/07/getting-started-with-usability-and-user.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0AFQX49fCp7ImA9WxFbFE4.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933.post-3999620843496019800</id><published>2010-06-25T10:41:00.003-03:00</published><updated>2010-07-06T15:08:30.064-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-06T15:08:30.064-03:00</app:edited><title>HTTP Content negociation; Spring Framework and Webkit (Chrome/Safari) Bug</title><content type="html">&lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html"&gt;HTTP&lt;/a&gt;,&amp;nbsp;the protocol used to serve most web pages allows  &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html#sec12"&gt;Content Negotiation&lt;/a&gt;. For example an external application would prefer an XML representation of the content, instead a human would prefer a HTML representation.
&lt;br /&gt;
This negotiation is accomplished this way:
&lt;br /&gt;
&lt;ul class="lista"&gt;
&lt;li&gt;The User Agent sends the request with the &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html"&gt;Accept Header&lt;/a&gt;. For example, a User Agent could send the header &lt;em&gt;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&lt;/em&gt;; preferring first html, then xml, and then any other representation.&lt;/li&gt;
&lt;li&gt;The server parses the Accept header and determines the representation that should be employed.&lt;/li&gt;
&lt;/ul&gt;
&lt;a href="http://www.springsource.org/about"&gt;Spring MVC&lt;/a&gt; lets web developers make use of content negotiation very easily with the  &lt;a href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.html"&gt;ContentNegotiatingViewResolver&lt;/a&gt; view resolver.
&lt;br /&gt;
Sadly, content negotiation doest not always works fine in every browser since Chrome/Safari (or any other browser based on &lt;a href="http://webkit.org/"&gt;WebKit&lt;/a&gt;) use a &lt;a href="http://www.gethifi.com/blog/webkit-team-admits-accept-header-error"&gt;wrong accept header&lt;/a&gt;&amp;nbsp;(&lt;a href="https://bugs.webkit.org/show_bug.cgi?id=27267"&gt;Issue #: 27267&lt;/a&gt;). So, if an application wanted to depend on the accept header (something allowed by the protocol) to display its content appropriately, it wouldn't work. There are some workarounds such as using different file extension or URIs for different formats; but none of them follows the REST essence and some applications can't rely on them, because actually there is no Content Negotiation.&lt;br /&gt;
To solve this problem in Java Servlet applications we have developed a  &lt;tt&gt;javax.servlet.Filter&lt;/tt&gt; named &lt;a href="https://code.zauber.com.ar/repos/sandbox/components/commons/code/trunk/web/utils/src/main/java/ar/com/zauber/commons/web/filter/webkit/WebKitContentTypeFilter.java"&gt;WebKitContentTypeFilter&lt;/a&gt; that recognizes &amp;nbsp;Webkits requests and modifies their Accept Header allowing content to be displayed correctly by using&amp;nbsp;&lt;a href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/servlet/view/ContentNegotiatingViewResolver.html"&gt;ContentNegotiatingViewResolver&lt;/a&gt;&amp;nbsp;&amp;nbsp;correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;dt&gt;What do you need to use it?&lt;/dt&gt;
&lt;br /&gt;
&lt;ul class="lista"&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Spring 3.0+&lt;/li&gt;
&lt;li&gt;Maven 2.2+&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;dt&gt;How to use it?&lt;/dt&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Change your pom.xml and add the following lines:
&lt;br /&gt;
&lt;pre class="xml" name="code"&gt;    &lt;repositories&gt;
     &lt;repository&gt;
       &lt;releases&gt;&lt;enabled&gt;true&lt;/enabled&gt;&lt;/releases&gt;
       &lt;snapshots&gt;&lt;enabled&gt;false&lt;/enabled&gt;&lt;/snapshots&gt;
       &lt;id&gt;zauber-code-releases&lt;/id&gt;
       &lt;name&gt;Zauber Code Releases&lt;/name&gt;
       &lt;url&gt;https://repo1.zaubersoftware.com/zauber/code/releases/&lt;/url&gt;
     &lt;/repository&gt;
     ...
    &lt;/repositories&gt;
    ...
    &lt;dependency&gt;
      &lt;artifactid&gt;commons-web-utils&lt;/artifactid&gt;
      &lt;groupid&gt;ar.com.zauber.commons.web&lt;/groupid&gt;
      &lt;version&gt;3.33&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;add this to your web.xml:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="xml" name="code"&gt;    &lt;filter&gt;
        &lt;filter-name&gt;webkitContentType&lt;/filter-name&gt;
        &lt;filter-class&gt; ar.com.zauber.commons.web.filter.webkit.WebKitContentTypeFilter &lt;/filter-class&gt;
    &lt;/filter&gt;
    ...
    &lt;filter-mapping&gt;
        &lt;filter-name&gt;webkitContentType&lt;/filter-name&gt;
        ...
   &lt;/filter-mapping&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7870515310189033933-3999620843496019800?l=blog.code.zauber.com.ar' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/3999620843496019800/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.code.zauber.com.ar/2010/06/http-content-negociation-spring.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/3999620843496019800?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/3999620843496019800?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ZauberCode/~3/LL--TrQhdKs/http-content-negociation-spring.html" title="HTTP Content negociation; Spring Framework and Webkit (Chrome/Safari) Bug" /><author><name>Mariano Semelman</name><email>noreply@blogger.com</email></author><thr:total>2</thr:total><feedburner:origLink>http://blog.code.zauber.com.ar/2010/06/http-content-negociation-spring.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYERH4zfyp7ImA9WxNbFEs.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933.post-9046267037702619175</id><published>2009-11-17T10:10:00.009-03:00</published><updated>2009-11-17T10:21:45.087-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-17T10:21:45.087-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="quality" /><category scheme="http://www.blogger.com/atom/ns#" term="agile" /><category scheme="http://www.blogger.com/atom/ns#" term="metrics" /><category scheme="http://www.blogger.com/atom/ns#" term="sonar" /><category scheme="http://www.blogger.com/atom/ns#" term="poirot" /><category scheme="http://www.blogger.com/atom/ns#" term="plugin" /><category scheme="http://www.blogger.com/atom/ns#" term="iso" /><title>Creating a Sonar Plugin for software development metrics</title><content type="html">&lt;p&gt;As you know, at &lt;a href="http://www.zauber.com.ar/"&gt;Zauber&lt;/a&gt; we follow high quality standards, that's why &lt;a href="http://blog.zauber.com.ar/2009/06/iso-90012008-quality-certification.html"&gt;we have obtained an ISO 9001:2008 Quality Certification&lt;/a&gt;. Part of following these standards implies measuring the performance of our company, getting metrics. Obtaining metrics from our development process allow us to understand our current situation, compare it with previous ones and set new objectives for the future.&lt;/p&gt;
&lt;p&gt;Until now, we had three main applications which allowed us to collect information about our projects:
  &lt;ul class="lista"&gt;
  &lt;li&gt;&lt;a href="http://www.zauber.com.ar/en/process/tools/#crono"&gt;Crono&lt;/a&gt;, our time-tracking tool&lt;/li&gt; 
  &lt;li&gt;&lt;a href="http://www.mantisbt.org/"&gt;Mantis Tracker&lt;/a&gt;, an open source issue tracker&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://hudson-ci.org/"&gt;Hudson&lt;/a&gt; a Continuous Integration engine.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;However, there was a problem, these applications didn't show us the metrics in a way that they could be studied through time, and Mantis was too dependent on developers' input, not always enforcing us to provide detailed information about the issues we were working on.(e.g.: sometimes people forget to fill in the 'worked hours' field for a certain issue).&lt;/p&gt;
&lt;dt&gt;Where to start?&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;We decided to start using &lt;a href="http://sonar.codehaus.org/"&gt;Sonar&lt;/a&gt;, a quality management platform that allows analyzing and measuring our projects in a continuous way, displaying our metrics in a very fancy way. To cope with the flaws we mentioned of Mantis, we also developed an application that queries our issue tracker database finding incomplete issues that make references to bugs, reporting them to who may be responsible of them, as well as projects managers.&lt;/p&gt;
&lt;p&gt;This way, &lt;a href="http://sonar.codehaus.org/"&gt;Sonar&lt;/a&gt; became our software metrics dashboard, but we also wanted to include custom metrics collected by our own tool Crono and from Mantis. To achiveve this, we implemented a Sonar plug-in using the &lt;a href="http://docs.codehaus.org/display/SONAR/Documentation"&gt;Sonar API&lt;/a&gt;. But many obstacles flourished on the road while we were implementing this plug-in, the main one was that the Sonar API is vaguely documented or not documented at all, so we had to check out how other plug-ins where implemented, so after studying other plugin’s implementations here is what we've learned &lt;/p&gt;


&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_U8y3Br-Rj18/SwKhJVRFfqI/AAAAAAAAByQ/EjyRWwJpAAs/s1600/poirot-workflow2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 331px;" src="http://3.bp.blogspot.com/_U8y3Br-Rj18/SwKhJVRFfqI/AAAAAAAAByQ/EjyRWwJpAAs/s400/poirot-workflow2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5405059684497718946" /&gt;&lt;/a&gt;
&lt;p&gt;As you can see sonar is somehow similar to the MVC pattern, except that we don't have much access to the logic beneath it. There are some classes you must use in order to make the plugin work &lt;/p&gt;
&lt;ul class="lista"&gt;
&lt;li&gt;The 'Plugin' class which tells the server all the classes this plugin will use.&lt;/li&gt;
&lt;li&gt;The 'Metric' class which is a list with all the new ways to measure each project, also it references all the information that the view may show&lt;/li&gt;
&lt;li&gt;The 'Widget' class in this case 'RubyRailsWidget' just gives the location of the Ruby template made on &lt;a href="http://www.modruby.net/en/index.rbx"&gt;eRuby&lt;/a&gt; to render in the sonar page&lt;/li&gt;
&lt;li&gt;The 'Sensor' and the 'Decorator' are the classes used to gather and process
all the previous  metrics, the difference between the Sensor and the Decorator is that the Sensor mainly collects information but has no access to what other plugins may collect. On the other side, the Decorator should be responsible for analyzing the information obtained and make cross reference to other information from other plugins.&lt;/li&gt;
&lt;li&gt;The data that the sensor and the decorator gather is sent to the server through the 'context', which is similar to a "command" class in Spring MVC.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; Except for the Sensor and the Decorator, the processes run on the &lt;a href="http://sonar.codehaus.org/"&gt;Sonar&lt;/a&gt; server. The workflow is the following: First, the Plugin class tells Sonar which classes it uses. Then, when you access the project page, the server calls the widgets classes to obtain the template to render the data on the database. When &lt;a href="http://hudson-ci.org/"&gt;Hudson&lt;/a&gt;  runs maven, the latter runs the Sonar plugins, which analyze the project with all the sonar plugins currently installed. Then, the Sensor and the Decorator do their job, saving the metrics information through the Context (the Context will hold a measure for each metric in the class Metric).&lt;/p&gt;&lt;/dd&gt;
&lt;dt&gt;What we did&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;We developed a plugin that uses the previously explained API and Crono REST API.  When running it against a project it calculates the total amount of worked hours obtained from Crono, the total amount of rework hours taken from Mantis, and some other information (quantity and category of issues grouped by status). But it is necessary to configure certain settings before obtaining that information. There are two kinds of settings: global settings such as Mantis database URL, Mantis username, Crono URL, username, etc. These can be configured from the plugin settings in the sonar server,
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_U8y3Br-Rj18/SwKhJoTM7fI/AAAAAAAAByY/l_EuhcrL5jc/s1600/sonar-settings.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 298px;" src="http://3.bp.blogspot.com/_U8y3Br-Rj18/SwKhJoTM7fI/AAAAAAAAByY/l_EuhcrL5jc/s400/sonar-settings.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5405059689606868466" /&gt;&lt;/a&gt;
and project related settings, such as the project id in the Mantis database or the Crono project unixname in Crono, which are configured in each project maven's pom like these:&lt;/p&gt;
&lt;pre name="code" class="xhtml"&gt;
&lt;sonar.mantis.id&gt;52&lt;/sonar.mantis.id&gt;
&lt;crono.organization.name&gt;zauber&lt;/crono.organization.name&gt;
&lt;crono.project.name&gt;zauber-crono&lt;/crono.project.name&gt;
&lt;crono.start.date&gt;2009-10-5&lt;/crono.start.date&gt;
&lt;/pre&gt;
&lt;p&gt;Where the start date means when the project started in &lt;a href="http://en.wikipedia.org/wiki/ISO_8601"&gt;ISO format&lt;/a&gt;.
Once configured, when sonar analyzes a project, this plugin connects to Mantis and Crono, gets all the necessary information and stores it on the sonar server. After that, when we access a project page, the widget from our plugin is rendered and "voilá": we have our plugin results being displayed like this:&lt;/p&gt;
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_U8y3Br-Rj18/SwKiRH0hoMI/AAAAAAAAByw/C4Wgx-g3r3E/s1600/sonar-widget.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 261px; height: 400px;" src="http://2.bp.blogspot.com/_U8y3Br-Rj18/SwKiRH0hoMI/AAAAAAAAByw/C4Wgx-g3r3E/s400/sonar-widget.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5405060917838848194" /&gt;&lt;/a&gt;
&lt;dt&gt;How will this help in the future?&lt;/dt&gt;
&lt;dd&gt;&lt;p&gt;We find this application very useful, because it gives us a complete software metrics dashboard for every project at a glance.&lt;p&gt;
Main Dashboard, a quick view of every project (red column provided by our plugin).
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_U8y3Br-Rj18/SwKhJIaKLZI/AAAAAAAAByI/VEWlMSBwzrQ/s1600/dash.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 600px; height: 400px;" src="http://3.bp.blogspot.com/_U8y3Br-Rj18/SwKhJIaKLZI/AAAAAAAAByI/VEWlMSBwzrQ/s1600/dash.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5405059681046113682" /&gt;&lt;/a&gt;
Tree-map: a tool that works perfectly when comparing projects on a specific subject.
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_U8y3Br-Rj18/SwKifO_JKzI/AAAAAAAABy4/hf6FO3x39q4/s1600/sonar-tree-map.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 285px; height: 373px;" src="http://2.bp.blogspot.com/_U8y3Br-Rj18/SwKifO_JKzI/AAAAAAAABy4/hf6FO3x39q4/s400/sonar-tree-map.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5405061160280599346" /&gt;&lt;/a&gt;


Timeline: a tool that lets you graphically see how the project evolves through time.
&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_U8y3Br-Rj18/SwKhJy0NpTI/AAAAAAAAByg/yAxlC6uWhDE/s1600/sonar+timeline.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 600px; height: 350px;" src="http://1.bp.blogspot.com/_U8y3Br-Rj18/SwKhJy0NpTI/AAAAAAAAByg/yAxlC6uWhDE/s1600/sonar+timeline.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5405059692429681970" /&gt;&lt;/a&gt;
&lt;p&gt;We hope that you found this article as useful as developing this plugin was for us. Feel free to &lt;a href="http://www.zauber.com.ar/en/contact"&gt;contact us&lt;/a&gt; if you have any questions.   &lt;/p&gt;&lt;/dd&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7870515310189033933-9046267037702619175?l=blog.code.zauber.com.ar' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/9046267037702619175/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.code.zauber.com.ar/2009/11/creating-sonar-plugin-for-software.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/9046267037702619175?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/9046267037702619175?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ZauberCode/~3/H1uHA5usQYY/creating-sonar-plugin-for-software.html" title="Creating a Sonar Plugin for software development metrics" /><author><name>Mariano Semelman</name><email>noreply@blogger.com</email></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_U8y3Br-Rj18/SwKhJVRFfqI/AAAAAAAAByQ/EjyRWwJpAAs/s72-c/poirot-workflow2.jpg" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://blog.code.zauber.com.ar/2009/11/creating-sonar-plugin-for-software.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0cFR3k7eSp7ImA9WxJUFko.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933.post-6241292615049109755</id><published>2009-07-14T16:33:00.010-03:00</published><updated>2009-07-15T12:16:56.701-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-15T12:16:56.701-03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="unit testing" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><title>Stay green: Javascript Unit Testing</title><content type="html">&lt;p&gt;With the improvement of our source code quality as a constant goal, we decided to find a way to write Unit Tests for our Javascript code.
&lt;a href="https://code.zauber.com.ar/repos/sandbox/components/javascript/validate/code/releases/0.2/"&gt;Our implementation&lt;/a&gt; of &lt;a href="http://commons.apache.org/lang/apidocs/org/apache/commons/lang/Validate.html"&gt;Apache Commons Lang Validate&lt;/a&gt; for Javascript was our first step to build more solid applications, but an important part was missing until now: unit testing.
We found a way to integrate JS unit tests with &lt;a href="http://maven.apache.org/"&gt;Maven&lt;/a&gt;, &lt;a href="http://eclipse.org/"&gt;Eclipse&lt;/a&gt;, and the continuous integration server &lt;a href="https://hudson.dev.java.net/"&gt;Hudson&lt;/a&gt;.&lt;/p&gt;

&lt;dl&gt;
 &lt;dt&gt;Zauber Javascript Validation Utils&lt;/dt&gt;
 &lt;dd&gt;
  Is an open source library inspired on &lt;a href="http://commons.apache.org/lang/apidocs/org/apache/commons/lang/Validate.html"&gt;org.apache.commons.lang.Validate&lt;/a&gt; written by Zauber and published under the &lt;a href="http://www.apache.org/licenses/LICENSE-2.0.html"&gt;Apache License v2.0&lt;/a&gt;.
  You can download it from 
&lt;li&gt;&lt;a href="https://code.zauber.com.ar/repos/sandbox/components/javascript/validate/code/releases/0.2/"&gt;https://code.zauber.com.ar/repos/sandbox/components/javascript/validate/code/releases/0.2/&lt;/a&gt;&lt;/li&gt;
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;dl&gt;
 &lt;dt&gt;How we test javascript code?&lt;/dt&gt;
 &lt;dd&gt;
 We use an open source framework called &lt;a href="http://jsunit.berlios.de/"&gt;JSUnit1.3&lt;/a&gt;, a port of &lt;a href="http://www.junit.org/"&gt;JUnit&lt;/a&gt;.
 There are two frameworks with the same name (JSUnit), the one we are using, JSUnit1.3, uses &lt;a href="http://www.mozilla.org/rhino/"&gt;Rhino&lt;/a&gt; to run the tests. 
 The second one, &lt;a href="http://www.jsunit.net/"&gt;JSUnit2&lt;/a&gt;, uses a HTML file called &lt;a href="http://www.jsunit.net/runner/testRunner.html"&gt;testRunner.html&lt;/a&gt; to run the tests on multiple browsers from client-side. This is great to do cross-browser compatibility tests, but for the moment we are just validating Javascript syntax and logic using the first toolkit.
 &lt;/dd&gt;
&lt;/dl&gt;

&lt;dl&gt;
 &lt;dt&gt;Project structure&lt;/dt&gt;
 &lt;dd&gt;The main idea is to respect Maven's conventions, so our project
 structure looks like this:&lt;/dd&gt;
 &lt;dd&gt;
 &lt;pre name="code" class="xml"&gt;
   /app
      /src
       * /main
           o /java
           o /javascript
               + validate.js (the library)
           o /resources
       * /test
           o /java
           o /javascript
               + validateTest.js (tests for validate.js written in JavaScript)
           o /resources
       * /target
           o /surefire-reports
               + TEST-JS-Validate.xml
       * pom.xml
 &lt;/pre&gt;
 &lt;/dd&gt;
&lt;/dl&gt;

&lt;dl&gt;
 &lt;dt&gt;Configuration - pom.xml&lt;/dt&gt;
 &lt;dd&gt;This file is the key for a successful configuration, you should
 declare the junit plugin for maven2, something like this:&lt;/dd&gt;
   &lt;pre name="code" class="xml"&gt;
   &amp;lt;plugin&amp;gt;
       &amp;lt;groupId&amp;gt;de.berlios.jsunit&amp;lt;/groupId&amp;gt;
       &amp;lt;artifactId&amp;gt;jsunit-maven2-plugin&amp;lt;/artifactId&amp;gt;
       &amp;lt;version&amp;gt;1.3&amp;lt;/version&amp;gt;
       &amp;lt;extensions&amp;gt;true&amp;lt;/extensions&amp;gt;
   &amp;lt;/plugin&amp;gt;
   &lt;/pre&gt;

 &lt;dd&gt;and then configure your tests, for example:&lt;/dd&gt;
   &lt;pre name="code" class="xml"&gt;
   &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
          &amp;lt;phase&amp;gt;test&amp;lt;/phase&amp;gt;
          &amp;lt;goals&amp;gt;
            &amp;lt;goal&amp;gt;jsunit-test&amp;lt;/goal&amp;gt;
          &amp;lt;/goals&amp;gt;
          &amp;lt;configuration&amp;gt;
         
             &amp;lt;!-- src --&amp;gt;
             &amp;lt;sourceDirectory&amp;gt;src/main/javascript&amp;lt;/sourceDirectory&amp;gt;
             &amp;lt;sources&amp;gt;
               &amp;lt;source&amp;gt;validate.js&amp;lt;/source&amp;gt;
             &amp;lt;/sources&amp;gt;
             
             &amp;lt;!-- test --&amp;gt;
             &amp;lt;testSourceDirectory&amp;gt;src/test/javascript&amp;lt;/testSourceDirectory&amp;gt;
             &amp;lt;testSuites&amp;gt;
               &amp;lt;testSuite&amp;gt;
                 &amp;lt;name&amp;gt;JS-Validate&amp;lt;/name&amp;gt;
               &amp;lt;/testSuite&amp;gt;
             &amp;lt;/testSuites&amp;gt;
            
             &amp;lt;!-- report --&amp;gt;
             &amp;lt;reportsDirectory&amp;gt;target/surefire-reports&amp;lt;/reportsDirectory&amp;gt;
           &amp;lt;/configuration&amp;gt;
         &amp;lt;/execution&amp;gt;
   &amp;lt;/executions&amp;gt;
   &lt;/pre&gt;

 &lt;dd&gt;That's all, you can now run your JS test just calling maven
 as usual (ie. &lt;tt&gt;mvn test&lt;/tt&gt;).&lt;/dd&gt;

&lt;pre name="code" class="xml"&gt;
$ mvn test
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building Validation Utils
[INFO]    task-segment: [test]
[INFO] ------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Copying 0 resource
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources]
[INFO] Copying 0 resource
[INFO] [compiler:testCompile]
[INFO] Compiling 1 source file to: target/test-classes
[INFO] [surefire:test]
[INFO] Surefire report directory: target/surefire-reports
------------------------------------------------------
T E S T S
-------------------------------------------------------
There are no tests to run.

Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

[INFO] [jsunit2:jsunit-test {execution: default}]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8 seconds
[INFO] Finished at: Tue Jul 14 10:43:00 ART 2009
[INFO] Final Memory: 18M/148M
[INFO] ------------------------------------------------------------------------
&lt;/pre&gt;
 &lt;dd&gt;Note that maven says &lt;em&gt;There are no tests to run&lt;/em&gt; but
 jsunit-test is being called.&lt;/dd&gt;
&lt;/dl&gt;

&lt;dl&gt;
 &lt;dt&gt;Configuration - Eclipse&lt;/dt&gt;

 &lt;dd&gt;There is also another way to run your tests: calling them from
 Eclipse just like you do with regular Java tests. To do that, you
 could write your own implementation or include a module from 
 &lt;a href="https://code.zauber.com.ar/repos/sandbox/components/commons/code/releases/3.16/"&gt;
 Zauber Commons 3.16&lt;/a&gt; called &lt;tt&gt;commons-javascript-test&lt;/tt&gt;. 
 We use the class &lt;a href="https://code.zauber.com.ar/repos/sandbox/components/commons/code/releases/3.16/test/javascript/src/main/java/ar/com/zauber/commons/test/javascript/JsTestCase.java"&gt;ar.com.zauber.commons.test.javascript.JsTestCase&lt;/a&gt;. 
 This class extends from JUnit &lt;a href="http://junit.org/apidocs/junit/framework/TestCase.html"&gt;TestCase&lt;/a&gt;, so it can be used just like a regular test case.&lt;/dd&gt;

 &lt;dd&gt;So, how can we run it from Eclipse? A very simple example,
 step by step:&lt;/dd&gt;
 &lt;dd&gt;
 &lt;ol class="lista"&gt;

   &lt;li&gt;write some Javascript code, like we did in &lt;em&gt;validate.js&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;write some tests for that code, you should follow this prototype
   &lt;pre name="code" class="js"&gt;
      function ValidateTest(name) {
          TestCase.call( this, name );
      }
      
      ValidateTest.prototype = new TestCase();
      
      //"import" validate class
      Validate = validate.Validate;
      
      /** 
       * this function tests Validate.notNull with many valid values and a null value 
       */
      ValidateTest.prototype.testNotNull = function(){
         var valids = new Array(0, 1, true, false, 'text', new Object(), 
                 new Array(1,2), function(){});
         var invalid = null;
      
         for(i in valids){ // tests all valid values
             try{ 
                 Validate.notNull(valids[i]); // testing a not null value, shoudn't fail.
             }catch(e){
                 fail("notNull shouldn't raise an exception with value:" + valids[i] + " (type: " + typeof(valids[i]) + ").");    
             }
         }
      
         try{
             Validate.notNull(invalid); // testing a null value, should fail.
             fail("notNull should raise an exception with a null value.");
         }catch(e){
             //notNull is working correctly
         }
      }
   &lt;/pre&gt;
   &lt;p&gt;Here you can use the code written in step one by "importing" it, just like
   we do in this example.&lt;/p&gt;
   &lt;/li&gt;

   &lt;li&gt;Write a Java Class extending from &lt;tt&gt;JsTestCase&lt;/tt&gt;, it will force
   you to implement a method called &lt;tt&gt;getIncludes()&lt;/tt&gt;. That method returns
   a &lt;tt&gt;String array&lt;/tt&gt; with the path for all files to be included in the
   test context, and all files that actually contain the tests. There
   is an important point here, and it is the name of this Java class.
   Normally you don't want this class to be executed by maven, so the
   class name should not end with &lt;em&gt;Test&lt;/em&gt;, any other name will work, for
   example, we like to use &lt;em&gt;Driver&lt;/em&gt;:
   &lt;pre name="code" class="java"&gt;
    public class ValidateDriver extends JsTestCase {
   
     /** @see JsTestCase#getIncludes() */
     @Override
     protected final String[] getIncludes() {
         return new String[] {
             "src/main/javascript/validate.js",
             "src/test/javascript/ValidateTest.js"
         };
     }
   &lt;/pre&gt;
   &lt;/li&gt;
   &lt;li&gt;Now, just click on Run As JUnit Test and you will see
   your tests running.&lt;/li&gt;
   &lt;li&gt;Optionally, you can check the test reports on standard
   output. This can be achieved over all your tests by passing the following
   argument to the JVM: &lt;tt&gt;-Djavascript.test.showdetails=true&lt;/tt&gt; or over an
   individual test by overriding the method &lt;tt&gt;showDetails()&lt;/tt&gt; to return
   true.&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/dd&gt;
&lt;/dl&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_xHN21ztrTuY/SlyYMSn9wyI/AAAAAAAAAAM/qI2zxaHYTFg/s1600-h/ValidateDriver.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 220px;" src="http://1.bp.blogspot.com/_xHN21ztrTuY/SlyYMSn9wyI/AAAAAAAAAAM/qI2zxaHYTFg/s320/ValidateDriver.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5358324993589363490" /&gt;&lt;/a&gt;

&lt;dl&gt;
 &lt;dt&gt;A working example&lt;/dt&gt;
 &lt;dd&gt;You can checkout this project from our svn repository at
 &lt;a href="https://code.zauber.com.ar/repos/sandbox/components/javascript/validate/code/releases/0.2/"&gt;
 https://code.zauber.com.ar/repos/sandbox/components/javascript/validate/code/releases/0.2/&lt;/a&gt;
 &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;We hope you like it and use it ! Any feedback is always welcome.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7870515310189033933-6241292615049109755?l=blog.code.zauber.com.ar' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/6241292615049109755/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.code.zauber.com.ar/2009/07/stay-green-javascript-unit-testing.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/6241292615049109755?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/6241292615049109755?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ZauberCode/~3/qLs2O0yhrTI/stay-green-javascript-unit-testing.html" title="Stay green: Javascript Unit Testing" /><author><name>Pablo Grigolatto</name><email>noreply@blogger.com</email></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_xHN21ztrTuY/SlyYMSn9wyI/AAAAAAAAAAM/qI2zxaHYTFg/s72-c/ValidateDriver.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://blog.code.zauber.com.ar/2009/07/stay-green-javascript-unit-testing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcMQXk4fyp7ImA9WxVaF0k.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933.post-300651632325198540</id><published>2009-04-14T17:37:00.002-03:00</published><updated>2009-04-14T17:48:00.737-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-14T17:48:00.737-03:00</app:edited><title>ControlFreak: Python Inversion of Control</title><content type="html">&lt;p&gt;Back in 2007 I started programming in python. At first, the goal was
to learn how to write programs the &lt;em&gt;pythonic way&lt;/em&gt;, being my background a
Java Enterprise programmer, I wanted to avoid programming java-like
in python.&lt;/p&gt;

&lt;p&gt;We started building a web application, using &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt;, &lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt; andp
&lt;a href="http://www.makotemplates.org/"&gt;Mako&lt;/a&gt; as the base frameworks. At first we struggled with poor
documentation (we were used to have lots of books about each
framework in java), but as the time passed, we started feeling
comfortable with python and its ways.&lt;/p&gt;

&lt;p&gt;The project became bigger and bigger, and it was at that time that we
started missing Java and its "&lt;em&gt;bureaucratic&lt;/em&gt;" way of coding. Don't
get me wrong, bureaucracy is not a bad thing. The issue is unnecessary
bureaucracy. We started missing &lt;em&gt;static types&lt;/em&gt;, &lt;em&gt;lack of module variables&lt;/em&gt;,
&lt;em&gt;long package names&lt;/em&gt;, and &lt;em&gt;inversion of control&lt;/em&gt; to rule them all.&lt;/p&gt;

&lt;p&gt;At that time we started using "&lt;em&gt;the java way of coding&lt;/em&gt;" in python, in order
to make the project more maintainable. For example, we quit using the
sqlAlchemy session as a module variable, and started injecting it. We
erased every static reference to a module variable, and we also wanted
to get good package names (at first they seem to be the same as java,
but that's misguided).&lt;/p&gt;

&lt;p&gt;So, we needed an inversion of control (IoC) library and started to look for one.&lt;/p&gt;

&lt;h3&gt;Why a new one?&lt;/h3&gt;

&lt;p&gt;When we started looking for an IoC library, we didn't find one that filled
ours needs. The exception was &lt;a href="http://springpython.webfactional.com/"&gt;Spring-Python&lt;/a&gt;, but from our point of view,
it was a port one on one of the Java &lt;a href="http://www.springsource.org/about"&gt;Spring framework&lt;/a&gt;; and we didn't want
something that complex.&lt;/p&gt;

&lt;p&gt;What we were looking for, was something that with much of the Spring
IoC capabilities, but taking into consideration that this was python
and not Java: There are things that are simpler to do in python,
and other that are simpler to do in Java. Above all, we wanted
to say "inject this instance on that other
instance" in the simplest way possible. That was the reason we decided to do our own. I named it "ControlFreak"&lt;/p&gt;

&lt;h3&gt;How and When?&lt;/h3&gt;

&lt;p&gt;This is kind of a disclaimer, because ControlFreak was built on spare
hours, spare and sparse hours. And it's something I would like to
refactor, probably as a whole, when I found the time for it.&lt;/p&gt;

&lt;p&gt;Enough of introducction, let's me show what is controlfreak!&lt;/p&gt;

&lt;h3&gt;ControlFreak: The library&lt;/h3&gt;

&lt;p&gt;Controlfreak is a IoC library with capabilities similar to what
spring does in Java. But there are some changes on it's design
that are worth to mention. 
The source code can be found in a &lt;a href="https://code.zauber.com.ar/repos/sandbox/components/controlfreak/"&gt;SVN repository&lt;/a&gt;&lt;/p&gt;. Also, controlfreak depends on pycommons, that can be found in this &lt;a href="https://code.zauber.com.ar/repos/sandbox/components/pycommons/"&gt;svn repo&lt;/a&gt;.

&lt;h4&gt;Components&lt;/h4&gt;

&lt;p&gt;When you code, you tend to think about interfaces and the different
implementations of them. It's like you have a contract, and several
providers of that contract.&lt;/p&gt;

&lt;p&gt;Discussing with a colleague of mine, we thought that it would be
interesting to take that concept into the IoC configurations. So, that
you won't be working just with beans, but with components. A component
is a group of beans, that, one can think, provides (or exports) some
beans. For example, a database component, will provide a session
bean. And one could have different implementations of this database
component. In order to take advantage of this metaphor is that
components where created. A component, may require other component to
work properly. For example, the DAO components will need the database
component to function properly, no matter who or how is this other
component "&lt;em&gt;implemented&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;So, in controlfreak, the application is a bundle of components, wired
together and configuration files for everything that is not beans.&lt;/p&gt;

&lt;h4&gt;Python Static Beans&lt;/h4&gt;

&lt;p&gt;When considering different alternatives to inject model objects, we
arrived to a different approach to the one we would took in java.&lt;/p&gt;

&lt;p&gt;To inject model objects with services and others beans, one would need
to intercept the model object creation, so as to let the IoC library
to create the object. The ORM is the one usually creating model
objects, so one would need to intercept the model creation there.&lt;/p&gt;

&lt;p&gt;When making queries that return hundreds of objects, objects that
won't probably use any of their injected properties, one starts to
wonder if the overhead of creating those objects with IoC makes
sense. But that's a question I don't plan to answer here.&lt;/p&gt;

&lt;p&gt;Our solution, doesn't involve injecting model objects, because we end
up injecting model classes. This is what we call static beans. Classes
in python are the same as instances, just objects. So it's pretty easy
to inject them with properties, not on creation, but afterwards.&lt;/p&gt;

&lt;p&gt;There's a catch on using class injection, instead of instance
injection. The injected properties must be stateless, not dependant of
the current instance that is calling them. But that's usually the case
with services.&lt;/p&gt;

&lt;h4&gt;ControlFreak ApplicationContext&lt;/h4&gt;

&lt;p&gt;The &lt;tt&gt;ApplicationContext&lt;/tt&gt; class is the same as Spring's one. That is, it
is given an application's configuration; and we can use it as a
Bean's Locator using the &lt;tt&gt;get()&lt;/tt&gt; method.&lt;/p&gt;

&lt;p&gt;The static beans are initialized at the same time as the
&lt;tt&gt;ApplicationContext&lt;/tt&gt;, cause they inject already created objects such as
class o modules.&lt;/p&gt;

&lt;p&gt;All other beans are created on demand, and they are cached for later
use.&lt;/p&gt;

&lt;p&gt;Right now the library supports the following kind of beans:&lt;/p&gt;

&lt;ul class="lista"&gt;
  &lt;li&gt;&lt;em&gt;bean&lt;/em&gt;: Constructs and inject a class&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;factory&lt;/em&gt;: Creates a bean by calling a function (callable)&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;alias&lt;/em&gt;: An alias of another bean&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;map&lt;/em&gt;: A map of beans&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;list&lt;/em&gt;:  a list of beans &lt;/li&gt;
  &lt;li&gt;&lt;em&gt;static&lt;/em&gt;: Inject on already created objects (on &lt;tt&gt;ApplicationContext&lt;/tt&gt;
    initialization), such as class or module objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Configuration&lt;/h4&gt;

&lt;p&gt;At this moment the only supported configuration format is yaml files.
There are 3 kinds of yaml files to define:&lt;/p&gt;

&lt;ul class="lista"&gt;
  &lt;li&gt;components definition&lt;/li&gt;
  &lt;li&gt;configuration variables for components&lt;/li&gt;
  &lt;li&gt;application definition&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Component's File&lt;/h5&gt;

&lt;p&gt;A component is defined by a name, required config keys, required
components and beans definitions. Several components can be defined
in the same file. That is, a component file is something like:&lt;/p&gt;

&lt;pre name="code" class="html"&gt;
component-name:
 config-keys:
   - a-config-key
   - another-config-key
 required-components:
   - other-comp-name
 definitions:
   # beans definitions

other-component-name:
  #same as before
  # ...
&lt;/pre&gt;

&lt;p&gt;Inside 'definitions' goes all components beans, next I'll show how to
configure each of the bean's types.&lt;/p&gt;

&lt;p&gt;A bean of type 'bean' can have setter or construction injection, so it
goes:&lt;/p&gt;

&lt;pre name="code" class="js"&gt;
   renderer:
     type: bean
     path: renderers.html.impl:HtmlRenderer
     constructor-args:
       debug_mode: config:debug_mode

   renderer:
     type: bean
     path: renderers.rest.impl:ReStructuredTextRenderer
     properties:
       syntax: bean:syntax_rules
&lt;/pre&gt;

&lt;p&gt;The bean's name in each case is &lt;tt&gt;'renderer'&lt;/tt&gt;, one uses constructor
injection, and the other setter injection. The first has a
constructor's keyword argument named &lt;tt&gt;'debug_mode'&lt;/tt&gt; and the value to set
is the config-key of the component &lt;tt&gt;'debug_mode'&lt;/tt&gt;. The second bean, has
a property named &lt;tt&gt;'syntax'&lt;/tt&gt; set with another bean, named
&lt;tt&gt;'syntax_rules'&lt;/tt&gt;. This bean, must be in the same component. If a bean
from another component is needed, first you need to declare the other
component in &lt;tt&gt;'required-components'&lt;/tt&gt; of the component, and then, when
referring to the bean, you should use it's absolute name, that is:
&lt;tt&gt;'comp_name::bean_name'&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;A bean of type 'factory', has only constructor-args, so it goes:&lt;/p&gt;

&lt;pre name="code" class="js"&gt;
   syntax_rules:
     type: factory
     path: renderers.rest.rules:create_rules
     constructor-args:
       keywords: config:accepted_keywords
&lt;/pre&gt;

&lt;p&gt;If instead of a keyword argument, you want to use positional
arguments, you would place a keyword the position of the argument,
beginning with 0.&lt;/p&gt;

&lt;p&gt;A bean of type 'alias' is just a link to another bean, so it goes:&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
   documents_generator:
     type: alias
     target: simple_generator
&lt;/pre&gt;
&lt;p&gt;A bean of type 'map' or 'list' needs you to define &lt;tt&gt;'properties'&lt;/tt&gt; as a
dictionary or list depending the case. Examples of this are:&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
   rules_map:
     type: map
     properties:
       rule1: bean:some_rule
       rule2: bean:some_other_rule
   exceptions_list:
     type: list
     properties:
       - bean:some_exception
       - my-string-exception
&lt;/pre&gt;
&lt;p&gt;A bean fo type &lt;tt&gt;'static'&lt;/tt&gt; has only setter injection, because
controlfreak is not involved in the object creation. For example:&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
   api-accounts:
     type: static
     path: popserver.controllers.api.accounts:AccountsController
     properties:
       service_dao: bean:dao::serviceDAO
       account_dao: bean:dao::accountDAO
       user_dao: bean:dao::userDAO
       account_service: bean:pop-services::accountService
&lt;/pre&gt;

&lt;h5&gt;Configuration Variables File&lt;/h5&gt;

&lt;p&gt;A configuration variables file, defines a values for component's
required configuration values. So if we have a component named
'database' that requires a config value &lt;tt&gt;'database_url'&lt;/tt&gt; the config file
would look like&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
database:
 database_url: postgres://user:password@mydbserver:5432/dbname
&lt;/pre&gt;
&lt;p&gt;In the same configuration file one can place configuration values for
several components.&lt;/p&gt;

&lt;h5&gt;Application File&lt;/h5&gt;

&lt;p&gt;An application file, is where we bundle several components files, with
their configuration files. The reason to separate the config values
from the component's bean is because  the config values will probably
change more often than the bean's wiring structure. Also, I believe
that is clearer to see configuration values on a separate place
than seeing them within the beans that are, in a way,
more coupled with the programming task itself.&lt;/p&gt;

&lt;p&gt;Another thing one can do in the application file is to redefine the
components wiring. That is, to decide witch components will fulfill
the required components of other component. For example, suppose that
we have two components that &lt;em&gt;"implements"&lt;/em&gt; the same contract, one it's
called &lt;tt&gt;'dummy-cache'&lt;/tt&gt; and the other &lt;tt&gt;'standard-cache'&lt;/tt&gt;. Now, we also have
a component, let's say &lt;tt&gt;'services'&lt;/tt&gt; that requires a 'cache'
component. The application file would be the place to wire one of the
cache components to the services components: dummy for development,
and standard for production environment.&lt;/p&gt;

&lt;p&gt;Another feature of the application file is to have a same component,
configured with two different config values at the same time. Think on
the component as a class definition, that we would want to instantiate
with different values each time. For example, we have a database
component, and we are using two databases, and we need to use the same
component with two different config values. To do this, we define two
aliases for 'database' in application context: &lt;tt&gt;'database1'&lt;/tt&gt; and
&lt;tt&gt;'database2'&lt;/tt&gt;. In the config file, we will then set the values for &lt;tt&gt;'database1'&lt;/tt&gt; and
&lt;tt&gt;'database2'&lt;/tt&gt;; and not for &lt;tt&gt;'database'&lt;/tt&gt;. &lt;/p&gt;

&lt;p&gt;An example of an application file is:&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
includes: #component files to include
 - "%(here)s/../../components/general/amazon-mock.yaml"
 - "%(here)s/../../components/general/cache.yaml"
 - "%(here)s/../../components/general/database.yaml"
 - "%(here)s/../../components/general/eye-services.yaml"
 - "%(here)s/../../components/general/pop-services.yaml"
 - "%(here)s/../../components/general/core-model.yaml"
 - "%(here)s/../../components/general/dao.yaml"
 - "%(here)s/../../components/general/domains.yaml"
 - "%(here)s/../../components/general/extauth-services.yaml"
customization: #aliases and rewiring as explained
 cache:
   required-components:
     cache-customization: dummy-cache-customization
 eye-services:
   required-components:
     item-age-customization: testing-item-age-customization
config: #config files to read
 - "%(here)s/../base/config.yaml"
 - "%(here)s/config.yaml"
&lt;/pre&gt;

&lt;h4&gt;Using the library&lt;/h4&gt;

&lt;p&gt;To load a control freak set up, one would to something like:&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
from controlfreak.config.yaml import createApplicationContext
appctx = createApplicationContext('my-app-file.yaml')
&lt;/pre&gt;
&lt;p&gt;To use the Application Context as a bean's locator, one need to give
it the absolute path of a bean, that is, the component and the bean
name together. For example:&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
session = appctx.get('database::session')
...
&lt;/pre&gt;
&lt;p&gt;This would result on the 'session' bean from the &lt;tt&gt;'database'&lt;/tt&gt; component.&lt;/p&gt;

&lt;h4&gt;Final Example&lt;/h4&gt;

&lt;p&gt;Here's an example of each file:&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
component file:
reSt-renderer:
 config-keys:
   - accepted_keywords
 definitions:
   renderer:
     type: bean
     path: renderers.rest.impl:ReStructuredTextRenderer
     properties:
       syntax: bean:syntax_rules
   syntax_rules:
     type: factory
     path: renderers.rest.rules:create_rules
     constructor-args:
       keywords: config:accepted_keywords


html-renderer:
 config-keys:
   - debug_mode
 definitions:
   renderer:
     type: bean
     path: renderers.html.impl:HtmlRenderer
     constructor-args:
       debug_mode: config:debug_mode

documents-generator:
 required-components:
   - renderer
 definitions:
   documents_generator:
     type: alias
     target: simple_generator
   simple_generator:
     type: bean
     path: generators.simple:SimpleGenerator
     propreties:
       renderer: bean:renderer:renderer
   complex_generator:
     type: bean
     path: generators.complex:ComplexGenerator
     constructor-args:
       rules: bean:rules_map
       exceptions: bean:exceptions_list
   rules_map:
     type: map
     properties:
       rule1: bean:some_rule
       rule2: bean:some_other_rule
   exceptions_list:
     type: list
     properties:
       - bean:some_exception
       - my-string-exception
   some_rule:
     type: bean
     path: rules:SomeRule
   some_other_rule:
     type: bean
     path: rules:SomeOtherRule
   some_exception:
     type: bean
     path: excpetions:MyGeneratorException
&lt;/pre&gt;
&lt;p&gt;config file:&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
reSt-renderer:
 accepted_keywords:
   - hey
   - jo

html-renderer:
 debug_mode: True
&lt;/pre&gt;
&lt;p&gt;application file:&lt;/p&gt;
&lt;pre name="code" class="js"&gt;
includes:
 - "%(here)s/my-components.yaml"
config:
 - "%(here)s/my-config.yaml"
&lt;/pre&gt;

&lt;p&gt;Well, that's all, I hope you will find this IoC library useful!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7870515310189033933-300651632325198540?l=blog.code.zauber.com.ar' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/300651632325198540/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.code.zauber.com.ar/2009/04/controlfreak-python-inversion-of.html#comment-form" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/300651632325198540?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/300651632325198540?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ZauberCode/~3/_yK10XvFYKs/controlfreak-python-inversion-of.html" title="ControlFreak: Python Inversion of Control" /><author><name>Mariano Cortesi (Cono)</name><uri>http://www.blogger.com/profile/04119628512196935720</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="11124797496634455987" /></author><thr:total>3</thr:total><feedburner:origLink>http://blog.code.zauber.com.ar/2009/04/controlfreak-python-inversion-of.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4HRH89fCp7ImA9WxVbEUU.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933.post-3867176819211100060</id><published>2009-03-25T11:08:00.007-03:00</published><updated>2009-03-27T18:22:15.164-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-27T18:22:15.164-03:00</app:edited><title>[RELEASE] Zauber Commons 3.10</title><content type="html">&lt;p&gt;If you are using Zauber Commons (our java components), you may be interested on the new version: 3.10. This release may not be  compatible with the 3.8/3.9 version.
 &lt;/p&gt;
 
 &lt;dl&gt;
   &lt;dt&gt;Global Notes:&lt;/dt&gt;
   &lt;dd&gt;
     &lt;ul class="lista"&gt;
      &lt;li&gt;new modules: &lt;em&gt;commons-web-transformation&lt;/em&gt; and &lt;em&gt;commons-wicket&lt;/em&gt;&lt;/li&gt;
      &lt;li&gt;The upgrade from older version might require supervision. Some transitive dependencies might be missing. (zauber commons changed some dependency versions)&lt;/li&gt;
      &lt;li&gt;You need to upgrade from log4j 1.2.8 to 1.2.14. We suggest to upgrade your application (this is required if you use commons-repository). Change your pom:   &lt;pre name="code" class="html"&gt;
           &lt;dependency&gt;
             &lt;groupId&gt;log4j&lt;/groupId&gt;
             &lt;artifactId&gt;log4j&lt;/artifactId&gt;
             &lt;version&gt;1.2.15&lt;/version&gt;
             &lt;exclusions&gt;
                &lt;exclusion&gt;
                  &lt;groupId&gt;javax.mail&lt;/groupId&gt;
                  &lt;artifactId&gt;mail&lt;/artifactId&gt;
                &lt;/exclusion&gt;
                &lt;exclusion&gt;
                  &lt;groupId&gt;javax.jms&lt;/groupId&gt;
                  &lt;artifactId&gt;jms&lt;/artifactId&gt;
                &lt;/exclusion&gt;
                &lt;exclusion&gt;
                  &lt;groupId&gt;com.sun.jmx&lt;/groupId&gt;
                  &lt;artifactId&gt;jmxri&lt;/artifactId&gt;
                &lt;/exclusion&gt;
                &lt;exclusion&gt;
                  &lt;groupId&gt;com.sun.jdmk&lt;/groupId&gt;
                  &lt;artifactId&gt;jmxtools&lt;/artifactId&gt;
                &lt;/exclusion&gt;
             &lt;/exclusions&gt;
            &lt;/dependency&gt;
&lt;/pre&gt;&lt;/li&gt;
     &lt;/ul&gt;
 
    &lt;/dd&gt;
 
   &lt;dt&gt;Changelog:&lt;/dt&gt;
   &lt;dd&gt;
     &lt;ul class="lista"&gt;
        &lt;li&gt;&lt;em&gt;commons-doxia:&lt;/em&gt;
            &lt;ul class="lista"&gt;
               &lt;li&gt;This module aims to provide functionality related to the transformation of &lt;em&gt;html/xml&lt;/em&gt; content.&lt;/li&gt;
               &lt;li&gt;So far we've implemented the &lt;em&gt;XmlSanitizer&lt;/em&gt; interface, the purpose of which is to parse a dom tree and "sanitize" the dangerous nodes.&lt;/li&gt;
               &lt;li&gt;The only implementation of &lt;em&gt;XmlSanitizer&lt;/em&gt; available at this time is &lt;em&gt;DeletingElementNodeSanitizer&lt;/em&gt;. It deletes element/attribute nodes considered invalid. In order to do this it requires a &lt;em&gt;TagSecutrityStrategy&lt;/em&gt;, implemented by &lt;em&gt;HashMapTagSecurityStrategy&lt;/em&gt;.&lt;/li&gt;
               &lt;li&gt;&lt;em&gt;XmlSanitizerTest&lt;/em&gt; provides an example of how to use this functionality.&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;em&gt;commons-web-wicket:&lt;/em&gt;
               &lt;ul class="lista"&gt;
                  &lt;li&gt;we start to detect reusable classes across wicket projects:&lt;em&gt;DynamicDetachableModel&lt;/em&gt;, &lt;em&gt;RepositoryDynamicDetachableModel&lt;/em&gt;, &lt;em&gt;ConfirmLink&lt;/em&gt;&lt;/li&gt;
               &lt;/ul&gt;
          &lt;/li&gt;
                 &lt;li&gt;&lt;em&gt;commons-doxia:&lt;/em&gt;
           &lt;ul class="lista"&gt;
              &lt;li&gt;upgrade to doxia 1.1 (http://jira.codehaus.org/secure/ReleaseNote.jspa?version=13617&amp;styleName=Html&amp;projectId=10780)&lt;/li&gt;
           &lt;/ul&gt;
          &lt;/li&gt;


         &lt;li&gt;&lt;em&gt;commons-spring:&lt;/em&gt;
           &lt;ul class="lista"&gt;
              &lt;li&gt;remove unused dependency: &lt;em&gt;org.springframework:spring-webmvc-struts&lt;/em&gt;&lt;/li&gt;
           &lt;/ul&gt;
          &lt;/li&gt;





         &lt;li&gt;&lt;em&gt;commons-web-utils:&lt;/em&gt;
           &lt;ul class="lista"&gt;
              &lt;li&gt;new filter (&lt;em&gt;NullFilter&lt;/em&gt;) that does nothing. usefull for conditional configuration of filters. for example in this example, depending on a property we activate/deactivate a caching filter depending on a flag:   &lt;pre name="code" class="html"&gt;
      &amp;lt;bean name="anunciosServletCache" class="ar.com.zauber.commons.spring.beans.factory.SwitchConditionalFactoryBean"&amp;gt;
            &amp;lt;property name="caseBlocks"&amp;gt;
                &amp;lt;list&amp;gt;
                    &amp;lt;bean class="ar.com.zauber.commons.spring.beans.factory.impl.BooleanPropertyCaseBlock"&amp;gt;
                        &amp;lt;constructor-arg index="0" value="${bar.cache.active}"/&amp;gt;
                        &amp;lt;constructor-arg index="1"&amp;gt;
                            &amp;lt;bean class="com.foo.bar.web.filters.AnunciosCacheFilter"&amp;gt;
                                &amp;lt;constructor-arg index="0" ref="anunciosCacheManager"/&amp;gt;
                                &amp;lt;constructor-arg index="1" value="anuncios"/&amp;gt;
                                &amp;lt;constructor-arg index="2" ref="seoStrategy"/&amp;gt;
                                &amp;lt;constructor-arg index="3" ref="pagingHelper"/&amp;gt;
                                &amp;lt;constructor-arg index="4" ref="commonsWebUtilsVersionProvider"/&amp;gt;
                                &amp;lt;constructor-arg index="5" ref="lastModificationEntities"/&amp;gt;
                            &amp;lt;/bean&amp;gt;
                        &amp;lt;/constructor-arg&amp;gt;
                    &amp;lt;/bean&amp;gt;
                    &amp;lt;bean class="ar.com.zauber.commons.spring.beans.factory.impl.DefaultCaseBlock"&amp;gt;
                        &amp;lt;constructor-arg index="0"&amp;gt;
                            &amp;lt;bean class="ar.com.zauber.commons.web.filter.NullFilter"/&amp;gt;
                        &amp;lt;/constructor-arg&amp;gt;
                    &amp;lt;/bean&amp;gt;
                &amp;lt;/list&amp;gt;
            &amp;lt;/property&amp;gt;
        &amp;lt;/bean&amp;gt;
    &lt;/pre&gt;&lt;/li&gt;
           &lt;/ul&gt;
          &lt;/li&gt;
          
          
          
          &lt;li&gt;&lt;em&gt;commons-repository:&lt;/em&gt;
           &lt;ul class="lista"&gt;
              &lt;li&gt;upgrade from hibernate 3.2.x to 3.3.1 (this is the lastest stable version. also it is the version that will be used with spring 3.x).  The changes that repository user need to take in consideration:
                  &lt;ul class="lista"&gt;
                    &lt;li&gt;Hibernate migration guide http://www.hibernate.org/250.html#A51 &lt;/li&gt;
                    &lt;li&gt;If you want to ehcache 2nd level cache you need to add   &lt;pre name="code" class="html"&gt;&amp;lt;dependency&amp;gt;
                    &amp;lt;groupId&amp;gt;org.hibernate&amp;lt;/groupId&amp;gt;
                    &amp;lt;artifactId&amp;gt;hibernate-ehcache&amp;lt;/artifactId&amp;gt;
                    &amp;lt;version&amp;gt;3.3.1.GA&amp;lt;/version&amp;gt;
                    &amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;/li&gt;
                  &lt;/ul&gt;
              &lt;/li&gt;
              &lt;li&gt;repository now has the ability to group by and apply an agregate function at the same time. This is usefull to lazy load entities and know how many entities are in the query:    &lt;pre name="code" class="html"&gt;
        final Query/lt;DireccionDummy&amp;gt; query = 
            new SimpleQuery&amp;lt;DireccionDummy&amp;gt;(DireccionDummy.class, 
                new NullFilter(), null,  new Ordering(Collections.emptyList()));
        AggregateFunction function = new CompositeAggregateFunction(
                Arrays.asList(new AggregateFunction[]{
                        new CountPropertyAggregateFunction("numero"),
                        new GroupPropertyAggregateFilter("direccion"),
                        new GroupPropertyAggregateFilter("numero"),
                }));
        
         for(Object row: repository.aggregate(query, function, List.class)) {
             final Object [] fields = (Object[]) row;
             System.out.println("frequency: " + fields[0] + " | direccion:  " + fields[1] + "numero:  " + fields[2]);
         }
&lt;/pre&gt;
              &lt;/li&gt;
              &lt;li&gt;Another implementation of &lt;em&gt;Value&lt;/em&gt; called  &lt;em&gt;PropertyValue&lt;/em&gt;  that allows queries that have to compare it's  properies. For example &lt;em&gt;select Person where length &amp;gt; age&lt;/em&gt;. For example:  &lt;pre name="code" class="html"&gt;
        final Query&amp;lt;PersonaDummy&amp;gt; q1 =
            new SimpleQuery&amp;lt;PersonaDummy&amp;gt;(
                    PersonaDummy.class, new EqualsPropertyFilter("id", 
                            new PropertyValue("id")), null, null);


        assertEquals(Integer.valueOf(6), 
                repository.aggregate(q1, new RowCountAggregateFilter(), Integer.class));
&lt;/pre&gt;&lt;/li&gt;
              &lt;li&gt;new Hibernate interceptor used to inject dependencies from a spring context to achieve a Domain Driven Design. It is called =SpringInjectionInterceptor=. The classes wishing being injected with this interceptor, must be annotated with the annotation =@Configurable= And each field that will be injected must be transient and annotated with &lt;em&gt;@Qualifier&lt;/em&gt;.The qualifier name can be used to set the bean name (else it uses the field &lt;em&gt;name&lt;/em&gt;). For example:   &lt;pre name="code" class="html"&gt;
@Entity
@Configurable
public class DomainEntityExample implements Persistible {
    @Id
    private Long id;

    @Qualifier(value = "someService")
    private transient SomeService service;
    @Qualifier
    private transient SomeService someService;
    ...

    private DomainEntityExample() {
       // hibernate's
    }

    public DomainEntityExample(SomeService service, SomeService someService) {
        .....
        this.service = service;
        this.someService = someService;
    }
    public final SomeService getService() {
        return service;
    }
    public final SomeService getSomeService() {
        return someService;
    }
    ....
}
&lt;/pre&gt; We also provide a &lt;em&gt;SpringInjectionHibernateAuditLoggerInterceptor&lt;/em&gt; that combines the &lt;em&gt;HibernateAuditLoggerInterceptor&lt;/em&gt; with &lt;em&gt;SpringInjectionInterceptor&lt;/em&gt; (hibernate only let you specify only one interceptor) enhance &lt;em&gt;SpringInjectionInterceptor&lt;/em&gt; (the interceptor that inject dependencies to hibernates entities). If the annotated bean implements &lt;em&gt;InitializingBean&lt;/em&gt;, the &lt;em&gt;afterPropertiesSet&lt;/em&gt; is called for post configuring settings.
              &lt;/li&gt;
            
           &lt;/ul&gt;
          &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/dd&gt;
    &lt;dt&gt;Known Bugs&lt;/dt&gt;
    &lt;dd&gt;None known at this time&lt;/dd&gt;
    &lt;dt&gt;How to use it&lt;/dt&gt;
    &lt;dd&gt;
 &lt;p&gt;There isn't a site with tutorials or formal documentation for Zauber Commons yet, but we are working on that. For now you can browse the source at the SVN repository &lt;a href="https://code.zauber.com.ar/repos/sandbox/components/commons/code/trunk/"&gt;https://code.zauber.com.ar/repos/sandbox/components/commons/code/trunk/&lt;/a&gt;. Also you can use Zauber Commons with a &lt;a href="http://maven.apache.org/"&gt;Maven 2&lt;/a&gt;:
 
 &lt;pre name="code" class="html"&gt;  &amp;lt;repositories&amp;gt;
     &amp;lt;repository&amp;gt;
       &amp;lt;id&amp;gt;zauber-code-releases&amp;lt;/id&amp;gt;
       &amp;lt;name&amp;gt;public zauber repository&amp;lt;/name&amp;gt;
       &amp;lt;url&amp;gt;https://repo1.zauber.com.ar/zauber/code/releases&amp;lt;/url&amp;gt;
       &amp;lt;releases&amp;gt;&amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;&amp;lt;/releases&amp;gt;
       &amp;lt;snapshots&amp;gt;&amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;&amp;lt;/snapshots&amp;gt;
     &amp;lt;/repository&amp;gt;
     &amp;lt;repository&amp;gt;
       &amp;lt;id&amp;gt;zauber-code-snapshots&amp;lt;/id&amp;gt;
       &amp;lt;name&amp;gt;public zauber repository&amp;lt;/name&amp;gt;
       &amp;lt;url&amp;gt;https://repo1.zauber.com.ar/zauber/code/snapshots&amp;lt;/url&amp;gt;
       &amp;lt;releases&amp;gt;&amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;&amp;lt;/releases&amp;gt;
       &amp;lt;snapshots&amp;gt;&amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;&amp;lt;/snapshots&amp;gt;
     &amp;lt;/repository&amp;gt;
   &amp;lt;/repositories&amp;gt;   
 &lt;/pre&gt;
 
 And for example add a dependency to your project
 
  &lt;pre name="code" class="html"&gt;  &amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;ar.com.zauber.commons.web&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;commons-web-version&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${commons.version}&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;&lt;/pre&gt;
 &lt;/p&gt;
 &lt;/dd&gt;
    &lt;dt&gt;Diffstat&lt;/dt&gt;
    &lt;dd&gt;&lt;pre&gt; auth/password/pom.xml                                                                                                               |    6 
 commons/pom.xml                                                                                                                     |    6 
 dao/src/test/java/ar/com/zauber/commons/dao/OrderTest.java                                                                          |   16 
 exception/pom.xml                                                                                                                   |    7 
 facebook/pom.xml                                                                                                                    |    1 
 jetty-launcher/pom.xml                                                                                                              |    6 
 message/impl/pom.xml                                                                                                                |    7 
 pom.xml                                                                                                                             |   83 +++
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/aggreate/GroupPropertyAggregateFilter.java                      |   30 +
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/filters/BeginsLikePropertyFilter.java                           |    8 
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/filters/ContainsLikePropertyFilter.java                         |    8 
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/filters/EndsLikePropertyFilter.java                             |    8 
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/filters/EqualsPropertyFilter.java                               |    6 
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/filters/ExactLikePropertyFilter.java                            |    8 
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/filters/GreaterThanEqualsPropertyFilter.java                    |    7 
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/filters/GreaterThanPropertyFilter.java                          |    7 
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/filters/LessThanEqualsPropertyFilter.java                       |    7 
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/filters/LessThanPropertyFilter.java                             |    7 
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/filters/LikePropertyFilter.java                                 |    8 
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/values/PropertyValue.java                                       |   42 +
 repository/api/src/main/java/ar/com/zauber/commons/repository/query/values/SimpleValue.java                                         |   17 
 repository/impl/entities/pom.xml                                                                                                    |    1 
 repository/impl/spring-hbm/pom.xml                                                                                                  |   39 +
 repository/impl/spring-hbm/src/main/java/ar/com/zauber/commons/repository/SpringHibernateRepository.java                            |    4 
 repository/impl/spring-hbm/src/main/java/ar/com/zauber/commons/repository/aggregate/ProjectionAggregateFunctionVisitor.java         |    3 
 repository/impl/spring-hbm/src/main/java/ar/com/zauber/commons/repository/query/visitor/CriteriaFilterVisitor.java                  |  102 ++--
 repository/impl/spring-hbm/src/main/java/ar/com/zauber/commons/repository/usertypes/URLUserType.java                                |  163 +++++++
 repository/impl/spring-hbm/src/main/java/ar/com/zauber/commons/repository/utils/SpringInjectionHibernateAuditLoggerInterceptor.java |   52 ++
 repository/impl/spring-hbm/src/main/java/ar/com/zauber/commons/repository/utils/SpringInjectionInterceptor.java                     |  217 ++++++++++
 repository/impl/spring-hbm/src/test/java/ar/com/zauber/commons/repository/test/model/DomainEntityExample.java                       |   82 +++
 repository/impl/spring-hbm/src/test/java/ar/com/zauber/commons/repository/test/model/SomeService.java                               |   27 +
 repository/impl/spring-hbm/src/test/java/ar/com/zauber/commons/repository/utils/SpringInjectionInterceptorTest.java                 |   77 +++
 repository/impl/spring-hbm/src/test/java/ar/com/zauber/commons/test/SpringHibernateRepositoryTest.java                              |   53 ++
 repository/impl/spring-hbm/src/test/resources/ar/com/zauber/commons/repository/utils/injection-hibernate-mapping-spring.xml         |   15 
 repository/impl/spring-hbm/src/test/resources/ar/com/zauber/commons/repository/utils/injection-hibernate-spring.xml                 |   52 ++
 repository/pom.xml                                                                                                                  |   49 --
 spring/pom.xml                                                                                                                      |   16 
 spring/src/main/java/ar/com/zauber/commons/spring/mail/NullMailSender.java                                                          |   16 
 web/pom.xml                                                                                                                         |    1 
 web/transformation/pom.xml                                                                                                          |   44 ++
 web/transformation/src/main/java/ar/com/zauber/commons/web/transformation/sanitizing/api/AttributeValueValidator.java               |   31 +
 web/transformation/src/main/java/ar/com/zauber/commons/web/transformation/sanitizing/api/TagSecutrityStrategy.java                  |   48 ++
 web/transformation/src/main/java/ar/com/zauber/commons/web/transformation/sanitizing/api/XmlSanitizer.java                          |   35 +
 web/transformation/src/main/java/ar/com/zauber/commons/web/transformation/sanitizing/impl/AbstractElementNodeSanitizer.java         |  125 +++++
 web/transformation/src/main/java/ar/com/zauber/commons/web/transformation/sanitizing/impl/DeletingElementNodeSanitizer.java         |   73 +++
 web/transformation/src/main/java/ar/com/zauber/commons/web/transformation/sanitizing/impl/HashMapTagSecurityStrategy.java           |   82 +++
 web/transformation/src/main/java/ar/com/zauber/commons/web/transformation/sanitizing/impl/HrefUrlOnlyValueValidator.java            |   41 +
 web/transformation/src/main/java/ar/com/zauber/commons/web/transformation/sanitizing/impl/StyleAlignmentOnlyValueValidator.java     |   42 +
 web/transformation/src/main/java/ar/com/zauber/commons/web/transformation/sanitizing/impl/StyleTextDecorationValueValidator.java    |   45 ++
 web/transformation/src/main/java/ar/com/zauber/commons/web/transformation/sanitizing/impl/TargetSelfBlankValueValidator.java        |   33 +
 web/transformation/src/test/java/ar/com/zauber/commons/web/transformation/sanitizing/impl/XmlSanitizerTest.java                     |  133 ++++++
 web/utils/src/main/java/ar/com/zauber/commons/web/filter/NullFilter.java                                                            |   51 ++
 wicket/impl/pom.xml                                                                                                                 |   58 ++
 wicket/impl/src/main/java/ar/com/zauber/commons/wicket/components/ConfirmLink.java                                                  |   69 +++
 wicket/impl/src/main/java/ar/com/zauber/commons/wicket/model/DynamicDetachableModel.java                                            |  107 ++++
 wicket/impl/src/main/java/ar/com/zauber/commons/wicket/model/RepositoryDynamicDetachableModel.java                                  |   93 ++++
 wicket/pom.xml                                                                                                                      |   20 
 &lt;/pre&gt;&lt;/dd&gt;
 &lt;/dl&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7870515310189033933-3867176819211100060?l=blog.code.zauber.com.ar' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/3867176819211100060/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.code.zauber.com.ar/2009/03/release-zauber-commons-310.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/3867176819211100060?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/3867176819211100060?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ZauberCode/~3/lThugFJgeEk/release-zauber-commons-310.html" title="[RELEASE] Zauber Commons 3.10" /><author><name>Juan F. Codagnone</name><uri>http://www.blogger.com/profile/11600098429143575610</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="16987717536058735653" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.code.zauber.com.ar/2009/03/release-zauber-commons-310.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ANQ3cyeyp7ImA9WxVaEE4.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933.post-655207439695231248</id><published>2009-02-11T22:35:00.005-02:00</published><updated>2009-04-06T14:43:12.993-03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-06T14:43:12.993-03:00</app:edited><title>[RELEASE] Zauber Commons 3.8</title><content type="html">&lt;p&gt;If you are using Zauber Commons (our java components), you may be interested on the new version: 3.8. This is a small release. Compatible with the 3.7 version.
&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Changelog:&lt;/dt&gt;
  &lt;dd&gt;
    &lt;ul class="lista"&gt;
     &lt;li&gt;&lt;em&gt;commons-spring&lt;/em&gt;
       &lt;ul class="lista"&gt;
          &lt;li&gt;&lt;em&gt;HttpPagingHelper&lt;/em&gt;: Now it is posible to use another GET parameter name to track the current page number (the default is "page)". The default value can be changed with the new method &lt;em&gt;setPageField(String)&lt;/em&gt;. &lt;/li&gt;
       &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;   
   &lt;/dd&gt;
   &lt;dt&gt;Known Bugs&lt;/dt&gt;
   &lt;dd&gt;None known at this time&lt;/dd&gt;
   &lt;dt&gt;How to use it&lt;/dt&gt;
   &lt;dd&gt;
&lt;p&gt;There isn't a site with tutorials or formal documentation for Zauber Commons yet, but we are working on that. For now you can browse the source at the SVN repository &lt;a href="https://code.zauber.com.ar/repos/sandbox/components/commons/code/trunk/"&gt;https://code.zauber.com.ar/repos/sandbox/components/commons/code/trunk/&lt;/a&gt;. Also you can use Zauber Commons with a &lt;a href="http://maven.apache.org/"&gt;Maven 2&lt;/a&gt;:

&lt;pre name="code" class="html"&gt;  &amp;lt;repositories&amp;gt;
    &amp;lt;repository&amp;gt;
      &amp;lt;id&amp;gt;zauber-code-releases&amp;lt;/id&amp;gt;
      &amp;lt;name&amp;gt;public zauber repository&amp;lt;/name&amp;gt;
      &amp;lt;url&amp;gt;https://repo1.zauber.com.ar/zauber/code/releases&amp;lt;/url&amp;gt;
      &amp;lt;releases&amp;gt;&amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;&amp;lt;/releases&amp;gt;
      &amp;lt;snapshots&amp;gt;&amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;&amp;lt;/snapshots&amp;gt;
    &amp;lt;/repository&amp;gt;
    &amp;lt;repository&amp;gt;
      &amp;lt;id&amp;gt;zauber-code-snapshots&amp;lt;/id&amp;gt;
      &amp;lt;name&amp;gt;public zauber repository&amp;lt;/name&amp;gt;
      &amp;lt;url&amp;gt;https://repo1.zauber.com.ar/zauber/code/snapshots&amp;lt;/url&amp;gt;
      &amp;lt;releases&amp;gt;&amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;&amp;lt;/releases&amp;gt;
      &amp;lt;snapshots&amp;gt;&amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;&amp;lt;/snapshots&amp;gt;
    &amp;lt;/repository&amp;gt;
  &amp;lt;/repositories&amp;gt;   
&lt;/pre&gt;

And for example add a dependency to your project

 &lt;pre name="code" class="html"&gt;  &amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;ar.com.zauber.commons.web&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;commons-web-version&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;${commons.version}&amp;lt;/version&amp;gt;
 &amp;lt;/dependency&amp;gt;&lt;/pre&gt;

&lt;/dd&gt;
   &lt;dt&gt;Diffstat&lt;/dt&gt;
   &lt;dd&gt;&lt;pre&gt; HttpPagingHelper.java |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
&lt;/pre&gt;&lt;/dd&gt;
&lt;/dl&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7870515310189033933-655207439695231248?l=blog.code.zauber.com.ar' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/655207439695231248/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.code.zauber.com.ar/2009/02/release-zauber-commons-38.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/655207439695231248?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/655207439695231248?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ZauberCode/~3/IoAJnJn4M3s/release-zauber-commons-38.html" title="[RELEASE] Zauber Commons 3.8" /><author><name>Juan F. Codagnone</name><uri>http://www.blogger.com/profile/11600098429143575610</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="16987717536058735653" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.code.zauber.com.ar/2009/02/release-zauber-commons-38.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIDRHo6fCp7ImA9WxVXEk0.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933.post-3582564221758528236</id><published>2009-02-09T15:54:00.001-02:00</published><updated>2009-02-09T16:02:55.414-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-09T16:02:55.414-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="anemic domain model" /><category scheme="http://www.blogger.com/atom/ns#" term="software design" /><category scheme="http://www.blogger.com/atom/ns#" term="programming" /><category scheme="http://www.blogger.com/atom/ns#" term="OOP" /><category scheme="http://www.blogger.com/atom/ns#" term="object oriented programming" /><title>Java, the Anemic Domain Model and how to return to Object Oriented  Programming</title><content type="html">&lt;p&gt;
I've been working in Java for about 7 years and I've changed my mind 
about Java application design many times during this period. However, 
since 2 years ago I think the paradigm adopted to develop applications 
in my team has been pretty the same and this gives me the enough 
confidence to work without thinking much about these issues. The main 
problem I encountered during the past time was the different approaches 
and technologies (&lt;acronym title="Enterprise JavaBeans"&gt;EJBs&lt;/acronym&gt;, &lt;acronym title="Web Services"&gt;WS&lt;/acronym&gt;, &lt;acronym title="Service Oriented Architecture"&gt;SOA&lt;/acronym&gt;, etc). The thing is that none of them gave good guidelines of how to do a good design and addressed mainly 
performance, portability, interoperability among other issues.
&lt;/p&gt;
&lt;p&gt;
As I said, the big problem here was that good desing guidelines were not 
given and I think most of the people working in Java appeared to forget 
that they were working in a Object Oriented Paradigm. In consequence, 
almost every Java application that I encountered was designed in a 
procedural way with most of the logic spreading along the different 
services of the application. This may be a good way to address the low 
coupling and high cohesion concerns but it throws away most of the 
object oriented paradigm benefits, such as inheritance, encapsulation 
and ease of re-usability.
&lt;/p&gt;

&lt;p&gt;
The problem is not entirely of the people that work in Java, but also of 
the language itself that made difficult to use the paradigm correctly 
mainly because of the big differences between objects and classes that 
the language has (in more OO languages like Smalltalk everything is an 
object, classes are objects).
&lt;/p&gt;
&lt;p&gt;
Furthermore, with the proliferation of &lt;acronym title="Inversion of control"&gt;IoC&lt;/acronym&gt; containers (&lt;a href="http://www.springsource.org/about"&gt;Spring&lt;/a&gt;, &lt;a href="http://www.picocontainer.org/"&gt;Pico 
Container&lt;/a&gt;, &lt;a href="http://code.google.com/p/google-guice/"&gt;Guice&lt;/a&gt;, etc), injecting dependencies to services that will be 
injected to controllers or managers became a commodity in this kind of 
applications and Services were converted in the Kings of Objects, 
leaving the Domain Objects very anemic only working as C &lt;tt&gt;struct&lt;/tt&gt;s or 
simply Database representation of the Model. As I said before, this kind 
of design is much less Object Oriented than having real domain objects 
that concentrates their responsibilities and delegates what doesn't 
concerns them, in other words, a truly object oriented system.
&lt;/p&gt;

&lt;p&gt;
Studing Smalltalk and &lt;a href="http://python.org/"&gt;Python&lt;/a&gt;, but also trying to find out a better way 
to program in Java made me realize that the best thing I could do was to 
return to the object oriented way of programming and designing software 
according to this paradigm. At this point some concerns came along, due 
to the nature of the language is not so easy to convert the domain 
objects in first class citizens of a system as it should have been always.
&lt;/p&gt;

&lt;p&gt;
There are some ways to overcome this problem, but I explored 2 with 
great success. The first one is to have Factories for non database 
objects that need some injection in order to provide them with all the 
dependencies they should have complemented with &lt;acronym title="Data Access Object"&gt;DAOs&lt;/acronym&gt; or Generic DAOs 
(a.k.a. Repositories) that also injects those domain objects that comes 
from the database. The other way is to use the &lt;acronym title="Aspect-oriented programming"&gt;AOP&lt;/acronym&gt; features of the 
language and inject those domain objects hanging some VM calls. This is 
a much more advanced technique and I will address the full explanation 
of how to do this in Java using Spring, &lt;a href="http://www.hibernate.org/"&gt;Hibernate&lt;/a&gt; and the &lt;a href="http://www.eclipse.org/aspectj/"&gt;AspectJ&lt;/a&gt; in a later article.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7870515310189033933-3582564221758528236?l=blog.code.zauber.com.ar' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/3582564221758528236/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.code.zauber.com.ar/2009/02/java-anemic-domain-model-and-how-to_09.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/3582564221758528236?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/3582564221758528236?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ZauberCode/~3/Xn1cw6EdkAo/java-anemic-domain-model-and-how-to_09.html" title="Java, the Anemic Domain Model and how to return to Object Oriented  Programming" /><author><name>Martín Andrés Márquez</name><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="17209791597738883599" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.code.zauber.com.ar/2009/02/java-anemic-domain-model-and-how-to_09.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08DQHw7fCp7ImA9WxVQGU4.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933.post-4767908719732941591</id><published>2009-01-28T15:40:00.022-02:00</published><updated>2009-02-06T12:51:11.204-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-06T12:51:11.204-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="about" /><category scheme="http://www.blogger.com/atom/ns#" term="blogger" /><category scheme="http://www.blogger.com/atom/ns#" term="welcome" /><title>How we created this blog</title><content type="html">We believe the best way to inaugurate it is talking about how we created it:
&lt;dl&gt;
&lt;dt&gt;Why are we using Blogger as engine?&lt;/dt&gt;
&lt;dd&gt;We are using Blogger because it was the simplest solution for us. Wordpress doesn't support PostgreSQL and Drupal seems too big for what we need&lt;/dd&gt;
&lt;dt&gt;What widgets are we using?&lt;/dt&gt;
&lt;dd&gt;&lt;ul class="lista"&gt;&lt;li&gt;We are using &lt;a href="http://fazibear.blogspot.com/2007/09/blogger-syntax-higlighter.html"&gt;Syntax Highlighter&lt;/a&gt;. Code snippets will be an important part of this blog and for that reason, they should be usable and look well.&lt;/li&gt;&lt;li&gt;We've implemented &lt;a href="http://en.wikipedia.org/wiki/SIFR"&gt;sIFR&lt;/a&gt; to replace some titles fonts, &lt;a href="http://infodotnet.blogspot.com/2007/12/tips-sifr-custom-fonts-for-blogger.html"&gt;following this tutorial&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Last but not least, we've used Twitter's official badge to add our tweets to the sidebar. More information about it &lt;a href="http://buzz.blogger.com/2007/07/twitter-badge-for-blogger.html"&gt;here&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/dd&gt;
&lt;dt&gt;What about the template?&lt;/dt&gt;
&lt;dd&gt;Well... we started with the simplest template we found: Minima, created by &lt;a href="http://stopdesign.com/portfolio/web/blogger-templates.html?fs=1"&gt;Douglas Bowman&lt;/a&gt;, but we've changed it a lot.&lt;/dd&gt;
&lt;/dl&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7870515310189033933-4767908719732941591?l=blog.code.zauber.com.ar' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/4767908719732941591/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.code.zauber.com.ar/2009/01/hello-world.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/4767908719732941591?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/4767908719732941591?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ZauberCode/~3/OReFoJEaAfM/hello-world.html" title="How we created this blog" /><author><name>Damian Calderon</name><uri>http://www.blogger.com/profile/11694872055620690195</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="09352563823751570984" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.code.zauber.com.ar/2009/01/hello-world.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ENR38zfyp7ImA9WxVQGU4.&quot;"><id>tag:blogger.com,1999:blog-7870515310189033933.post-2678541209343520525</id><published>2009-01-21T12:03:00.001-02:00</published><updated>2009-02-06T12:48:16.187-02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-06T12:48:16.187-02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="about" /><title>¡Hello world!</title><content type="html">&lt;p&gt;

At &lt;a href="http://www.zauber.com.ar/"&gt;Zauber&lt;/a&gt;, every day we deliver solutions and bytes that solves our customers problems. We created this blog, as a place where all Zauberins can share with the community some findings, tips, and experimental projects we develop.
&lt;/p&gt;
&lt;p&gt;Stay tunned!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7870515310189033933-2678541209343520525?l=blog.code.zauber.com.ar' alt='' /&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.code.zauber.com.ar/feeds/2678541209343520525/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://blog.code.zauber.com.ar/2009/01/hello-world_21.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/2678541209343520525?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7870515310189033933/posts/default/2678541209343520525?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ZauberCode/~3/EhbeZjEqbec/hello-world_21.html" title="¡Hello world!" /><author><name>Juan F. Codagnone</name><uri>http://www.blogger.com/profile/11600098429143575610</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="16987717536058735653" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.code.zauber.com.ar/2009/01/hello-world_21.html</feedburner:origLink></entry></feed>
