tag:blogger.com,1999:blog-14089103610647876212024-03-17T01:21:43.868-07:00On Java HellAnother java programmer blog by Julien DechmannJulien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.comBlogger19125tag:blogger.com,1999:blog-1408910361064787621.post-67055910016721879472012-06-18T13:51:00.000-07:002012-06-18T13:51:33.494-07:00The 248 days oracle 10g bugIt was a a day like another at the office. I was working on my software trying to improve it. I was pretty confident that this day will be fine and I could do the work I have to do without being disturb by some production bug.
<br><br>
I was wrong. Happily this doesn't happen to me in production.
<br><br>
Everyday some of my tables are emptied and loaded by scripts using sqlplus client. This day every scripts failed to do their jobs. More than that, I had some processes hanging there and consumming CPU.
<br><br>
After a lot of head scratching, I finally tried to run the sqlplus command on my linux server. Nothing happen and I had to hit Ctrl+C to get the prompt back. And guess what... I had another process doing nothing.
<br><br>
I asked to the database guys of my company and they told me that I probably hit an oracle bug known as bug 4612267.
<br><br>
<b>Oracle client connection will hang and leads to high CPU Utilization when machine uptime > 248 days</b>
<br><br>
Possible solutions :<br>
- reboot<br>
- install patch 4944727<br>Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com6tag:blogger.com,1999:blog-1408910361064787621.post-4735038351138312922010-06-20T04:58:00.000-07:002010-06-24T05:01:26.432-07:00Be warn, The BigDecimal stripTrailingZeros method could have you fired.Not enough people are aware of the flaws of the oracle jdbc driver when using java 5 and BigDecimal (bug# 5527479 and it is fixed in 10.2.0.4). You can see a full example on this <a href="http://www.javalobby.org/java/forums/t88158.html?start=0">thread</a> of the javalobby forums. If you never heard about this bug and you're using an older version of the oracle driver (before 1.2.0.4), you <span style="font-weight:bold;">should </span>really follow the link above.<br /><br />To resume, when instantiating a BigDecimal using its non String constructor, sometimes the driver makes a bad interpretation and insert a bad value in the database. Imagine my surprise, since I'm working on a trading application, when I ran across it. A client bought 2250 shares of a certain company and got only 22 shares. We only saw this the day after when our client complains. Oups... <br /><br />The solution I found was quite simple. We just have to use the String constructor of the BigDecimal. OK.<br /><br />The thing I didn't understand was that I always created my BigDecimal objects using the String constructor. So I should not have run into that bug. <br /><br />My mistake was to use the <span style="font-weight:bold;">stripTrailingZeros</span> method right after I created my BigDecimal objects. This method returns a new Bigdecimal using the BigInteger/scale constructor stripped from its trailing zeros. <br /><br />If you really want to use this method and you cannot upgrade your driver (10.2.0.4 has some issues too), a simple solution is to re-create a new BigDecimal object after calling stripTrailingZeros like this :<br /><pre class="prettyprint" style="overflow: auto;">BigDecimal myNumber = new BigDecimal("2250.0");<br />myNumber = myNumber.stripTrailingZeros();<br />myNumber = new BigDecimal(myNumber.toPlainString());<br /></pre>If you're using iBatis, you can use the solution described <a href="http://rolfje.wordpress.com/2007/01/31/java-5-bigdecimaltostring-and-oracle-10g-jdbc/">here</a>.Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com0tag:blogger.com,1999:blog-1408910361064787621.post-56943950981302640412009-12-04T12:40:00.000-08:002009-12-23T05:14:09.080-08:00Releasing a multi-module project using the maven-release-pluginTo create a release the maven-release-plugin will execute 2 steps: prepare and perform. Let's first describe those steps.<br /><h4>Prepare the release</h4>Preparing a release executes the following steps:<br /><ol><li>Check that there are no uncommitted changes in the sources</li><li>Check that there are no SNAPSHOT dependencies</li><li>Change the version in the poms from x-SNAPSHOT to a new version (you will be prompted for the versions to use)</li><li>Transform the SCM information in the POM to include the final destination of the tag</li><li>Run the project tests against the modified POMs to confirm everything is in working order</li><li>Commit the modified POMs</li><li>Tag the code in the SCM with a version name (this will be prompted for)</li><li>Bump the version in the POMs to a new value y-SNAPSHOT (these values will also be prompted for)</li><li>Commit the modified POMs</li></ol>To execute this step, run<br /><pre class="prettyprint" style="overflow: auto;">mvn release:prepare<br /></pre><h4>Perform the release</h4>Performing a release does the following:<br /><ol><li>Checkout from an SCM URL with optional tag</li><li>Run the predefined Maven goals to release the project (by default, deploy site-deploy)</li></ol>To execute this step, run<br /><pre class="prettyprint" style="overflow: auto;">mvn release:perform</pre><h4>Which strategy to use to release a multi-module project</h4><p>Let's consider a multi-module project with the following architecture :<br /><br />_ project-parent<br />|_ _ project-child-1<br />|_ _ project-child-2<br />...<br />|_ _ project-child-n<br />|_ _ pom.xml<br /><br />The parent project is a POM project and the parent of the other modules.<br /><br />When you have a lot of child modules, the easiest way to release your projects is to release them all at the same time by executing the prepare and perform command at parent level. You certainly don't want to release your modules one at a time because you don't have time for that.<br /><br />There is 2 issues with this strategy :<br /></p><ol><li> The prepare step will fail if it finds any SNAPSHOT dependencies in one of your child module</li><li>If you resolve the first problem, you will be prompted for each child module version. This one is not really a major problem but it can be a pain in the ass if you don't want to use the default versionning.<br /></li></ol><p>The first issue can be resolved by not setting the version of your child module. Remember, every child module inherits the groupId and the version of its parent module.</p><br><p>The second issue can be resolved by setting the <span style="font-weight: bold;">autoversionsubmodules</span> to true in the maven-release-plugin configuration.</p><br /><p>Here's how to define the plugin in the POM file of the parent project :</p><pre class="prettyprint" style="overflow: auto;"><plugin><br /> <groupid>org.apache.maven.plugins</groupid><br /> <artifactid>maven-release-plugin</artifactid><br /> <version>2.0-beta-9</version><br /> <configuration><br /> <goals>deploy</goals><br /> <autoversionsubmodules>true</autoversionsubmodules><br /> </configuration><br /></plugin><br /></pre><br /><p>By setting the autoversionsubmodules to true the maven-release-plugin will not prompt you for the version of your child modules.</p><br /><span style="font-weight: bold;">Tips</span> : The prepare step does a lot of things and you can hesitate to execute the command the first time you're releasing a project. In that case use the DryRun option to simulate what will happen : <pre class="prettyprint" style="overflow: auto;">mvn release:prepare -DdryRun</pre>The DryRun option will create the following files :<br /><br />- pom.xml.next : what the projects pom looks like after the release<br />- pom.xml.releaseBackup : what the pom looked like before<br />- pom.xml.tag : the pom for the tagged version of project<br />- release.properties : the information about the release of the project<br /><br />If you're happy with that, execute the mvn release:clean command to clean the generated files.<br /><br /><span style="font-weight: bold;">Resources </span>:<br /><a href="http://maven.apache.org/plugins/maven-release-plugin/">http://maven.apache.org/plugins/maven-release-plugin/</a><br /><a href="http://maven.apache.org/guides/mini/guide-releasing.html">http://maven.apache.org/guides/mini/guide-releasing.html</a>Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com8tag:blogger.com,1999:blog-1408910361064787621.post-65208253989700917312009-10-24T05:05:00.000-07:002009-10-26T05:45:04.717-07:00Managing and sharing your eclipse configuration with PulsePulse is a tool designed for development teams to share your eclipse configurations. You can create various profiles based on known eclipse builds and add your own plugins from the pulse catalog or an update site. You can even customize the launch arguments and the workspace settings. Once your eclipse profile is ready, you just have to run it and your eclipse installation will be ready in a few minutes with all your plugins and custom settings. Pulse provides a multithreaded download so the installation is quite fast.<br /><br />Here's how to proceed :<br /><br />1. You have to download and install the pulse application from the pulse <a href="http://www.poweredbypulse.com/download_win.php" target="_BLANK">website</a>.<br /><br />2. Create an account.<br /><br />3. Choose your eclipse base bundle from the catalog.<br /><br /><a href="http://dechmann.free.fr/images/pulse_1.jpg" title="Click to enlarge" target="_BLANK"><img height="100%" width="100%" src="http://dechmann.free.fr/images/pulse_1.jpg"></a><br /><br />4. Add your own eclipse plugins from the catalog or from an update site.<br /><br /><a href="http://dechmann.free.fr/images/pulse_2.jpg" title="Click to enlarge" target="_BLANK"><img height="100%" width="100%" src="http://dechmann.free.fr/images/pulse_2.jpg"></a><br /><br />5. The last step is to run your profile.<br /><br /><a href="http://dechmann.free.fr/images/pulse_4.jpg" title="Click to enlarge" target="_BLANK"><img height="100%" width="100%" src="http://dechmann.free.fr/images/pulse_4.jpg"></a><br /><br />Pulse will create an entry in your program files directory where you can find your new eclipse installation. <br /><br />Using Pulse you can customize the launch arguments of your eclipse installation.<br /><br /><a href="http://dechmann.free.fr/images/pulse_3.jpg" title="Click to enlarge" target="_BLANK"><img height="75%" width="75%" src="http://dechmann.free.fr/images/pulse_3.jpg"></a><br /><br />And save your eclipse workspace settings directly from your eclipse installation as shown in the screenshot above.<br /><br /><a href="http://dechmann.free.fr/images/pulse_5.jpg" title="Click to enlarge" target="_BLANK"><img height="100%" width="100%" src="http://dechmann.free.fr/images/pulse_5.jpg"></a>Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com1tag:blogger.com,1999:blog-1408910361064787621.post-11942768394562915292009-09-20T04:51:00.000-07:002009-09-28T04:16:16.587-07:00Monitoring EhCache with JMX and SpringEhCache provides an easy way to manage your caches with JMX. The ManagementService class is the API entry point. You can easily integrate it in your Spring configuration files.<br /><br />Here's how you can do it :<br /><pre class="prettyprint" style="overflow: auto;"><br /> <ehcache:config configLocation="classpath:config/ehcache.xml" failQuietly="true" /><br /> <br /> <ehcache:annotations><br /> <ehcache:caching id="yourCacheModel" cacheName="yourCache"/><br /> </ehcache:annotations><br /> <br /> <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"><br /> <property name="locateExistingServerIfPossible" value="true" /><br /> </bean><br /><br /> <bean class="net.sf.ehcache.management.ManagementService" init-method="init"><br /> <constructor-arg ref="cacheManager" /><br /> <constructor-arg ref="mbeanServer" /><br /> <constructor-arg value="true" /><br /> <constructor-arg value="true" /><br /> <constructor-arg value="true" /><br /> <constructor-arg value="true" /><br /> </bean><br /></pre><br />After doing this, you will have access to your caches configuration and operations such as cache flushing. You will also have access to useful statistics like cache hits, cache misses, object count and some more. These statistics will give you critical information on how to configure your caches for an optimal use. <br /><br />Resources : <br />- <a href="http://ehcache.org/documentation/jmx.html">JMX Management and Monitoring</a> from the ehcache official documentation.Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com8tag:blogger.com,1999:blog-1408910361064787621.post-40225274923794421382009-09-19T03:55:00.000-07:002009-09-22T00:12:53.687-07:00Annotation driven Caching with EhCache and SpringCaching is the key of fast applications. The Spring modules framework provides us with an easy way to cache the return of our methods using java 5 annotations.<br /><br />Here's an example :<br /><br />ehCache.xml :<br /><pre class="prettyprint" style="overflow: auto;"><br /><ehcache><br /> <defaultCache<br /> maxElementsInMemory="500"<br /> eternal="true"<br /> overflowToDisk="false"<br /> memoryStoreEvictionPolicy="LFU" /><br /> <br /> <cache name="getTestCache"<br /> maxElementsInMemory="50"<br /> eternal="true"<br /> overflowToDisk="false"<br /> memoryStoreEvictionPolicy="LFU" /><br /></ehcache><br /><br /></pre><br />applicationContext.xml :<br /><pre class="prettyprint" style="overflow: auto;"><br /><beans xmlns="http://www.springframework.org/schema/beans"<br /> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <br /> xmlns:ehcache="http://www.springmodules.org/schema/ehcache"<br /> xsi:schemaLocation="http://www.springframework.org/schema/beans <br /> http://www.springframework.org/schema/beans/spring-beans-2.5.xsd <br /> http://www.springmodules.org/schema/ehcache <br /> http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd"><br /><br /> <ehcache:config configLocation="classpath:ehcache.xml" /><br /> <ehcache:annotations><br /> <ehcache:caching id="getTestCacheModel" cacheName="getTestCache" /><br /> <ehcache:flushing id="getTestFlushModel" cacheNames="getTestCache" /><br /> </ehcache:annotations><br /><br /> <bean id="customerManager" class="services.impl.CustomerManagerImpl"/><br /> <br /></beans><br /></pre><br />The CustomerManager interface :<br /><pre class="prettyprint" style="overflow: auto;"><br />import org.springmodules.cache.annotations.Cacheable;<br />import org.springmodules.cache.annotations.CacheFlush;<br />import vo.Customer;<br /><br />public interface CustomerManager {<br /> <br /> @Cacheable(modelId="getTestCacheModel")<br /> public Customer load(long customerId);<br /><br /> @CacheFlush(modelId="getTestFlushModel")<br /> public void add(Customer customer);<br />}<br /></pre><br />In order to do a simple test, we create a simple implementation of the CustomerManager interface :<br /><pre class="prettyprint" style="overflow: auto;"><br />import services.CustomerManager;<br />import vo.Customer;<br /><br />public class CustomerManagerImpl implements CustomerManager {<br /> <br /> public Customer load(long customerId) {<br /> //This part should normally call a DAO<br /> return new Customer("Rene", 34);<br /> }<br /><br /> public void add(Customer customer) {<br /> //This part should normally call a DAO<br /> }<br />}<br /></pre><br />And the test class :<br /><pre class="prettyprint" style="overflow: auto;"><br />import org.springframework.context.ApplicationContext;<br />import org.springframework.context.support.ClassPathXmlApplicationContext;<br /><br />import services.CustomerManager;<br /><br />public class Main {<br /><br /> public static void main(String[] args) { <br /> ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");<br /> CustomerManager customerManager = (CustomerManager) context.getBean("customerManager");<br /> <br /> System.err.println("Loading customer");<br /> customerManager.load(455L);<br /> <br /> System.err.println("Loading customer again");<br /> customerManager.load(455L);<br /> <br /> System.err.println("Adding customer");<br /> customerManager.add(new Customer("Jean",34));<br /> }<br />}<br /></pre><br />The final step is to add this simple log4j.properties file to the classpath :<br /><pre class="prettyprint" style="overflow: auto;"><br /># Set root category priority to INFO and its only appender to CONSOLE.<br />log4j.rootCategory=DEBUG, CONSOLE<br /><br /># CONSOLE is set to be a ConsoleAppender using a PatternLayout.<br />log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender<br />log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout<br />log4j.appender.CONSOLE.layout.ConversionPattern=- %m%n<br /></pre><br />Here's the log result of the execution of this class :<br /><pre>Loading customer<br />- Attempt to retrieve a cache entry using key <1187678266|32099260> and cache model <org.springmodules.cache.provider.ehcache.EhCacheCachingModel@14d5bc9[cacheName='getTestCache']><br />- Retrieved cache element <null><br />- Attempt to store the object <Rene> in the cache using key <1187678266|32099260> and model <org.springmodules.cache.provider.ehcache.EhCacheCachingModel@14d5bc9[cacheName='getTestCache']><br />- Object was successfully stored in the cache<br />Loading customer again<br />- Attempt to retrieve a cache entry using key <1187678266|32099260> and cache model <org.springmodules.cache.provider.ehcache.EhCacheCachingModel@14d5bc9[cacheName='getTestCache']><br />- Retrieved cache element <Rene><br />Adding customer<br />- Attempt to flush the cache using model <org.springmodules.cache.provider.ehcache.EhCacheFlushingModel@7cd37a[cacheNames={'getTestCache'}, flushBeforeMethodExecution=false]><br />- Cache has been flushed.<br /></pre><br />We can see that the first time we call the load method, the retrieved Customer object is stored in the cache. The second time, the object is directly retrieved from the cache. When we call the add method the cache is flushed.<br /><br />Here's the maven pom file I used :<br /><br />We'll use the 0.8 version of springmodules, the latest in the maven repo central. This version has dependencies on spring 2.0 and ehcahe 1.1. In order to use the latest library we will add our own version of spring (2.5.6) and ehcache (1.6.2) and excludes the old ones. We have to exclude also all the proprietary libraries which should be optional but are not. <br /><pre class="prettyprint" style="overflow: auto;"><br /><dependencies><br /> <dependency><br /> <groupId>org.springframework</groupId><br /> <artifactId>spring</artifactId><br /> <version>2.5.6</version><br /> </dependency><br /> <dependency><br /> <groupId>net.sf.ehcache</groupId><br /> <artifactId>ehcache</artifactId><br /> <version>1.6.2</version><br /> </dependency><br /> <dependency><br /> <groupId>org.springmodules</groupId><br /> <artifactId>spring-modules-cache</artifactId><br /> <version>0.8</version><br /> <exclusions><br /> <exclusion><br /> <artifactId>gigaspaces-ce</artifactId><br /> <groupId>gigaspaces</groupId><br /> </exclusion><br /> <exclusion><br /> <groupId>jini</groupId><br /> <artifactId>jsk-lib</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jini</groupId><br /> <artifactId>jsk-platform</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jini</groupId><br /> <artifactId>mahalo</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jini</groupId><br /> <artifactId>reggie</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jini</groupId><br /> <artifactId>start</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jini</groupId><br /> <artifactId>boot</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jini</groupId><br /> <artifactId>webster</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jboss</groupId><br /> <artifactId>jboss-cache</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jboss</groupId><br /> <artifactId>jboss-common</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jboss</groupId><br /> <artifactId>jboss-jmx</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jboss</groupId><br /> <artifactId>jboss-minimal</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jboss</groupId><br /> <artifactId>jboss-system</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>jcs</groupId><br /> <artifactId>jcs</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>xpp3</groupId><br /> <artifactId>xpp3_min</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>ehcache</groupId><br /> <artifactId>ehcache</artifactId><br /> </exclusion><br /> <exclusion><br /> <groupId>org.springframework</groupId><br /> <artifactId>spring</artifactId><br /> </exclusion><br /> </exclusions><br /></dependency><br /></dependencies></pre><br /><br />In conclusion, annotation driven Caching with EhCache and Spring is very straightforward to implement.<br /><br /><b>However</b>, be aware that the springmodules framework is in a dead status and have some unresolved issues you should be aware of. You can see those issues listed <a href="http://stubbisms.wordpress.com/2009/04/02/spring-modules-ehcache-and-ehcache-issues-you-should-be-aware-of/">here</a>. Take a look at it before using it though most of the issues have workarounds. There is also a 0.9 version you can only download because it has never been released in the maven central repository. <br /><br />A project named <a href="http://wiki.github.com/astubbs/spring-modules">Spring modules fork</a> has been created to revive this useful project and to make it evoluate. They've created a 0.10-SNAPSHOT version hosted on their own server.Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com11tag:blogger.com,1999:blog-1408910361064787621.post-86795885599254970422009-07-11T02:44:00.000-07:002009-09-03T12:25:44.180-07:00Introducing the Builder Design PatternStatic factories and constructors have limitations when dealing with objects with large numbers of optional parameters. <br /><br />A classic solution is to use multiple constructors. The first constructor will have only the required parameters. The second one, the required parameters and a single optional parameter. The third one, the required parameters and two optional parameter and so one until the last optional parameter. The problem with this solution is that you can easily invert two parameters when constructing the object.<br /><br />Another solution is to use the JavaBean pattern, in which you call the paramterless constructor and call the setter methods to populate your objects. The problem with this pattern is that you cannot enforce consistency. Your objects may be in an inconsistent state if you do not set the required parameters.<br /><br />A third solution is to use the builder design pattern.<br /><br />Here's an interesting implementation of this design pattern described by Joshua Bloch in the book 'Effective Java Second Edition' (which is, by the way, a book to put in every programmer hands).<br /><br />The client calls a constructor with all the required parameters and gets a builder object. Then the client calls methods on the builder object to set each optional parameters. Finally the client calls a build method which generate an instance of the object which is immutable. Immutable objects have a lots of benefits and may be very useful.<br /><pre class="prettyprint" style="overflow: auto;"><br />public class Customer {<br /> <br /> private final String name;<br /> private final String surname;<br /> private final int age;<br /> private final String address;<br /> private final String email;<br /> <br /> public static class Builder {<br /> <br /> //Mandatory parameters<br /> private String name;<br /> private String surname;<br /> <br /> //Optional parameters<br /> private int age;<br /> private String address;<br /> private String email;<br /> <br /> public Builder(String name, String surname) {<br /> this.name = name;<br /> this.surname = surname;<br /> }<br /> <br /> public Builder age(int val) {<br /> age = val;<br /> return this;<br /> }<br /> <br /> public Builder address(String val) {<br /> address = val;<br /> return this;<br /> }<br /> <br /> public Builder email(String val) {<br /> email = val;<br /> return this;<br /> }<br /> <br /> public Customer build() {<br /> return new Customer(this);<br /> }<br /> }<br /> <br /> private Customer(Builder builder) {<br /> name = builder.name;<br /> surname = builder.surname;<br /> age = builder.age;<br /> address = builder.address;<br /> email = builder.email;<br /> }<br />}<br /></pre><br />A good practice is to check the invariants in the build method and send an IllegalStateException if one of the attribute is invalid. This way, you will always be sure that your object is valid after being instantiated.<br /><br />Here's how the client code looks :<br /><pre class="prettyprint" style="overflow: auto;"><br />Customer customer = new Customer.Builder("John", "Doe").age(25).email("johndoe@gmail.com").build();<br /></pre><br />The result is a client code easy to write and read.<br /><br />Resources : <a href="http://www.ibm.com/developerworks/java/library/j-jtp02183.html">To mutate or not to mutate ?</a>Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com17tag:blogger.com,1999:blog-1408910361064787621.post-71272121336416870462009-05-20T02:39:00.000-07:002009-07-17T05:18:18.863-07:00Testing private methods using Reflection- What about testing private methods ? <br />- Hum... You can't because they're private dummy.<br />- And what about using reflection to make them accessible ?<br /><br />Because we don't have access to private methods, we generally don't test them. This can be a weakness in your testing strategy. Private methods are usually a very sensible part of your code. I've have seen a lot of developers modifying the visibility of their code from private to protected. That's a bad practice. Don't change the visibility of your code for testing purposes.<br /><br />A solution consists of using reflection to make these private methods accessible for testing. <br /><br />I really don't like to use reflexion in my application code because if someone is doing some refactoring like renaming a method and forget to update the reflexive code part, you will get a very bad runtime exception. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it.<br /><br />Test code is not application code. Your tests does not go into production, that's why I'm not afraid of using reflection in my test classes. <br /><br />Here's an example :<br /><br />MyClass.java<br /><pre class="prettyprint" style="overflow: auto;"><br />public class MyClass {<br /> <br /> private String myPrivateMethod(Long id) {<br /> //Do something private<br /> return "SomeString_" + id;<br /> }<br />}<br /></pre><br />MyClassTest.java<br /><pre class="prettyprint" style="overflow: auto;"><br />import java.lang.reflect.Method;<br /><br />import static org.junit.Assert.*;<br />import org.junit.Test;<br /><br />public class MyClassTest {<br /> <br /> private MyClass underTest;<br /><br /> @Test<br /> public void testMyPrivateMethod() throws Exception {<br /><br /> underTest = new MyClass();<br /> <br /> Class[] parameterTypes = new Class[1];<br /> parameterTypes[0] = java.lang.Long.class;<br /> <br /> Method m = underTest.getClass().getDeclaredMethod("myPrivateMethod", parameterTypes);<br /> m.setAccessible(true);<br /> <br /> Object[] parameters = new Object[1];<br /> parameters[0] = 5569L;<br /> <br /> String result = (String) m.invoke(underTest, parameters); <br /> <br /> //Do your assertions<br /> assertNotNull(result);<br /> }<br />}<br /></pre>Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com17tag:blogger.com,1999:blog-1408910361064787621.post-52343434529830161392009-05-17T03:50:00.000-07:002009-07-23T14:43:20.915-07:00Integration testing with maven 2.0One thing to keep in mind is that unit tests are not integration tests.<br /><br />The characteristics of unit tests are :<br />- They test your code in isolation<br />- They must be fast because they have to be run a lot of times<br /><br />The problem with unit testing is that even if they cover a lot of your code, you can still have errors on integration when you put all the pieces together. That's why you must create integration tests.<br /><br />The characteristics of integration tests are :<br />- They tests all your pieces of code together.<br />- They are pretty slow because they can be fired in a context like a spring context. They rely on real database or web services.<br /><br />Integration tests are slow so they must not be run in the same phase as unit tests. Unit testing must be run in the maven test phase while integration tests must be run in the maven integration-test phase. The problem is that maven doesn't help you with that.<br /><br />The trick is to customize the maven surefire plugin. You have to write your integration tests in a specific package and exclude them from the execution of the maven test phase. Then, you have to bind the execution of your integration tests to the maven integration-test phase.<br /><br />Here's how you do that :<br /><pre class="prettyprint" style="overflow: auto;"><plugin><br /> <groupId>org.apache.maven.plugins</groupId><br /> <artifactId>maven-surefire-plugin</artifactId><br /> <configuration><br /> <excludes><br /> <exclude>**/integration/*Test.java</exclude><br /> </excludes><br /> </configuration><br /> <executions><br /> <execution><br /> <id>integration-tests</id><br /> <phase>integration-test</phase><br /> <goals><br /> <goal>test</goal><br /> </goals><br /> <configuration><br /> <skip>false</skip><br /> <excludes><br /> <exclude>none</exclude><br /> </excludes><br /> <includes><br /> <include>**/integration/*Test.java</include><br /> </includes><br /> </configuration><br /> </execution><br /> </executions><br /></plugin><br /></pre>A common thing to do is to start a web server like Jetty in the pre-integration-test phase using the <a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin" target="_BLANK">maven-jetty plugin</a>.<br /><pre class="prettyprint" style="overflow: auto;"><plugin><br /> <groupId>org.mortbay.jetty</groupId><br /> <artifactId>maven-jetty-plugin</artifactId><br /> <version>6.1.10</version><br /> <configuration><br /> <contextPath>/yourContextPath</contextPath><br /> </configuration><br /> <executions><br /> <execution><br /> <id>start-jetty</id><br /> <phase>pre-integration-test</phase><br /> <goals><br /> <goal>run-exploded</goal><br /> </goals><br /> <configuration><br /> <scanIntervalSeconds>0</scanIntervalSeconds><br /> <daemon>true</daemon><br /> </configuration><br /> </execution><br /> </executions><br /></plugin><br /></pre><br />You can even populate your database in the pre-integration-test phase with the <a href="http://mojo.codehaus.org/dbunit-maven-plugin/" target="_BLANK">dbunit-maven plugin</a> if you need to add specific test case in your database.<br /><br />Maybe maven 3.0 will improve the integration of integration testing in the maven process. A good solution would be to have something similar to the test phase like a src/it directory where you will put all your integration tests.<br /><br /><b>Updated</b> on July 23, 2009 :<br /><br />Another solution is to use the <a href="http://mojo.codehaus.org/failsafe-maven-plugin/">Maven Failsafe Plugin</a>. The Failsafe Plugin is a fork of the Surefire plugin designed to run integration tests.<br /><br />By default, the Surefire plugin executes **/Test*.java, **/*Test.java, and **/*TestCase.java test classes. The Failsafe plugin will look for **/IT*.java, **/*IT.java, and **/*ITCase.java<br /><br />Take a look at this <a href="http://www.sonatype.com/people/2009/06/integration-tests-with-maven-part-1-failsafe-plugin/">article</a> on Sonatype Blog.Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com14tag:blogger.com,1999:blog-1408910361064787621.post-90846980542812029112009-05-16T07:42:00.000-07:002009-09-22T14:10:03.968-07:00A simple example of the State Design PatternHere's the formal definition of the state design pattern :<br /><blockquote><br /><b>The State Pattern</b> allows an object to alter its behavior when its internal state changes. The object will appear to change its class.<br /></blockquote><br /><br />The UML diagram :<img src="http://upload.wikimedia.org/wikipedia/commons/9/90/State_Design_Pattern_UML_Class_Diagram.png" height="90%" width="90%"><br /><br /><br />If you don't understand this obscure definition nor the UML diagram, don't worry. I made a simple example for you. The state pattern is just a clean way for an object to partially change its type at runtime.<br /><br />Let's take a pizza store. A pizza store is cooking pizza, baking it and delivering it to their clients. Our pizza is the context object with a state.<br /><br />So here's how you do that the old fashion way :<br /><br /><br /><b>Pizza.class</b><br /><pre class="prettyprint" style="overflow: auto;"><br />public class Pizza {<br /> <br /> public final static int COOKED = 0;<br /> public final static int BAKED = 1;<br /> public final static int DELIVERED = 2;<br /> <br /> private String name;<br /> <br /> int state = COOKED;<br /> <br /> public String getName() {<br /> return name;<br /> }<br /> <br /> public void setName(String name) {<br /> this.name = name;<br /> }<br /> <br /> public int getState() {<br /> return state;<br /> }<br /> <br /> public void setState(int state) {<br /> this.state = state;<br /> }<br /> <br /> public void bake() throws Exception {<br /> <br /> if(state == COOKED) {<br /> System.out.print("Baking the pizza...");<br /> state = BAKED;<br /> }<br /> else if(state == BAKED) {<br /> throw new Exception("Can't bake a pizza already baked");<br /> }<br /> else if(state == DELIVERED) {<br /> throw new Exception("Can't bake a pizza already delivered");<br /> }<br /> } <br /> <br /> public void deliver() throws Exception {<br /> <br /> if(state == COOKED) {<br /> throw new Exception("Can't deliver a pizza not baked yet");<br /> }<br /> else if(state == BAKED) {<br /> System.out.print("Delivering the pizza...");<br /> state = DELIVERED;<br /> }<br /> else if(state == DELIVERED) {<br /> throw new Exception("Can't deliver a pizza already delivered");<br /> }<br /> }<br />}<br /></pre><br />The problem with this implementation is that everything is going messy when you have a lot of state. Moreover, the add of a new state is not that simple.<br /><br />Let's see the re-factored example using the State Design Pattern.<br /><br />Firstable, we have to write the state interface. This interface will describe the different transitions.<br /><br /><br /><b>PizzaState.class</b><br /><pre class="prettyprint" style="overflow: auto;"><br />public interface PizzaState {<br /><br /> void bake() throws Exception;<br /><br /> void deliver() throws Exception;<br />}<br /></pre><br />Then, we refactor our Pizza object with our new state interface.<br /><br /><br /><b>Pizza.class</b><br /><pre class="prettyprint" style="overflow: auto;"><br />public class Pizza {<br /> <br /> PizzaState cookedState;<br /> PizzaState bakedState;<br /> PizzaState deliveredState;<br /> <br /> private String name;<br /> <br /> //State initialization<br /> private PizzaState state = cookedState;<br /> <br /> public Pizza() {<br /> cookedState = new CookedPizzaState(this);<br /> bakedState = new BakedPizzaState(this);<br /> deliveredState = new DeliveredPizzaState(this);<br /> }<br /> <br /> public String getName() {<br /> return name;<br /> }<br /><br /> public void setName(String name) {<br /> this.name = name;<br /> }<br /><br /> public PizzaState getState() {<br /> return state;<br /> }<br /><br /> public void setState(PizzaState state) {<br /> this.state = state;<br /> }<br /> <br /> public void bake() throws Exception {<br /> this.state.bake();<br /> } <br /> <br /> public void deliver() throws Exception {<br /> this.state.deliver();<br /> }<br /><br /> public PizzaState getCookedState() {<br /> return createdState;<br /> }<br /><br /> public PizzaState getBakedState() {<br /> return bakedState;<br /> }<br /><br /> public PizzaState getDeliveredState() {<br /> return deliveredState;<br /> }<br />}<br /></pre><br />And last but not least, we write the state implementations.<br /><br /><br /><b>CookedPizzaState.class</b><br /><pre class="prettyprint" style="overflow: auto;"><br />public class CookedPizzaState implements PizzaState {<br /> <br /> private Pizza pizza;<br /> <br /> public CookedPizzaState(Pizza pizza) {<br /> this.pizza = pizza;<br /> }<br /><br /> public void bake() throws Exception {<br /> System.out.print("Baking the pizza...");<br /> pizza.setState(pizza.getBakedState());<br /> }<br /><br /> public void deliver() throws Exception {<br /> throw new Exception("Can't deliver a pizza not baked yet");<br /> }<br /><br />}<br /></pre><br />You still have to write <b>BakedPizzaState.class</b> and the <b>DeliveredPizzaState.class</b>.<br /><br />The state design pattern is one of those you need to know and master. It can help you in complex situations.Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com15tag:blogger.com,1999:blog-1408910361064787621.post-9599011724843011672009-05-16T07:40:00.000-07:002009-07-08T05:24:14.945-07:00Entreprise Integration Pattern with Apache Camel 2.0<a href="http://camel.apache.org/">Apache Camel</a> is an open source messaging routing framework based on the <a href="http://camel.apache.org/enterprise-integration-patterns.html">enterprise integration pattern</a> described in the book of the same name written by Gregor Hohpe and Bobby Woolf.<br /><br />Apache Camel can easily work with any kind of transport or messaging model such as HTTP, JMS, CXF, POP and a lot of others.<br /><br />Camel lets you create the Enterprise Integration Patterns to implement routing and mediation rules in either Java based DSL (Domain Specific Language), via Spring configuration files or via the Scala DSL .<br /><br />Personally, I recommend using the Java DSL which is maybe a bit confusing at first sight but is very powerful in the end. The benefits of using the Java DSL is that your IDE can smart complete your code as you start typing, rather than having to mess around with buckets of XML.<br /><br />Let's try with an example. We have a CSV file containing candidates for a job. Each line represents the candidates characteristics (name, size and age).<br /><br />Our goal is to process this file, find if the candidate is suitable for the job and then send the result in XML into a JMS queue.<br /><br />First, let's create our CSV file named testfile.csv in the src/test/resources directory with the content below :<br /><br />Georges,14,168<br />Alain,58,175<br />Jean,67,168<br /><br />To start our Camel example, we have to create a route by implementing the RouteBuilder interface.<br /><br /><b>CandidateRouteBuilder.java</b><br /><pre class="prettyprint" style="overflow: auto;">package com.jdechmann.proto.camel.route;<br /><br />import java.util.List;<br /><br />import org.apache.camel.builder.RouteBuilder;<br />import org.apache.camel.dataformat.xstream.XStreamDataFormat;<br /><br />import com.jdechmann.proto.vo.Candidate;<br />import com.thoughtworks.xstream.XStream;<br /><br />public class CandidateRouteBuilder extends RouteBuilder {<br /><br />@Override<br />public void configure() throws Exception {<br /><br /> XStream xstream = new XStream();<br /> xstream.processAnnotations(Candidate.class);<br /><br /> XStreamDataFormat xStreamDataFormat = new XStreamDataFormat();<br /> xStreamDataFormat.setXStream(xstream);<br /><br /> //Intercept the exceptions<br /> onException(Exception.class)<br /> .handled(true)<br /> //Convert the object to XML<br /> .marshal(xStreamDataFormat)<br /> //Send the result to a JMS queue<br /> .to("jms:queue.candidate.rejected");<br /><br /> //THE ROUTE STARTS HERE<br /><br /> //Consume from CSV files<br /> from("file:src/test/resources/?fileName=testfile.csv")<br /> //Unmarshal CSV files. The resulting message contains a List<List<String>><br /> .unmarshal().csv()<br /> //Split the message into a number of pieces<br /> .split(body(List.class))<br /> //Convert the message into a Person object<br /> .convertBodyTo(Candidate.class)<br /> //Process the candidates<br /> .process(new CandidateProcessor())<br /> //Convert the object to XML<br /> .marshal(xStreamDataFormat)<br /> //Send the result to a JMS queue<br /> .to("jms:queue.candidate.selected");<br />}<br />}<br /></pre><br />The spring configuration file contains the location of the RouteBuilder classes and the configuration of the JMS broker. You will need to have an activeMQ server running to make this example works.<br /><br /><b>applicationContext.xml</b><br /><pre class="prettyprint" style="overflow: auto;"><?xml version="1.0" encoding="UTF-8"?><br /><beans xmlns="http://www.springframework.org/schema/beans"<br /> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br /> xmlns:context="http://www.springframework.org/schema/context"<br /> xmlns:camel="http://camel.apache.org/schema/spring"<br /> xsi:schemaLocation="<br /> http://www.springframework.org/schema/beans<br /> http://www.springframework.org/schema/beans/spring-beans-2.5.xsd<br /> http://www.springframework.org/schema/context<br /> http://www.springframework.org/schema/context/spring-context-2.5.xsd<br /> http://camel.apache.org/schema/spring<br /> http://camel.apache.org/schema/spring/camel-spring.xsd"><br /><br /><bean id="camelTracer" class="org.apache.camel.processor.interceptor.Tracer"><br /> <property name="traceOutExchanges" value="true" /><br /></bean><br /><br /><bean id="traceFormatter" class="org.apache.camel.processor.interceptor.DefaultTraceFormatter"><br /> <property name="showOutBody" value="true" /><br /> <property name="showOutBodyType" value="true" /><br /></bean> <br /><br /><camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"><br /><package>com.jdechmann.proto.camel.route</package><br /></camelContext><br /><br /><bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent"><br /> <property name="brokerURL" value="tcp://localhost:61616"/><br /></bean><br /><br /></beans><br /></pre><br />Then we have to create our Java business object.<br /><br /><b>Candidate.java</b><br /><pre class="prettyprint" style="overflow: auto;">package com.jdechmann.proto.vo;<br /><br />import com.thoughtworks.xstream.annotations.XStreamAlias;<br /><br />@XStreamAlias("candidate")<br />public class Candidate {<br /><br /> private String name;<br /> private int age;<br /> private int size;<br /><br /> public String getName() {<br /> return name;<br /> }<br /> public void setName(String name) {<br /> this.name = name;<br /> }<br /> public int getAge() {<br /> return age;<br /> }<br /> public void setAge(int age) {<br /> this.age = age;<br /> }<br /> public int getSize() {<br /> return size;<br /> }<br /> public void setSize(int size) {<br /> this.size = size;<br /> }<br /><br /> @Override<br /> public String toString() {<br /> return "Candidate - " + " Name: " + name + <br /> " Age: " + age + " Size: " + size;<br /> }<br />}<br /></pre><br />Here's the processor which have to implement the camel Processor interface.<br />This class will send an exception if the candidate does not fit for the job.<br /><br /><b>CandidateProcessor.java</b><br /><pre class="prettyprint" style="overflow: auto;">package com.jdechmann.proto.camel.route;<br /><br />import org.apache.camel.Exchange;<br />import org.apache.camel.Processor;<br /><br />import com.jdechmann.proto.vo.Candidate;<br /><br />/**<br />* Process a Candidate object<br />* Throw an exception if the candidate does not<br />* match the criterias<br />*/<br />public class CandidateProcessor implements Processor {<br /><br /> @Override<br /> public void process(Exchange exchange) throws Exception {<br /> Candidate candidate = exchange.getIn().getBody(Candidate.class);<br /><br /> if(candidate.getAge() > 60 || candidate.getSize() < 160)<br /> throw new Exception("Candidate refused " + candidate.toString());<br /> else<br /> System.out.println("Candidate accepted " + candidate.toString());<br /> }<br />}<br /></pre><br />In order to convert the message body into a Candidate object, you need to tell Camel where to find your converter class. Camel will look in the classpath for a file named TypeConverter in META-INF/services/org/apache/camel/ directory. The TypeConverter file must contains the name of your package (com.jdechmann.proto.camel.converter in our case).<br /><br /><b>CandidateConverter.java</b><br /><pre class="prettyprint" style="overflow: auto;">package com.jdechmann.proto.camel.converter;<br /><br />import java.util.List;<br /><br />import org.apache.camel.Converter;<br />import com.jdechmann.proto.vo.Candidate;<br /><br />@Converter<br />public class CandidateConverter {<br /><br />@Converter<br />public Candidate toCandidate(List<string> personArray) {<br /><br /> Candidate candidate = new Candidate();<br /> candidate.setName(personArray.get(0));<br /> candidate.setAge(Integer.valueOf(personArray.get(1)));<br /> candidate.setSize(Integer.valueOf(personArray.get(2)));<br /><br /> return candidate;<br />}<br />}<br /></string></pre><br />Finally, here's our Main class to start our route.<br /><br /><b>Main.java</b><br /><pre class="prettyprint" style="overflow: auto;">package com.jdechmann.proto;<br /><br />import org.apache.camel.CamelContext;<br />import org.springframework.context.ApplicationContext;<br />import org.springframework.context.support.ClassPathXmlApplicationContext;<br /><br />public class Main {<br /><br />public static void main(String[] args) throws Exception {<br /> ApplicationContext context =<br /> new ClassPathXmlApplicationContext("applicationContext.xml");<br /><br /> //Starting the camel context<br /> CamelContext camel = (CamelContext) context.getBean("camel");<br /> camel.start();<br />}<br />}<br /></pre><br />If you're using maven, you will need to add the following dependencies to you POM file.<br /><pre class="prettyprint" style="overflow: auto;"><dependency><br /> <groupId>org.apache.camel</groupId><br /> <artifactId>camel-spring</artifactId><br /> <version>2.0-M1</version><br /></dependency><br /><dependency><br /> <groupId>org.apache.camel</groupId><br /> <artifactId>camel-core</artifactId><br /> <version>2.0-M1</version><br /></dependency><br /><dependency><br /> <groupId>org.apache.camel</groupId><br /> <artifactId>camel-jms</artifactId><br /> <version>2.0-M1</version><br /></dependency><br /><dependency><br /> <groupId>org.apache.camel</groupId><br /> <artifactId>camel-csv</artifactId><br /> <version>2.0-M1</version><br /></dependency><br /><dependency><br /> <groupId>org.apache.camel</groupId><br /> <artifactId>camel-xstream</artifactId><br /> <version>2.0-M1</version><br /></dependency><br /></pre>If you want to see the route traces, add log4j in your dependencies<br /><pre class="prettyprint" style="overflow: auto;"><dependency><br /> <groupId>log4j</groupId><br /> <artifactId>log4j</artifactId><br /> <version>1.2.14</version><br /></dependency><br /></pre>And add a log4j.properties in your classpath<br /><br /># Set root category priority to INFO and its only appender to CONSOLE.<br />log4j.rootCategory=DEBUG, CONSOLE<br /><br /># CONSOLE is set to be a ConsoleAppender using a PatternLayout.<br />log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender<br />log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout<br />log4j.appender.CONSOLE.layout.ConversionPattern=- %m%n<br /><br />You can download the code of this example from this <a href="http://dechmann.free.fr/doc/divers/camelTest.zip">URL</a>Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com18tag:blogger.com,1999:blog-1408910361064787621.post-40722169197504379112009-05-11T01:07:00.001-07:002009-05-12T04:45:40.867-07:00Validation of nested properties with Oval 1.3xWhen I used Oval for the first time I didn't realize right away that Oval didn't validate nested properties. <br /><br />At the beginning of the project I was working on, I had simple objects with simple types like String or int. But my objects evolved in a more complex way with nested objects in it. I was very disappointed when I ran my Oval validator and didn't see the outcome I expected. <br /><br />I found the solution on this <a href="http://anydoby.com/jblog/article.htm?id=74" target="_BLANK">blog</a> and customize it a little bit.<br /><br />The solution consists of creating an annotation and a custom validator class which wrap the OVal validator. <br /><br />Here's the implementation.<br /><br />Firstable we have to create the annotation.<br /><pre class="prettyprint" style="overflow: auto;">import java.lang.annotation.ElementType;<br />import java.lang.annotation.Retention;<br />import java.lang.annotation.RetentionPolicy;<br />import java.lang.annotation.Target;<br /><br />@Retention(RetentionPolicy.RUNTIME)<br />@Target(ElementType.FIELD)<br />public @interface ValidateNestedProperty {<br /><br />}<br /></pre>The second step is to wrap the OVal validator into our own Validator class like this :<br /><pre class="prettyprint" style="overflow: auto;">import java.lang.reflect.Field;<br />import java.util.ArrayList;<br />import java.util.List;<br /><br />import net.sf.oval.ConstraintViolation;<br /><br />/**<br /> * Default oval implementation does not validate nested property<br /> * <br /> * @author Julien Dechmann<br /> *<br /> */<br />public class CustomOValValidator {<br /> <br /> private net.sf.oval.Validator validator;<br /> <br /> public CustomOValValidator() {<br /> validator = new net.sf.oval.Validator();<br /> }<br /> <br /> /**<br /> * Process the validation<br /> * @param objectToValidate<br /> */<br /> public List<ConstraintViolation> validate(Object objectToValidate) {<br /> return doValidate(objectToValidate, new ArrayList<ConstraintViolation>() );<br /> }<br /> <br /> private List<ConstraintViolation> doValidate(Object target, List<ConstraintViolation> errors) {<br /> <br /> List<ConstraintViolation> violations = validator.validate(target);<br /> <br /> if(violations != null)<br /> errors.addAll(violations);<br /> <br /> Field[] fields = getFields(target);<br /> <br /> for (Field field : fields) {<br /> ValidateNestedProperty validate = field.getAnnotation(ValidateNestedProperty.class);<br /> <br /> if(validate!=null) {<br /> if (!field.isAccessible()) {<br /> field.setAccessible(true);<br /> }<br /><br /> Object nestedProperty;<br /> <br /> try {<br /> nestedProperty = field.get(target);<br /> } catch (Exception ex) {<br /> throw new RuntimeException("Reflexion error", ex);<br /> }<br /> <br /> if(nestedProperty!=null)<br /> doValidate(nestedProperty, errors); <br /> }<br /> }<br /> return errors;<br /> }<br /> <br /> /**<br /> * Return the list of fields from an object<br /> * @param clazz<br /> * @return<br /> */<br /> @SuppressWarnings("unchecked")<br /> public static Field[] getFields(Object target) {<br /> Class clazz = target.getClass();<br /> return clazz.getDeclaredFields();<br /> }<br />}<br /></pre><br />Let's write a simple example.<br /><br />NestedBusinessObject.java :<br /><pre class="prettyprint" style="overflow: auto;"><br />import net.sf.oval.constraint.NotEmpty;<br />import net.sf.oval.constraint.NotNull;<br /><br />/**<br /> * Nested business object<br /> */<br />public class NestedBusinessObject {<br /> <br /> @NotNull<br /> @NotEmpty<br /> private String property;<br /><br /> public String getProperty() {<br /> return property;<br /> }<br /> public void setProperty(String property) {<br /> this.property = property;<br /> }<br />}<br /></pre>Here's the business object we want to validate :<br /><br />BusinessObject.java<br /><pre class="prettyprint" style="overflow: auto;">import net.sf.oval.constraint.NotEmpty;<br />import net.sf.oval.constraint.NotNull;<br /><br />public class BusinessObject {<br /> <br /> @NotNull<br /> private int id;<br /> <br /> @NotNull<br /> @NotEmpty<br /> private String name;<br /> <br /> @ValidateNestedProperty<br /> private NestedBusinessObject nestedBusinessObject;<br /> <br /> public int getId() {<br /> return id;<br /> }<br /> public void setId(int id) {<br /> this.id = id;<br /> }<br /> public String getName() {<br /> return name;<br /> }<br /> public void setName(String name) {<br /> this.name = name;<br /> }<br /> public NestedBusinessObject getNestedBusinessObject() {<br /> return nestedBusinessObject;<br /> }<br /> public void setNestedBusinessObject(NestedBusinessObject nestedBusinessObject) {<br /> this.nestedBusinessObject = nestedBusinessObject;<br /> }<br />}<br /></pre><br />And the JUnit 4 test class :<br /><pre class="prettyprint" style="overflow: auto;">import java.util.List;<br />import net.sf.oval.ConstraintViolation;<br /><br />import org.junit.Before;<br />import org.junit.Test;<br /><br />public class BuisinessObjectValidationTest {<br /> <br /> private BusinessObject businessObject;<br /> <br /> @Before<br /> public void before() {<br /> businessObject = new BusinessObject();<br /> businessObject.setId(3455);<br /> businessObject.setName("My business object");<br /> <br /> //Since the property of the nestedBusinessObject <br /> //is empty, the validation of the businessObject <br /> //should return a ConstraintViolation<br /> NestedBusinessObject nestedBusinessObject = new NestedBusinessObject();<br /> nestedBusinessObject.setProperty("");<br /><br /> businessObject.setNestedBusinessObject(nestedBusinessObject);<br /> }<br /> <br /> /**<br /> * Test with the OVal validator<br /> */<br /> @Test<br /> public void testValidationWithOvalValidator() {<br /> net.sf.oval.Validator validator = new net.sf.oval.Validator(); <br /> List<ConstraintViolation> violations = validator.validate(businessObject);<br /> <br /> System.out.println("testValidationWithOvalValidator " +<br /> "- Number of errors: "+violations.size());<br /> }<br /> <br /> /**<br /> * Test with the custom validator<br /> */<br /> @Test<br /> public void testValidationWithCustomValidator() {<br /> CustomOValValidator validator = new CustomOValValidator();<br /> List<ConstraintViolation> violations = validator.validate(businessObject);<br /> <br /> System.out.println("testValidationWithCustomValidator " +<br /> "- Number of errors: "+violations.size());<br /> }<br />}<br /></pre><br />The output of the execution of this test is :<br /><pre class="prettyprint" style="overflow: auto;">testValidationWithOvalValidator - Number of errors: 0<br />testValidationWithCustomValidator - Number of errors: 1<br /></pre>The custom validator found 1 error . On the contrary, the OVal validator found none.Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com8tag:blogger.com,1999:blog-1408910361064787621.post-28413364431918149122009-05-10T05:54:00.000-07:002009-06-01T16:00:49.873-07:00Good unit testing with JMock 2Sometimes it can be difficult to unit test objects like services which can return multiple errors. A good unit testing strategy is to test every part of your code. <a href="http://www.jmock.org/" target="_BLANK">JMock</a> can help you do that by mocking your objects and code what they will return. You don't need to create your mock objects anymore.<br /><br />Here's an example. <br /><br />Account.java :<br /><pre class="prettyprint" style="overflow: auto;">package com.jmock.vo;<br /><br />public class Account {<br /> <br /> private String id;<br /> private String name;<br /> private boolean activated;<br /> <br /> public String getId() {<br /> return id;<br /> }<br /> public void setId(String id) {<br /> this.id = id;<br /> }<br /> public String getName() {<br /> return name;<br /> }<br /> public void setName(String name) {<br /> this.name = name;<br /> }<br /> public boolean isActivated() {<br /> return activated;<br /> }<br /> public void setActivated(boolean activated) {<br /> this.activated = activated;<br /> }<br />}<br /></pre><br />AccountServicesImpl.java is the class under test.<br /><br />AccountServicesImpl.java :<br /><pre class="prettyprint" style="overflow: auto;">package com.jmock.services.impl;<br /><br />import org.springframework.beans.factory.annotation.Autowired;<br /><br />import com.jmock.dao.AccountDAO;<br />import com.jmock.general.ErrorConst;<br />import com.jmock.services.exception.AccountServicesException;<br />import com.jmock.vo.Account;<br /><br />public class AccountServicesImpl {<br /> <br /> @Autowired<br /> private AccountDAO accountDAO; //Spring injected<br /> <br /> public Account getAccount(String id) throws AccountServicesException {<br /> Account account = accountDAO.selectAccount(id);<br /> <br /> if(account == null)<br /> throw new AccountServicesException(ErrorConst.ERROR_ACCOUNT_UNKNOWN);<br /> <br /> if(!account.isActivated())<br /> throw new AccountServicesException(ErrorConst.ERROR_ACCOUNT_INACTIVE);<br /> <br /> return account;<br /> }<br />}<br /></pre><br />As you can see, there is 3 scenarios to implement :<br />- The normal test case<br />- The account unknown test case<br />- The account inactive test case<br /><br />And here's the test class.<br /><br />AccountServicesTest.java :<br /><pre class="prettyprint" style="overflow: auto;"><br />import static org.junit.Assert.assertEquals;<br />import static org.junit.Assert.fail;<br /><br />import java.lang.reflect.Field;<br /><br />import org.jmock.Expectations;<br />import org.jmock.Mockery;<br />import org.jmock.integration.junit4.JMock;<br />import org.jmock.integration.junit4.JUnit4Mockery;<br />import org.junit.Before;<br />import org.junit.Test;<br /><br />import com.jmock.dao.AccountDAO;<br />import com.jmock.general.ErrorConst;<br />import com.jmock.services.exception.AccountServicesException;<br />import com.jmock.services.impl.AccountServicesImpl;<br />import com.jmock.vo.Account;<br />import org.junit.runner.RunWith;<br /><br />@RunWith(JMock.class)<br />public class AccountServicesTest {<br /> <br /> //Mock context<br /> private Mockery context;<br /> <br /> private AccountDAO accountDAO;<br /> <br /> private AccountServicesImpl underTest;<br /> <br /> @Before<br /> public void before() throws Exception {<br /> context = new JUnit4Mockery();<br /> accountDAO = context.mock(AccountDAO.class);<br /> <br /> underTest = new AccountServicesImpl();<br /> <br /> //We use reflection to access the private field<br /> Field fieldCurrencyServices = underTest.getClass().getDeclaredField("accountDAO");<br /> fieldCurrencyServices.setAccessible(true);<br /> fieldCurrencyServices.set(underTest, accountDAO);<br /> } <br /> <br /> @Test<br /> public void <b>testGetAccount()</b> {<br /> final Account account = new Account();<br /> account.setId("124110002055");<br /> account.setActivated(true);<br /> <br /> context.checking(new Expectations() {{<br /> oneOf (accountDAO).selectAccount(with(account.getId())); <br /> will(returnValue(account));<br /> }});<br /> <br /> try {<br /> underTest.getAccount(account.getId());<br /> } catch (AccountServicesException ex) {<br /> ex.printStackTrace();<br /> fail("No exception expected");<br /> }<br /> }<br /> <br /> @Test<br /> public void <b>testGetUnknownAccount()</b> {<br /> final Account account = new Account();<br /> account.setId("124110002055");<br /> account.setActivated(true);<br /> <br /> context.checking(new Expectations() {{<br /> oneOf (accountDAO).selectAccount(with(account.getId())); <br /> will(returnValue(null));<br /> }});<br /> <br /> try {<br /> underTest.getAccount(account.getId());<br /> } catch (AccountServicesException ex) {<br /> assertEquals(ErrorConst.ERROR_ACCOUNT_UNKNOWN, ex.getErrorId());<br /> }<br /> }<br /> <br /> @Test<br /> public void <b>testGetInactiveAccount()</b> {<br /> final Account account = new Account();<br /> account.setId("124110002055");<br /> account.setActivated(false);<br /> <br /> context.checking(new Expectations() {{<br /> oneOf (accountDAO).selectAccount(with(account.getId())); <br /> will(returnValue(account));<br /> }});<br /> <br /> try {<br /> underTest.getAccount(account.getId());<br /> } catch (AccountServicesException ex) {<br /> assertEquals(ErrorConst.ERROR_ACCOUNT_INACTIVE, ex.getErrorId());<br /> }<br /> }<br />}<br /></pre><br />Here's are the dependencies you need to add to your pom.xml<br /><pre class="prettyprint" style="overflow: auto;"><dependency><br /> <groupId>org.jmock</groupId><br /> <artifactId>jmock</artifactId><br /> <version>2.5.1</version><br /></dependency><br /><dependency><br /> <groupId>org.jmock</groupId><br /> <artifactId>jmock-junit4</artifactId><br /> <version>2.5.1</version><br /></dependency><br /></pre>Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com5tag:blogger.com,1999:blog-1408910361064787621.post-4632331529264738372009-05-08T09:00:00.001-07:002009-12-30T03:55:53.926-08:00Using the iBATOR eclipse plugin for iBATIS code generationThis tutorial explains how to use the <a href="http://ibatis.apache.org/ibator.html" target="_BLANK">iBATOR</a> eclipse plugin 1.2.0 for iBATIS. <br /><br />iBATOR is a code generator for iBATIS. iBATOR will introspect one or more database table and will generate iBATIS artifacts that can be used to access the tables.<br /><br />iBATOR will generate the following artifacts :<br /><br />- SqlMapXML files (XML files used by iBATIS to map objects and data).<br />- Java model classes (Match the fields of the table).<br />- Dao classes (Implements the CRUD operations).<br /><br />You will still need to hand code SQL and objects for custom queries, or stored procedures.<br /><br />But what happen to your custom SQL queries when you re-launch iBATOR. Don't worry, <b>any hand coded additions to generated Java classes or SqlMap files will remain undisturbed</b>. The eclipse plugin will merge Java and XML Files.<br /><br />Let's start,<br /><br /><b>1.</b> First of all, install the ibator plugin for eclipse using the update site http://ibatis.apache.org/tools/ibator<br /><br /><b>2.</b> Create a simple java project named ibator. if you have multiple projects, it's a good practice to isolate the ibator generation part. Since I use iBATOR in a pretty big financial project, I have multiple maven module like project-persistence, project-core, project-server, etc... I generate the DAO classes in the persistence project and the domain objects in the core project. If you are, like me, writing some customs plugins for iBATOR, you can put these classes in the ibator project and not polluting your other projects.<br /><br /><b>3.</b> Right click on your new ibator project and if the plugin is correctly installed, you'll see the entry 'Add iBATOR to the build path'. Click on it.<br /><br /><b>4.</b> Create the configuration file ibatorConfig.xml<br /><pre class="prettyprint" style="overflow: auto;"><br /><?xml version="1.0" encoding="UTF-8"?><br /><!DOCTYPE ibatorConfiguration<br /> PUBLIC "-//Apache Software Foundation//DTD Apache iBATIS Ibator Configuration 1.0//EN"<br /> "http://ibatis.apache.org/dtd/ibator-config_1_0.dtd"><br /><br /><ibatorConfiguration><br /><ibatorContext <br /> id="ibatorContext" <br /> targetRuntime="Ibatis2Java5" <br /> defaultModelType="flat"><br /><br /><ibatorPlugin type="org.apache.ibatis.ibator.plugins.SerializablePlugin"/><br /><br /><jdbcConnection <br /> driverClass="oracle.jdbc.driver.OracleDriver"<br /> connectionURL="jdbc:oracle:thin:@host:1521:dbname"<br /> userId="user" <br /> password="password"><br /></jdbcConnection><br /><br /><javaModelGenerator targetPackage="com.yourcompany.vo"<br /> targetProject="yourEclipseProject"><br /> <property name="enableSubPackages" value="true" /><br /> <property name="trimStrings" value="true" /><br /></javaModelGenerator><br /><br /><sqlMapGenerator targetPackage="com.yourcompany.dao.ibatis.ibatis.maps"<br /> targetProject="yourEclipseProject"><br /> <property name="enableSubPackages" value="true" /><br /></sqlMapGenerator><br /><br /><daoGenerator type="SPRING" <br />targetPackage="com.yourcompany.dao"<br />implementationPackage="com.yourcompany.dao.ibatis.impl"<br />targetProject="yourEclipseProject"><br /> <property name="enableSubPackages" value="true" /><br /> <property name="methodNameCalculator" value="extended" /><br /></daoGenerator><br /><br /><table tableName="MY_TABLE" domainObjectName="yourObject"><br /><br /></ibatorContext><br /></ibatorConfiguration><br /></pre><br />I use some special properties in this file. To fully understand the configuration file, see the online <a href="http://ibatis.apache.org/docs/tools/ibator/" target="_BLANK">documentation</a>.<br /><br /><b>5.</b> Create a build.xml file at the root of your ibator project.<br /><pre class="prettyprint" style="overflow: auto;"><br /><project default="runIbator"><br /> <br /><target name="runIbator"><br /> <eclipse.convertPath resourcepath="ibator/resources/ibatorConfig.xml" property="thePath"/><br /> <ibator.generate configfile="${thePath}" ></ibator.generate><br /></target><br /> <br /></project><br /></pre><br /><b>6.</b> Create a lib directory and put your ojdbc jar in it.<br /><br /><b>7.</b> Create an external tool to run ibator. Go to Run/External tools/External tools configuration... and create a new Ant build configuration. In the main tab, select your build.xml file in the buildfile part. Add your ojdbc jar file in the classpath tab. In the JRE tab, tick 'Run in the same JRE as the workspace'.<br /><br /><b>8.</b> Run the tool.<br /><br />Another way would be to use the 'Generate Ibatis artifacts' instead of an external tool when you right click on your project. The problem is, in that case, you don't have any control over the classpath. Since I create custom plugins for iBATOR, I need to add these classes to the classpath.<br /><br />To conclude, iBATOR is a great tool if you manage to make it work. It can save you a lot of time at the beginning of a project generating all the DAOs and the domain objects.Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com33tag:blogger.com,1999:blog-1408910361064787621.post-70285871711218271402009-04-13T02:40:00.000-07:002009-05-30T03:46:26.247-07:00Using the Singleton Design Pattern in a multithreaded environmentLet's take a look first at the definition of the Singleton Pattern. <br /><br /><b>The Singleton Pattern</b> ensures a class has only one instance, and provides a global point of access to it. <br /><br />Here the implementation of this definition :<br /><pre class="prettyprint" style="overflow: auto;"><br />public class Singleton {<br /><br /> /** The unique instance **/<br /> private static Singleton instance;<br /> <br /> /** The private constructor **/<br /> private Singleton() {}<br /><br /> public static Singleton getInstance() {<br /> if (instance == null) {<br /> instance = new Singleton();<br /> }<br /> return instance;<br /> }<br />}<br /></pre><br />There is a problem with the code above in a multithreaded environment. Two threads might get ahold of two different instances if they enter at same time in the getInstance method.<br /><br />So how to deal with multithreading ?<br /><br />This problem can be fixed using the synchronized keyword.<br /><pre class="prettyprint" style="overflow: auto;"><br />public class Singleton {<br /><br /> /** The unique instance **/<br /> private static Singleton instance;<br /> <br /> /** The private constructor **/<br /> private Singleton() {}<br /><br /> public static <b>synchronized</b> Singleton getInstance() {<br /> if (instance == null) {<br /> instance = new Singleton();<br /> }<br /> return instance;<br /> }<br />}<br /></pre><br />The getInstance method is now synchronized so we force every threads to wait its turn before it can enter the method. This solution fixes our problem but it is very expensive. Indeed we only need synchronization for the first call. After that synchronization is totally unneeded. Remember that synchronization decreases performance by a factor of 100.<br /><br />A solution consists of relying on the JVM to create our instance when the class is loaded. You can use this solution if the overhead of the creation and runtime aspects of the singleton are not onerous.<br /><pre class="prettyprint" style="overflow: auto;"><br />public class Singleton {<br /><br /> /** The unique instance **/<br /> <b>private static Singleton instance = new Singleton();</b><br /> <br /> /** The private constructor **/<br /> private Singleton() {}<br /><br /> public static Singleton getInstance() {<br /> return instance;<br /> }<br />}<br /></pre>Since Java 1.5, there is a new approach to implement Singletons. Simply make it an enum type :<br /><pre class="prettyprint" style="overflow: auto;"><br />public enum Singleton {<br /><br /> INSTANCE;<br /><br /> //Singleton method<br /> public void someMethod( ) {...}<br />}<br /></pre>Accessing the enum singleton :<br /><pre class="prettyprint" style="overflow: auto;">Singleton.INSTANCE.someMethod( );<br /></pre><br />If you don't want to automatically create an instance of your singleton when the JVM start, there is another solution called "double-checked locking". With this solution, we first check to see if an instance is created and only then we synchronize. This way we only synchronize the first call and there's no performance issue anymore. Another requirement is to use the volatile keyword for the Singleton instance.<br /><pre class="prettyprint" style="overflow: auto;"><br />public class Singleton {<br /><br /> /** The unique instance **/<br /> private <b>volatile</b> static Singleton instance;<br /> <br /> /** The private constructor **/<br /> private Singleton() {}<br /><br /> public static Singleton getInstance() {<br /> <b>if (instance == null) {<br /> synchronized(Singleton.class) {<br /> if (instance == null) {<br /> instance = new Singleton();<br /> }<br /> }<br /> }</b><br /> return instance;<br /> }<br />}<br /></pre><br />!!! This solution will not work in Java 1.4 or earlier. Many JVMs in Java version 1.4 and earlier contains implementation of the volatile keyword that allow improper synchronization fo double checed locking.<br /><br />Here's an interresting <a href="http://www.ibm.com/developerworks/java/library/j-dcl.html" target="_BLANK">article</a> on the double-checked locking pattern and the use of the volatile keyword.<br /><br />Another <a href="http://christophej.developpez.com/tutoriel/java/singleton/multithread/" target="_BLANK">article</a> in french.Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com13tag:blogger.com,1999:blog-1408910361064787621.post-66447629411016941692009-04-12T11:25:00.001-07:002009-05-17T05:24:50.035-07:00How to validate a XML document from a XML schema using javax.xml.validation.ValidatorSince 1.5, you can validate a XML document from a XML schema using the javax.xml.validation.Validator object.<br /><br />Here's a snippet of code showing how to use this validator.<br /><pre class="prettyprint" style="overflow: auto;"><br />import java.io.ByteArrayInputStream;<br />import java.io.File;<br />import java.io.IOException;<br />import java.io.InputStream;<br /><br />import javax.xml.XMLConstants;<br />import javax.xml.parsers.DocumentBuilder;<br />import javax.xml.parsers.DocumentBuilderFactory;<br />import javax.xml.parsers.ParserConfigurationException;<br />import javax.xml.transform.Source;<br />import javax.xml.transform.dom.DOMSource;<br />import javax.xml.validation.Schema;<br />import javax.xml.validation.SchemaFactory;<br /><br />import org.w3c.dom.Document;<br />import org.xml.sax.SAXException;<br /><br /><br />public class Main {<br /><br /> /**<br /> * Will throw a SAXException if the XML document is not valid<br /> * @param args<br /> * @throws ParserConfigurationException<br /> * @throws IOException<br /> * @throws SAXException<br /> */<br /> public static void main(String[] args) throws ParserConfigurationException,<br /> SAXException, IOException {<br /> <br /> String xml = "<test>...</test>";<br /> <br /> //XML parsing<br /> DocumentBuilderFactory docBuilderfactory = DocumentBuilderFactory.newInstance();<br /> DocumentBuilder builder = docBuilderfactory.newDocumentBuilder();<br /> <br /> InputStream is = new ByteArrayInputStream(xml.getBytes());<br /> Document xmlDocument = builder.parse(is);<br /> xmlDocument.getDocumentElement().normalize();<br /> <br /> //XSD parsing<br /> File xsd = new File("src/main/resources/xsd/yourXsd.xsd");<br /> SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);<br /> Schema schema = schemaFactory.newSchema(xsd);<br /> <br /> //Validation<br /> javax.xml.validation.Validator validator = schema.newValidator();<br /> Source source = new DOMSource(xmlDocument);<br /> validator.validate(source);<br /> }<br />}<br /></pre><br />This validator is very verbose. In a real application, a good practice is to create a component encapsulating the code above.Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com0tag:blogger.com,1999:blog-1408910361064787621.post-54684753656244043102009-04-05T04:15:00.000-07:002009-05-17T05:26:05.776-07:00Dependencies injection with Spring annotations (@Repository, @Service, @Autowired)One of the big downfall with frameworks relying on XML configurations file is that they are not synchronized with your code. For example, if you are doing a refactoring of your code like renaming a package or a class, you need to update your XML files too. If you're not, you will end up with a configuration exception at runtime.<br /><br />Spring 2.5 introduces injection dependencies by annotation with stereotypes annotation like @Repository, @Service, etc... and the @Autowired annotation.<br /><br />Here's how you define your beans the old school way :<br /><br />applicationContext.xml :<br /><pre class="prettyprint" style="overflow: auto;"><br /><beans xmlns="http://www.springframework.org/schema/beans"<br />xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</span><br />xsi:schemaLocation="http://www.springframework.org/schema/beans<br />http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"><br /><br /><bean id="beanDAO_1" class="com.yourcompany.dao.BeanDAO_1_Impl"/><br />...<br /><bean id="beanDAO_N" class="com.yourcompany.dao.BeanDAO_N_Impl"/><br /><br /><bean id="beanServices_1" class="com.yourcompany.services.BeanServices_1_Impl"><br /> <property name="beanDAO_1" ref="beanDAO_1"/><br /></bean><br />...<br /><bean id="beanServices_N" class="com.yourcompany.services.BeanServices_N_Impl"><br /> <property name="beanDAO_N" ref="beanDAO_N"/><br /></bean><br /><br /></beans><br /></pre><br />BeanDAO_1_Impl.class :<br /><pre class="prettyprint" style="overflow: auto;"><br />package com.yourcompany.dao.impl;<br /><br />public class BeanDAO_1_Impl implements BeanDAO_1 {<br /> ...<br />}<br /></pre><br />BeanServices_1.class :<br /><pre class="prettyprint" style="overflow: auto;"><br />package com.yourcompany.services.impl;<br /><br />public class BeanServices_1_Impl implements BeanServices_1 {<br /> private BeanDAO_1 beanDAO_1;<br /> ...<br /> public setBeanDAO_1(BeanDAO_1 beanDAO_1) {<br /> this.beanDAO_1 = beanDAO_1;<br /> }<br />}<br /></pre><br /><br />Here's how you define your beans with spring annotations :<br /><br />applicationContext.xml :<br /><pre class="prettyprint" style="overflow: auto;"><br /><beans xmlns="http://www.springframework.org/schema/beans"<br />xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />xmlns:context="http://www.springframework.org/schema/context"<br />xsi:schemaLocation="http://www.springframework.org/schema/beans<br /> http://www.springframework.org/schema/beans/spring-beans-2.5.xsd<br /> http://www.springframework.org/schema/context<br /> http://www.springframework.org/schema/context/spring-context-2.5.xsd"/><br /><br /><context:component-scan base-package="com.yourcompany.dao.impl"/><br /><context:component-scan base-package="com.yourcompany.services.impl"/><br /></beans><br /></pre><br />BeanDAO_1_Impl.class :<br /><pre class="prettyprint" style="overflow: auto;"><br />package com.yourcompany.dao.impl;<br /><br />@Repository("beanDAO_1")<br />public class BeanDAO_1_Impl implements BeanDAO_1 {<br /> ...<br />}<br /></pre><br />BeanServices_1.class :<br /><pre class="prettyprint" style="overflow: auto;"><br />package com.yourcompany.services.impl;<br /><br />@Service("beanServices_1")<br />public class BeanServices_1_Impl implements BeanServices_1 {<br /> @Autowired<br /> private BeanDAO_1 beanDAO_1;<br /> //No need of a setter anymore. Spring can inject the beanDAO_1<br /> //even if it's a private properties<br />}<br /></pre><br />And that's how it's done... No more big XML configuration files.<br /><br />Consult the <a href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-classpath-scanning">spring documentation</a> for a detailed explanation of the differences between the annotation sterotypes (@Repository, @Services, @Component ...)Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com49tag:blogger.com,1999:blog-1408910361064787621.post-29753345961596059912009-04-04T09:01:00.000-07:002009-04-15T12:34:11.427-07:00Object validation by annotations with the OVal framework<a href="http://oval.sourceforge.net/">OVal</a> is a validation framework for any kind of java objects. For example when you want to validate a JavaBean you just have to annotate its properties like this :<br /><br /><pre class="prettyprint" style="overflow: auto;"><br />public class object {<br /> @NotNull<br /> @NotEmpty<br /> @Length(max=32)<br /> private String name;<br />}<br /></pre><br />To process the validation just call the OVal validator :<br /><pre class="prettyprint" style="overflow: auto;"><br />net.sf.oval.Validator validator = new net.sf.oval.Validator();<br />List<constraintviolation> violations = validator.validate(obj);<br /><br />if(!violations.isEmpty())<br />{<br /> //Do whatever you want<br />}<br /></pre><br />In a real world application you need sometimes to return an error code to the client depending on the error type. Do not worry, OVal is doing it for you. Just add the error code property in your annotations like this<br /><pre class="prettyprint" style="overflow: auto;"><br />public class object {<br /> @NotNull(errorCode="46")<br /> ...<br /> private String name;<br />}<br /></pre><br />You can retrieve the error code in each ConstraintViolation object with the getErrorCode() method.<br /><br />OVal does not only validate JavaBeans.<br /><br />By utilizing AspectJ, OVal provides support for several aspects of programming by contract - however it is not a full blown programming by contract implementation.<br /><br />With OVal you can<br /><ul><br /><li>enforce that a parameterized constructor/method is invoked only if the given arguments satisfy prior defined constraints (precondition)<br /></li><br /><li>enforce that a method is invoked only if the object is in a certain state (precondition/invariant)</span></span></li><br /><li>enforce that the return value of a method must satisfy prior defined constraints (postcondition)</li><br /><li>enforce that the object must be in a certain state after a method has been executed (postcondition/invariant)</li><br /></ul><br />I suggest you read the <a href="http://oval.sourceforge.net/userguide.html">user guide</a> for more detailed examples.<br /><br />Here is the list of the OVAL annotations :<br /><span style="font-size:85%;"><span style="font-weight: bold;">Assert</span> Check if evaluating the expression in the specified expression language returns true.<br /><span style="font-weight: bold;">AssertConstraintSet</span> Check if the value satisfies the all constraints of specified constraint set.<br /><span style="font-weight: bold;">AssertFalse </span>Check if the value is false.<br /><span style="font-weight: bold;">AssertFieldConstraints </span>Check if the value satisfies the constraints defined for the specified field.<br /><span style="font-weight: bold;">AssertTrue </span>Check if the value is true.<br /><span style="font-weight: bold;">AssertURL </span>Check if the value is a valid URL.<br /><span style="font-weight: bold;">AssertValid </span>Check if the value passes a validation by Validator.validate().<br /><span style="font-weight: bold;">CheckWith </span>Check the value by a method of the same class that takes the value as argument and returns true if valid and false if invalid.<br /><span style="font-weight: bold;">CheckWithMultiple </span>Check the value with the given CheckWith constraints.<br /><span style="font-weight: bold;">DateRange </span>Check if the date is within the a date range.<br /><span style="font-weight: bold;">EqualToField </span>Check if value equals the value of the referenced field.<br /><span style="font-weight: bold;">Future </span>Check if the date is in the future.<br /><span style="font-weight: bold;">HasSubstring </span>Check if the string contains a certain substring.<br /><span style="font-weight: bold;">InstanceOf </span>Check if the value is an instance of the specified class or implements all specified interfaces.<br /><span style="font-weight: bold;">InstanceOfAny </span>Check if the value is an instance of the specified class or implements one of the specified interfaces.<br /><span style="font-weight: bold;">Length </span>Check if the string representation has certain length.<br /><span style="font-weight: bold;">MatchPattern </span>Check if the specified regular expression pattern is matched.<br /><span style="font-weight: bold;">Max </span>Check if the number is smaller than or equal to X.<br /><span style="font-weight: bold;">MaxLength </span>Check if the string representation does not exceed the given length.<br /><span style="font-weight: bold;">MaxSize </span>Check if an array or collection does not exceed the given size.<br /><span style="font-weight: bold;">MemberOf </span>Check if the string representation is contained in the given string array.<br /><span style="font-weight: bold;">Min </span>Check if the number is greater than or equal to X.<br /><span style="font-weight: bold;">MinLength </span>Check if the string representation has at least the given length.<br /><span style="font-weight: bold;">MinSize </span>Check if the array or collection has at least the given number of elements.<br /><span style="font-weight: bold;">NoSelfReference </span>Check that the value is not a reference to the validated object itself.<br /><span style="font-weight: bold;">NotBlank </span>Check if the string representation is not empty and does not only contain white spaces.<br /><span style="font-weight: bold;">NotEmpty </span>Check if the string representation is not empty ("").<br /><span style="font-weight: bold;">NotEqual </span>Check if the string representation does not equal a given string.<br /><span style="font-weight: bold;">NotEqualToField </span>Check if value does not equal the value of the referenced field.<br /><span style="font-weight: bold;">NotMemberOf </span>Check if the string representation is not contained in the given string array.<br /><span style="font-weight: bold;">NotNegative </span>Check if the number is greater or equal zero.<br /><span style="font-weight: bold;">NotNull </span>Check if not null.<br /><span style="font-weight: bold;">Past </span>Check if the date is in the past.<br /><span style="font-weight: bold;">Range </span>Check if the number is in the given range.<br /><span style="font-weight: bold;">Size </span>Check if the array or collection has the given size.<br /><span style="font-weight: bold;">ValidateWithMethod </span>Check the value by a method of the same class that takes the value as argument and returns true if valid and false if invalid.<br /><br /></span></span></span><span style="font-family:courier new;"><br /></span>Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com4tag:blogger.com,1999:blog-1408910361064787621.post-57349107560131718992009-04-04T08:45:00.000-07:002009-04-04T08:57:41.734-07:00First postI called my blog java hell for a simple reason. Since I began developing in Java, things are getting more and more complicated along the way. Frameworks like Spring, hibernate, EJBs and others appeared. At the beginning, They were designed to simplify our work but in the end people tends to use them even for simple things. Moreover these frameworks are far from perfect and sometimes they are difficult to use due to their complexity and the lack of real examples or documentation.<br /><br />I will share in this blog my experience in software development in order to help people to not make the same errors I did.Julien Dechmannhttp://www.blogger.com/profile/12619192889843922362noreply@blogger.com1