<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2531455513819948701</id><updated>2026-06-10T01:34:11.205-07:00</updated><category term="Spring 3"/><category term="maven"/><category term="Google App Engine"/><category term="unit test"/><category term="TDD"/><category term="GAE"/><category term="JavaScript"/><category term="MVC"/><category term="POM"/><category term="java"/><category term="overlay"/><category term="project"/><category term="DataNucleus"/><category term="JUnit"/><category term="annotations"/><category term="ant"/><category term="deployment"/><category term="fat war"/><category term="integration test"/><category term="jstestdriver"/><category term="skinny war"/><category term="war"/><title type='text'>Mike&#39;s Site</title><subtitle type='html'>A technology blog for those who are passionate for good unit testing (TDD) applied to Spring, Maven, google appengine, PaaS or other Java based web application framework. This blog will focus on both the front-end and backend development and hope to provide some good practices from lessons learned.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.ensor.cc/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>24</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-8964772997788625576</id><published>2016-12-29T11:27:00.001-08:00</published><updated>2016-12-29T11:55:55.339-08:00</updated><title type='text'>Adding microbenchmarking to your build process</title><content type='html'>&lt;h2&gt;
Introduction&lt;/h2&gt;
&lt;div&gt;
As an industry, we are adopting higher transparent and more predictable build processes in order to reduce the risks in building software. &amp;nbsp;One of the core principles of Continuous Delivery is to gather feedback via Feedback Loops. &amp;nbsp;At &lt;a href=&quot;http://www.dev9.com/&quot; target=&quot;_blank&quot;&gt;Dev9&lt;/a&gt;, we have adopted a &quot;&lt;i&gt;first to know&lt;/i&gt;&quot; principle that aligns with the CD principle which means that we (the dev team) wants to be the first to know when there is a failure, degradation of performance or any result not consistent with the business objectives. &lt;br /&gt;
&lt;br /&gt;
Maven and other build tools have provided developers a standardized tool and ecosystem in which to establish and communicate feedback. &amp;nbsp;While unit tests, functional, build acceptance, database migration, performance testing and code analysis tools have become a mainstay in a development pipeline, benchmarking has largely remained outside of the process. &amp;nbsp;This could be due to the lack of open sourced, low cost tooling or lightweight libraries that add minimal complexity. &lt;br /&gt;
&lt;br /&gt;
The existing tools often compound complexity by requiring an outside tool to be integrated with the runtime artifact and the tests are not saved in the same source repository or even stored in a source repository. &amp;nbsp;Local developers are unable to run the benchmarks without effort and therefore the tests lose their value quickly. &amp;nbsp;Adding to the mainstream solution problems, benchmarking is not typically taught in classes and is often implemented without the necessary isolation required to gather credible results. &amp;nbsp;This makes all blogs or posts about benchmark results a ripe target for trolls.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
With all that said, it is still very important to put some sort of benchmark coverage around critical areas of your codebase. &amp;nbsp;Building up historical knowledge about critical sections of code can help influence optimization efforts, inform the team about technical debt, alert when a performance threshold change has been committed and compare previous or new versions of algorithms. &amp;nbsp;The question should now be, how do find and easily add benchmarking to my new or existing project. &amp;nbsp;In this blog, we will focus on Java projects (1.7+). &amp;nbsp;The sample code will utilize Maven, though Gradle works very similarly. &amp;nbsp;I make a few recommendations throughout the blog and they are based on experience from past projects.&amp;nbsp;&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
Introducing JHM&lt;/h3&gt;
There are many strong choices when looking to benchmark Java based code, but most of them have drawbacks that include license fees, additional tooling, byte code manipulation and/or java agents, tests outlined using non-Java based code and highly complex configuration settings. &amp;nbsp;I like to have tests as close to the code under test as possible to reduce brittleness, lower cohesion and reduce coupling. &amp;nbsp;I consider most of the benchmarking solutions I have previously used to be too cumbersome to work with or the code to run the tests are either not isolated enough (literally integrated in the code) or contained in a secondary solution far from the source.&lt;br /&gt;
&lt;br /&gt;
The purpose of this blog is to demonstrate how to add a lightweight benchmarking tool to your build pipeline so I will not go into detail about how to use JMH, the following blogs are excellent sources to learn:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://jmhwiki.blogspot.com/&quot; target=&quot;_blank&quot;&gt;http://jmhwiki.blogspot.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://java-performance.info/jmh/&quot; target=&quot;_blank&quot;&gt;http://java-performance.info/jmh/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/&quot; target=&quot;_blank&quot;&gt;http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h4&gt;
Benchmarking Modes&lt;/h4&gt;
There are a small number of items I want to point out with respect to the modes and scoring as they play an important role in how the base configuration is setup. &amp;nbsp;At a basic level, JMH has two main types of measure: &amp;nbsp;throughput and time-based.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Throughput Measuring&lt;/h4&gt;
Throughput is the amount of operations that can be completed per the unit of time. &amp;nbsp;JMH maintains a collection of successful and failed operations as the framework increases the amount of load on the test. &amp;nbsp;Note: &amp;nbsp;ensure the method or test is well isolated and dependencies like test object creation is done outside of the method or pre-test in a setup method. &amp;nbsp;With Throughput, the higher the value, the better as it indicates that more operations can be run per unit-time.&lt;br /&gt;
&lt;h4&gt;
Time-Based Measuring&lt;/h4&gt;
&lt;div&gt;
Time-based measuring is the counter-partner to throughput. &amp;nbsp;The goal of time-based measuring is to identify how long a particular operation takes to run per unit-time. &amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;AverageTime&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
The most common time-based measurement is the &quot;AverageTime&quot; which calculates the average time of the operation. &amp;nbsp;JMH will also produce a &quot;&lt;b&gt;Score Error&lt;/b&gt;&quot; to help determine confidence in the produced score. &amp;nbsp;The &quot;&lt;b&gt;Score Error&lt;/b&gt;&quot; is typically 1/2 of the confidence interval and indicates how close the results deviated from the average time. &amp;nbsp;The lower the result, the better as it indicates a lower average time to run per operation.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;SampleTime&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
SampleTime is similar to AverageTime, but JMH attempts to push more load and look for failures which produces a matrix of failed percentages. &amp;nbsp;With AverageTime, lower numbers are better and the percentages are useful to determine where you are comfortable with failures due to throughput and length of time.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;b&gt;SingleShotTime&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
The last and least commonly used mode is SingleShotTime. &amp;nbsp;This mode is literally a single run and can be useful for cold testing a method or testing your tests. &amp;nbsp;SingleShotTime could be useful if passed in as a parameter when running benchmarking tests, but reducing the time required to run tests (though, this diminishes the value of the tests and may make them deadweight). &amp;nbsp;As with the rest of the time-based measurements, the lower the value the better.&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
Adding JMH to a Java Project&lt;/h3&gt;
&lt;b&gt;Goal:&lt;/b&gt;&amp;nbsp; This section will show how to create a repeatable harness that allows new tests to be added with minimal overhead or duplication of code. &amp;nbsp;Note, the dependencies are in the &quot;test&quot; scope to avoid JMH being added to the final artifact. &amp;nbsp;I have created a github repository that uses JMH while working on&amp;nbsp;&lt;a href=&quot;http://www.ensor.cc/2016/12/protobuf-alternative-to-rest-for.html&quot; target=&quot;_blank&quot;&gt;Protobuf alternative to REST for Microservices&lt;/a&gt;. &amp;nbsp;The code can be found here:&amp;nbsp;&lt;a href=&quot;https://github.com/mike-ensor/protobuf-serialization&quot; target=&quot;_blank&quot;&gt;https://github.com/mike-ensor/protobuf-serialization&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
1) Start by adding the dependencies to the project:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/mike-ensor/db2b299a46e9019fea448c3bfb535200.js&quot;&gt;&lt;/script&gt;

2) JMH recommends that benchmark tests and the artifact be packaged in the same &lt;i&gt;uber&lt;/i&gt;&amp;nbsp;jar. &amp;nbsp;There are several ways to implement an uber jar, explicitly using the &quot;shade&quot; plugin for maven or implicitly using Spring Boot, Dropwizard or some framework with similar results. &amp;nbsp;For the purposes of this blog post, I have used a Spring Boot application.&lt;br /&gt;
&lt;br /&gt;
3) Add a test harness with a main entry class and global configuration. &amp;nbsp;In this step, create an entry point in the &lt;i&gt;test&lt;/i&gt;&amp;nbsp;area of your project (indicated with &lt;b&gt;&lt;i&gt;#1&lt;/i&gt;&lt;/b&gt;). &amp;nbsp;The intention is to avoid having benchmarking code being packaged with the main artifact.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5vIvqcgEk0jsKjEoM2m1cWOPdtVI4BWazZxtBw3kGF1poLkrnaBYY5740oBvtrifVx3pnKhWQETNJnyJBipvRepK_4k0nkOy7-LSF_fSiAztdNww8nNS0Jf9OphdBZSMKakzi7P7-RzQ/s1600/jmh-folderstructure.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5vIvqcgEk0jsKjEoM2m1cWOPdtVI4BWazZxtBw3kGF1poLkrnaBYY5740oBvtrifVx3pnKhWQETNJnyJBipvRepK_4k0nkOy7-LSF_fSiAztdNww8nNS0Jf9OphdBZSMKakzi7P7-RzQ/s400/jmh-folderstructure.png&quot; width=&quot;345&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
3.1) Add the BenchmarkBase file (indicated above &lt;b&gt;&lt;i&gt;#2&lt;/i&gt;&lt;/b&gt;). &amp;nbsp;This file will serve as the entry point for the benchmark tests and contain all of the global configuration for the tests. &amp;nbsp;The class I have written looks for a &quot;benchmark.properties&quot; file containing configuration properties (indicated above in &lt;b&gt;&lt;i&gt;#3&lt;/i&gt;&lt;/b&gt;). &amp;nbsp;JMH has an option to output file results and this configuration is setup for JSON. &amp;nbsp;The results are used in conjunction with your continuous integration tool and can (should) be stored for historical usage.&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/mike-ensor/849857258283b3b91bdb25761b9d7fa2.js&quot;&gt;&lt;/script&gt;
&lt;small&gt;This code segment is the base harness and entry point into the Benchmark process run by Maven (setup in step #5 below)&lt;/small&gt;

At this point, the project should be able to run a benchmark test, so let&#39;s add a test case.&lt;br /&gt;
&lt;br /&gt;
4) &amp;nbsp;Create a Class to benchmark an operation. &amp;nbsp;Keep in mind, benchmark tests will run against the entirety of the method body, this includes logging, file reading, external resources, etc. &amp;nbsp;Be aware of what you want to benchmark and reduce or remove dependencies in order to isolate your subject code to ensure higher confidence in results. &amp;nbsp;In this example, the configuration setup during&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/mike-ensor/33ed0d2d54d25af10be67276ae6bf896.js&quot;&gt;&lt;/script&gt;

Caption: &amp;nbsp;This gist is a sample benchmark test case extracted from &lt;a href=&quot;https://github.com/mike-ensor/protobuf-serialization&quot; target=&quot;_blank&quot;&gt;Protobuf Serialization&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
All of your *Benchmark*.java test classes will now run when you execute the test jar, but this is often not ideal as the process is not segregated and having some control over when and how the benchmarks are run is important to keeping build times down. &amp;nbsp;Let&#39;s build a Maven profile to control when the benchmarks are run and potentially start the application. &amp;nbsp;Note, for the purposes of showing that maven integration tests start/stop the server, I have included this in the blog post. &amp;nbsp;I would caution the need to start or stop the application server as you might be incurring the costs of resource fetching (REST calls) which would not be very isolated.&lt;br /&gt;
&lt;br /&gt;
5) &amp;nbsp;The concept is to create a maven profile to run all of the benchmark tests in isolation (ie. no unit or functional tests). &amp;nbsp;This will allow the benchmark tests to be run in parallel with the rest of the build pipeline. &amp;nbsp;Note that the code uses the &quot;exec&quot; plugin and runs the &lt;i&gt;uber&lt;/i&gt; jar looking for the full classpath path to the main class. &amp;nbsp;Additionally, the executable scope is only limited to the &quot;test&quot; sources to avoid putting benchmark code into final artifacts.&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/mike-ensor/a1f1bf5891cb533e7eac8f2912d8b37e.js&quot;&gt;&lt;/script&gt;
&lt;small&gt;This code segment shows an example maven profile to run just the Benchmark tests&lt;/small&gt;
&lt;br /&gt;
&lt;br /&gt;
6) &amp;nbsp;Last, optional item is to create a runnable build step in your Continuous Integration build pipeline. &amp;nbsp;In order to run your benchmark tests in isolation, you or your CI can run: &lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/mike-ensor/e1061d981c8f860cbccf79b2833f991e.js&quot;&gt;&lt;/script&gt;

&lt;br /&gt;
&lt;h2&gt;
Conclusion&lt;/h2&gt;
&lt;div&gt;
If you are using a Java based project, JMH is relativly easy to add to your project and pipeline. &amp;nbsp;The benefits of a historical ledger relating to critical areas of your project can be very useful in keeping the quality bar high. &amp;nbsp;Adding JMH to your pipeline also adheres to the Continuous Delivery principles including feedback loops, automation, repeatable, and improving continuously. &amp;nbsp;Consider adding a JMH harness and a few tests to the critical areas of your solution.&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/8964772997788625576/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/8964772997788625576' title='44 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/8964772997788625576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/8964772997788625576'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2016/12/adding-microbenchmarking-to-your-build.html' title='Adding microbenchmarking to your build process'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5vIvqcgEk0jsKjEoM2m1cWOPdtVI4BWazZxtBw3kGF1poLkrnaBYY5740oBvtrifVx3pnKhWQETNJnyJBipvRepK_4k0nkOy7-LSF_fSiAztdNww8nNS0Jf9OphdBZSMKakzi7P7-RzQ/s72-c/jmh-folderstructure.png" height="72" width="72"/><thr:total>44</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-8383577727639360625</id><published>2016-12-26T21:11:00.000-08:00</published><updated>2016-12-27T12:47:35.343-08:00</updated><title type='text'>Protobuf alternative to REST for Microservices</title><content type='html'>&lt;h2&gt;
Introduction&lt;/h2&gt;
A few months ago a colleague and long-time friend of mine published an&amp;nbsp;&lt;a href=&quot;https://www.credera.com/blog/technology-insights/open-source-technology-insights/a-common-pitfall-with-microservice-architectures/&quot; target=&quot;_blank&quot;&gt;intriguing blog on a few of the less discussed costs associated with implementing microservices&lt;/a&gt;. &amp;nbsp;The blog post made several important points on performance when designing and consuming microservices. &amp;nbsp;There is an overhead to using a remote service beyond the obvious network latency due to routing and distance. &amp;nbsp;The blog describes how there is a cost attributed to serialization of JSON and therefore a microservice should do meaningful work to overcome the costs of serialization. &amp;nbsp;While this is a generally accepted guideline for microservices, it is often overlooked and thus a concrete reminder helps to illustrate the point. &amp;nbsp;The second point of interest is the costs associated to the bandwidth size of JSON based RESTful API responses. &amp;nbsp;One potential pitfall of having a more substantive endpoint is that the payload of a response can degrade performance and quickly consume thread pools and overload the network.&lt;br /&gt;
&lt;br /&gt;
These two main points made me think about alternatives and I decided to create an experiment to see if there were benefits from using&amp;nbsp;&lt;a href=&quot;https://developers.google.com/protocol-buffers/&quot; target=&quot;_blank&quot;&gt;Google Protocol Buffers&lt;/a&gt;&amp;nbsp;(aka, &quot;Protobuf&quot; for short) over JSON in RESTful API calls. &amp;nbsp;I set out to show this by first highlighting performance differences between converting JSON using Jackson into POJOs versus Protobuf messages into and out of the a data model. &amp;nbsp;I decided to create a sufficiently complex data model that utilized nested objects, lists and primitives while trying to keep the model simple to understand; &amp;nbsp;Therefore I ended up with a Recipe domain model that I would probably not use in a serious cooking application, but serves the purpose for this experiment.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Test #1: &amp;nbsp;Measure Costs of Serialization and Deserialization&lt;/h4&gt;
The first challenge I encountered was how to work effectively with Protobuf messages. &amp;nbsp;After spending some time reading through sparse documentation that focused on an elementary demonstration of Protobuf messages, I finally decided on a method for converting Messages in and out of my domain model. &amp;nbsp;The preceding statements about using Protobufs is opinionated and someone who uses them often may disagree, but my experience was not smooth and I found messages to be rigid and more difficult than I expected.&lt;br /&gt;
&lt;br /&gt;
The second challenge I encountered came when I wanted to measure the &quot;performance&quot; of both marshaling JSON and Serializing Protobufs. &amp;nbsp;I spent some time learning JMH and designed my plan on how to test both methods. &amp;nbsp;Using JMH, I designed a series of tests that allowed me to populate my POJO model, then construct a method that converted into and out of each of the technologies. &amp;nbsp;I isolated the conversion of the objects in order to capture just the costs associated with conversion.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Test #1: Results&lt;/h4&gt;
My results were not surprising as I expected Protobuf to be more efficient. &amp;nbsp;I measured the average time to marshal an object into JSON at&amp;nbsp;&lt;b&gt;876.754 ns/operation&lt;/b&gt;&amp;nbsp;(±43.222ns) versus&amp;nbsp;&lt;b&gt;148.160 ns/operation&lt;/b&gt;&amp;nbsp;(±6.922ns) showing that equivalent objects converted into Protobuf was nearly&amp;nbsp;&lt;b&gt;6 times&lt;/b&gt;&amp;nbsp;faster than into JSON.&lt;br /&gt;
&lt;br /&gt;
Reversing a JSON and Protobuf message into a POJO yielded slower results and were closer together, but Protobuf still out performed JSON un-marshaling. &amp;nbsp;Converting a JSON string into the domain object took on average&amp;nbsp;&lt;b&gt;2037.075 ns/operation&lt;/b&gt;&amp;nbsp;(±121.997) and Protobuf message to object took on average&amp;nbsp;&lt;b&gt;844.382 ns/operation&lt;/b&gt;&amp;nbsp;(±41.852), nearly&amp;nbsp;&lt;b&gt;2.4 times faster than JSON&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkvnMY8cJ89VLKQrsOqXzXE9YZVF2jGJYjhoL4P-ysrdJFAmiKUyCVmWc8Q-hcj8UlGabGqK5qvEixntdvtZFH0FiZVGgHE_KsH8vr0Solzklbcz2CxbOnusQwBw7QLq6urOfhjGQRlK0/s1600/serialize-vs-deserialize-json-vs-protobuf.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img alt=&quot;JSON vs Protobuf Serialization Graph&quot; border=&quot;0&quot; height=&quot;367&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkvnMY8cJ89VLKQrsOqXzXE9YZVF2jGJYjhoL4P-ysrdJFAmiKUyCVmWc8Q-hcj8UlGabGqK5qvEixntdvtZFH0FiZVGgHE_KsH8vr0Solzklbcz2CxbOnusQwBw7QLq6urOfhjGQRlK0/s400/serialize-vs-deserialize-json-vs-protobuf.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;font-size: 12.8px;&quot;&gt;Serialize/Deserialize times in μSeconds&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEIrdoDg6cSIrWQuwa3kojhwNbHvzsTEj4mXuCBXYdZS4Q3_AAJKAAgqqtgyzFSDcNRkFo8J3yhUfMlX4u-tXAHv87l17KRzP0I9wCqQJp_nImyWwr5NQ8uYgnLwrPuzK-ZKK7RTrZ6v8/s1600/serialize-vs-deserialize-json-vs-protobuf-data.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;JSON Protobuf Data&quot; border=&quot;0&quot; height=&quot;60&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEIrdoDg6cSIrWQuwa3kojhwNbHvzsTEj4mXuCBXYdZS4Q3_AAJKAAgqqtgyzFSDcNRkFo8J3yhUfMlX4u-tXAHv87l17KRzP0I9wCqQJp_nImyWwr5NQ8uYgnLwrPuzK-ZKK7RTrZ6v8/s400/serialize-vs-deserialize-json-vs-protobuf-data.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Run the samples yourself using the github project created for this project:&amp;nbsp;&lt;a href=&quot;https://github.com/mike-ensor/protobuf-serialization&quot; target=&quot;_blank&quot;&gt;https://github.com/mike-ensor/protobuf-serialization&lt;/a&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h4&gt;
Test #2: Bandwidth differences&lt;/h4&gt;
I did not find a straight forward way to capture bandwidth using traditional Java-based tools, so I decided to setup a service on AWS and communicate to the API using JSON and Protobuf requests. &amp;nbsp;I then captured the traffic using Wireshark and calculated the total amount of bytes sent for these requests. &amp;nbsp;I included the headers and payload in the calculation since both JSON and Protobufs require Accepts and Content-Type mime-type headers.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Test #2: Results&lt;/h4&gt;
The total size of the request for the JSON request was 789 bytes versus the Protobuf at 518 bytes. &amp;nbsp;While the JSON request was 45% greater in size than the Protobuf, there was no optimization applied to either request. &amp;nbsp;The JSON was minified but not compressed. &amp;nbsp;Using compression can be detrimental to the overall performance of the solution based on the payload size. &amp;nbsp;If the payload is too small, the cost of compressing and decompressing will overcome the benefits of a smaller payload. &amp;nbsp;This is a very similar problem to the costs associated with marshaling JSON with small payloads as found by Jeremy&#39;s blog.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a alt=&quot;JSON vs Protobuf Payload Sizes&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0Y0FLsNSGo363TcV3ulL3GtqVu_euyVZcBUNLeMVeRc3v_-uTEJi-IxujTie6RAO81zBzWeTqXCpBlNEdUsYY2S69584IlFTmiFkiUOIQl75dJ6obDNPlcjEtOivL8FUyOqOW2couwI8/s1600/protobuf-vs-json-payload-sizes.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;295&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0Y0FLsNSGo363TcV3ulL3GtqVu_euyVZcBUNLeMVeRc3v_-uTEJi-IxujTie6RAO81zBzWeTqXCpBlNEdUsYY2S69584IlFTmiFkiUOIQl75dJ6obDNPlcjEtOivL8FUyOqOW2couwI8/s400/protobuf-vs-json-payload-sizes.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
After completing a project to help determine the overall benefits of using Protobuf over JSON I have come to a conclusion that unless performance is absolutely critical and the developing team&#39;s maturity level is high enough to understand the high costs of using Protobufs, then it is a legitimate option to increase the performance associated with message passing.&amp;nbsp; That being said, the costs of working with Protobufs is very high.&amp;nbsp; Developers lose access to human readable messages often useful during debugging.&amp;nbsp; Additionally, Protobufs are messages, not objects and therefore come with more structure and rigger which I found to be complicated due to the inflexibility using only primitives and enums, and updating messages requires the developer to mark new fields as &quot;optional&quot; for backwards compatibility.&amp;nbsp; Lastly, there is limited documentation on Protocol Buffers beyond the basic &quot;hello world&quot; applications. </content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/8383577727639360625/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/8383577727639360625' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/8383577727639360625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/8383577727639360625'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2016/12/protobuf-alternative-to-rest-for.html' title='Protobuf alternative to REST for Microservices'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkvnMY8cJ89VLKQrsOqXzXE9YZVF2jGJYjhoL4P-ysrdJFAmiKUyCVmWc8Q-hcj8UlGabGqK5qvEixntdvtZFH0FiZVGgHE_KsH8vr0Solzklbcz2CxbOnusQwBw7QLq6urOfhjGQRlK0/s72-c/serialize-vs-deserialize-json-vs-protobuf.png" height="72" width="72"/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-9140121195449366705</id><published>2014-02-02T08:47:00.001-08:00</published><updated>2014-02-02T08:47:39.125-08:00</updated><title type='text'>AES-256 Encryption with Java and JCEKS</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Security has become a great topic of discussion in the last few years due to the recent releasing of documents from &lt;a href=&quot;http://en.wikipedia.org/wiki/Edward_Snowden&quot; target=&quot;_blank&quot;&gt;Edward Snowden&lt;/a&gt; and the explosion of hacking against online commerce stores like &lt;a href=&quot;http://krebsonsecurity.com/2013/07/hacker-ring-stole-160-million-credit-cards/&quot; target=&quot;_blank&quot;&gt;JC Penny&lt;/a&gt;, &lt;a href=&quot;http://www.huffingtonpost.com/2011/05/02/sony-online-entertainment_n_856673.html&quot; target=&quot;_blank&quot;&gt;Sony&lt;/a&gt; and &lt;a href=&quot;http://money.cnn.com/2014/01/10/news/companies/target-hacking/&quot; target=&quot;_blank&quot;&gt;Target&lt;/a&gt;. While this post will not give you all of the tools to help prevent the use of illegally sourced data, this post will provide a starting point for building a set of tools and tactics that will help prevent the use of data by other parties.&lt;/p&gt;

&lt;p&gt;This post will show how to adopt AES encryption for strings in a Java environment.  It will talk about creating AES keys and storing AES keys in a &lt;abbr title=&quot;Java Cryptography Extension Key Store&quot;&gt;JCEKS&lt;/abbr&gt; keystore format. A working example of the code in this blog is located at &lt;a href=&quot;https://github.com/mike-ensor/aes-256-encryption-utility&quot; target=&quot;_blank&quot;&gt;https://github.com/mike-ensor/aes-256-encryption-utility&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is recommended to read each section in order because each section builds off of the previous section, however, this you might want to just jump quickly jump to a particular section.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#setup&quot;&gt;Setup&lt;/a&gt; - Setup and create keys with keytool&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#encrypt&quot;&gt;Encrypt&lt;/a&gt; - Encrypt messages using byte[] keys&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#decrypt&quot;&gt;Decrypt&lt;/a&gt; - Decrypt messages using same IV and key from encryption&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#obtainkey&quot;&gt;Obtain Keys from Keystore&lt;/a&gt; - Obtain keys from keystore via an alias&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;


&lt;h3&gt;What is JCEKS?&lt;/h3&gt;
&lt;p&gt;
JCEKS stands for &lt;strong&gt;J&lt;/strong&gt;ava &lt;strong&gt;C&lt;/strong&gt;ryptography &lt;strong&gt;E&lt;/strong&gt;xtension &lt;strong&gt;K&lt;/strong&gt;ey&lt;strong&gt;S&lt;/strong&gt;tore and it is an alternative keystore format for the Java platform.  Storing keys in a KeyStore can be a measure to prevent your encryption keys from being exposed.  Java KeyStores securely contain individual certificates and keys that can be referenced by an alias for use in a Java program.  Java KeyStores are often created using the &quot;&lt;a href=&quot;http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html&quot; target=&quot;_blank&quot; title=&quot;Java JDK keytool documentation&quot;&gt;keytool&lt;/a&gt;&quot; provided with the Java JDK.&lt;/p&gt;
&lt;p&gt;
NOTE: It is strongly recommended to create a complex passcode for KeyStores to keep the contents secure. The KeyStore is a file that is considered to be public, but it is advisable to not give easy access to the file.
&lt;/p&gt;


&lt;a name=&quot;setup&quot; id=&quot;setup&quot;&gt;&lt;/a&gt;
&lt;h2&gt;Setup&lt;/h2&gt;
&lt;p&gt;
All encryption is governed by laws of each country and often have restrictions on the strength of the encryption.  One example is that in the United States, all encryption over 128-bit is restricted if the data is traveling outside of the boarder.  By default, the Java JCE implements a strength policy to comply with these rules. If a stronger encryption is preferred, and adheres to the laws of the country, then the JCE needs to have access to the stronger encryption policy.  Very plainly put, if you are planning on using AES 256-bit encryption, you &lt;strong&gt;must&lt;/strong&gt; install the &lt;a href=&quot;http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html&quot; target=&quot;_blank&quot;&gt;Unlimited Strength Jurisdiction Policy Files&lt;/a&gt;. Without the policies in place, 256-bit encryption is not possible.
&lt;/p&gt;
&lt;h3&gt;Installation of JCE Unlimited Strength Policy&lt;/h3&gt;
&lt;p&gt;
This post is focusing on the keys rather than the installation and setup of the JCE.  The installation is rather simple with explicit instructions &lt;a href=&quot;http://suhothayan.blogspot.com/2012/05/how-to-install-java-cryptography.html&quot; target=&quot;_blank&quot;&gt;found here&lt;/a&gt; (NOTE: this is for JDK7, if using a different JDK, search for the appropriate JCE policy files).
&lt;/p&gt;
&lt;h3&gt;Keystore Setup&lt;/h3&gt;
&lt;p&gt;
When using the KeyTool manipulating a keystore is simple.  Keystores must be created with a link to a new key or during an import of an existing keystore.  In order to create a new key and keystore simply type:
&lt;pre  class=&quot;Cpp&quot; name=&quot;code&quot;&gt;keytool -genseckey -keystore aes-keystore.jck -storetype jceks -storepass mystorepass -keyalg AES -keysize 256 -alias jceksaes -keypass mykeypass 
&lt;/pre&gt;
&lt;/p&gt;
&lt;h4&gt;Important Flags&lt;/h4&gt;
&lt;p&gt;In the example above here are the explanations for the keytool&#39;s parameters:&lt;br/&gt;

&lt;h4&gt;Keystore Parameters&lt;/h4&gt;
&lt;dl&gt;
  &lt;dt&gt;genseckey&lt;/dt&gt;
    &lt;dd&gt;Generate SecretKey. This is the flag indicating the creation of a synchronous key which will become our AES key&lt;/dd&gt;
  &lt;dt&gt;keystore&lt;/dt&gt;
    &lt;dd&gt;Location of the keystore.  If the keystore does not exist, the tool will create a new store. Paths can be relative or absolute but must be local&lt;/dd&gt;
  &lt;dt&gt;storetype&lt;/dt&gt;
    &lt;dd&gt;this is the type of store (JCE, PK12, JCEKS, etc). JCEKS is used to store symmetric keys (AES) not contained within a certificate.&lt;/dd&gt;
  &lt;dt&gt;storepass&lt;/dt&gt;
    &lt;dd&gt;password related to the keystore.  Highly recommended to create a strong passphrase for the keystore&lt;/dd&gt;
&lt;/dl&gt; 

&lt;h4&gt;Key Parameters&lt;/h4&gt;
&lt;dl&gt;
  &lt;dt&gt;keyalg&lt;/dt&gt;
    &lt;dd&gt;algorithm used to create the key (AES/DES/etc)&lt;/dd&gt;
  &lt;dt&gt;keysize&lt;/dt&gt;
    &lt;dd&gt;size of the key (128, 192, 256, etc)&lt;/dd&gt;
  &lt;dt&gt;alias&lt;/dt&gt;
    &lt;dd&gt;alias given to the newly created key in which to reference when using the key&lt;/dd&gt;
  &lt;dt&gt;keypass&lt;/dt&gt;
    &lt;dd&gt;password protecting the use of the key&lt;/dd&gt;
&lt;/dl&gt;
&lt;/p&gt;

&lt;a name=&quot;encrypt&quot; id=&quot;encrypt&quot;&gt;&lt;/a&gt;
&lt;h2&gt;Encrypt&lt;/h2&gt;
&lt;p&gt;
As it pertains to data in Java and at the most basic level, encryption is an algorithmic process used to programmatically obfuscate data through a reversible process where both parties have information pertaining to the data and how the algorithm is used.  In Java encryption, this involves the use of a Cipher.  A Cipher object in the JCE is a generic entry point into the encryption provider typically selected by the algorithm. This example uses the default Java provider but would also work with Bouncy Castle.
&lt;/p&gt;
&lt;h4&gt;Generating a Cipher object&lt;/h4&gt;
&lt;p&gt;
Obtaining an instance of Cipher is rather easy and the same process is required for both encryption and decryption. (NOTE: Encryption and Decryption require the same algorithm but do not require the same object instance)
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;Cipher cipher = Cipher.getInstance(&quot;AES/CBC/PKCS5Padding&quot;);
&lt;/pre&gt;
Once we have an instance of the Cipher, we can encrypt and decrypt data according to the algorithm.  Often the algorithm will require additional pieces of information in order to encrypt/decrypt data.  In this example, we will need to pass the algorithm the bytes containing the key and an initial vector (explained below).&lt;/p&gt;
&lt;h4&gt;Initialization&lt;/h4&gt;
&lt;p&gt;
In order to use the Cipher, we must first initialize the cipher. This step is necessary so we can provide additional information to the algorithm like the AES key and the Initial Vector (aka IV).
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;cipher.init(Cipher.ENCRYPT_MODE, secretKeySpecification, initialVector);&lt;/pre&gt;
&lt;/p&gt;
&lt;h4&gt;Parameters&lt;/h4&gt;
&lt;p&gt;
The SecretKeySpecification is an object containing a reference to the bytes forming the AES key. The AES key is nothing more than a specific sized byte array (256-bit for AES 256 or 32 bytes) that is generated by the &lt;em&gt;keytool&lt;/em&gt; (see above). 
&lt;/p&gt;
&lt;h4&gt;Alternative Parameteters&lt;/h4&gt;
&lt;p&gt;
There are multiple methods to create keys such as a hash including a salt, username and password (or similar). This method would utilize a SHA1 hash of the concatenated strings, convert to bytes and then truncate result to the desired size. This post will not show the generation of a key using this method or the use of a PBE key method using a password and salt. The password and/or salt usage for the keys is handled by the &lt;em&gt;keytool&lt;/em&gt; using the inputs during the creation of new keys.
&lt;/p&gt;
&lt;h4&gt;Initialization Vector&lt;/h4&gt;
&lt;p&gt;
The AES algorithm also requires a second parameter called the &lt;strong&gt;I&lt;/strong&gt;nitialiation &lt;strong&gt;V&lt;/strong&gt;ector.  The &lt;a href=&quot;http://en.wikipedia.org/wiki/Initialization_vector&quot; target=&quot;_blank&quot;&gt;IV&lt;/a&gt; is used in the process to randomize the encrypted message and prevent the key from easy guessing.  The IV is considered a publicly shared piece of information, but again, it is not recommended to openly share the information (for example, it wouldn&#39;t be wise to post it on your company&#39;s website).  When encrypting a message, it is not uncommon to prepend the message with the IV since the IV will be a set/known size based on the algorithm.  NOTE: the AES algorithm will output the same result if using the same IV, key and message. It is recommended that the IV be randomly created &lt;strong&gt;each time&lt;/strong&gt; an encryption takes place.
&lt;/p&gt;
&lt;p&gt;
With the newly initialized Cipher, encrypting a message is simple.  Simply call:
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;byte[] encryptedMessageInBytes = Cipher.doFinal((message.getBytes(&quot;UTF-8&quot;));
String base64EncodedEncryptedMsg = BaseEncoding.base64().encode(encryptedMessageInBytes);
String base32EncodedEncryptedMsg = BaseEncoding.base32().encode(encryptedMessageInBytes);
&lt;/pre&gt;
&lt;/p&gt;
&lt;h4&gt;Encoding Results&lt;/h4&gt;
&lt;p&gt;
Byte arrays are difficult to visualize since they often do not form characters in any charset. The best recommendation to solve this is to represent the bytes in &lt;a href=&quot;http://en.wikipedia.org/wiki/Base16&quot; target=&quot;_blank&quot;&gt;HEX (base-16)&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Base32&quot; target=&quot;_blank&quot;&gt;Double HEX (base-32)&lt;/a&gt; or &lt;a href=&quot;http://en.wikipedia.org/wiki/Base64&quot; target=&quot;_blank&quot;&gt;Base64&lt;/a&gt; format.  If the message will be passed via a URL or POST parameter, be sure to use a web-safe Base64 encoding. &lt;a href=&quot;http://code.google.com/p/guava-libraries/&quot; target=&quot;_blank&quot;&gt;Google Guava&lt;/a&gt; library provides a excellent &lt;a href=&quot;http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/io/BaseEncoding.html&quot; target=&quot;_blank&quot;&gt;BaseEncoding utility&lt;/a&gt;. NOTE: Remember to decode the encoded message before decrypting.
&lt;/p&gt;

&lt;a name=&quot;decrypt&quot; id=&quot;decrypt&quot;&gt;&lt;/a&gt;
&lt;h2&gt;Decrypt&lt;/h2&gt;
&lt;p&gt;
Decrypting a message is almost a reverse of the encryption process with a few exceptions. Decryption requires a known initialization vector as a parameter unlike the encryption process generating a random IV.
&lt;/p&gt;
&lt;h4&gt;Decryption&lt;/h4&gt;
&lt;p&gt;When decrypting, obtain a cipher object with the same process as the encryption method.  The Cipher object will need to utilize the exact same algorithm including the method and padding selections.  Once the code has obtained a reference to a Cipher object, the next step is to initialize the cipher for decryption and pass in a reference to a key and the initialization vector.
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;// key is the same byte[] key used in encryption
SecretKeySpec secretKeySpecification = new SecretKeySpec(key, &quot;AES&quot;);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpecification, initialVector);&lt;/pre&gt;
&lt;small&gt;NOTE: The &lt;em&gt;key&lt;/em&gt; is stored in the keystore and obtained by the use of an &lt;em&gt;alias&lt;/em&gt;. See below for details on obtaining keys from a keystore&lt;/small&gt;
&lt;/p&gt;
&lt;p&gt;
Once the cipher has been provided the key, IV and initialized for decryption, the cipher is ready to perform the decryption.
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;byte[] encryptedTextBytes = BaseEncoding.base64().decode(message);
byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
String origMessage = new String(decryptedTextBytes);
&lt;/pre&gt;
&lt;/p&gt;
&lt;h4&gt;Strategies to keep IV&lt;/h4&gt;
&lt;p&gt;
The IV used to encrypt the message is important to decrypting the message therefore the question is raised, how do they stay together.  One solution is to Base Encode (see above) the IV and prepend it to the encrypted and encoded message: Base64UrlSafe(myIv) + delimiter + Base64UrlSafe(encryptedMessage).  Other possible solutions might be contextual such as including an attribute in an XML file with the IV and one for the alias to the key used.
&lt;/p&gt;
&lt;a name=&quot;obtainkey&quot; id=&quot;obtainkey&quot;&gt;&lt;/a&gt;
&lt;h2&gt;Obtain Key from Keystore&lt;/h2&gt;
&lt;p&gt;
The beginning of this post has shown how easy it is to create new AES-256 keys that reference an alias inside of a keystore database. The post then continues on how to encrypt and decrypt a message given a key, but has yet shown how to obtain a reference to the key in a keystore.
&lt;/p&gt;
&lt;h4&gt;Solution&lt;/h4&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;// for clarity, ignoring exceptions and failures
InputStream keystoreStream = new FileInputStream(keystoreLocation);

KeyStore keystore = KeyStore.getInstance(&quot;JCEKS&quot;);
keystore.load(keystoreStream, keystorePass.toCharArray());

if (!keystore.containsAlias(alias)) {
    throw new RuntimeException(&quot;Alias for key not found&quot;);
}

Key key = keystore.getKey(alias, keyPass.toCharArray());
&lt;/pre&gt;
&lt;h4&gt;Parameters&lt;/h4&gt;
&lt;dl&gt;
  &lt;dt&gt;keystoreLocation&lt;/dt&gt;
    &lt;dd&gt;String - Location to local keystore file location&lt;/dd&gt;
  &lt;dt&gt;keypass&lt;/dt&gt;
    &lt;dd&gt;String - Password used when creating or modifying the keystore file with keytool (see above)&lt;/dd&gt;
  &lt;dt&gt;alias&lt;/dt&gt;
    &lt;dd&gt;String - Alias used when creating new key with keytool (see above)&lt;/dd&gt;
&lt;/dl&gt; 

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;
This post has shown how to encrypt and decrypt string based messages using the AES-256 encryption algorithm.  The keys to encrypt and decrypt these messages are held inside of a JCEKS formatted KeyStore database created using the JDK provided &quot;keytool&quot; utility.  The examples in this post should be considered a solid start to encrypting/decrypting symmetric keys such as AES.  This should not be considered the only line of defense when encrypting messages, for example key rotation.  Key rotation is a method to mitigate risks in the event of a data breach.  If an intruder obtains data and manages to hack a single key, the data contained in multiple files should have used several keys to encrypt the data thus bringing down risk of a total exposure loss.
&lt;/p&gt;
&lt;p&gt;
All of the examples in this blog post have been condensed into a simple tool allowing for the viewing of keys inside of a keystore, an operation that is not supported out of the box by the JDK keytool.  Each aspect of the steps and topics outlined in this post are available at: &lt;a href=&quot;https://github.com/mike-ensor/aes-256-encryption-utility&quot; target=&quot;_blank&quot;&gt;https://github.com/mike-ensor/aes-256-encryption-utility&lt;/a&gt;.  NOTE: The examples, sample code and any reference is to be used at the sole implementers risk and there is no implied warranty or liability, you assume all risks.
&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/9140121195449366705/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/9140121195449366705' title='108 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/9140121195449366705'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/9140121195449366705'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2014/02/aes-256-encryption-with-java-and-jceks.html' title='AES-256 Encryption with Java and JCEKS'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>108</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-6115993544369274166</id><published>2013-01-22T23:14:00.000-08:00</published><updated>2013-01-22T23:14:22.041-08:00</updated><title type='text'>How to Publish Maven Site Docs to BitBucket or GitHub Pages</title><content type='html'>&lt;h3&gt;Introduction&lt;/h3&gt;
&lt;p&gt;
In this post we will Utilize GitHub and/or BitBucket&#39;s static web page hosting capabilities to publish our project&#39;s Maven 3 Site Documentation. Each of the two SCM providers offer a slightly different solution to host static pages. The approach spelled out in this post would also be a viable solution to &quot;backup&quot; your site documentation in a supported SCM like Git or SVN. This solution does not directly cover site documentation deployment covered by the maven-site-plugin and the Wagon library (scp, WebDAV or FTP).
&lt;/p&gt;
&lt;p&gt;
There is one main project hosted on GitHub that I have posted with the full solution. The project URL is &lt;a href=&quot;https://github.com/mike-ensor/clickconcepts-master-pom/&quot; target=&quot;_blank&quot;&gt;https://github.com/mike-ensor/clickconcepts-master-pom/&lt;/a&gt;. The POM has been pushed to Maven Central and will continue to be updated and maintained.
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;
&amp;lt;parent&amp;gt;
    &amp;lt;groupId&amp;gt;com.clickconcepts.project&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;master-site-pom&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;0.16&amp;lt;/version&amp;gt;
&amp;lt;/parent&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;

&lt;h3&gt;GitHub Pages&lt;/h3&gt;
&lt;p&gt;GitHub hosts static pages by using a special branch &quot;gh-pages&quot; available to each GitHub project. This special branch can host any HTML and local resources like JavaScript, images and CSS. There is no server side development. &lt;/p&gt;
&lt;p&gt;
To navigate to your static pages, the URL structure is as follows:&lt;br/&gt;
&lt;pre&gt;http://&amp;lt;some-username&amp;gt;.github.com/&amp;lt;project-name&amp;gt;&lt;/pre&gt;

An example of the project I am using in this blog post: &lt;a href=&quot;http://mike-ensor.github.com/clickconcepts-master-pom/index.html&quot; target=&quot;_blank&quot;&gt;http://&lt;strong&gt;mike-ensor&lt;/strong&gt;.github.com/&lt;strong&gt;clickconcepts-master-pom&lt;/strong&gt;/&lt;/a&gt; where the first &lt;strong&gt;bold&lt;/strong&gt; URL segment is a username and the second &lt;strong&gt;bold&lt;/strong&gt; URL segment is the project.
&lt;/p&gt;
&lt;p&gt;
GitHub does allow you to create a base static hosted static site for your username by creating a repository with your &lt;strong&gt;username&lt;/strong&gt;.github.com.  The contents would be all of your HTML and associated static resources. This is not required to post documentation for your project, unlike the BitBucket solution.
&lt;/p&gt;
&lt;p&gt;
There is a GitHub Site plugin that publishes site documentation via GitHub&#39;s object API but this is outside the scope of this blog post because it does not provide a single solution for GitHub and BitBucket projects using Maven 3.
&lt;/p&gt;

&lt;h3&gt;BitBucket&lt;/h3&gt;
&lt;p&gt;
BitBucket provides a similar service to GitHub in that it hosts static HTML pages and their associated static resources. However, there is one large difference in how those pages are stored. Unlike GitHub, BitBucket requires you to create a new repository with a name fitting the convention. The files will be located on the &lt;em&gt;master&lt;/em&gt; branch and each project will need to be a directory off of the root.
&lt;/p&gt;
&lt;pre&gt;
mikeensor.bitbucket.org/
     /some-project
      +index.html
      +...
          /css
          /img
     /some-other-project
      +index.html
      +...
          /css
          /img
index.html
.git
.gitignore
&lt;/pre&gt;
&lt;p&gt;
The naming convention is as follows:
&lt;pre&gt;&amp;lt;username&amp;gt;.bitbucket.org&lt;/pre&gt;
An example of a BitBucket static pages repository for me would be: &lt;a href=&quot;http://mikeensor.bitbucket.org/&quot; target=&quot;_blank&quot;&gt;http://mikeensor.bitbucket.org/&lt;/a&gt;. The structure does not require that you create an index.html page at the root of the project, but it would be advisable to avoid 404s. 
&lt;/p&gt;

&lt;h3&gt;Generating Site Documentation&lt;/h3&gt;
&lt;p&gt;
Maven provides the ability to post documentation for your project by using the &lt;em&gt;maven-site-plugin&lt;/em&gt;. This plugin is difficult to use due to the many configuration options that oftentimes are not well documented. There are many blog posts that can help you write your documentation including &lt;a href=&quot;http://www.ensor.cc/2012/03/maven-3-site-docs-part-1-basic-site.html&quot;&gt;my post on maven site documentation&lt;/a&gt;. I did not mention how to use &quot;xdoc&quot;, &quot;apt&quot; or other templating technologies to create documentation pages, but not to fear, I have provided this in my &lt;a href=&quot;https://github.com/mike-ensor/clickconcepts-master-pom/&quot; target=&quot;_blank&quot;&gt;GitHub project&lt;/a&gt;.  
&lt;/p&gt;

&lt;h3&gt;Putting it all Together&lt;/h3&gt;
&lt;p&gt;
The &lt;em&gt;Maven SCM Publish&lt;/em&gt; plugin (&lt;a href=&quot;http://maven.apache.org/plugins/maven-scm-publish-plugin/&quot; target=&quot;_blank&quot;&gt;http://maven.apache.org/plugins/maven-scm-publish-plugin/&lt;/a&gt; publishes site documentation to a supported SCM.  In our case, we are going to use Git through BitBucket or GitHub.  Maven SCM Plugin does allow you to publish multi-module site documentation through the various properties, but the scope of this blog post is to cover single/mono module projects and the process is a bit painful.
&lt;/p&gt;
&lt;p&gt;
Take a moment to look at the POM file located in the &lt;a href=&quot;https://github.com/mike-ensor/clickconcepts-master-pom/&quot;&gt;clickconcepts-master-pom&lt;/a&gt; project. This master POM is rather comprehensive and the site documentation is only one portion of the project, but we will focus on the site documentation. There are a few things to point out here, first, the scm-publish plugin and the idiosyncronies when implementing the plugin.
&lt;/p&gt;
&lt;p&gt;
In order to create the site documentation, the &quot;site&quot; plugin must first be run.  This is accomplished by running &lt;em&gt;site:site&lt;/em&gt;. The plugin will generate the documentation into the &quot;target/site&quot; folder by default.
&lt;/p&gt;
&lt;p&gt;
The SCM Publish Plugin, by default, looks for the site documents to be in &quot;target/staging&quot; and is controlled by the &lt;em&gt;content&lt;/em&gt; parameter.  As you can see, there is a mismatch between folders. &lt;strong&gt;NOTE:&lt;/strong&gt; My first approach was to run the &lt;em&gt;site:stage&lt;/em&gt; command which is supposed to put the site documents into the &quot;target/staging&quot; folder. This is not entirely correct, the site plugin combines with the distributionManagement.site.url property to stage the documents, but there is very strange behavior and it is not documented well.
&lt;/p&gt;
&lt;p&gt;
In order to get the site plugin&#39;s site documents and the SCM Publish&#39;s location to match up, use the &lt;em&gt;content&lt;/em&gt; property and set that to the location of the Site Plugin output (&amp;lt;siteOutputDirectory&amp;gt;).
&lt;/p&gt;
&lt;p&gt;
If you are using GitHub, there is no modification to the siteOutputDirectory needed, however, if you are using BitBucket, you will need to modify the property to add in a directory layer into the site documentation generation (see above for differences between GitHub and BitBucket pages). The second property will tell the SCM Publish Plugin to look at the root &quot;site&quot; folder so that when the files are copied into the repository, the project folder will be the containing folder.  The property will look like:
&lt;pre name=&quot;code&quot; class=&quot;Cpp&quot;&gt;
&amp;lt;siteOutputDirectory&amp;gt;${project.build.directory}/site/${project.artifactId}&amp;lt;/siteOutputDirectory&amp;gt;
&amp;lt;scm-publish.siteDocOuputDirectory&amp;gt;${project.build.directory}/site&amp;lt;/scm-publish.siteDocOuputDirectory&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
Next we will take a look at the custom properties defined in the master POM and used by the SCM Publish Plugin above.  Each project will need to define several properties to use the Master POM that are used within the plugins during the site publishing. Fill in the variables with your own settings.

&lt;h4&gt;BitBucket&lt;/h4&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;!-- Override Site Documentation SCM publishing parameters --&amp;gt;
&amp;lt;properties&amp;gt;
...
...
&amp;lt;scm-publish.scmBranch&amp;gt;master&amp;lt;/scm-publish.scmBranch&amp;gt;
&amp;lt;scm-publish.pubScmUrl&amp;gt;scm:git:git@bitbucket.org:mikeensor/mikeensor.bitbucket.org.git&amp;lt;/scm-publish.pubScmUrl&amp;gt;

&amp;lt;!-- Location of where &amp;quot;site&amp;quot; documentation is output; This is for BitBucket only!!! --&amp;gt;
&amp;lt;siteOutputDirectory&amp;gt;${project.build.directory}/site/${project.artifactId}&amp;lt;/siteOutputDirectory&amp;gt;
&amp;lt;scm-publish.siteDocOuputDirectory&amp;gt;${project.build.directory}/site&amp;lt;/scm-publish.siteDocOuputDirectory&amp;gt;

&amp;lt;!-- Overwrite from Parent Pom  --&amp;gt;
&amp;lt;changelog.fileUri&amp;gt;${changelog.bitbucket.fileUri}&amp;lt;/changelog.fileUri&amp;gt;
&amp;lt;changelog.revision.fileUri&amp;gt;${changelog.revision.bitbucket.fileUri}&amp;lt;/changelog.revision.fileUri&amp;gt;
...
...
&amp;lt;/properties&amp;gt;
&lt;/pre&gt;

&lt;h4&gt;GitHub&lt;/h4&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;!-- Override Site Documentation SCM publishing parameters --&amp;gt;
&amp;lt;properties&amp;gt;
...
...
&amp;lt;scm-publish.scmBranch&amp;gt;gh-pages&amp;lt;/scm-publish.scmBranch&amp;gt;
&amp;lt;scm-publish.pubScmUrl&amp;gt;scm:git:git@github.com:mikeensor/clickconcepts-master-pom.git&amp;lt;/scm-publish.pubScmUrl&amp;gt;

&amp;lt;!-- Location of where &amp;quot;site&amp;quot; documentation is output; This is for 
&amp;lt;scm-publish.siteDocOuputDirectory&amp;gt;${project.build.directory}/site&amp;lt;/scm-publish.siteDocOuputDirectory&amp;gt;

&amp;lt;!-- Overwrite from Parent Pom  --&amp;gt;
&amp;lt;changelog.fileUri&amp;gt;${changelog.github.fileUri}&amp;lt;/changelog.fileUri&amp;gt;
&amp;lt;changelog.revision.fileUri&amp;gt;${changelog.revision.github.fileUri}&amp;lt;/changelog.revision.fileUri&amp;gt;
...
...
&amp;lt;/properties&amp;gt;
&lt;/pre&gt;

&lt;small&gt;NOTE: changelog parameters are required to use the Master POM and are not directly related to publishing site docs to GitHub or BitBucket&lt;/small&gt;
&lt;/p&gt;

&lt;h3&gt;How to Generate&lt;/h3&gt;
&lt;p&gt;
If you are using the Master POM (or have abstracted out the Site Plugin and the SCM Plugin) then to generate and publish the documentation is simple.

&lt;pre class=&quot;cpp&quot; name=&quot;code&quot;&gt;
mvn clean site:site scm-publish:publish-scm
&lt;/pre&gt;

&lt;pre class=&quot;cpp&quot; name=&quot;code&quot;&gt;
mvn clean site:site scm-publish:publish-scm -Dscmpublish.dryRun=true
&lt;/pre&gt;
&lt;/p&gt;

&lt;h3&gt;Gotchas&lt;/h3&gt;
&lt;p&gt;
In the SCM Publish Plugin documentation&#39;s &quot;tips&quot; they recommend creating a location to place the repository so that the repo is not cloned each time. There is a risk here in that if there is a git repository already in the folder, the plugin will overwrite the repository with the new site documentation.  This was discovered by publishing two different projects and having my root repository wiped out by documentation from the second project. There are ways to mitigate this by adding in another folder layer, but make sure you test often!
&lt;/p&gt;
&lt;p&gt;
Another gotcha is to use the &lt;em&gt;-Dscmpublish.dryRun=true&lt;/em&gt; to test out the site documentation process without making the SCM commit and push
&lt;/p&gt;
&lt;h3&gt;Project and Documentation URLs&lt;/h3&gt;
&lt;p&gt;
Here is a list of the fully working projects used to create this blog post:
&lt;ul&gt;
&lt;li&gt;Master POM with Site and SCM Publish plugins &amp;ndash &lt;a href=&quot;https://github.com/mike-ensor/clickconcepts-master-pom&quot;&gt;https://github.com/mike-ensor/clickconcepts-master-pom&lt;/a&gt;. Documentation URL: &lt;a href=&quot;http://mike-ensor.github.com/clickconcepts-master-pom/&quot;&gt;http://mike-ensor.github.com/clickconcepts-master-pom/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Child Project using Master Pom &amp;ndash &lt;a href=&quot;http://mikeensor.bitbucket.org/fest-expected-exception&quot;&gt;http://mikeensor.bitbucket.org/fest-expected-exception&lt;/a&gt;. Documentation URL: &lt;a href=&quot;http://mikeensor.bitbucket.org/fest-expected-exception/&quot;&gt;http://mikeensor.bitbucket.org/fest-expected-exception/&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;
&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/6115993544369274166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/6115993544369274166' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/6115993544369274166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/6115993544369274166'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2013/01/how-to-publish-maven-site-docs-to.html' title='How to Publish Maven Site Docs to BitBucket or GitHub Pages'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-7211876166958931109</id><published>2012-11-19T18:37:00.001-08:00</published><updated>2012-11-19T18:37:41.414-08:00</updated><title type='text'>How to test a Custom Exception using custom FEST assertions</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;
This is part three of my posts on assertions testing using Fest, JUnit and custom Exceptions.  The first post was covering the &lt;a href=&quot;http://www.ensor.cc/2012/09/brief-overview-of-java-assertions.html&quot;&gt;basics of assertions&lt;/a&gt;, then followed up with &lt;a href=&quot;http://www.ensor.cc/2012/09/testing-custom-exceptions-w-junits.html&quot;&gt;testing custom Exceptions using JUnit and JUnit&#39;s ExpectedException class&lt;/a&gt;.  At this point you should know that you have a custom Runtime Exception class and you would like to test it using the Fluent API provided by FEST.
&lt;/p&gt;
&lt;h2&gt;Custom Assertions with Fest&lt;/h2&gt;
&lt;p&gt;
This blog post will not go into the details on creating a custom assertion, but the solution posted &lt;a href=&quot;https://github.com/mike-ensor/fest-backed-expected-exception&quot; target=&quot;_blank&quot;&gt;in the Github project&lt;/a&gt; does contain a custom assertion. In addition, please refer to the official &lt;a href=&quot;https://github.com/alexruiz/fest-assert-2.x/wiki/Creating-specific-assertions&quot; target=&quot;_blank&quot;&gt;site docs&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Building off of the last post, you will see that &lt;a href=&quot;http://kentbeck.github.com/junit/javadoc/4.10/org/junit/rules/ExpectedException.html&quot; target=&quot;_blank&quot;&gt;ExpectedException&lt;/a&gt; is a great improvement over the &lt;em&gt;@Test&lt;/em&gt;(expected) and Try/Catch techniques, however the ExpectedException object can still be improved by adding in a fluent-style API backed by Fest Assertion project. So, how do you do it? Let&#39;s get right to the solution!
&lt;/p&gt;

&lt;h2&gt;Expected Exceptions with FEST and JUnit @Rule&lt;/h2&gt;
&lt;p&gt;
Now that we have an understanding of FEST assertions, JUnit&#39;s @Rule functionality and ClickConcept&#39;s &lt;a href=&quot;http://www.ensor.cc/2012/09/allowing-junit-tests-to-pass-test-case.html&quot;&gt;@ExpectedFailure&lt;/a&gt; we can combine the first two to provide fluent-style expected exception behavior while testing the assertion class using @ExpectedFailure annotations.
&lt;/p&gt;
&lt;h2&gt;Testing your custom exception with FEST&lt;/h2&gt;
&lt;p&gt;
Let&#39;s begin by creating a new @Rule object &quot;&lt;em&gt;ExpectedException&lt;/em&gt;&quot; which extends TestRule. When creating the class, we will expose the construction through a simple factory method to return a new ExpectedException.  The default factory will return a base implementation where the functionality is muted in all other cases where exceptions are not desired.&lt;/p&gt;
&lt;p&gt;
We can start out with the code first, but I will explain that in order to build your own custom Fluent API for FEST, you must re-create the API for the base exception assertion.  The fluent API you create will be in addition to the FEST exception assertion class.  Fluent API help was derived off of several blogs, but the most informative has been &lt;a href=&quot;http://www.unquietcode.com/blog/2011/programming/using-generics-to-build-fluent-apis-in-java/
&quot; target=&quot;_blank&quot;&gt;http://www.unquietcode.com/blog/2011/programming/using-generics-to-build-fluent-apis-in-java/&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
NOTE: &lt;em&gt;AbstractExpectedException&lt;/em&gt; encapsulates the base API for FEST&#39;s ExceptionAssertion. The code for this is found at the Github site: &lt;a href=&quot;https://github.com/mike-ensor/fest-backed-expected-exception&quot; target=&quot;_blank&quot;&gt;https://github.com/mike-ensor/fest-backed-expected-exception&lt;/a&gt;
&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;

public class ExpectedCustomException extends AbstractExpectedException&amp;lt;ExpectedCustomException&amp;gt; {

    private Integer code;

    public static ExpectedCustomException none() {
        return new ExpectedCustomException();
    }

    /**
     * Checks to see if the CustomException has the specified code
     *
     * @param code int
     * @return AbstractExpectedException
     */
    public AbstractExpectedException hasCode(int code) {
        // method telling class that a custom exception is being asked for
        markExpectedException();
        this.code = code;
        return this;
    }

    @Override
    protected void checkAssertions(Exception e) {
        // check parent&#39;s exceptions
        super.checkAssertions(e);

        if (getCode() != null) {
            // FEST Custom Assert object
            CustomExceptionAssert.assertThat(e).hasCode(code);
        }
    }

    private Integer getCode() {
        return code;
    }

}
&lt;/pre&gt;

&lt;h3&gt;Analysis&lt;/h3&gt;
&lt;p&gt;
In this example, my CustomException has exposed a &quot;code&quot; to store when the exception was created. In order to test this my custom ExpectedException object must look for the proper code on the CustomException object, in a fluent manor.
&lt;/p&gt;
&lt;p&gt;
Here is an example test case to explain how to use your new fluent API Custom Exception test. &lt;strong&gt;Take note of the third test case&lt;/strong&gt; to see the Fluent API in use! (NOTE: Full test cases are available on my &lt;a href=&quot;https://github.com/mike-ensor/fest-backed-expected-exception&quot;&gt;github account&lt;/a&gt;.
&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;
public class CustomExceptionTest {

    @Rule
    public ExpectedCustomException exception =
            ExpectedCustomException.none();

    @Rule
    public ExpectedTestFailureWatcher expectedTestFailureWatcher =
            ExpectedTestFailureWatcher.instance();

    @Test
    public void hasCode_worksAsExpected() {
        exception.hasCode(123);
        throw new CustomException(&quot;Message&quot;, 123);
    }

    @Test
    @ExpectedFailure
    public void getCode_fails() {
        exception.hasCode(456);
        throw new CustomException(&quot;Message&quot;, 123);
    }

    @Test
    @ExpectedFailure
    public void getMessageAndCode_codeFailsFirst() {
        exception.hasCode(456).hasMessage(&quot;Message&quot;);
        throw new CustomException(&quot;Message&quot;, 123);
    }

}
&lt;/pre&gt;


&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;
Thank you to those of you who have read through this little series covering assertions, how to test exceptions (both the exception flow and custom exceptions) and then on to testing your custom exceptions using FEST assertions.  Please come back to &lt;a href=&quot;http://www.ensor.cc&quot;&gt;my blog&lt;/a&gt; in the near future where I will have a REST API checklist to look over when architecting your next REST API.
&lt;/p&gt;
&lt;p&gt;
Those who are reading this blog are most likely a small subset of the software development community, but if you are not, and you find the idea of a fluent-API really cool (as I do), please check out the FEST assertion library.  If you are new to test driven development, please take up the practice and try applying to your code immediately. If all developers used TDD as a general practice, the level in quality would grow world wide!
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/7211876166958931109/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/7211876166958931109' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/7211876166958931109'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/7211876166958931109'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2012/11/how-to-test-custom-exception-using.html' title='How to test a Custom Exception using custom FEST assertions'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-1671838997114433191</id><published>2012-09-25T23:27:00.001-07:00</published><updated>2012-09-25T23:27:20.464-07:00</updated><title type='text'>Testing Custom Exceptions w/ JUnit&#39;s ExpectedException and @Rule</title><content type='html'>&lt;br/&gt;
&lt;h2&gt;Exception Testing&lt;/h2&gt;
&lt;p&gt;
Why test exception flows? Just like with all of your code, test coverage writes a contract between your code and the business functionality that the code is supposed to produce leaving you with a &lt;strong&gt;living documentation&lt;/strong&gt; of the code along with the added ability to stress the functionality early and often.  I won&#39;t go into the many benefits of testing instead I will focus on just Exception Testing.
&lt;/p&gt;
&lt;p&gt;
There are many ways to test an exception flow thrown from a piece of code. Lets say that you have a guarded method that requires an argument to be not null. How would you test that condition?  How do you keep JUnit from reporting a failure when the exception is thrown?  This blog covers a few different methods culminating with &lt;strong&gt;JUnit&#39;s ExpectedException&lt;/strong&gt; implemented with &lt;strong&gt;JUnit&#39;s @Rule functionality&lt;/strong&gt;.
&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;The &quot;old&quot; way&lt;/h3&gt;
&lt;p&gt;In a not so distant past the process to test an exception required a dense amount of boilerplate code in which you would start a try/catch block, report a failure if your code did not produce the expected behavior and then catch the exception looking for the specific type.  Here is an example:
&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;public class MyObjTest {

    @Test
    public void getNameWithNullValue() {

        try {
            MyObj obj = new MyObj();
            myObj.setName(null);
            
            fail(&quot;This should have thrown an exception&quot;);

        } catch (IllegalArgumentException e) {
            assertThat(e.getMessage().equals(&quot;Name must not be null&quot;));
        }
    }
}
&lt;/pre&gt;
&lt;p&gt;
As you can see from this old example, many of the lines in the test case are just to support the lack of functionality present to specifically test exception handling.  One &lt;strong&gt;good point&lt;/strong&gt; to make for the try/catch method is the ability to test the &lt;strong&gt;specific message and any custom fields&lt;/strong&gt; on the expected exception. We will explore this a bit further down with JUnit&#39;s ExpectedException and @Rule annotation.
&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;JUnit adds expected exceptions&lt;/h3&gt;
&lt;p&gt;
JUnit responded back to the users need for exception handling by adding a @Test annotation field &quot;expected&quot;. The intention is that the entire test case will pass if the type of exception thrown matched the exception class present in the annotation.
&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;public class MyObjTest {

    @Test(expected = IllegalArgumentException.class)
    public void getNameWithNullValue() {
        MyObj obj = new MyObj();
        myObj.setName(null);
    }
}
&lt;/pre&gt;
&lt;p&gt;
As you can see from the newer example, there is quite a bit less boiler plate code and the test is very concise, however, &lt;strong&gt;there are a few flaws&lt;/strong&gt;. The main flaw is that the test condition is too broad. Suppose you have two variables in a signature and both cannot be null, then how do you know which variable the IllegalArgumentException was thrown for? What happens when you have extended a Throwable and need to check for the presence of a field?  Keep these in mind as you read further, solutions will follow.
&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;JUnit @Rule and ExpectedException&lt;/h3&gt;
&lt;p&gt;
If you look at the previous example you might see that you are expecting an IllegalArgumentException to be thrown, but what if you have a custom exception?  What if you want to make sure that the message contains a specific error code or message?  This is where JUnit really excelled by providing a JUnit @Rule object specifically tailored to exception testing.  If you are unfamiliar with JUnit @Rule, read the &lt;a href=&quot;http://kentbeck.github.com/junit/javadoc/4.10/org/junit/Rule.html&quot; target=&quot;_blank&quot;&gt;docs here&lt;/a&gt;.
&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;ExpectedException&lt;/h3&gt;
&lt;p&gt;
JUnit provides a JUnit class ExpectedException intended to be used as a @Rule. The ExpectedException allows for your test to declare that an exception is expected and gives you some basic built in functionality to clearly express the expected behavior.  Unlike the @Test(expected) annotation feature, ExpectedException class allows you to test for specific error messages and custom fields via the &lt;a href=&quot;http://code.google.com/p/hamcrest/wiki/MatcherLibraries&quot; target=&quot;_blank&quot;&gt;Hamcrest matchers library&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;An example of JUnit&#39;s ExpectedException&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;import org.junit.rules.ExpectedException;

public class MyObjTest {

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void getNameWithNullValue() {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage(&quot;Name must not be null&quot;);

        MyObj obj = new MyObj();
        obj.setName(null);
    }
}
&lt;/pre&gt;
&lt;p&gt;
As I eluded to above, the framework allows you to test for specific messages ensuring that the exception being thrown is the case that the test is specifically looking for. This is very helpful when the nullability of multiple arguments is in question.
&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;Custom Fields&lt;/h3&gt;
&lt;p&gt;Arguably the &lt;strong&gt;most useful feature&lt;/strong&gt; of the ExpectedException framework is the ability to use &lt;strong&gt;Hamcrest matchers&lt;/strong&gt; to test your custom/extended exceptions. For example, you have a custom/extended exception that is to be thrown in a method and inside the exception has an &quot;errorCode&quot;.  How do you test that functionality without introducing the boiler plate code from the try/catch block listed above?  How about a custom Matcher!
&lt;/p&gt;
&lt;p&gt;
&lt;h4&gt;This code is available at: &lt;a href=&quot;https://github.com/mike-ensor/custom-exception-testing&quot; target=&quot;_blank&quot;&gt;https://github.com/mike-ensor/custom-exception-testing&lt;/a&gt;&lt;/h4&gt;
&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;Solution: First the test case&lt;/h3&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;import org.junit.rules.ExpectedException;

public class MyObjTest {

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void someMethodThatThrowsCustomException() {
        thrown.expect(CustomException.class);
        thrown.expect(CustomMatcher.hasCode(&quot;110501&quot;));

        MyObj obj = new MyObj();
        obj.methodThatThrowsCustomException();
    }
}
&lt;/pre&gt;
&lt;br/&gt;
&lt;h3&gt;Solution: Custom matcher&lt;/h3&gt;

&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;import com.thepixlounge.exceptions.CustomException;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;

public class CustomMatcher extends TypeSafeMatcher&amp;lt;CustomException&amp;gt; {

    public static BusinessMatcher hasCode(String item) {
        return new BusinessMatcher(item);
    }

    private String foundErrorCode;
    private final String expectedErrorCode;

    private CustomMatcher(String expectedErrorCode) {
        this.expectedErrorCode = expectedErrorCode;
    }

    @Override
    protected boolean matchesSafely(final CustomException exception) {
        foundErrorCode = exception.getErrorCode();
        return foundErrorCode.equalsIgnoreCase(expectedErrorCode);
    }

    @Override
    public void describeTo(Description description) {
        description.appendValue(foundErrorCode)
                .appendText(&quot; was not found instead of &quot;)
                .appendValue(expectedErrorCode);
    }
}

&lt;/pre&gt;

&lt;strong&gt;NOTE: Please visit &lt;a href=&quot;https://github.com/mike-ensor/custom-exception-testing&quot; target=&quot;_blank&quot;&gt;https://github.com/mike-ensor/custom-exception-testing&lt;/a&gt; to get a copy of a working Hamcrest Matcher, JUnit @Rule and ExpectedException.&lt;/strong&gt;

&lt;p&gt;
And there you have it, a quick overview of different ways to test Exceptions thrown by your code along with the ability to test for specific messages and fields from within custom exception classes.  Please be specific with your test cases and try to target the exact case you have setup for your test, remember, tests can save you from introducing side-effect bugs!
&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/1671838997114433191/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/1671838997114433191' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/1671838997114433191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/1671838997114433191'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2012/09/testing-custom-exceptions-w-junits.html' title='Testing Custom Exceptions w/ JUnit&#39;s ExpectedException and @Rule'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-4478993325711486229</id><published>2012-09-18T22:55:00.003-07:00</published><updated>2012-09-18T23:01:23.406-07:00</updated><title type='text'>Brief Overview of Java Assertions</title><content type='html'>&lt;!--
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;
This blog post will describe the current assertion framework landscape along with some history on how the industry arrived at FEST assertions. If you are current on assertion frameworks, feel free to skip to the &lt;a href=&quot;#expected-exception&quot;&gt;Expected Exceptions&lt;/a&gt; for which this post is intended to cover
&lt;/p&gt;
--&gt;
&lt;h2&gt;What are asserts?&lt;/h2&gt;
&lt;p&gt;
An assertion is a predicate (a true–false statement) placed in a program to indicate that the developer thinks that the predicate is always true at that place. &lt;small&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Assertion_%28computing%29&quot; target=&quot;_blank&quot;&gt;[wikipedia]&lt;/a&gt;&lt;/small&gt;
&lt;/p&gt;
&lt;h3&gt;Traditional asserts&lt;/h3&gt;
&lt;p&gt;
Traditional testing frameworks started with the built in keyword &lt;strong&gt;assert&lt;/strong&gt;.
&lt;/p&gt;
&lt;p&gt;
An example of the keyword &lt;em&gt;assert&lt;/em&gt;:
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;assert &amp;lt;condition&amp;gt; value&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
Assert has a few drawbacks including stopping the test execution and lengthy and hard to describe assert statements.
&lt;/p&gt;
&lt;h3&gt;Second generation assertions&lt;/h3&gt;
&lt;p&gt;
Along comes JUnit&#39;s assert framework.  Built on top of the &lt;em&gt;assert&lt;/em&gt; keyword, JUnit provided developers the ability to be more descriptive about the testing statements.
&lt;/p&gt;
An example of JUnit&#39;s asserts:
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;// asserts that the condition must be true
assertTrue(&quot;This should be true&quot;, &quot;abc&quot;.equalsIgnoreCase(&quot;ABC&quot;));
// asserts that the object must not be null
assertNotNull(new MyObject());
//...
assertFalse(false == true);
//
assertNull(null);
// etc...
&lt;/pre&gt;
&lt;p&gt;
While there are some improvements on readability and usability to the basic &lt;em&gt;assert&lt;/em&gt; keyword provided by JUnit, they share some of the same drawbacks in that many developers just use the &quot;&lt;em&gt;assertTrue()&lt;/em&gt;&quot;, &quot;&lt;em&gt;assertEquals()&lt;/em&gt;&quot; and &quot;&lt;em&gt;assertFalse()&lt;/em&gt;&quot; methods still providing a very cryptic assertion statement.
&lt;/p&gt;
&lt;h3&gt;Third generation assertions&lt;/h3&gt;
&lt;p&gt;
In an effort to guide developers into writing test assertions that are more readable and usable the &lt;a href=&quot;http://code.google.com/p/hamcrest/&quot;&gt;&lt;strong&gt;Hamcrest library&lt;/strong&gt;&lt;/a&gt; was created which switched the philosophy from many &lt;em&gt;assert&lt;/em&gt; functions to just one basic function. The fundamental thought is that the assert is the same but the conditions will change.  Hamcrest was built using the concepts of BDD (behavior driven design) where the test assertion is closer to that of a sentence.
&lt;/p&gt;
&lt;p&gt;An example of hamcrest assertions&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;@Test
public void showoffSomeHamcrestAssertsAndMatchers() {
    // asserts that string &quot;abc&quot; is &quot;ABC&quot; ignoring case
    assertThat(&quot;abc&quot;, is(equalToIgnoringCase(&quot;ABC&quot;)));
    assertThat(myObject.getFirst(), is(&quot;Mike!&quot;));
    assertThat(myObject.getAddress(), is(notNullValue));
}
&lt;/pre&gt;
&lt;p&gt;
Hamcrest is a great improvement on top of the JUnit framework providing a flexible and readable testing platform. Hamcrest + JUnit is a comprehensive testing framework and when combined with &lt;a href=&quot;http://code.google.com/p/mockito/&quot; target=&quot;_blank&quot;&gt;Mockito&lt;/a&gt; (or other mocking framework) can provide a very descriptive and thorough unit testing solution. One of the drawbacks to using Hamcrest is that while descriptive, multiple assertions must be made to ensure that a test case has been covered. Many TDD purest agree that a test case should contain one and only one assertion, but how is this possible with a complex object? (purest will say refactoring, but oftentimes this is not feasible)
&lt;/p&gt;
&lt;h3&gt;Fourth generation frameworks&lt;/h3&gt;
&lt;p&gt;
And finally we come to the present with the latest assertion frameworks. &lt;a href=&quot;http://code.google.com/p/fest/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Fest Assertion framework&lt;/strong&gt;&lt;/a&gt; takes off where Hamcrest stopped providing a &lt;a href=&quot;http://en.wikipedia.org/wiki/Fluent_interface&quot; target=&quot;_blank&quot;&gt;fluent style&lt;/a&gt; assertion framework giving the developer the ability to test objects with a single assertion.&lt;/p&gt;
&lt;p&gt;An example of Fest assertions&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;@Test
public void getAddressOnStreet() {
    List&amp;lt;Address&amp;gt; addresses = addressDAO.liveOnStreet(&quot;main&quot;);
    assertThat(addresses).hasSize(10).contains(address1, address2);
    assertThat(stringObj).hasSize(7).isEqualToIgnoringCase(&quot;abcdefg&quot;);
}
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
As you can see, FEST exceptions provide a cleaner approach to assertions.  FEST is very extensible and easy to use.
&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;
Assertions are a key tool in a professional developer&#39;s toolbox in which to stress test their code. This post is a part in a series with the culmination being a fluent style ExpectedException mechanism, backed by Fest, in which to add better clarity to your test cases when exceptions are being introduced.  Feel free to read the lead up to this post; &lt;a href=&quot;http://www.ensor.cc/2012/09/allowing-junit-tests-to-pass-test-case.html&quot;&gt;Allowing known failing JUnit Tests to pass test cases&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
NOTE: This blog is providing an overview on assertion frameworks it should be noted that there are various other second and third generation testing frameworks that strive to provide better clarity and usability for testing including notables such as &lt;a href=&quot;http://testng.org&quot; target=&quot;_blank&quot;&gt;TestNG&lt;/a&gt; and &lt;a href=&quot;http://www.parasoft.com/jsp/solutions/java_solution.jsp&quot; target=&quot;_blank&quot;&gt;JTest&lt;/a&gt;
&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/4478993325711486229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/4478993325711486229' title='96 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/4478993325711486229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/4478993325711486229'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2012/09/brief-overview-of-java-assertions.html' title='Brief Overview of Java Assertions'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>96</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-3732687967186967051</id><published>2012-09-09T20:51:00.000-07:00</published><updated>2012-09-11T22:40:56.512-07:00</updated><title type='text'>Allowing JUnit Tests to Pass Test Case on Failures</title><content type='html'>&lt;br/&gt;
&lt;h3&gt;Why create a mechanism to expect a test failure?&lt;/h3&gt;
&lt;p&gt;
There comes a time when one would want and expect a JUnit &lt;a href=&quot;http://junit.sourceforge.net/javadoc/org/junit/Test.html&quot; target=&quot;_blank&quot;&gt;@Test&lt;/a&gt; case fail. Though this is pretty rare, it happens. I had the need to detect when a JUnit Test fails and then, if expected, to pass instead of fail. The specific case was that I was testing a piece of code that could throw an Assert error inside of a call of the object. The code was written to be an enhancement to the popular new &lt;a href=&quot;http://code.google.com/p/fest/&quot; target=&quot;_blank&quot;&gt;Fest Assertions&lt;/a&gt; framework, so in order to test the functionality, one would expect test cases to fail on purpose.&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;A Solution&lt;/h3&gt;
&lt;p&gt;&lt;small&gt;&lt;a href=&quot;#coded-solution&quot;&gt;Jump to the Code&lt;/a&gt;&lt;/small&gt;&lt;br/&gt;One possible solution is to utilize the functionality provided by a JUnit &lt;a href=&quot;http://kentbeck.github.com/junit/javadoc/4.10/org/junit/Rule.html&quot; target=&quot;_blank&quot; class=&quot;code&quot;&gt;@Rule&lt;/a&gt; in conjunction with a custom marker in the form of an annotation.&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;Why use a @Rule?&lt;/h3&gt;
&lt;p&gt;
@Rule objects provide an AOP-like interface to a test class and each test cases.  Rules are reset prior to each test case being run and they expose the workings of the test case in the style of an @Around AspectJ advice would.
&lt;/p&gt;

&lt;h3&gt;Required code elements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;@Rule object to check the status of each @Test case&lt;/li&gt;
&lt;li&gt;@ExpectedFailure custom marker annotation&lt;/li&gt;
&lt;li&gt;Test cases proving code works!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional&lt;/strong&gt; specific exception to be thrown if annotated test case does not fail&lt;/li&gt;
&lt;/ul&gt;
&lt;br/&gt;
&lt;p&gt;
&lt;strong&gt;NOTE: working code is available on &lt;a href=&quot;https://github.com/mike-ensor/expected-failure&quot; target=&quot;_target&quot;&gt;my github page&lt;/a&gt; and has been added to Maven Central. Feel free to &lt;a href=&quot;https://github.com/mike-ensor/expected-failure/fork&quot; target=&quot;_blank&quot;&gt;Fork the project&lt;/a&gt; and submit a pull request&lt;/strong&gt;
&lt;/p&gt;

&lt;h4&gt;Maven Usage&lt;/h4&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.clickconcepts.junit&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;expected-failure&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;0.0.9&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;
&lt;br/&gt;

&lt;h3&gt;Example Usage&lt;/h3&gt;
&lt;p&gt;In this example, the &quot;exception&quot; object is a Fest assertion enhanced ExpectedException (look for my next post to expose this functionality). The expected exception will make assertions and in order to test those, the test case must be marked as @ExpectedFailure&lt;/p&gt;

&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;
public class ExceptionAssertTest {

    @Rule
    public ExpectedException exception = ExpectedException.none();

    @Rule
    public ExpectedTestFailureWatcher watcher = ExpectedTestFailureWatcher.instance();

    @Test
    @ExpectedFailure(&quot;The matcher should fail becasue exception is not a SimpleException&quot;)
    public void assertSimpleExceptionAssert_exceptionIsOfType() {
        // expected exception will be of type &quot;SimpleException&quot;
        exception.instanceOf(SimpleException.class);
        // throw something other than SimpleException...expect failure
        throw new RuntimeException(&quot;this is an exception&quot;);
    }
}
&lt;/pre&gt;
&lt;br/&gt;

&lt;a name=&quot;coded-solution&quot; id=&quot;coded-solution&quot; style=&quot;display:none;&quot;&gt;&lt;/a&gt;
&lt;h3&gt;Implementation of Solution&lt;/h3&gt;
&lt;p&gt;Reminder, the latest code is available on my &lt;a href=&quot;https://github.com/mike-ensor/expected-failure&quot; target=&quot;_target&quot;&gt;github page&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;@Rule code (ExpectedTestFailureWatcher.java)&lt;/h4&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
// YEAH Guava!!
import static com.google.common.base.Strings.isNullOrEmpty;

public class ExpectedTestFailureWatcher implements TestRule {

    /**
     * Static factory to an instance of this watcher
     *
     * @return New instance of this watcher
     */
    public static ExpectedTestFailureWatcher instance() {
        return new ExpectedTestFailureWatcher();
    }

    @Override
    public Statement apply(final Statement base, final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                boolean expectedToFail = description.getAnnotation(ExpectedFailure.class) != null;
                boolean failed = false;
                try {
                    // allow test case to execute
                    base.evaluate();
                } catch (Throwable exception) {
                    failed = true;
                    if (!expectedToFail) {
                        throw exception; // did not expect to fail and failed...fail
                    }
                }
                // placed outside of catch
                if (expectedToFail &amp;&amp; !failed) {
                    throw new ExpectedTestFailureException(getUnFulfilledFailedMessage(description));
                }
            }

            /**
             * Extracts detailed message about why test failed
             * @param description
             * @return
             */
            private String getUnFulfilledFailedMessage(Description description) {
                String reason = null;
                if (description.getAnnotation(ExpectedFailure.class) != null) {
                    reason = description.getAnnotation(ExpectedFailure.class).reason();
                }
                if (isNullOrEmpty(reason)) {
                    reason = &quot;Should have failed but didn&#39;t&quot;;
                }
                return reason;
            }
        };
    }
}
&lt;/pre&gt;

&lt;h4&gt;@ExpectedFailure custom annotation (ExpectedFailure.java)&lt;/h4&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;
import java.lang.annotation.*;

/**
 * Initially this is just a marker annotation to be used by a JUnit4 Test case in conjunction
 * with ExpectedTestFailure @Rule to indicate that a test is supposed to be failing
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
public @interface ExpectedFailure {
    // TODO: enhance by adding specific information about what type of failure expected
    //Class&lt;? extends Throwable&gt; assertType() default Throwable.class;

    /**
     * Text based reason for marking test as ExpectedFailure
     * @return String
     */
    String reason() default &quot;&quot;;
}
&lt;/pre&gt;

&lt;h4&gt;Custom Exception (Optional, you can easily just throw RuntimeException or existing custom exception)&lt;/h4&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;
public class ExpectedTestFailureException extends Throwable {
    public ExpectedTestFailureException(String message) {
        super(message);
    }
}
&lt;/pre&gt;
&lt;br/&gt;

&lt;h3&gt;Can&#39;t one exploit the ability to mark a failure as expected?&lt;/h3&gt;
&lt;p&gt;
&lt;strong&gt;With great power comes great responsibility&lt;/strong&gt;, it is advised that you do not mark a test as being @ExpectedFailure if you do not understand exactly why the test if failing. It is recommended that this testing method be implemented with care.  &lt;strong&gt;DO NOT&lt;/strong&gt; use the @ExpectedFailure annotation as an alternative to &lt;a href=&quot;http://kentbeck.github.com/junit/javadoc/4.10/org/junit/Ignore.html&quot; target=&quot;_blank&quot;&gt;@Ignore&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
Possible future enhancements could include ways to specify the specific assertion or the specific message asserted during the test case execution.
&lt;/p&gt;

&lt;h3&gt;Known issues&lt;/h3&gt;
&lt;p&gt;
In this current state, the @ExpectedFailure annotation can cover up additional assertions and until the future enhancements have been put into place, it is advised to use this methodology wisely.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/3732687967186967051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/3732687967186967051' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/3732687967186967051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/3732687967186967051'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2012/09/allowing-junit-tests-to-pass-test-case.html' title='Allowing JUnit Tests to Pass Test Case on Failures'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-2930961329493235161</id><published>2012-03-19T17:52:00.000-07:00</published><updated>2012-03-19T17:52:32.564-07:00</updated><title type='text'>Maven 3 Site Docs Part 1: Basic Site Documentation</title><content type='html'>&lt;h2&gt;What is documentation?&lt;/h2&gt;
&lt;dl&gt;
&lt;dt style=&quot;display:inline; font-weight:bold; font-style:italic;&quot;&gt;Documentation&lt;/dt&gt;
&lt;dd style=&quot;display:inline; font-weight:bold; font-style:italic;&quot;&gt;The process of documenting knowledge&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;
Documentation for software developers are documents that describe how to run or use the artifact/project.  Typically documentation provides any exposed settings, their uses and default values.  In addition information about integration, entry and exit points such as JMS queues, JMX MBeans, DataSource objects and/or JNDI variables in order to run and use the artifact.  There are many programs and standards to produce this level of documentation including &lt;a href=&quot;http://www.microsoft.com&quot; target=&quot;_blank&quot;&gt;MS word&lt;/a&gt;, Sharepoint, &lt;a href=&quot;http://www.doxygen.org&quot; target=&quot;_blank&quot;&gt;doxygen&lt;/a&gt;, &lt;a href=&quot;http://www.latex-project.org&quot; target=&quot;_blank&quot;&gt;Latex&lt;/a&gt;, &lt;a href=&quot;http://www.mediawiki.org&quot; target=&quot;_blank&quot;&gt;Wiki&lt;/a&gt;, &lt;a href=&quot;http://daringfireball.net/projects/markdown/&quot; target=&quot;_blank&quot;&gt;markdown&lt;/a&gt;, textile, etc.
&lt;/p&gt;
&lt;p&gt;
Outside of artifact specific documentation team leads, architects and project managers usually ask for JavaDocs to be included.  JavaDocs, if combined with Maven provide more documentation for your IDE and better information for the consumers of your artifact.  Other important documentation includes testing reports, test coverage, static analysis tools, dependencies of your artifact, change log and issue management such as Jira or Bugzilla.
&lt;/p&gt;

&lt;h2&gt;Why create docs?&lt;/h2&gt;
&lt;p&gt;
The best reason to care about documentation is to provide information for external developers and team members outside of the project&#39;s development environment.  Documentation can be utilized inside of IDEs as well and face it, how many times do you wish you had sources and/or JavaDocs for a dependency when you were programming or to send back an email with the site docs so someone can be self-served rather than take your time.
&lt;/p&gt;

&lt;h2&gt;Problems with traditional documentation&lt;/h2&gt;
&lt;p&gt;
The largest complaint with traditional documentation is that it becomes stale over time.  Time is never allocated in a project&lt;sup&gt;&amp;dagger&lt;/sup&gt; to provide or update documentation and stale docs can lead a developer or team down many wrong paths leading to hours or days of misinformation lead rabbit holes.
&lt;/p&gt;
&lt;sup&gt;&lt;small&gt;&amp;dagger; Agile, SCRUM and Lean processes should allow time to be built-in to handle technical debt like documentation, even thought it is called the &quot;necessary evil&quot;. &lt;a href=&quot;http://www.agilemodeling.com/essays/agileDocumentation.htm#IssuesWithDocumentation&quot; target=&quot;_blank&quot;&gt;Read more here&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;

&lt;p&gt;
Secondly, developers are the ones who are &lt;strike&gt;asked&lt;/strike&gt;forced to maintain the documentation and typically developers are not great in the writing department and unless segments of the documentation process are automated, developers are people and we forget.
&lt;/p&gt;

&lt;p&gt;
Last major problem with traditional documentation is that it is typically not automated and is an extra step during the build/release cycle.  Any process in the build cycle that is not automated and tested will break down at some point.  Humans are great at abstract thinking, not repetitive processes.
&lt;/p&gt;


&lt;h2&gt;Solution to the problems&lt;/h2&gt;
&lt;p&gt;
As stated above, the main problems are developers maintaining all documentation and documentation that is either built outside of the immediate environment or is not automated.  This is where Maven&#39;s site documentation comes in.  Maven was built with the understanding that documentation needs to be automated and has been progressively improved throughout updates to the maven project.
&lt;/p&gt;
&lt;p&gt;
The most common case for Maven site docs is to deploy generated documentation to an external web server via SCP, FTP, WebDAV or SFTP.  The site plugin takes use of Apache&#39;s Wagon library for secure transfer of docs.  Most of the time the site docs are generated during the &lt;strong&gt;release&lt;/strong&gt;&amp;dagger; or &lt;strong&gt;deploy&lt;/strong&gt; phases and generate on the &lt;em&gt;verify&lt;/em&gt; phase.
&lt;/p&gt;
&lt;sup&gt;&lt;small&gt;&amp;dagger; Release isn&#39;t a phase in maven, it is a plugin, but it is considered a best practice when publishing versioned artifacts to a maven repository&lt;/small&gt;&lt;/sup&gt;

&lt;h2&gt;Maven 3 vs Maven 2&lt;/h2&gt;
&lt;p&gt;
Maven decided to change the way that reports were collected and generated in between the Maven 2 and Maven 3 releases.  In Maven 2, the POM would have a section called &amp;gt;reports&amp;lt; where plugins that handled &lt;a href=&quot;http://maven.apache.org/ref/3.0.4/maven-model/apidocs/org/apache/maven/model/ReportSet.html&quot; target=&quot;_blank&quot;&gt;ReportSet&lt;/a&gt; would be handled.  In Maven 3, there is now a plugin that handles and collates the ReportSets instead of Maven handling it.  The plugin is called &lt;em&gt;maven-project-info-reports-plugin&lt;/em&gt; and documentation can be found &lt;a href=&quot;http://maven.apache.org/plugins/maven-project-info-reports-plugin/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.
&lt;/p&gt;

&lt;h3&gt;Sources for this series of blog post&lt;/h3&gt;
&lt;p&gt;I have provided a link to a fully functional multi-module maven project that publishes to both &lt;a href=&quot;http://mike-ensor.github.com/multi-module-site-doc-project/index.html&quot; target=&quot;_blank&quot;&gt;http://mike-ensor.github.com/multi-module-site-doc-project/index.html&lt;/a&gt; and locally to ${env.HOME}/sitedocs/${project.artifactId}.&lt;br/&gt;&lt;br/&gt;
&lt;a href=&quot;https://github.com/mike-ensor/multi-module-site-doc-project&quot; target=&quot;_blank&quot;&gt;https://github.com/mike-ensor/multi-module-site-doc-project&lt;/a&gt;.
&lt;/p&gt;

&lt;h2&gt;Maven 3 Site Docs&lt;/h2&gt;
&lt;p&gt;
There are two important elements with respect to site docs for Maven.  Plugins, which generate ReportSet elements and Site Doc/Descriptors.
&lt;/p&gt;
&lt;h3&gt;Plugins&lt;/h3&gt;
&lt;p&gt;
Plugins are an important part of the documentation process and will typically run throughout the maven build lifecycle generating artifacts for the plugin phase that generates the ReportSet.  A good example would be the maven-checkstyle-plugin.  The plugin is typically bound to the process-resources or packakge phases so that developers know they have a checkstyle violation early in the build lifecycle.  The plugin generates a checkstyle.xml document that is then used in the site phase by the maven-project-info-reports-plugin to generate a checkstyle report page. 
&lt;/p&gt;

&lt;h4&gt;Maven Site Plugin&lt;/h4&gt;
&lt;p&gt;
The maven-site-plugin is the main plugin that is used to crate all site documentation. Each plugin that produces and/or consumes a ReportSet will need to be configured inside of the &amp;lt;reportPlugins&amp;gt; section. NOTE: This is where the Wagon plugin is set as a dependency.  The Site plugin will use the &amp;lt;distributionManagement&amp;gt;&amp;lt;site&amp;gt; line to determine where the site docs are to be published (SCM, WebDAV, SFTP, etc)
&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
 &amp;lt;artifactId&amp;gt;maven-site-plugin&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;${plugin.maven-site.version}&amp;lt;/version&amp;gt;
 &amp;lt;dependencies&amp;gt;
  &amp;lt;dependency&amp;gt;&amp;lt;!-- add support for ssh/scp --&amp;gt;
   &amp;lt;groupId&amp;gt;org.apache.maven.wagon&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;wagon-ssh&amp;lt;/artifactId&amp;gt;
   &amp;lt;version&amp;gt;${plugin.wagon-ssh.version}&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
 &amp;lt;/dependencies&amp;gt;
 &amp;lt;configuration&amp;gt;
  &amp;lt;attach&amp;gt;true&amp;lt;/attach&amp;gt;
  &amp;lt;reportPlugins&amp;gt;
   &amp;lt;plugin&amp;gt;
   ...
   ... Plugins go here
   ....
   &amp;lt;/plugin&amp;gt;
  &amp;lt;/reportPlugins&amp;gt;
  &amp;lt;attach&amp;gt;true&amp;lt;/attach&amp;gt;
 &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;


&lt;h4&gt;Maven Project Info Report Plugin&lt;/h4&gt;
&lt;p&gt;The maven-project-info-report-plugin is the main plugin used by the maven-site-plugin that Maven 3 utilizes to collate and produce the common site reporting docs for the artifact&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-project-info-reports-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;dependencyDetailsEnabled&amp;gt;false&amp;lt;/dependencyDetailsEnabled&amp;gt;
        &amp;lt;dependencyLocationsEnabled&amp;gt;false&amp;lt;/dependencyLocationsEnabled&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;!-- simpler configuration without
        reportSets available for usual cases --&amp;gt;
    &amp;lt;!-- distribution-management,
        index, dependencies, help,
        issue-tracking, plugins,
        cim, license, dependency-management,
        mailing-list, project-team,
        dependency-convergence,
        scm, plugin-management,
        modules, summary --&amp;gt;
    &amp;lt;reports&amp;gt;
        &amp;lt;report&amp;gt;summary&amp;lt;/report&amp;gt;
        &amp;lt;report&amp;gt;dependencies&amp;lt;/report&amp;gt;
        &amp;lt;report&amp;gt;project-team&amp;lt;/report&amp;gt;
        &amp;lt;report&amp;gt;issue-tracking&amp;lt;/report&amp;gt;
        &amp;lt;report&amp;gt;scm&amp;lt;/report&amp;gt;
        &amp;lt;report&amp;gt;cim&amp;lt;/report&amp;gt;
        &amp;lt;report&amp;gt;modules&amp;lt;/report&amp;gt;
        &amp;lt;report&amp;gt;plugins&amp;lt;/report&amp;gt;
    &amp;lt;/reports&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;&lt;br/&gt;
&lt;p&gt;
Take a quick look at the types of reports that are automatically generated using the maven-project-info-reports-plugin. Many of these automatically generated reports provide additional information on top of the redundant information provided by the below listed plugins.
&lt;/p&gt;
&lt;h5&gt;List of automatically provided reports&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;distribution-management&lt;/li&gt;
&lt;li&gt;index&lt;/li&gt;
&lt;li&gt;dependencies&lt;/li&gt;
&lt;li&gt;help&lt;/li&gt;
&lt;li&gt;issue-tracking&lt;/li&gt;
&lt;li&gt;plugins&lt;/li&gt;
&lt;li&gt;cim&lt;/li&gt;
&lt;li&gt;license&lt;/li&gt;
&lt;li&gt;dependency-management&lt;/li&gt;
&lt;li&gt;mailing-list&lt;/li&gt;
&lt;li&gt;project-team&lt;/li&gt;
&lt;li&gt;dependency-convergence&lt;/li&gt;
&lt;li&gt;scm&lt;/li&gt;
&lt;li&gt;plugin-management&lt;/li&gt;
&lt;li&gt;modules&lt;/li&gt;
&lt;li&gt;summary&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;Common Plugins&lt;/h4&gt;
&lt;a name=&quot;checkstyle&quot;&gt;&lt;/a&gt;
&lt;p&gt;
  &lt;strong&gt;Checkstyle - maven-checkstyle-plugin&lt;/strong&gt; &amp;ndash; Provides static analysis on source files &amp;ndash; NOTE: Checkstyle needs to be run during build AND report phases
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Example report plugin&lt;/strong&gt;&lt;br/&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
 &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;maven-checkstyle-plugin&amp;lt;/artifactId&amp;gt;
 &amp;lt;configuration&amp;gt;
  &amp;lt;skip&amp;gt;${checkstyle.skip}&amp;lt;/skip&amp;gt;
  &amp;lt;configLocation&amp;gt;${checkstyle.configUrl}&amp;lt;/configLocation&amp;gt;
  &amp;lt;failsOnError&amp;gt;false&amp;lt;/failsOnError&amp;gt;
  &amp;lt;enableRulesSummary&amp;gt;true&amp;lt;/enableRulesSummary&amp;gt;
  &amp;lt;includeTestSourceDirectory&amp;gt;true&amp;lt;/includeTestSourceDirectory&amp;gt;
 &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;NOTE: A best practice is to provide a flag to enable/disable the plugin on a project-by-project basis. Also, notice the failsOnError, this will ensure that the plugin will produce an artifact on error and present that to the user.
&lt;/p&gt;

&lt;a name=&quot;findbugs&quot;&gt;&lt;/a&gt;
&lt;p&gt;
  &lt;strong&gt;FindBugs - maven-findbugs-plugin&lt;/strong&gt; &amp;ndash; Provides static analysis on source files &amp;ndash; Plugin does not need to be run outside of report phase
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Example report plugin&lt;/strong&gt;&lt;br/&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
 &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;findbugs-maven-plugin&amp;lt;/artifactId&amp;gt;
 &amp;lt;configuration&amp;gt;
  &amp;lt;skip&amp;gt;${findbugs.skip}&amp;lt;/skip&amp;gt;
  &amp;lt;xmlOutput&amp;gt;true&amp;lt;/xmlOutput&amp;gt;
 &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;NOTE: A best practice is to provide a flag to enable/disable the plugin on a project-by-project basis. Also, notice the failsOnError, this will ensure that the plugin will produce an artifact on error and present that to the user.
&lt;/p&gt;


&lt;a name=&quot;cobertura&quot;&gt;&lt;/a&gt;
&lt;p&gt;
  &lt;strong&gt;Cobertura - maven-cobertura-plugin&lt;/strong&gt; &amp;ndash; Provides code coverage during Unit Test (&lt;em&gt;test&lt;/em&gt;) phase.  NOTE: Must be run during build AND during reporting phases
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Example report plugin&lt;/strong&gt;&lt;br/&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
 &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;cobertura-maven-plugin&amp;lt;/artifactId&amp;gt;
 &amp;lt;configuration&amp;gt;
  &amp;lt;skip&amp;gt;${cobertura.skip}&amp;lt;/skip&amp;gt;
 &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;NOTE: A best practice is to provide a flag to enable/disable the plugin on a project-by-project basis. Also, notice the failsOnError, this will ensure that the plugin will produce an artifact on error and present that to the user.
&lt;/p&gt;


&lt;a name=&quot;pmd-cpd&quot;&gt;&lt;/a&gt;
&lt;p&gt;
  &lt;strong&gt;PMD and CPD - maven-pmd-plugin&lt;/strong&gt; &amp;ndash; Provides static analysis (PMD) and code duplication/cut-copy-paste detection for artifact.  Read more about the PMD plugin &lt;a href=&quot;http://maven.apache.org/plugins/maven-pmd-plugin/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Example report plugin&lt;/strong&gt;&lt;br/&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
 &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;maven-pmd-plugin&amp;lt;/artifactId&amp;gt;
 &amp;lt;configuration&amp;gt;
  &amp;lt;skip&amp;gt;${pmd.skip}&amp;lt;/skip&amp;gt;
  &amp;lt;targetJdk&amp;gt;${maven.compiler.source}&amp;lt;/targetJdk&amp;gt;
  &amp;lt;sourceEncoding&amp;gt;${project.build.sourceEncoding}&amp;lt;/sourceEncoding&amp;gt;
  &amp;lt;minimumTokens&amp;gt;100&amp;lt;/minimumTokens&amp;gt;
  &amp;lt;rulesets&amp;gt;
   &amp;lt;ruleset&amp;gt;${maven-pmd-plugin.configLocation}&amp;lt;/ruleset&amp;gt;
  &amp;lt;/rulesets&amp;gt;
  &amp;lt;failOnViolation&amp;gt;false&amp;lt;/failOnViolation&amp;gt;
 &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;



&lt;a name=&quot;surefire-failsafe&quot;&gt;&lt;/a&gt;
&lt;p&gt;
  &lt;strong&gt;Surefire and Failsafe - maven-surefire-report-plugin&lt;/strong&gt; &amp;ndash; Creates reports based on tests cases for unit tests and optionally integration tests.  NOTE, This is a different plugin than the maven-surefire-plugin, this is the report plugin that operates on the ResultSet for both Surefire and Failsafe.  Both Surefire and Failsafe must be run during the build for this plugin to generate reports.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Example report plugin&lt;/strong&gt;&lt;br/&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-surefire-report-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;reportSets&amp;gt;
        &amp;lt;reportSet&amp;gt;
            &amp;lt;id&amp;gt;integration-tests&amp;lt;/id&amp;gt;
            &amp;lt;reports&amp;gt;
                &amp;lt;report&amp;gt;report-only&amp;lt;/report&amp;gt;
                &amp;lt;report&amp;gt;failsafe-report-only&amp;lt;/report&amp;gt;
            &amp;lt;/reports&amp;gt;
        &amp;lt;/reportSet&amp;gt;
    &amp;lt;/reportSets&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;



&lt;a name=&quot;javadoc&quot;&gt;&lt;/a&gt;
&lt;p&gt;
  &lt;strong&gt;JavaDoc - maven-javadoc-plugin&lt;/strong&gt; &amp;ndash; Bundles JavaDocs into the reporting structure. NOTE, this does not need to be run during the standard build, only during the reporting phase
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Example report plugin&lt;/strong&gt;&lt;br/&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-javadoc-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;skip&amp;gt;${javadocs.skip}&amp;lt;/skip&amp;gt;
        &amp;lt;failOnError&amp;gt;false&amp;lt;/failOnError&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;



&lt;a name=&quot;jxr&quot;&gt;&lt;/a&gt;
&lt;p&gt;
  &lt;strong&gt;JXR - maven-jx-plugin&lt;/strong&gt; &amp;ndash; Builds cross-link information for classes. Checkstyle, PMD, FindBugs, JavaDocs and various other plugins can utilize the JXR configuration.  NOTE, this plugin must be run at an early place in the Maven lifecycle (suggest process-resources) in addition to the sitedoc plugin section.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Example report plugin&lt;/strong&gt;&lt;br/&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-jxr-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;aggregate&amp;gt;true&amp;lt;/aggregate&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;


&lt;h4&gt;Useful Plugins&lt;/h4&gt;
&lt;p&gt;Other handy plugins to use for site documentation include:
&lt;ul&gt;
&lt;li&gt;Taglist &amp;ndash; Searches source code for specific words like @TODO and FIXME, then collates them into a report per project &amp;mdash; &lt;a href=&quot;http://mojo.codehaus.org/taglist-maven-plugin/&quot; target=&quot;_blank&quot;&gt;http://mojo.codehaus.org/taglist-maven-plugin/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Versions &amp;ndash; Uses maven central and/or local mirror to look up each dependency, project properities and plugin versions, then produces a report with what can be updated both minor and major updates &amp;mdash; &lt;a href=&quot;http://mojo.codehaus.org/versions-maven-plugin/&quot; target=&quot;_blank&quot;&gt;http://mojo.codehaus.org/versions-maven-plugin/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Changelog - Uses SCM listed in the distributionManagement section to pull in a simple history for each file; listing most changed files, top contributors and links up changes with web-based SCM tool like github or web-svn &amp;mdash; &lt;a href=&quot;http://maven.apache.org/plugins/maven-changelog-plugin/index.html&quot; target=&quot;_blank&quot;&gt;http://maven.apache.org/plugins/maven-changelog-plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Changes - Integrates with Jira, Trac or Bugzilla (or any changelist.xml produced by an Issue Management system) and displays what bugs have been updated in between the current and previous release &amp;mdash; &lt;a href=&quot;http://maven.apache.org/plugins/maven-changes-plugin/&quot; target=&quot;_blank&quot;&gt;http://maven.apache.org/plugins/maven-changes-plugin/&lt;/a&gt;
&lt;/ul&gt;

&lt;h3&gt;End of Part 1&lt;/h3&gt;
&lt;p&gt;The next post will cover the developer portion of the documentation; more specifically covering XDoc and APT.  The site documentation is robust and the next post will show how to program some of the XDoc portions of the docs by leveraging Velocity templates.
&lt;/p&gt;
&lt;p&gt;The last part of this blog post will cover multi-module projects.  In addition, that post will show how to deploy site-docs to a &lt;a href=&quot;http://pages.github.com/&quot; target=&quot;_blank&quot;&gt;Github Pages&lt;/a&gt; so you can have site docs at http://&amp;lt;&lt;strong&gt;username&lt;/strong&gt;&amp;gt;.github.com/&amp;lt;&lt;strong&gt;your-project&lt;/strong&gt;&amp;gt;.
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/2930961329493235161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/2930961329493235161' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/2930961329493235161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/2930961329493235161'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2012/03/maven-3-site-docs-part-1-basic-site.html' title='Maven 3 Site Docs Part 1: Basic Site Documentation'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-1957728046133881521</id><published>2012-02-21T20:21:00.000-08:00</published><updated>2012-02-28T07:34:43.353-08:00</updated><title type='text'>Colorized Maven Output on Mac OSX</title><content type='html'>&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;
Unlike many other open source build tools (for example, git) Maven does not provide any type of colorized output.  Maven&#39;s excessive amount of output can be hard to read and you tend to get lost in the sea of text.  My current client I&#39;ve been given a Mac to use and quickly found out that the existing Linux scripts did not work with iTerm.  My solution, take the existing Linux scripts and modify for the Mac OSX.
&lt;/p&gt;

&lt;h2&gt;Approach&lt;/h2&gt;
&lt;p&gt;
Since Maven does not have colorized output, the only option is to use &quot;sed&quot; (stream editor) that takes the output of maven, matches strings with regex and then adds in color codes.  The terminal does not escape ansi colors during the stream editing phase.  The solution is to use the &quot;tput&quot; command along with setab and setaf for the background and foreground respectively.
&lt;/p&gt;

&lt;h3&gt;Example of ANSI colors&lt;/h3&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;echo -e &quot;\033[1;34RED TEXT\[0m&quot;&lt;/pre&gt;

&lt;h3&gt;Example of TPUT colors&lt;/h3&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;echo -e &quot;${`tput setaf 1`}RED TEXT${`tput sgr0`}&quot;&lt;/pre&gt;

&lt;h2&gt;The Script&lt;/h2&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;
#!/bin/sh

# Written by Mike Ensor (mike@ensor.cc)
# Copywrite 2012
# Use as needed, modify, have fun!
# This is intended to be used for Maven3 + Mac OSX
#
# To use:
# in your &quot;.bashrc&quot; or &quot;.bash_profile&quot; add the following line:
# source ~/&lt;path to script&gt;/colorize-maven.sh
#

#Predefine all variables
c_black=
c_cyan=
c_magenta=
c_red=
c_white=
c_green=
c_yellow=
c_blue=
c_bg_black=
c_bg_cyan=
c_bg_magenta=
c_bg_red=
c_bg_white=
c_bg_green=
c_bg_yellow=
c_bg_blue=
c_end=
c_bold=

xterm_color() {
 # 0 Black
 # 1 Red
 # 2 Green
 # 3 Yellow
 # 4 Blue
 # 5 Magenta
 # 6 Cyan
 # 7 White

    # Yes, this could be a map
    c_bold=`tput setaf 0`
    c_bg_bold=`tput setab 0`
    c_black=`tput setab 0`
    c_bg_black=`tput setab 0`
    c_cyan=`tput setaf 6`
    c_bg_cyan=`tput setab 6`
    c_magenta=`tput setaf 5`
    c_bg_magenta=`tput setab 5`
    c_red=`tput setaf 1`
    c_bg_red=`tput setab 1`
    c_white=`tput setaf 7`
    c_bg_white=`tput setab 7`
    c_green=`tput setaf 2`
    c_bg_green=`tput setab 2`
    c_yellow=`tput setaf 3`
    c_bg_yellow=`tput setab 3`
    c_blue=`tput setaf 4`
    c_bg_blue=`tput setab 4`
    c_end=`tput sgr0`
}

#This is not used (yet)
ansi_color() {
    c_bold=   &#39;[1m&#39;
    c_blue=   &#39;[1;34m&#39;
    c_black=  &#39;[1;30m&#39;
    c_green=  &#39;[1;32m&#39;
    c_magenta=&#39;[1;35m&#39;
    c_red=    &#39;[1;31m&#39;
    c_cyan=   &#39;[1;36m&#39;
    c_end=    &#39;[0m&#39;
}

color_maven() {

    # pick color type
    if [ $TERM = &#39;xterm-color&#39; ]
    then
        xterm_color
#    elif [ $TERM = &#39;ansi&#39; ]
#    then
#     ansi_color
 else
     echo &quot;${c_red}WARNING:::Terminal &#39;${TERM}&#39; is not supported at this time. Colorized output will not happen for Maven${c_end}&quot;
 fi

 error=${c_bold}${c_red}
 info=${c_white}
 warn=${c_yellow}
 success=${c_green}
 projectname=${c_bold}${c_cyan}
 skipped=${c_white}
 downloading=${c_magenta}

 $MAVEN_HOME/bin/mvn $* | sed -e &quot;s/(\[INFO\]) Building( .*)/ ${info}\1${projectname}\2 ${c_end}/g&quot; \
  -e &quot;s/(Time elapsed: )([0-9]+[.]*[0-9]*.sec)/${c_cyan}\1${c_white}\2${c_end}/g&quot; \
  -e &quot;s/(Downloading: .*)/${downloading}\1${c_end}/g&quot; \
  -e &quot;s/BUILD FAILURE/${error}BUILD FAILURE${c_end}/g&quot; \
  -e &quot;s/WARNING: ([a-zA-Z0-9.-/\\ :]+)/${warn}WARNING: \1${c_end}/g&quot; \
  -e &quot;s/SEVERE: (.+)/${c_white}${c_bg_red}SEVERE: \1${c_end}/g&quot; \
  -e &quot;s/Caused by: (.+)/${c_white}${c_bg_green}Caused by: \1${c_end}/g&quot; \
  -e &quot;s/Running (.+)/${c_green}Running \1${c_end}/g&quot; \
  -e &quot;s/FAILURE (\[[0-9]+.[:0-9]+s\])/${error}FAILURE \1${c_end}/g&quot; \
  -e &quot;s/SUCCESS (\[[0-9]+.[:0-9]+s\])/${success}SUCCESS \1${c_end}/g&quot; \
  -e &quot;s/(\[INFO.*)/${info}\1${c_end}/g&quot; \
  -e &quot;s/INFO: (.+)/${c_white}INFO: \1${c_end}/g&quot; \
     -e &quot;s/(\[WARN.*)/${warn}\1${c_end}/g&quot; \
     -e &quot;s/(\[ERROR.*)/${error}\1${c_end}/g&quot; \
     -e &quot;s/(&lt;&lt;&lt; FAILURE!)/${error}\1${c_end}/g&quot; \
     -e &quot;s/Tests run: ([0-9]*), Failures: ([0-9]*), Errors: ([0-9]*), Skipped: ([0-9]*)/${c_green}Tests run: \1 ${c_end}, Failures: ${warn}\2 ${c_end}, Errors: ${error}\3 ${c_end}, Skipped:  ${skipped}\4 ${c_end}/g&quot;
}

alias mvn=color_maven

&lt;/pre&gt;
&lt;small&gt;NOTE: This script is intended to be used with Green text on Black background.  Adjust the colors as you want to come up with something more personal&lt;/small&gt;

&lt;h3&gt;Download script from Github&lt;/h3&gt;
&lt;a href=&quot;https://gist.github.com/1881211&quot; target=&quot;_blank&quot;&gt;Click here to view Gist on Github&lt;/a&gt;

&lt;h2&gt;How to install/use&lt;/h2&gt;
&lt;p&gt;
In your &quot;.bashrc&quot; or &quot;.bash_profile&quot; add the following line:&lt;br/&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;source ~/&amp;lt;path to script&amp;gt;/colorize-maven.sh&lt;/pre&gt;  
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/1957728046133881521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/1957728046133881521' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/1957728046133881521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/1957728046133881521'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2012/02/colorized-maven-output-on-mac-osx.html' title='Colorized Maven Output on Mac OSX'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-1957791946237170926</id><published>2012-01-17T21:29:00.000-08:00</published><updated>2012-01-17T21:29:59.359-08:00</updated><title type='text'>Mocking with JodaTime&#39;s DateTime and Google Guava&#39;s Supplier</title><content type='html'>&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;
If you&#39;re a seasoned unit tester, you&#39;ve learned to take note when you see any code working with &lt;em&gt;time&lt;/em&gt;, &lt;em&gt;concurrency&lt;/em&gt;, &lt;em&gt;random&lt;/em&gt;, &lt;em&gt;persistence&lt;/em&gt; and &lt;em&gt;disc I/O&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;
The reason for this is that tests can be very brittle and sometimes down-right impossible to test properly. This post will show how to abstract out &quot;time&quot; by injecting a replacement for it in the consumer.&amp;nbsp; This post will be using &lt;a href=&quot;http://www.springsource.org/&quot; target=&quot;_blank&quot;&gt;Spring 3&lt;/a&gt; as the Dependency Injection container, though &lt;a href=&quot;http://code.google.com/p/google-guice/&quot; target=&quot;_blank&quot;&gt;Guice&lt;/a&gt;, other DI containers or constructor/setters on POJOs would work as well.&amp;nbsp; I will also ignore Locales since the focus is on the injection of the DateTime, not DateTime itself.&lt;/p&gt;
&lt;h3&gt;Existing code&lt;/h3&gt;
&lt;p&gt;
You&#39;ve been handed a piece of code to unit test (or you are creating one and this is your first stab at it).&amp;nbsp; Our first piece of code, only one class: (&lt;span class=&quot;note&quot;&gt;This class is a Spring 3.1 controller and the purpose is to return back the current time as a String&lt;/span&gt;)&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;@Controller
@RequestMapping(value = &quot;/time&quot;)
@VisibleForTesting
class TimeController {

    @RequestMapping(value = &quot;/current&quot;, method = RequestMethod.GET)
    @ResponseBody
    public String showCurrentTime() {
        // BAD!!! Can&#39;t test
        DateTime dateTime = new DateTime();
        return DateTimeFormat.forPattern(&quot;hh:mm&quot;).print(dateTime);
    }
}
&lt;/pre&gt;
&lt;p&gt;Take note that the class does a &quot;new DateTime()&quot; in the class.&amp;nbsp; Here is the corresponding test class:&lt;/p&gt;
&lt;p&gt;
What happens when we run the test?&amp;nbsp; How about assuming we have a &lt;b&gt;very&lt;/b&gt; slow machine. You could (and most likely will) end up with &lt;strong&gt;your comparison &lt;em&gt;DateTime&lt;/em&gt; to be different than the returned &lt;em&gt;DateTime&lt;/em&gt;&lt;/strong&gt;. This is a problem!&lt;/p&gt;
&lt;p&gt;
First thing to do is to remove the dependency, but how are we going to do this?&amp;nbsp; If we make the DateTime a field on the class, we will still have the same problem.&amp;nbsp; Introduce Google Guava&#39;s Supplier interface.&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;Google Guava Supplier&lt;/h3&gt;
&lt;p&gt;
The Supplier interface only has one method, &quot;get()&quot; which will return an instance of whatever the supplier is setup for.&amp;nbsp; An example, the supplier will return a user&#39;s first name if they have logged in, and a default one if they have not:&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;public class FirstNameSupplier implements Supplier&amp;lt;String&amp;gt; {

    private String value;
    private static final String DEFAULT_NAME = &quot;GUEST&quot;;

    public FirstNameSupplier() {
        // Just believe that this goes and gets a User from somewhere
        String firstName = UserUtilities.getUser().getFirstName();
        // more Guava
        if(isNullOrEmpty(firstName)) {
            value = DEFAULT_NAME;
        } else {
            value = firstName;
        }
    }

    @Override
    public String get() {
        return value;
    }
}
&lt;/pre&gt;
&lt;p&gt;
To your implementing method, you don&#39;t care what the first name is, only that you get one.
&lt;/p&gt;
&lt;br/&gt;
&lt;h3&gt;Refactoring out DateTime&lt;/h3&gt;
&lt;p&gt;
Let&#39;s move on. For a much more real example of using a Supplier (and the point of this post) let&#39;s implement a &lt;em&gt;DateTime&lt;/em&gt; supplier to give us back the current &lt;em&gt;DateTime&lt;/em&gt;. While we&#39;re at it, let&#39;s also create an interface so that we can create mock implementations for testing:
&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;public interface DateTimeSupplier extends Supplier&amp;lt;DateTime&amp;gt; {
    DateTime get();
}
&lt;/pre&gt;
&lt;p&gt;
and &lt;strong&gt;an&lt;/strong&gt; implementation:
&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;public class DateTimeUTCSupplier implements DateTimeSupplier {
    @Override
    public DateTime get() {
        return new DateTime(DateTimeZone.UTC);
    }
}
&lt;/pre&gt;
&lt;p&gt;
Now we can take the &lt;em&gt;DateTimeUTCSupplier&lt;/em&gt; and inject that into our code that needs the current &lt;em&gt;DateTime&lt;/em&gt; as the &lt;em&gt;DateTimeSupplier&lt;/em&gt; interface:
&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;@Controller
@RequestMapping(value = &quot;/time&quot;)
@VisibleForTesting
class TimeController {

    @Autowired
    @VisibleForTesting
    // Injected DateTimeSupplier
    DateTimeSupplier dateTime;

    @RequestMapping(value = &quot;/current&quot;, method = RequestMethod.GET)
    @ResponseBody
    public String showCurrentTime() {
        return DateTimeFormat.forPattern(&quot;hh:mm&quot;).print(dateTime.get());
    }
}
&lt;/pre&gt;
&lt;p&gt;
In order to test this, we&#39;ll need to create a MockDateTimeSupplier and have a controller to pass in the specific instance we want to return:
&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;public class MockDateTimeSupplier implements DateTimeSupplier {

    private final DateTime mockedDateTime;

    public MockDateTimeSupplier(DateTime mockedDateTime) {
        this.mockedDateTime = mockedDateTime;
    }

    @Override
    public DateTime get() {
        return mockedDateTime;
    }
}
&lt;/pre&gt;
&lt;p&gt;
&lt;small&gt;Notice that the object being saved is passed in via the constructor. This will not get you the current date/time back, but will return back the specific instance you want&lt;/small&gt;
&lt;/p&gt;
&lt;p&gt;
and finally our test that exercises (slightly) the TimeController we implemented above:
&lt;/p&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;public class TimeControllerTest {

    private final int HOUR_OF_DAY = 12;
    private final int MINUTE_OF_DAY = 30;

    @Test
    public void testShowCurrentTime() throws Exception {
        TimeController controller = new TimeController();
        // Create the mock DateTimeSupplier with our known DateTime
        controller.dateTime = new MockDateTimeSupplier(new DateTime(2012, 1, 1, HOUR_OF_DAY, MINUTE_OF_DAY, 0, 0));

        // Call our method
        String dateTimeString = controller.showCurrentTime();

        // Using hamcrest for easier to read assertions and condition matchers
        assertThat(dateTimeString, is(String.format(&quot;%d:%d&quot;, HOUR_OF_DAY, MINUTE_OF_DAY)));
    }

}
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;
This post has shown how to use Google Guava&#39;s Supplier interface to abstract out a DateTime object so you can better design your implementations with unit testing in mind!  Suppliers are a great way to solve the &quot;just give me something&quot;, mind you it&#39;s a known type of something.&lt;/p&gt;
&lt;br/&gt;
Good luck!
&lt;br/&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/1957791946237170926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/1957791946237170926' title='42 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/1957791946237170926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/1957791946237170926'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2012/01/mocking-with-jodatimes-datetime-and.html' title='Mocking with JodaTime&#39;s DateTime and Google Guava&#39;s Supplier'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>42</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-2742407706523534806</id><published>2011-12-15T14:10:00.000-08:00</published><updated>2012-03-26T17:09:58.379-07:00</updated><title type='text'>How to setup several GitHub accounts on multiple machines with separate SSH keys</title><content type='html'>&lt;h4&gt;Problem&lt;/h4&gt;

So you&#39;ve got a personal GitHub account, one for one client, one for another and you want to keep them all separate.  How do you setup your box to clone private repositories based on which account you&#39;re using?  Here&#39;s the simple guide on how to do this

&lt;h4&gt;Assumptions&lt;/h4&gt;
I have set this up on Linux (Ubuntu 11.10) and Windows, but only via the Git Bash and/or Cygwin.  This post will not cover how to setup and where to store SSH keys for Windows or Mac, though Mac should be fairly similar to Linux.

&lt;h4&gt;Setup first SSH key&lt;/h4&gt;
I&#39;m not going to go into depth on how to setup SSH keys, you can read more about that &lt;a href=&quot;http://help.github.com/set-up-git-redirect/&quot;&gt;here&lt;/a&gt;. However, I will show the steps I used to get there.

For first-account: (please replace &quot;first-account&quot; with your GitHub account)
&lt;ol&gt;

&lt;li&gt;Change to your home .ssh folder
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;cd ~/.ssh
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;Setup your RSA key
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;ssh-keygen -t rsa -f ~/.ssh/first-account-rsa -C &quot;first-account@example.com&quot;
&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;After following the directions, you should get something that looks like:
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;The key fingerprint is:
00:ff:00:cc:13:00:bb:ll:aa:hh

The key&#39;s randomart image is:
+--[ RSA 2048]----+
|     .+   +      |
|       = o P .   |
|        = * *    |
|       o = +     |
|      o S .      |
|     o o =       |
|      o . E      |
|                 |
|                 |
+-----------------+

&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;Open your GitHub.com account setup page, click on the &quot;SSH Public Keys&quot; tab.&lt;/li&gt;

&lt;li&gt;Create a new SSH key and copy the contents of ~/.ssh/first-account-rsa.pub and place into the new text field. &lt;b&gt;Name it something unique&lt;/b&gt; so you can remember which machine you&#39;re using for your account.&lt;br/&gt;
&lt;br/&gt;
If you plan on each of your accounts needing access, open each of those accounts and add your SSH key to each account. This isn&#39;t very common, so only do this if you need to.
&lt;/li&gt;

&lt;li&gt;To test, type in:
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;ssh -t git@github.com
&lt;/pre&gt;
&lt;br/&gt;
As long as you do not see &quot;access denied&quot;, you&#39;re good.  You might see &quot;failed on channel 0&quot;, this is ok.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;Adding a second account&lt;/h4&gt;
&lt;p&gt;Now you should have your first account working, let&#39;s setup and add the second account.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Repeat process 1-5 and stop (using the next account)&lt;/li&gt;
&lt;li&gt;Create a file named &quot;config&quot; in your ~/.ssh folder
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;echo &#39;&#39; &gt; ~/.ssh/config
&lt;/pre&gt;
&amp;ndash;or&amp;ndash;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;touch ~/.ssh/config
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Use your favorite editor to add the configuration information for the SSH client to determine which RSA key to use:
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;
# first-account GitHub account
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/first-account-rsa # Note, this is the private key matching the .pub

# second-account
Host github-second-account  # NOTE: The host is NOT github.com, more on this further down
HostName github.com
User git
IdentityFile ~/.ssh/second-account-rsa # Private key for the second account

# repeat for the third and so on
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Save the file and your configuration is done&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let&#39;s look at the config file in a bit more detail.  The first account is the base &lt;em&gt;github.com&lt;/em&gt; host name, and you typically see a git URL as &lt;em&gt;git@&lt;strong&gt;github.com&lt;/strong&gt;:user/project.git&lt;/em&gt;.  With your first account, you will leave this the domain the same&lt;sup&gt;**&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;NOTE: This doesn&#39;t stop you from modifying your ~/.ssh/config file and instead of using &quot;github.com&quot; as your default host, setting the value to &quot;github-first-account&quot;.&lt;/p&gt;

&lt;p&gt;
Now, for your second account, you will need to modify the URL you are using to clone the repository.  This is done by changing the domain from &quot;github.com&quot; to &quot;github-second-account&quot;.  For example: &lt;em&gt;git@&lt;strong&gt;github-second-account&lt;/strong&gt;:user/project.git&lt;/em&gt;
&lt;/p&gt;

&lt;h4&gt;Summary&lt;/h4&gt;
&lt;p&gt;You should now have the setup to clone and modify code for multiple accounts on the same machine. Repeat this process for each machine you would like to make available to GitHub.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/2742407706523534806/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/2742407706523534806' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/2742407706523534806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/2742407706523534806'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2011/12/how-to-setup-several-github-accounts-on.html' title='How to setup several GitHub accounts on multiple machines with separate SSH keys'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-3351459501921598780</id><published>2011-12-03T21:36:00.001-08:00</published><updated>2011-12-03T22:55:20.992-08:00</updated><title type='text'>Spring 3.1 + Cloud Foundry + Local Development</title><content type='html'>This post will help you build a Spring 3.1 web application using MongoDB on Cloud Foundry.&amp;nbsp; In addition to pushing to Cloud Foundry, you will also be able to develop in your local environment with a MongoDB instance.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Goals&lt;/span&gt;&lt;br /&gt;
The goals for this blog posting 
will be to build the application locally, then publish to your local 
Cloud Foundry instance.&amp;nbsp; We will utilize the Cloud Foundry runtime, and 
the new Spring Profiles&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Setup&lt;/span&gt;&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Create an account with Cloud Foundry (&lt;a href=&quot;https://www.cloudfoundry.com/micro&quot;&gt;https://www.cloudfoundry.com/micro&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Follow instructions to setup your own Micro Cloud&lt;/li&gt;
&lt;ol&gt;
&lt;li&gt;I use VMWare&#39;s player&lt;/li&gt;
&lt;li&gt;Verify &quot;vmc info&quot; that the micro cloud console matches &lt;/li&gt;
&lt;/ol&gt;
&lt;li&gt;Download MongoDB (at least version 2.0)&lt;/li&gt;
&lt;li&gt;Install and be familiar with Maven 3 (&lt;a href=&quot;http://maven.apache.org/&quot;&gt;http://maven.apache.org&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Familiarize yourself with Spring 3.1, Spring Data and Spring MongoDB&lt;/li&gt;
&lt;li&gt;Clone or download the source (&lt;a href=&quot;https://github.com/mike-ensor/first-cloud-app&quot;&gt;https://github.com/mike-ensor/first-cloud-app&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Run the app locally with:
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;mvn clean package cargo:run -DskipTests&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Go to &lt;a href=&quot;http://localhost:8080/home&quot; target=&quot;_blank&quot;&gt;http://localhost:8080/home&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Profiles&lt;/span&gt;&lt;br /&gt;
New in Spring 3.1 are the environment profiles which allow a developer to activate groups of beans based on an environment parameter.&amp;nbsp; There are several &quot;&lt;b&gt;gotchas&lt;/b&gt;&quot; that I&#39;ve discovered, one being an undocumented ordering for beans using profiles.&lt;br /&gt;
&lt;br /&gt;
Take a look at &lt;a href=&quot;https://github.com/mike-ensor/first-cloud-app/blob/master/src/main/resources/data-services.xml&quot; target=&quot;_blank&quot;&gt;data-services.xml&lt;/a&gt;.&amp;nbsp; Notice how the MongoTemplate is defined before the &lt;beans&gt;.&amp;nbsp; This is against my intuition because the MongoTemplate takes a reference to the MongoFactory object, which is defined below the MongoTemplate definition.&lt;/beans&gt;&lt;br /&gt;
&lt;br /&gt;
The second &quot;gotcha&quot; came from when and where to set the parameter to enable Spring&#39;s profiles.&amp;nbsp; The documentation and blogs do not explicitly mention that the developer must specify the profile that is active.&amp;nbsp; It was implied by the documentation that &quot;&lt;b&gt;default&lt;/b&gt;&quot; was active by default, but this is not true.&amp;nbsp; In order for the default profile to be active, I added it as a system property in my cargo settings.&amp;nbsp; (as long as it is a system environment property, feel free to set it anywhere or any way you&#39;d like).&amp;nbsp; Take a look at the &lt;a href=&quot;https://github.com/mike-ensor/first-cloud-app/blob/master/pom.xml&quot; target=&quot;_blank&quot;&gt;pom.xml&lt;/a&gt; file around &lt;i&gt;line 40&lt;/i&gt; for the local Maven property and then around &lt;i&gt;line 253&lt;/i&gt; for the environment variable to be set.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Local development vs. Cloud Development&lt;/span&gt;&lt;br /&gt;
One of the main goals I had for interacting with Cloud Foundry is that I wanted a local development environment to speed up and ease development and reduce complexity with debugging.&amp;nbsp; Notice that in &lt;a href=&quot;https://github.com/mike-ensor/first-cloud-app/blob/master/src/main/resources/data-services.xml&quot; target=&quot;_blank&quot;&gt;data-services.xml&lt;/a&gt; there is a &quot;cloud&quot; profile and a &quot;default&quot;.&amp;nbsp; The point of the &quot;default&quot; profile is to have beans that are constructed when on a local environment.&amp;nbsp; You can see that there are two definitions of MongoFactory, one using Spring Data MongoDB&#39;s XML namespace and one using CloudFoundry Runtime&#39;s namespace.&amp;nbsp; I am not going to cover why these work the way they do, so if you&#39;d like information, refer to &lt;a href=&quot;http://blog.springsource.org/2011/04/12/cloud-foundry-for-spring-developers/&quot;&gt;http://blog.springsource.org/2011/04/12/cloud-foundry-for-spring-developers/&lt;/a&gt; and &lt;a href=&quot;http://blog.springsource.org/2011/11/09/using-cloud-foundry-services-with-spring-applications-part-3-the-cloud-namespace/&quot;&gt;http://blog.springsource.org/2011/11/09/using-cloud-foundry-services-with-spring-applications-part-3-the-cloud-namespace/&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Pushing to Cloud Foundry&lt;/span&gt;&lt;br /&gt;
Now that you have a local running instance of the webapp, you will notice that the artifact is called &quot;&lt;b&gt;first-cloud-app.war&lt;/b&gt;&quot;, which you can find in the &quot;/target&quot; folder.&amp;nbsp; This is a problem when pushing to the Cloud Foundry instance since the name cannot contain any non-alpha characters.&amp;nbsp; Cloud Foundry&#39;s vmc tool is built from the VCAP open source project that is responsible for the open source PaaS services.&amp;nbsp; Another PaaS service includes App Fog, which allows you to basically use the same commands, but replace &quot;vmc&quot; for &quot;af&quot;.&amp;nbsp; Both services fall victim to the naming problem.&lt;br /&gt;
&lt;br /&gt;
In order to get around the naming problem, I have created a Maven profile &lt;b&gt;cloud&lt;/b&gt; that builds the WAR artifact as &quot;mikeensor.war&quot;.&amp;nbsp; Please change this to match your application&#39;s name since you won&#39;t have the user/password to publish (or the DNS) to publish to my micro instance.&amp;nbsp; The name will need to fit into the URL pattern http://&amp;lt;&lt;b&gt;applicationname&lt;/b&gt;&amp;gt;.&lt;cloudfoundry-name-when-registered&gt;.cloudfoundry.me.&lt;/cloudfoundry-name-when-registered&gt;&lt;br /&gt;
&lt;br /&gt;
To publish to your local cloud foundry micro instance, goto the root folder and type the following.&amp;nbsp; (this is assuming your micro instance is running and there are no &quot;red&quot; errors.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;mvn clean package -Pcloud
vmc push &amp;lt;application name&amp;gt; -path target/&lt;/pre&gt;
&lt;br /&gt;
(if you have already pushed before, you will need to type:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;vmc update &amp;lt;application name&amp;gt; -path target/&lt;/pre&gt;
&lt;br /&gt;
&lt;div style=&quot;font-family: Georgia,&amp;quot;Times New Roman&amp;quot;,serif;&quot;&gt;
Note: It is possible to use the Maven Plugin for Cloud Foundry, however, I have still not been able to get it to work without changing the name of the artifact.&lt;/div&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Enabling and connecting to services&lt;/span&gt;&lt;br /&gt;
You must create a service(s) so that your application can bind to the data source.&amp;nbsp; The VCAP (vmc) application handles how the configuration works when loading your application into Cloud Foundry.&amp;nbsp; It does this via an environment variable that is consumed in the &lt;cloud&gt; namespaced configuration element.&lt;/cloud&gt;&lt;br /&gt;
&lt;br /&gt;
In my example, I created a MongoDB service by typing:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;vmc create-service mongodb --name &amp;lt;what you want to call your instance&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
I named mine &quot;second&quot; (because I had created a first) and you will see that in &lt;a href=&quot;https://github.com/mike-ensor/first-cloud-app/blob/master/src/main/resources/data-services.xml&quot; target=&quot;_blank&quot;&gt;data-services.xml&lt;/a&gt; the cloud XML configuration refers to the name of the service. &lt;br /&gt;
&amp;nbsp; &lt;br /&gt;
&lt;span style=&quot;font-family: Georgia,&amp;quot;Times New Roman&amp;quot;,serif;&quot;&gt;Note that if you have multiple MongoDB instances, you will need to do some Spring configuration (@Qualifier) when you want to use different instances.&amp;nbsp; This is not covered by this blog posting.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Now you will need to &quot;bind&quot; the service to your application.&amp;nbsp; This is done by typing:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;vmc bind-service &amp;lt;name above&amp;gt; &amp;lt;application name&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Testing it out&lt;/span&gt;&lt;br /&gt;
You should be able to goto &lt;i&gt;http://&lt;application name=&quot;&quot;&gt;.&lt;cloudfoundry-registry&gt;.cloudfoundry.me/home&lt;/cloudfoundry-registry&gt;&lt;/application&gt;&lt;/i&gt; (example: http://mikeensor.mikeensor.cloudfoundry.me/home)&lt;br /&gt;
&lt;br /&gt;
Congratulations!&amp;nbsp; You should have not only successfully deployed to Cloud Foundry (micro instance), bound to a MongoDB instance, but should be able to run in your local environment too!&amp;nbsp; As I get time, I will try to add in more detailed features such as multiple types of storage and post other &quot;gotchas&quot; as I find them.&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/3351459501921598780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/3351459501921598780' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/3351459501921598780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/3351459501921598780'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2011/12/spring-31-cloud-foundry-local.html' title='Spring 3.1 + Cloud Foundry + Local Development'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-2232394967394955602</id><published>2011-08-02T16:02:00.000-07:00</published><updated>2011-08-03T08:28:57.765-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="jstestdriver"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><category scheme="http://www.blogger.com/atom/ns#" term="unit test"/><title type='text'>Maven + JavaScript Unit Test: Running in a Continuous Integration Environment</title><content type='html'>&lt;h3&gt;JavaScript Unit Testing Continued&lt;/h3&gt;So you&#39;re still interested in unit testing JavaScript (good). This post is an extension of my much more indepth first posting on how to unit test JavaScript using JS Test Driver. &lt;a href=&quot;http://www.ensor.cc/2011/05/maven-javascript-unit-test-using.html&quot; target=&quot;_blank&quot;&gt;Please check it out here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Recap Last Posting&lt;/h3&gt;In the last posting we successfully unit tested JavaScript using Maven and JsTest Driver.  This allowes us to test JavaScript when on an environment that has a modern browser installed and can be run.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Problem with typical CI environments&lt;/h3&gt;So what happens when the test are passing on your local box, but you go to check in your code and the Continuous Integration (&lt;abbr&gt;CI&lt;/abbr&gt;) server pukes on the new tests becasue there is no &quot;screen&quot; to run chrome or firefox?  As of this posting, none of the top-tier browsers have a &quot;headless&quot; or an in-memory only browser window.  There are alternatives to running JavaScript in a browser, such as rhino.js, env.js or HtmlUnit, however, these are just ports of browsers and the JavaScript and DOM representation are not 100% accurate which can lead to problems with your code when rendered in a client&#39;s browser.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Approach&lt;/h3&gt;What we need to do is to run JSTestDriver&#39;s browser in a Virtual X Framebuffer (Xvfb) which is possible on nearly all Linux based systems.  The example below uses a Solaris version of Linux, however, Debian and RedHat linux distrubutions come with the simplified bash script to easily run an appliation in a virtual framebuffer.  This solution was derived from one posted solution on the JS Test Driver wiki (&lt;a href=&quot;http://code.google.com/p/js-test-driver/wiki/ContinuousBuild&quot; target=&quot;_blank&quot;&gt;http://code.google.com/p/js-test-driver/wiki/ContinuousBuild&lt;/a&gt;.  The given example is also a full working example that is in use at my current client.&lt;br /&gt;
&lt;br /&gt;
Here is the quick list of what we will accomplish.  Note, several of these steps are discussed in depth in the &lt;a href=&quot;http://www.ensor.cc/2011/05/maven-javascript-unit-test-using.html&quot; target=&quot;_blank&quot;&gt;previous post&lt;/a&gt; and are not covered in depth here.&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Create a profile to run Js Unit-Tests&lt;/li&gt;
&lt;li&gt;Copy JsTestDriver library to a known location for Maven to use&lt;/li&gt;
&lt;li&gt;Copy JavaScript main and test files to known locations&lt;/li&gt;
&lt;li&gt;Use ANT to start JsTestDriver and pipe the screen into xvfb&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
Here is a sample profile to use.  You will need to adjust the properties at the top of the profile to match your system.&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;profile&amp;gt;
    &amp;lt;!-- Runs JS Unit Test inside of Xvfb --&amp;gt;
    &amp;lt;id&amp;gt;ci-jstests&amp;lt;/id&amp;gt;
    &amp;lt;properties&amp;gt;
        &amp;lt;firefox.location&amp;gt;/opt/swf/bin/firefox&amp;lt;/firefox.location&amp;gt;
        &amp;lt;js-test-driver.version&amp;gt;1.3.2&amp;lt;/js-test-driver.version&amp;gt;
        &amp;lt;xvfb.location&amp;gt;/opt/X11R6/xvfb-run&amp;lt;/xvfb.location&amp;gt;
    &amp;lt;/properties&amp;gt;
    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;!-- Copy JS Test Driver JAR to target folder --&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-dependency-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;2.1&amp;lt;/version&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;id&amp;gt;copy&amp;lt;/id&amp;gt;
                        &amp;lt;phase&amp;gt;generate-resources&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;copy&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;artifactItems&amp;gt;
                                &amp;lt;artifactItem&amp;gt;
                                    &amp;lt;groupId&amp;gt;com.google.jstestdriver&amp;lt;/groupId&amp;gt;
                                    &amp;lt;artifactId&amp;gt;jstestdriver&amp;lt;/artifactId&amp;gt;
                                    &amp;lt;version&amp;gt;${js-test-driver.version}&amp;lt;/version&amp;gt;
                                    &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;
                                    &amp;lt;overWrite&amp;gt;true&amp;lt;/overWrite&amp;gt;
                                    &amp;lt;destFileName&amp;gt;jsTestDriver.jar&amp;lt;/destFileName&amp;gt;
                                &amp;lt;/artifactItem&amp;gt;
                            &amp;lt;/artifactItems&amp;gt;
                            &amp;lt;outputDirectory&amp;gt;${project.build.directory}/jstestdriver&amp;lt;/outputDirectory&amp;gt;
                            &amp;lt;overWriteReleases&amp;gt;false&amp;lt;/overWriteReleases&amp;gt;
                            &amp;lt;overWriteSnapshots&amp;gt;true&amp;lt;/overWriteSnapshots&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;

            &amp;lt;!-- Copy JavaScript files and Tests files  --&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-resources-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;2.4.3&amp;lt;/version&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;id&amp;gt;copy-main-files&amp;lt;/id&amp;gt;
                        &amp;lt;phase&amp;gt;generate-test-resources&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;copy-resources&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;outputDirectory&amp;gt;${project.build.directory}/test-classes/main-js&amp;lt;/outputDirectory&amp;gt;
                            &amp;lt;resources&amp;gt;
                                &amp;lt;resource&amp;gt;
                                    &amp;lt;directory&amp;gt;src/main/webapp/scripts&amp;lt;/directory&amp;gt;
                                    &amp;lt;filtering&amp;gt;false&amp;lt;/filtering&amp;gt;
                                &amp;lt;/resource&amp;gt;
                            &amp;lt;/resources&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;id&amp;gt;copy-test-files&amp;lt;/id&amp;gt;
                        &amp;lt;phase&amp;gt;generate-test-resources&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;copy-resources&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;outputDirectory&amp;gt;${project.build.directory}/test-classes/test-js&amp;lt;/outputDirectory&amp;gt;
                            &amp;lt;resources&amp;gt;
                                &amp;lt;resource&amp;gt;
                                    &amp;lt;directory&amp;gt;src/test/webapp/scripts&amp;lt;/directory&amp;gt;
                                    &amp;lt;filtering&amp;gt;false&amp;lt;/filtering&amp;gt;
                                &amp;lt;/resource&amp;gt;
                            &amp;lt;/resources&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;

            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-antrun-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;1.6&amp;lt;/version&amp;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;run&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;target&amp;gt;
                                &amp;lt;mkdir dir=&amp;quot;${project.build.directory}/js-test-results&amp;quot; /&amp;gt;
                                &amp;lt;exec executable=&amp;quot;${xvfb.location}&amp;quot;&amp;gt;
                                    &amp;lt;arg line=&amp;quot;java&amp;quot; /&amp;gt;
                                    &amp;lt;arg line=&amp;quot;-jar ${project.build.directory}/jstestdriver/jsTestDriver.jar&amp;quot; /&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--port 4220&amp;quot; /&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--testOutput ${project.build.directory}/js-test-results&amp;quot; /&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--config ${project.build.directory}/test-classes/jsTestDriver.conf&amp;quot; /&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--browser ${firefox.location}&amp;quot; /&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--tests all&amp;quot; /&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--verbose&amp;quot; /&amp;gt;
                                &amp;lt;/exec&amp;gt;
                            &amp;lt;/target&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
&amp;lt;/profile&amp;gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Possible problems&lt;/h3&gt;Although I cannot predict or fix all problems, I can share the one major problem I ran into with Solaris and the script used to fix that.  In Solaris (and could happen to other distros) the xvfb-run script was not available and several of the other libraries did not exist.  I first had to download the latest X libraries and place them in their appropriate locations on the CI server.  Next, I had to re-engineer the xvfb-run script.  Here is a copy of my script (&lt;small&gt;NOTE: This is the solution for my server and this may not work for you&lt;/small&gt;)&lt;br /&gt;
&lt;br /&gt;
I created a script that contains:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;/usr/openwin/bin/Xvfb :1 screen 0 1280x1024x8 pixdepths 8 24 fbdir /tmp/.X11-vbf &amp;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/2232394967394955602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/2232394967394955602' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/2232394967394955602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/2232394967394955602'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2011/08/maven-javascript-unit-test-running-in.html' title='Maven + JavaScript Unit Test: Running in a Continuous Integration Environment'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-7394534495092409336</id><published>2011-07-12T00:58:00.000-07:00</published><updated>2011-07-12T00:58:31.246-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fat war"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><category scheme="http://www.blogger.com/atom/ns#" term="overlay"/><category scheme="http://www.blogger.com/atom/ns#" term="POM"/><category scheme="http://www.blogger.com/atom/ns#" term="skinny war"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring 3"/><category scheme="http://www.blogger.com/atom/ns#" term="war"/><title type='text'>Maven&#39;s WAR Overlays: How to manage dependencies</title><content type='html'>If you&#39;re stumbling on this post looking for a way to manage dependencies with WAR overlays, please make sure you check out &lt;a href=&quot;http://www.ensor.cc/2011/06/mavens-war-overlay-what-are-war.html&quot; target=&quot;_blank&quot;&gt;part one&lt;/a&gt; of this blog posting to get the background about how to apply and use WAR overlays in your POM file. This post picks up from the last post and it&#39;s assumed that you understand how to apply a WAR to an existing master project.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Quick recap&lt;/h2&gt;Why a quick recap?  We&#39;re going to go into depth on how dependencies and libraries are applied to the master project.  In order to have a WAR overlay, you must include the WAR as a dependency to the master project and must be overlayed during the war-plugin package phase.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Where do the dependency libraries go?&lt;/h2&gt;As mentioned in &lt;a href=&quot;http://www.ensor.cc/2011/06/mavens-war-overlay-what-are-war.html&quot; target=&quot;_blank&quot;&gt;part one&lt;/a&gt; of this blog posting, files are placed in their parent&#39;s locations if it exists. What this means is that if, in your overlay WAR you have a .jsp file in /WEB-INF/welcome.jsp, the master WAR will then have a file named &quot;welcome.jsp&quot; in the /WEB-INF.  Furthermore, if there is already a file named &quot;welcome.jsp&quot;, that file will not be overwritten.  If we extrapolate this a bit more, the libraries in the /WEB-INF/lib folder from the overlay will be placed inside the /WEB-INF/lib folder of the master project.  This is great and all except when different versions of libraries exist causing runtime failures.  Good news, there are ways to manage the dependencies in both the overlay WAR and the master project.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;How to see your main artifact&#39;s libraries?&lt;/h2&gt;In order to determine what libraries are in which artifact, there are two simple ways.  First, determine what libraries are in your master WAR.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;mvn clean package 

ls -al target/YOUR_ARTIFACT_WAR/WEB-INF/lib

&lt;/pre&gt;&lt;small&gt;NOTE: adding &quot;-DskipTests&quot; when added to the above maven command would skip tests and would make this step a bit faster, though, it is strictly optional&lt;/small&gt;&lt;br /&gt;
&lt;br /&gt;
Secondly, add the &quot;workDirectory&quot; parameter to the configuration portion of your war-plugin when applying the overlay. Example: &amp;lt;workDirectory&amp;gt;target/extract_here&amp;lt;/workDirectory&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your master project&#39;s POM file:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugins&amp;gt;
...
...
&amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;2.1.1&amp;lt;/version&amp;gt;
        &amp;lt;configuration&amp;gt;
                &amp;lt;workDirectory&amp;gt;target/overlay-war-folder&amp;lt;/workDirectory&amp;gt;
                &amp;lt;overlays&amp;gt;
                        &amp;lt;overlay&amp;gt;
                                &amp;lt;groupId&amp;gt;com.yourcompany&amp;lt;/groupId&amp;gt;
                                &amp;lt;artifactId&amp;gt;branded-templates&amp;lt;/artifactId&amp;gt;
                        &amp;lt;/overlay&amp;gt;
                &amp;lt;/overlays&amp;gt;
        &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
...
...
&amp;lt;/plugins&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
This additional property will place each overlay&#39;s exploded contents into the specified folder to help debug library conflicts.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;How to exclude dependencies/libraries at build time?&lt;/h2&gt;It can be a pain to manage the dependencies between each of the overlays, especially if the overlay is not under your development control.  One method would be to manage the dependencies within the two POM files by utilizing the &quot;provided&quot; and &quot;optional&quot; dependencies that maven provides.  However, if the overlay project can also stand as stand-alone project, this method will not work because the libraries are not considered to be provided or optional when running independently.  This is common when trying to test each of the overlays independently.  An additional option to control the libraries is to exclude them from the master WAR during the package phase.  This is achieved by using the &quot;excludes&quot; parameter in each of the overlay sections.  For example, to remove all of the spring libraries, you could exclude &quot;spring*.jar&quot;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugins&amp;gt;
...
...
&amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;2.1.1&amp;lt;/version&amp;gt;
        &amp;lt;configuration&amp;gt;
                &amp;lt;workDirectory&amp;gt;target/overlay-war-folder&amp;lt;/workDirectory&amp;gt;
                &amp;lt;overlays&amp;gt;
                        &amp;lt;overlay&amp;gt;
                                &amp;lt;groupId&amp;gt;com.yourcompany&amp;lt;/groupId&amp;gt;
                                &amp;lt;artifactId&amp;gt;branded-templates&amp;lt;/artifactId&amp;gt;
                                &amp;lt;excludes&amp;gt;
                                        &amp;lt;exclude&amp;gt;WEB-INF/lib/spring*.jar&amp;lt;/exclude&amp;gt;
                                &amp;lt;/excludes&amp;gt;
                                &amp;lt;excludes&amp;gt;
                                        &amp;lt;exclude&amp;gt;WEB-INF/lib/log4j*.jar&amp;lt;/exclude&amp;gt;
                                &amp;lt;/excludes&amp;gt;
                        &amp;lt;/overlay&amp;gt;
                &amp;lt;/overlays&amp;gt;
        &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
...
...
&amp;lt;/plugins&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
You might start asking yourself, this is going to get complicated really quickly, and you&#39;re right, there are other options.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Skinny vs Fat WAR Overlays&lt;/h2&gt;Up until now, all of our overlays have been considered &quot;fat&quot; because they contain all of it&#39;s dependencies which get overlaid onto the master WAR file.  There is an alternative that is more commonly known as the &quot;skinny WAR&quot;.  A skinny WAR is a combination between most of this post&#39;s tactics.  NOTE: &lt;em&gt;The method I am showing you is known as a &quot;skinnier WAR&quot; because the dependency libraries do exist in the overlay&#39;s WAR file, however, the classes will be externalized and the libraries can be removed during final packaging of the master project.&lt;/em&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Achieving the &quot;skinny WAR&quot;&lt;/h2&gt;First, in the overlay project, during the &lt;em&gt;package&lt;/em&gt; phase, tell maven to build the project&#39;s classes as an extra artifact in addition to the WAR file.  This set of classes will become a jar file which will be used as a second dependency in the master project&#39;s POM.&lt;br /&gt;
&lt;br /&gt;
In the Overlay&#39;s POM file (add to the existing war plugin):&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugins&amp;gt;
...
...
&amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;2.1.1&amp;lt;/version&amp;gt;
        &amp;lt;configuration&amp;gt;
                &amp;lt;attachClasses&amp;gt;true&amp;lt;/attachClasses&amp;gt;
        &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
...
...
&amp;lt;/plugins&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
After successfully installing/deploying the overlay project, we will add the classes/jar file and the WAR dependency to the master project&#39;s POM file.&lt;br /&gt;
&lt;br /&gt;
In the master project&#39;s POM file:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;dependency&amp;gt;  
   &amp;lt;groupId&amp;gt;com.yourcompany&amp;lt;/groupId&amp;gt;  
   &amp;lt;artifactId&amp;gt;branded-templates&amp;lt;/artifactId&amp;gt;  
   &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;  
&amp;lt;/dependency&amp;gt;  


&amp;lt;dependencies&amp;gt;
...
...
&amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;com.yourcompany&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;branded-templates&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.1&amp;lt;/version&amp;gt;
        &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;com.yourcompany&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;branded-templates&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.1&amp;lt;/version&amp;gt;
        &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;
        &amp;lt;classifier&amp;gt;classes&amp;lt;/classifier&amp;gt;
&amp;lt;/dependency&amp;gt;
...
...
&amp;lt;/dependencies&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
And finally, combine the excludes learned in the last example section above to exclude all .jar files from the overlay WAR.&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugins&amp;gt;
...
...
&amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;2.1.1&amp;lt;/version&amp;gt;
        &amp;lt;configuration&amp;gt;
                &amp;lt;workDirectory&amp;gt;target/overlay-war-folder&amp;lt;/workDirectory&amp;gt;
                &amp;lt;overlays&amp;gt;
                        &amp;lt;overlay&amp;gt;
                                &amp;lt;groupId&amp;gt;com.yourcompany&amp;lt;/groupId&amp;gt;
                                &amp;lt;artifactId&amp;gt;branded-templates&amp;lt;/artifactId&amp;gt;
                                &amp;lt;excludes&amp;gt;
                                        &amp;lt;exclude&amp;gt;WEB-INF/lib/*.jar&amp;lt;/exclude&amp;gt;
                                &amp;lt;/excludes&amp;gt;
                        &amp;lt;/overlay&amp;gt;
                &amp;lt;/overlays&amp;gt;
        &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
...
...
&amp;lt;/plugins&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;strong&gt;NOTE: Dependencies that exist in the Overlay will need to be added as dependencies to the master project because they have been removed from the overlay&#39;s /WEB-INF/lib folder.  This is the main &lt;em&gt;known&lt;/em&gt; risk of using skinny war overlays&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Congratulations!&lt;/h2&gt;You now have a project with limited library conflicts and can better manager the main project and it&#39;s stability.&lt;br /&gt;
&lt;br /&gt;
Thank you for reading &lt;a href=&quot;http://www.ensor.cc/2011/06/mavens-war-overlay-what-are-war.html&quot; target=&quot;_blank&quot;&gt;part one&lt;/a&gt; and this post, part two. Please feel free too leave comments or questions and I will do my best to answer them in a timely manor.</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/7394534495092409336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/7394534495092409336' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/7394534495092409336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/7394534495092409336'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2011/07/mavens-war-overlays-how-to-manage.html' title='Maven&#39;s WAR Overlays: How to manage dependencies'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-613627678394893927</id><published>2011-06-27T23:02:00.000-07:00</published><updated>2011-06-27T23:26:41.698-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><category scheme="http://www.blogger.com/atom/ns#" term="overlay"/><title type='text'>Maven&#39;s WAR Overlay: What are WAR Overlays?</title><content type='html'>&lt;h2&gt;What is a WAR overlay?&lt;/h2&gt;&lt;cite&gt;def: Overlays are used to share common resources across multiple web applications. The dependencies of a WAR project are collected in WEB-INF/lib, except for WAR artifacts which are overlayed on to the WAR project itself.&lt;/cite&gt; &lt;small&gt;&lt;a href=&quot;http://maven.apache.org/plugins/maven-war-plugin/overlays.html&quot; target=&quot;_blank&quot;&gt;http://maven.apache.org/plugins/maven-war-plugin/overlays.html&lt;/a&gt;&lt;/small&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Why and where would you use a WAR overlay?&lt;/h2&gt;WAR overlays make up one more tool in your arsenal to combat repetitive code and/or resources.  Overlays allow you to combine many similar resources, for example, images, CSS and JavaScript files all into one project.  At build time, the overlay will be predictably merged into a master WAR project.  A great example of a WAR overlay is a branded website, combined with Sitemesh decorators.  Imagine you have a branded company website which consists of multiple web applications.  An industry standard approach would be to utilize Sitemesh decorators to decorate the application with brand specific styles and allow each of your applications to focus on the specific purpose of that application.  At this time, this blog post will not go into depth on Sitemesh decorators, however, more details are available at &lt;a href=&quot;http://www.sitemesh.org/&quot; target=&quot;_blank&quot;&gt;http://www.sitemesh.org/&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Leading on with our example, each of the decorators will need a set of CSS, images and possibly JavaScript files to define the application&#39;s branded style.  If your applications are to be deployed to production to look and act as one cohesive branded site, you will need to make sure that the images, CSS, JavaScript, decorator files and JSP files are all the same in each of your applications in order to keep a consistant brand across your applications.  Well, this is &lt;em&gt;duplicated code&lt;/em&gt; (currently ranked in my top 5 biggest &quot;code avoid-at-all-cost&quot; list).&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;How do you solve code duplication using WAR Overlays?&lt;/h2&gt;One approach to reducing the amount of duplicated code is to create a separate maven project with the packaging target type of WAR.  Then in each of your application&#39;s pom.xml file, include the overlay project as a dependency and construct it as an overlay using the maven-war-plugin.  This is known as a &lt;em&gt;Fat WAR Overlay&lt;/em&gt;. (&lt;em&gt;NOTE: In the next post I will cover other types of WAR overlays to help mitigate transient dependency problems&lt;/em&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;More specifics please!&lt;/h2&gt;First, let&#39;s create a new maven WAR project and name it &lt;strong&gt;&quot;branded-templates&quot;&lt;/strong&gt;.  (&lt;em&gt;NOTE: This post is not intended to be a comprehensive guide on creating a maven project, only adding to an already working maven project. If you need more assistance, please refer to some of my other post or maven&#39;s website for more guidance.&lt;/em&gt;)&lt;br /&gt;
&lt;br /&gt;
In our new branded-templates application, we will need to fill this with our resources.  Here is my recommended locations to place web-related resources within your project:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;em&gt;/src/main/webapp/styles&lt;/em&gt; &amp;ndash; used to hold your CSS files, (example: brand.css, reset.css, etc)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;/src/main/webapp/scripts/&lt;/em&gt; &amp;ndash; used to hold brand-wide JavaScript files, (example: jquery.1.x.x-min.js, jquery-my-company-validation.js, etc&lt;/li&gt;
&lt;li&gt;&lt;em&gt;/src/main/webapp/images/&lt;/em&gt; &amp;ndash; used to hold brand-wide images, (example: company-logo.png, facebook-icon.png, company-background.jpg, etc)&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Naming for now will not be important, but you will have to make decisions here because you have two naming options here that will have development implications.  You can name your resources and/or folders the same in both of your applications or you can name them different to get different desired results.  How is this going to impact my design and why do you need to think about this? (Answer coming after we add to the containing webapp project, keep following!)&lt;br /&gt;
&lt;br /&gt;
Let&#39;s continue.  We can now &lt;em&gt;install&lt;/em&gt; your &lt;em&gt;branded-templates&lt;/em&gt; WAR overlay to your local maven repository:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;mvn clean install&lt;/pre&gt;&lt;br /&gt;
If all is good, you should see a &quot;Successful build&quot; along with a 1.0-SNAPSHOT for your WAR&#39;s version.&lt;br /&gt;
&lt;br /&gt;
Next, let&#39;s crate a new main application called &lt;strong&gt;&quot;main-webapp&quot;&lt;/strong&gt;.  If you have an existing webapp, feel free to use that and work along with this example.  Inside of the main-webapp&#39;s pom.xml file, we need to add a plugin to build the two WARs into one WAR and add the overlay as a dependency to the project. &lt;br /&gt;
&lt;br /&gt;
Add to your dependencies section:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;dependency&amp;gt;
   &amp;lt;groupId&amp;gt;com.yourcompany&amp;lt;/groupId&amp;gt;
   &amp;lt;artifactId&amp;gt;branded-templates&amp;lt;/artifactId&amp;gt;
   &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Note that we are adding this as a &lt;strong&gt;WAR&lt;/strong&gt; type, do not leave the &lt;em&gt;type&lt;/em&gt; blank.&lt;br /&gt;
&lt;br /&gt;
Add to your plugins section:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
 &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;2.1.1&amp;lt;/version&amp;gt;
 &amp;lt;configuration&amp;gt;
   &amp;lt;overlays&amp;gt;
     &amp;lt;overlay&amp;gt;
       &amp;lt;groupId&amp;gt;com.yourcompany&amp;lt;/groupId&amp;gt;
       &amp;lt;artifactId&amp;gt;branded-templates&amp;lt;/artifactId&amp;gt;
     &amp;lt;/overlay&amp;gt;
   &amp;lt;/overlays&amp;gt;
 &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Next, we&#39;ve added the war-plugin which will take our application and build a WAR. If you&#39;re familiar with maven&#39;s artifact types, you&#39;ll already know that your project builds a WAR already, so why the plugin?  The plugin is where the &quot;magic&quot; of the overlay happens.  This is where the overlay is placed into the main-webapp&#39;s WAR file.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;How many WAR files will I have?&lt;/h2&gt;When using a WAR overlay, you will start with two or more WAR files (presumably one or more overlays and a main-webapp), but will ultimately end up with &lt;strong&gt;one WAR artifact&lt;/strong&gt; (your main-webapp) in which to deploy to your environment.  Though it is completely possible to run your overlay as a standalone application, I recommended you read my next post (coming soon) on dependency management within overlay projects to avoid dependency problems in your main-webapp project.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;So what happens when there is a conflicting resource?&lt;/h2&gt;As you can imagine, there can be conflicts between overlay&#39;s resource names and the main project&#39;s resources.  This is what I asked you to think about from the question posed above. If you have the same location and named file in your overlay application as you do in your main application, the &lt;strong&gt;overlay version will be ignored for the main application&#39;s version&lt;/strong&gt;. This can work for or against you, so think about how you might use both.  How would you want to leverage the customization abilities in the main webapp.&lt;br /&gt;
&lt;br /&gt;
Note, if you plan on utilizing Sitemesh decorators, it&#39;s not a bad idea to put your decorators.xml and sitemesh.xml file in your WEB-INF folder and the corresponding JSPs in the WEB-INF folder (suggest placing them in /WEB-INF/decorators folder).  Remember to add the sitemesh web.xml information into your containing main-webapp&#39;s web.xml!&lt;br /&gt;
&lt;br /&gt;
One more gotcha that might arise out of this would be dealing with the web.xml. The &lt;strong&gt;overlay&#39;s web.xml file is NOT copied over nor is it merged in any way&lt;/strong&gt;, so if your overlay has specific web.xml file information you can either manually add it to the web.xml or use a &amp;lt;include file=&quot;/WEB-INF/web-overlay.xml&quot;&amp;gt; tag where you&#39;ve added the contents to a file named &lt;em&gt;web-overlay.xml&lt;/em&gt; to the overlay war project. &lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Tips for rapid development&lt;/h2&gt;At this point you should have an overlay and a working master webapp leveraging that WAR overlay.  Since you have your resources in the overlay and you are probably working in your main-webapp, and it is probably becoming a pain to keep deploying a new version of your overlay project, you can simply refer to the SNAPSHOT version of your overlay inside your main-webapp pom.xml file and do a local install of your overlay.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Leaving notes&lt;/h2&gt;Follow my blog and get the next blog post dealing with dependency management with overlays.&lt;br /&gt;
&lt;br /&gt;
Feel free to leave comments or questions and I&#39;ll do my best to get back to you in a reasonable time frame.  I would like to thank &lt;a href=&quot;http://www.dynacrongroup.com/&quot; target=&quot;_blank&quot;&gt;Dynacron Group&lt;/a&gt; (my consulting firm) for allowing me some time to work on this blog post!</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/613627678394893927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/613627678394893927' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/613627678394893927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/613627678394893927'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2011/06/mavens-war-overlay-what-are-war.html' title='Maven&#39;s WAR Overlay: What are WAR Overlays?'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-1294444167181155360</id><published>2011-05-31T23:41:00.000-07:00</published><updated>2011-06-27T23:25:39.146-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="unit test"/><title type='text'>Maven + JavaScript Unit Test using JsTestDriver</title><content type='html'>&lt;b&gt;What are we doing?&lt;/b&gt;&lt;br /&gt;
You wake up to the annoying Justin Timberlake ringtone you set for the office only to discover it&#39;s the site is on fire&quot; call.  A quick glance at the alarm clock and you realize it&#39;s 3am.  It&#39;s this time when you decide that you need to get some test coverage on your Java Script.  &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;What is Unit Testing?&lt;/b&gt;&lt;br /&gt;
&lt;em&gt;Unit Testing&lt;/em&gt; is a method by which individual units of source code are tested to determine if they are fit for use. A unit is the smallest testable part of an application and in JavaScript, typically it is a function.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Why would you want to unit test JavaScript?&lt;/b&gt;&lt;br /&gt;
JavaScript has grown from the little scripts that would change button images on rollover to a fully functional, and often application critical, complex applications.  There are many interactions with DOM objects, AJAX request/response and user events that make testing your code a must-have.  Unit testing will give you the the confidence to add new features and change existing code.  In addition, unit test self-document the code so you can be sure that the rad new function you wrote does exactly what you want it to.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;What is covered&lt;/b&gt;&lt;br /&gt;
What the rest of this blog will describe is one approach to integrate maven and JsTestDriver for local development. In a near future blog, this approach will be extended to use on a Linux/Unix based system for a continuous integration system.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Approach&lt;/b&gt;&lt;br /&gt;
There are many approaches to unit testing JavaScript (QUnit being one of the many), however, most of the unit test frameworks do not easily allow you to integrate your unit test as a part of a maven testing cycle.  The one problem with all JavaScript unit testing frameworks is that you need to have a place to run your test.  At the time of this blog, there is not a &quot;headless&quot; browser, thus you (or your framework) must open a browser, accept JavaScript loading and running the test cases while providing repeatable testing output.  This blog series will discuss a few different methods to run unit test, including a method to run in a virtual framebuffer for continuous integration systems that do not allow you to open a browser in the default display.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;What is JsTestDriver?&lt;/b&gt;&lt;br /&gt;
JsTestDriver is an small application that controls your test cases, your source files and the interaction between the browsers you choose to test against.  JsTestDriver allows you to only load the source files you want, along with only the DOM elements you need to unit test your source code, in other words, the browser ONLY loads your JavaScript files and optionally HTML and/or DOM elements needed by your test.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;How to integrate with Maven&lt;/b&gt;&lt;br /&gt;
The approach here is to add JavaScript testing via a profile, so you can create a CI build specifically for your JavaScript unit test.&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;&lt;b&gt;JsTestDriver Setup&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
This blog will not discuss in depth how to setup and run JsTestDriver.  For more in-depth information, please visit &lt;a href=&quot;http://code.google.com/p/js-test-driver/&quot; target=&quot;_blank&quot;&gt;http://code.google.com/p/js-test-driver/&lt;/a&gt; website.  This blog is using JsTestDriver 1.3.2.&lt;br /&gt;
&lt;br /&gt;
In order to load your test scripts, you must create a configuration file.  For a maven application, place your configuration file in your &quot;/resources&quot; folder.&lt;br /&gt;
&lt;br /&gt;
Here is an example properties file (&lt;b&gt;jsTestDriver.conf&lt;/b&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;server: http://localhost:4220

load:
 # Header JS Files, all files are loaded top-down
 - main-js/lib/jquery.min.js
 # Body JS files
 - main-js/Person.js
 # Test files
 - test-js/*.js

exclude:
 - main-js/exclude.js

&lt;/pre&gt;&lt;br /&gt;
The above configuration file assumes your file structure is similar to:&lt;br /&gt;
/src/main/webapp/scripts/*.js&lt;br /&gt;
/src/test/webapp/resources/jsTestDriver.conf&lt;br /&gt;
/src/test/webapp/scripts/*.js&lt;br /&gt;
&lt;br /&gt;
(&lt;em&gt;NOTE: You might notice that the file path is different than the &quot;main-js&quot;. Keep reading!&lt;/em&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Maven Dependencies and Profile&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Next, let&#39;s add the dependencies to the POM file in your project.&lt;br /&gt;
&lt;br /&gt;
Add the following to your &quot;dependencies&quot; section in your pom.xml&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;dependency&amp;gt;
 &amp;lt;groupid&amp;gt;com.google.jstestdriver&amp;lt;/groupId&amp;gt;
 &amp;lt;artifactid&amp;gt;jstestdriver&amp;lt;/artifactId&amp;gt;
 &amp;lt;version&amp;gt;1.2.2&amp;lt;/version&amp;gt;
 &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
 &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;
&amp;lt;/dependency&amp;gt;

&lt;/pre&gt;&lt;br /&gt;
Next, we need to add a profile, which will do quite a few things.  First, the JsTestDriver jar file will be copied from the repository to a known folder in the /target folder for use when running the JsTestDriver server. Next, we need to copy the JavaScript files from your project&#39;s location to a known folder in the &quot;/test&quot; folder, and also to match the &quot;main-js/*&quot; and &quot;test-js/*&quot; folder structures that we setup in the jsTestDriver.conf file.  Lastly, we need to startup the JsTestDriver server so we can run our test.&lt;br /&gt;
&lt;br /&gt;
Here is a profile to start with:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;profile&amp;gt;
    &amp;lt;id&amp;gt;local-jstests&amp;lt;/id&amp;gt;
    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;

            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-dependency-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;2.1&amp;lt;/version&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;id&amp;gt;copy&amp;lt;/id&amp;gt;
                        &amp;lt;phase&amp;gt;generate-resources&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;copy&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;artifactItems&amp;gt;
                                &amp;lt;artifactItem&amp;gt;
                                    &amp;lt;groupId&amp;gt;com.google.jstestdriver&amp;lt;/groupId&amp;gt;
                                    &amp;lt;artifactId&amp;gt;jstestdriver&amp;lt;/artifactId&amp;gt;
                                    &amp;lt;version&amp;gt;${js-test-driver.version}&amp;lt;/version&amp;gt;
                                    &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;
                                    &amp;lt;overWrite&amp;gt;true&amp;lt;/overWrite&amp;gt;
                                    &amp;lt;destFileName&amp;gt;jsTestDriver.jar&amp;lt;/destFileName&amp;gt;
                                &amp;lt;/artifactItem&amp;gt;
                            &amp;lt;/artifactItems&amp;gt;
                            &amp;lt;outputDirectory&amp;gt;${project.build.directory}/jstestdriver&amp;lt;/outputDirectory&amp;gt;
                            &amp;lt;overWriteReleases&amp;gt;false&amp;lt;/overWriteReleases&amp;gt;
                            &amp;lt;overWriteSnapshots&amp;gt;true&amp;lt;/overWriteSnapshots&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;

            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;skipTests&amp;gt;true&amp;lt;/skipTests&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;

            &amp;lt;plugin&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-resources-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;2.4.3&amp;lt;/version&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;id&amp;gt;copy-main-files&amp;lt;/id&amp;gt;
                        &amp;lt;phase&amp;gt;generate-test-resources&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;copy-resources&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;outputDirectory&amp;gt;${basedir}/target/test-classes/main-js&amp;lt;/outputDirectory&amp;gt;
                            &amp;lt;resources&amp;gt;
                                &amp;lt;resource&amp;gt;
                                    &amp;lt;directory&amp;gt;src/main/webapp/scripts&amp;lt;/directory&amp;gt;
                                    &amp;lt;filtering&amp;gt;false&amp;lt;/filtering&amp;gt;
                                &amp;lt;/resource&amp;gt;
                            &amp;lt;/resources&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;id&amp;gt;copy-test-files&amp;lt;/id&amp;gt;
                        &amp;lt;phase&amp;gt;generate-test-resources&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;copy-resources&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;outputDirectory&amp;gt;${basedir}/target/test-classes/test-js&amp;lt;/outputDirectory&amp;gt;
                            &amp;lt;resources&amp;gt;
                                &amp;lt;resource&amp;gt;
                                    &amp;lt;directory&amp;gt;src/test/webapp/scripts&amp;lt;/directory&amp;gt;
                                    &amp;lt;filtering&amp;gt;false&amp;lt;/filtering&amp;gt;
                                &amp;lt;/resource&amp;gt;
                            &amp;lt;/resources&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;

            &amp;lt;plugin&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-antrun-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;1.6&amp;lt;/version&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;phase&amp;gt;test&amp;lt;/phase&amp;gt;
                        &amp;lt;configuration&amp;gt;

                            &amp;lt;target&amp;gt;
                                &amp;lt;!-- make output folder --&amp;gt;
                                &amp;lt;mkdir dir=&amp;quot;${basedir}/target/js-test-results&amp;quot;/&amp;gt;
                                &amp;lt;!-- start jsTestDriver server --&amp;gt;
                                &amp;lt;exec executable=&amp;quot;java&amp;quot;&amp;gt;
                                    &amp;lt;arg line=&amp;quot;-jar ${basedir}/target/jstestdriver/jsTestDriver.jar&amp;quot;/&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--port 4220&amp;quot;/&amp;gt;
                                    &amp;lt;!-- Possibly set this up to point to the same location of your surefire output --&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--testOutput ${basedir}/target/js-test-results&amp;quot;/&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--config ${basedir}/target/test-classes/jsTestDriver.conf&amp;quot;/&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--browser /opt/google/chrome/google-chrome&amp;quot;/&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--tests all&amp;quot;/&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--verbose&amp;quot;/&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--captureConsole&amp;quot;/&amp;gt;
                                    &amp;lt;arg line=&amp;quot;--preloadFiles&amp;quot;/&amp;gt;
                                &amp;lt;/exec&amp;gt;
                            &amp;lt;/target&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;run&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;

            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
&amp;lt;/profile&amp;gt;

&lt;/pre&gt;&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Sample Unit Test&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Now you need to have a sample JavaScript file and a corresponding unit test.&lt;br /&gt;
&lt;br /&gt;
Here is a simple JavaScript file (&lt;b&gt;/src/main/webapp/scripts/Person.js&lt;/b&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;NAMESPACE = {};
 
NAMESPACE.Person = function(initObj) {
 this.name = initObj.name;
 this.age = initObj.age;
 this.address = initObj.address;
 this.sex = initObj.sex;
 this.significantOther = initObj.significantOther;
 
 function setSignificantOther(person) {
  this.significantOther = person;
 }
 
 this.setSignificantOther = setSignificantOther;
}
&lt;/pre&gt;&lt;br /&gt;
And a sample test case might be: (&lt;b&gt;/src/test/webapp/scripts/PersonTest.js&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;TestCase(&quot;PersonTest&quot;, {
 testA:function(){
  expectAsserts(1);

   var peterGriffin = new NAMESPACE.Person({
    name: &amp;quot;Peter Griffin&amp;quot;,
    age: 43,
    address: {
     address1: &amp;quot;31 Spooner Street&amp;quot;,
     address2: &amp;quot;&amp;quot;,
     city: &amp;quot;Quhog&amp;quot;,
     state:&amp;quot;RI&amp;quot;
    },
    sex: &amp;quot;Male&amp;quot;,
    significantOther: null
   });
   
   assertNotNull(&quot;The variable should not be null&quot;, peterGriffin);
  };
 }
});

&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Running your test&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
In order to run your test, you can now type:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;mvn clean test -Plocal-js&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
Please stay tuned for the expansion to this on how to run in a virtual framebuffer for a CI environment (and of course, updates for found errors)</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/1294444167181155360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/1294444167181155360' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/1294444167181155360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/1294444167181155360'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2011/05/maven-javascript-unit-test-using.html' title='Maven + JavaScript Unit Test using JsTestDriver'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-3600115961981944310</id><published>2010-11-17T11:25:00.000-08:00</published><updated>2011-06-27T23:27:39.337-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Google App Engine"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring 3"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="unit test"/><title type='text'>Unit Testing Named Queues: Spring 3+maven2+Google App Engine</title><content type='html'>&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Intro&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;
Problem, you have a task that you know can take more than 30 seconds to complete, what do you do?&amp;nbsp; What if this task needs to be triggered every day at a specific time?&amp;nbsp; Google provides several mechanisms to to solve just this problem, queues and scheduled task, respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;Queues&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
First, let&#39;s explore the &quot;queue&quot; system implemented in GAE.&amp;nbsp; Note, at this time, the &quot;queue&quot; is still experimental which means that the API can change around some, so make sure you have strong unit testing, but don&#39;t worry, we&#39;ll cover that a bit further down the page.&amp;nbsp; To implement queues, you need to let the web app know that your expecting queues to be used, and to do this, you need to create a file named &lt;b&gt;queue.xml&lt;/b&gt; in your WEB-INF folder (&lt;i&gt;example: /src/main/webapp/WEB-INF/queue.xml&lt;/i&gt;).&amp;nbsp; The queue.xml file has a specific layout and that will not be covered in depth in this post.&amp;nbsp; Please read up on the queue.xml structure on &lt;a href=&quot;http://code.google.com/appengine/docs/java/taskqueue/overview.html&quot;&gt;Google&#39;s documentation&lt;/a&gt;.&amp;nbsp; We will expand on the knowledge since the documentation is not complete.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;Scheduled Task&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
Scheduled task are task that will trigger by GAE at repeatable times, emulating linux &lt;i&gt;cron&lt;/i&gt;, or Quartz application.&amp;nbsp; To implement a cron task, simply create a file called &lt;b&gt;cron.xml&lt;/b&gt; and place it in your WEB-INF folder (&lt;i&gt;example:/src/main/webapp/WEB-INF/cron.xml&lt;/i&gt;).&amp;nbsp; This post will not go into detail on the implementation of scheduled task so please check &lt;a href=&quot;http://code.google.com/appengine/docs/java/config/cron.html&quot;&gt;Google&#39;s documentation&lt;/a&gt; to get a firm understanding before reading on. In order to not pack too much into one post, Scheduled Task will be covered in the next post.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;Our Problem&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
The scenario we&#39;re going to explain is: You have an birthday tracking software and you want a user&#39;s friends to be notified, via email, that their friend is having a birthday.&amp;nbsp; &lt;i&gt;Assume that the code for the services named are tested and fully working&lt;/i&gt;. &lt;br /&gt;
&lt;br /&gt;
To solve this we will use a queue and the scheduled task system provided by Google App Engine.&lt;br /&gt;
&lt;br /&gt;
First, let&#39;s tackle the queue portion, then we will create the scheduled task.&amp;nbsp; Google&#39;s documentation on unit testing queues is very limited and only shows how to retrieve the &quot;default&quot; queue.&amp;nbsp; Since we could have multiple task in our system that need to be run at different rates, we will want to create a new Queue.&amp;nbsp; Let&#39;s open (or create) the &lt;i&gt;queue.xml&lt;/i&gt; file and insert the following:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;queue-entries&amp;gt;
    &amp;lt;queue&amp;gt;
        &amp;lt;name&amp;gt;birthdayemail&amp;lt;/name&amp;gt;
        &amp;lt;rate&amp;gt;10/s&amp;lt;/rate&amp;gt;
        &amp;lt;bucket-size&amp;gt;10&amp;lt;/bucket-size&amp;gt;
    &amp;lt;/queue&amp;gt;
&amp;lt;/queue-entries&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Next, let&#39;s create a simple service (&lt;i style=&quot;color: #666666;&quot;&gt;Note: assume that the Autowired resources are working and imports are included at the top of the file, this has been reduced to emphasize the solution&lt;/i&gt;) &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;@Service(&quot;birthdayService&quot;)
public class BirthdayServiceImpl implements BirthdayService {

    // this is the same name as in your queue.xml file
    private static final String EVENT_REMINDER_TASK_NAME = &quot;birthdayemail&quot;;
    
    @Autowired
    private BirthdayDAO birthdayDAO;

    public List handleGuestEmailsForBirthday(Date date) {
        if (date == null) {
            throw new IllegalArgumentException(&quot;Date can not be null&quot;);
        }
        List&amp;lt;Guest&amp;gt; guestBirthdays = birthdayDAO.getByDate(date);
        for (Guest guest : guestBirthdays) {
            String TASK_URL = &quot;/queue/birthday-emails/&quot; + guest.getId()
            final TaskOptions taskOptions = TaskOptions.Builder.url(TASK_URL);
            // create a unique task name, note, must conform to [a-z] regex
            taskOptions.taskName(guest.getName() + &quot;Task&quot;);
            taskOptions.method(TaskOptions.Method.POST);

            Queue queue = QueueFactory.getQueue(EVENT_REMINDER_TASK_NAME);
            // commented out to show the default queue shown in the docs
            //Queue queue = QueueFactory.getDefaultQueue();
            queue.add(taskOptions);
        }
        return events;
    }
}
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;Let&#39;s look at what&#39;s here:&lt;/b&gt;&lt;br /&gt;
First, we have to create a URL that will be run when the task is implemented. This URL will handle the unit of work specified, and should run in under 30 seconds per GAE&#39;s restrictions.  We will not cover what this servlet does, just assume it uses the ID given in the URL path, pulls up the Guest, then uses that to get the Guest&#39;s friends&#39; emails; then uses that to construct an email and pass to an EmailService. (HINT: the EmailService could also implement a queue so each email is separated out to run individually)&lt;br /&gt;
&lt;br /&gt;
Next, notice that we are implementing a &quot;Task Name&quot;.  The this is optional, but does help when debugging to figure out what task is failing or what is running.&lt;br /&gt;
&lt;br /&gt;
Now we&#39;re on to the TaskOptions.  TaskOptions are a helper function used to combine URL and model data to pass on to the servlet handling the queue.  Just a suggestion, but to follow the REST ideals, setting the RequestMethod to POST or PUT is advisable, depending on what you are trying to do.  All Task should be idempotent, meaning that if the task fails or is interrupted, the task can be run again and not harm the data.&lt;br /&gt;
&lt;br /&gt;
Lastly, we have the QueueFactory retrieving the Named Queue (the same name in the queue.xml file).  Simply add your taskOptions object to the queue.add and move on.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Unit Testing Named Queues&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
Next, let&#39;s setup a unit test to test our named queue.&amp;nbsp; The Google documentation does not explicitly explain how to properly setup a test case for one, datastore aware context and named queries.&amp;nbsp; Below is an example of a test case written to test our Named Queries.&amp;nbsp; (&lt;i style=&quot;color: #666666;&quot;&gt;Note, as before, imports have been removed and the services used have been used before.&amp;nbsp; This is not intended to be the end-all-be-all for unit testing GAE, please refer to previous post for more help, and yes, you might be able to use JMock or Mockito instead of persisting data, but I have not explored the option&lt;/i&gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {&quot;/testApplicationContext.xml&quot;})
public class QueueBirthdayServiceTest
        extends AbstractJUnit4SpringContextTests {

    @Autowired
    private BirthdayService birthdayService;
    private final LocalServiceTestConfig[] configs = {
        new LocalDatastoreServiceTestConfig(),
    /* NOTE: THE QUEUE XML PATH RELATIVE TO WEB APP ROOT, More info below */
        new LocalTaskQueueTestConfig()
                .setQueueXmlPath(&quot;src/test/resources/test-queue.xml&quot;)};
    private final LocalServiceTestHelper helper
            = new LocalServiceTestHelper(configs);

    @Before
    public void setUp() {
        helper.setUp();
    }

    @After
    public void tearDown() {
        helper.tearDown();
    }

    @Test
    public void testHandleBirthdayQueueEmails() throws InterruptedException {
        // setup data
        Date birtdayDate = DateUtils.parse(&quot;10/16/1900&quot;);
        // assume this builds the data for guest/guest&#39;s friends
        int guestWithBD = 5; // # of birthdays on date
        int gPerBirthday = 10; // # of emails being sent per birthday
        setupDataForBirthdays(birthdayDate, guestWithBD, gPerBirthday);

        List&amp;lt;Guest&amp;gt; birthdayOnDay = birthdayService.
                handleGuestEmailsForBirthday(birthdayDate);
        assertEquals(guestWithBD, birthdayOnDay.size());
        // pause for a moment to allow queue to fill from previous statment
        Thread.sleep(1000);
        // verify # of birthdays with that day&#39;s expire date
        LocalTaskQueue ltq = LocalTaskQueueTestConfig.getLocalTaskQueue();
        final Queue queue = QueueFactory
                .getQueue(BirthdayService.EVENT_REMINDER_TASK_NAME);
        //final Queue queue = QueueFactory.getDefaultQueue();
        QueueStateInfo qsi = ltq.getQueueStateInfo()
                .get(queue.getQueueName());
        assertNotNull(qsi);
        int expectedTaskCount = guestWithBD*gPerBirthday;
        assertEquals(expectedTaskCount, qsi.getTaskInfo().size());
        assertEquals(birthdayOnDay.get(0).getID() + &quot;Task&quot;,
                qsi.getTaskInfo().get(0).getTaskName());

    }
}
&lt;/pre&gt;&lt;i&gt;NOTE: If the syntax or unit testing is very foreign to you, please visit my previous post on Unit Testing on Google App Engine.&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Let&#39;s explore more&lt;/b&gt;&lt;br /&gt;
The first half is not too exiting, just setting up data and calling the service that creates the queue.&amp;nbsp; We are creating 5 guest with birthdays on the given date, and each of those 5 guest have 10 friends who we intend to email.&amp;nbsp; This service is already &quot;written&quot; out (above)&lt;br /&gt;
&lt;br /&gt;
What you need to pay attention to is at the top of the file, during the setup of the &amp;quot;helper&amp;quot;, we have constructed it with a LocalDatastoreServiceTestConfig and LocalTaskQueueTestConfig objects.  The second, the &amp;quot;LocalTaskQueueTestConfig&amp;quot; is the important one to add when using a queue.  If you are not using the DefaultQueue, you will need to explicitly state where the queue.xml file is.  I suggest that you create a test-queue.xml file and place it in your &lt;i&gt;/src/test/resources&lt;/i&gt; folder, so as to not mix production data and testing.  &lt;b&gt;NOTE: This file is loaded based relative to the ROOT application folder&lt;/b&gt;.  The rest of the test should be pretty self explanatory.&lt;br /&gt;
&lt;br /&gt;
In the next post, we will uncover how to wire the service up to a Scheduled Task so you can automate the emails being sent.  Stay tuned!</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/3600115961981944310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/3600115961981944310' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/3600115961981944310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/3600115961981944310'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2010/11/unit-testing-named-queues-spring.html' title='Unit Testing Named Queues: Spring 3+maven2+Google App Engine'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-6317592397682485848</id><published>2010-09-15T22:26:00.000-07:00</published><updated>2012-09-09T21:50:51.751-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Google App Engine"/><category scheme="http://www.blogger.com/atom/ns#" term="integration test"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring 3"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="unit test"/><title type='text'>Spring 3 + maven2 + Google App Engine: Part 6 [Integration Testing using HttpUnit]</title><content type='html'>In my previous post &lt;a href=&quot;http://www.ensor.cc/2010/09/spring-3-maven2-google-app-engine-part_15.html&quot;&gt;spring3 + maven2 + Google App Engine: Part 5[Unit Testing]&lt;/a&gt; I demonstrated how to create unit test for your Google App Engine application. Unit testing is only one part of the goal of 100% test coverage. The next major topic to cover, and arguably the most difficult to setup is &lt;em&gt;integration tests&lt;/em&gt;.  Integration test are test that use more than one component to complete the test.  In web application testing, this is typically where test that can only be run when there is a running application server.&lt;br /&gt;
&lt;br /&gt;
This post will cover Integration test using HttpUnit and the Failsafe Maven Plugin. Your first question is probably, why use failsafe in addition to the surefire.  The quick answer is that the failsafe will continue if your servlets cause an exception allowing you to test all of your files.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Failsafe plugin&lt;/b&gt;&lt;br /&gt;
We&#39;ll get started adding the Failsafe plugin to the POM file.  In your pom.xml file, add the following to your &lt;plugins&gt; section:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-failsafe-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.6&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*SysTest.java&amp;lt;/include&amp;gt;
        &amp;lt;/includes&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;integration-test&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
When the goal &quot;integration-test&quot; is run, the this testing plugin will include all files named &lt;anything&gt;SysTest.java. This should be changed to your specific package setup.  Using &quot;SysTest&quot;, &quot;ITCase&quot; or other pre/post fixes and separate packages are other options to segregate your integration test from your unit test.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Application Server&lt;/b&gt;&lt;br /&gt;
We now have the failsafe plugin, but we have to figure out how to run the application server before the integration test run.  This is achieved by running the maven-gae-plugin, yes, the same plugin used to run your webapp.  In recent releases of the maven-gae-plugin, developers added the stopPort and stopKey methods which allow failsafe to start and stop the application sever.  The plugin can used the phases &quot;pre-integration-test&quot; and the &quot;post-integration-test&quot; to start and stop the GAE server.&lt;br /&gt;
&lt;br /&gt;
Here is sample code to add to your pom.xml file inside of the &lt;plugins&gt; section (typically right below the failsafe-plugin added above:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;net.kindleit&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-gae-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;0.7.1&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;scanIntervalSeconds&amp;gt;10&amp;lt;/scanIntervalSeconds&amp;gt;
        &amp;lt;stopKey&amp;gt;STOP&amp;lt;/stopKey&amp;gt;
        &amp;lt;stopPort&amp;gt;8005&amp;lt;/stopPort&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;id&amp;gt;start-gae&amp;lt;/id&amp;gt;
            &amp;lt;phase&amp;gt;pre-integration-test&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;start&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;scanIntervalSeconds&amp;gt;0&amp;lt;/scanIntervalSeconds&amp;gt;
                &amp;lt;daemon&amp;gt;true&amp;lt;/daemon&amp;gt;
            &amp;lt;/configuration&amp;gt;
        &amp;lt;/execution&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;id&amp;gt;stop-gae&amp;lt;/id&amp;gt;
            &amp;lt;phase&amp;gt;post-integration-test&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;stop&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Notice, we are using the &quot;start&quot; verses using &quot;run&quot; because &quot;start&quot; does not include all of the task to &quot;package&quot; the war allowing the failsafe plugin to stop the GAE server.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Adding HttpUnit&lt;/b&gt;&lt;br /&gt;
In this posting, we will be adding and using HttpUnit as it&#39;s one of the most comprehensive and stable HTML unit testing libraries.  HttpUnit not only allows you to query your URLs, but you can unit-test JavaScript, see errors for CSS, JavaScript and malformed HTML.  HtmlUnit also allows you to emulate various different browsers including FireFox and Internet Explorer.&lt;br /&gt;
&lt;br /&gt;
The integration test are very similar to the unit test buy using the same testing context file, Spring JUnit helper, Google Local Testing helpers and JUnit.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;An integration test using HttpUnit&lt;/b&gt;&lt;br /&gt;
Here is a very basic example of an integration test:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;package com.example.web.controllers;

...imports...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {&quot;/testApplicationContext.xml&quot;})
public class HomeControllerSysTest extends AbstractJUnit4SpringContextTests {

    private static final Logger log = Logger.getLogger(
            HomeControllerSysTest.class.getName());
    private final LocalServiceTestHelper helper =
            new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

    @Before
    public void setUp() {
        helper.setUp();
    }

    @After
    public void tearDown() {
        helper.tearDown();
    }

    @Test
    public void testHomeController() throws IOException {
        final String url = &quot;http://localhost:8080/movie/test&quot;;

        final WebClient webClient = new WebClient();
        final HtmlPage page = webClient.getPage(url);
        assertEquals(&quot;The Page Title&quot;, page.getTitleText());

        // there are many different methods to query everything on your
        // page. Please refer to the HttpUnit homepage
        HtmlElement header = page.getElementsByTagName(&quot;h1&quot;).get(0);
        assertNotNull(header);

        String headerValue = header.getNodeValue();
        assertEquals(headerValue, &quot;Hello World!&quot;);
    }
}
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;How to test&lt;/b&gt;&lt;br /&gt;
Now, it&#39;s time to run the test. There are several methods for running integration test without running the unit test, but those tactics will not be covered in this posting.  To run the integration test, type the following:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;mvn integration-test&lt;/pre&gt;&lt;br /&gt;
That&#39;s it! Between this posting and the previous [Part 5] you should be able to test a large majority of your Java Web Application.</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/6317592397682485848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/6317592397682485848' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/6317592397682485848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/6317592397682485848'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2010/09/spring-3-maven2-google-app-engine-part_3585.html' title='Spring 3 + maven2 + Google App Engine: Part 6 [Integration Testing using HttpUnit]'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-3567969233531178577</id><published>2010-09-15T21:44:00.000-07:00</published><updated>2011-06-27T23:34:41.935-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Google App Engine"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring 3"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="unit test"/><title type='text'>Spring 3 + maven2 + Google App Engine: Part 5 [Unit test]</title><content type='html'>Unit testing is one of the most important keystones to Agile programming methodologies. Testing with maven and Spring can be a big pain, so here&#39;s a quick tutorial on how to set it up.  I will not cover proper testing strategies, but I&#39;ll give you the ability to setup your own testing.&lt;br /&gt;
&lt;br /&gt;
First, we&#39;ll focus on unit testing.  Unit testing is easily done using the &quot;&lt;b&gt;surefire plugin&lt;/b&gt;&quot;. To add the plugin, edit your pom.xml file, add the following inside of the &lt;plugins&gt; section:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.4&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*Test.java&amp;lt;/include&amp;gt;
        &amp;lt;/includes&amp;gt;
        &amp;lt;excludes&amp;gt;
            &amp;lt;exclude&amp;gt;**/*SysTest.java&amp;lt;/exclude&amp;gt;
        &amp;lt;/excludes&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
What this does is to tell Maven that during the phase &quot;test&quot;, to run the JUnit test using the include/exclude rules.&lt;br /&gt;
&lt;br /&gt;
Next we need to create a test file to run. Luckily we can use annotations to decorate our test files making it much easier.  For this example, I will create a file in the test package called EventServiceTest.java.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;package com.example;
...imports...
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {&quot;/testApplicationContext.xml&quot;})
public class EventServiceTest extends AbstractJUnit4SpringContextTests {

    @Autowired
    private EventService eventService;

    // Google&#39;s helper file to put all data storage in memory
    private final LocalServiceTestHelper helper =
            new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

    @Before
    public void setUp() {
        helper.setUp();
    }

    @After
    public void tearDown() {
        helper.tearDown();
    }

    @Test
    public void testCreateEvent() {
        Event event = eventService.getByName(&quot;pie day&quot;);
        assertNotNull(&quot;Pie Day should always exist!&quot;, event);
    }
}
&lt;/pre&gt;&lt;br /&gt;
There are a few things to notice in this example. The LocalServiceTestHelper is a class provided by Google that will allow data to be stored in memory instead of interferring with your local datastore.  There are several different types of configurations and customizations that can be passed into the constructor.  Visit http://code.google.com/appengine/docs/java/tools/localunittesting/javadoc/ to check out other options.&lt;br /&gt;
&lt;br /&gt;
If you noticed, we are loading a new context in the @ContextConfiguration annotation. You will need to create a new context file (similar to applicationContext.xml) which usually is a copy of the applicationContext.xml file, with changes to use mock services.&lt;br /&gt;
&lt;br /&gt;
I choose to specify the context file by location, which is set in my POM file to be at &lt;i&gt;/src/test/resources&lt;/i&gt; (refer to Part 2 to see full POM file). Another option could be to use classpath scanning.&lt;br /&gt;
&lt;br /&gt;
Lastly, notice that the @RunWith(SpringJUnit4ClassRunner.class), this sets up the test file for class loading.&lt;br /&gt;
&lt;br /&gt;
You can now run your unit test by running the following command:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;mvn test
&lt;/pre&gt;&lt;br /&gt;
Next post will contain information about how to create and run integration test.</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/3567969233531178577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/3567969233531178577' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/3567969233531178577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/3567969233531178577'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2010/09/spring-3-maven2-google-app-engine-part_15.html' title='Spring 3 + maven2 + Google App Engine: Part 5 [Unit test]'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-4444453464675779671</id><published>2010-09-10T13:37:00.000-07:00</published><updated>2011-08-17T06:42:30.156-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="deployment"/><category scheme="http://www.blogger.com/atom/ns#" term="Google App Engine"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring 3"/><title type='text'>Spring 3 + maven2 + Google App Engine: Part 4 [Deployment]</title><content type='html'>Now you should have an easy application that is working and you&#39;d like to deploy to Google&#39;s servers. Let&#39;s take a look at the &lt;i&gt;appengine-web.xml&lt;/i&gt; file located in the project&#39;s /WEB-INF folder. This file contains all of the settings related to the appengine web application.&lt;br /&gt;
&lt;br /&gt;
Here is an example &lt;i&gt;appengine-web.xml&lt;/i&gt; file:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;appengine-web-app xmlns=&amp;quot;http://appengine.google.com/ns/1.0&amp;quot;&amp;gt;
    &amp;lt;application&amp;gt;my-unique-app-name&amp;lt;/application&amp;gt;
    &amp;lt;!--  This variable is defined in your POM file --&amp;gt;
    &amp;lt;version&amp;gt;${gae.application.version}&amp;lt;/version&amp;gt;
    &amp;lt;system-properties&amp;gt;
        &amp;lt;property name=&amp;quot;java.util.logging.config.file&amp;quot; value=&amp;quot;WEB-INF/classes/logging.properties&amp;quot;/&amp;gt;
    &amp;lt;/system-properties&amp;gt;
    &amp;lt;sessions-enabled&amp;gt;true&amp;lt;/sessions-enabled&amp;gt;
    &amp;lt;!--
    &amp;lt;static-files&amp;gt;
        &amp;lt;include path=&amp;quot;/site/**&amp;quot; expiration=&amp;quot;1d 12h&amp;quot; /&amp;gt;
    &amp;lt;/static-files&amp;gt;
    --&amp;gt;
&amp;lt;/appengine-web-app&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Notice that the &lt;i&gt;application&lt;/i&gt; node is filled out with your unique Google App Engine application name which was created during the creation of the application.&lt;br /&gt;
&lt;br /&gt;
If you take a look at &lt;a href=&quot;http://www.ensor.cc/2010/04/spring-3-maven2-google-app-engine-part.html&quot;&gt;part 2&lt;/a&gt; of this series which goes more in depth on the POM file, you will notice at the bottom of the file there are several properties/variables set.  One of these is the application version, which correspond to the different versions you can deploy to Google&#39;s servers.  Notice that in the POM file, there are several version setup using different profiles.  When you deploy your application, you can setup different version numbers for testing, integration builds, staging or other required environments.  The deployed version will follow the following URL format:&lt;br /&gt;
&lt;br /&gt;
For a version of &quot;0&quot;:&lt;br /&gt;
http://0.latest.your-unique-appengine-name.appspot.com/&lt;br /&gt;
&lt;br /&gt;
For a version of &quot;2&quot;:&lt;br /&gt;
http://2.latest.your-unique-appengine-name.appspot.com/&lt;br /&gt;
&lt;br /&gt;
I recommend using the &quot;0&quot; version for testing, &quot;1&quot; for staging and &quot;2&quot; for production. This allows you to release to test and stage versions of your application, which will still use the same database, without releasing to production.&lt;br /&gt;
&lt;br /&gt;
Now, onto how to deploy.  If you have been following this series, you will be using the GAE plugin for Maven, which comes with many handy goals.  Using the &quot;gae:deploy&quot; will deploy your application to the Google servers according to the appengine-web.xml file.&lt;br /&gt;
&lt;br /&gt;
NOTE: I recommend creating batch files to deploy your application.  Here is a very basic example of a bash script file:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;#!/bin/bash
mvn gae:deploy -Dmaven.test.skip=true -Prelease-build
&lt;/pre&gt;&lt;br /&gt;
I have set the profile to &quot;release-build&quot; and decided to skip my test when doing my releases. Typically you will need to provide your email and password on the Google App Engine account to deploy.&lt;br /&gt;
&lt;br /&gt;
Lastly, once your have a successful deployment, follow these directions.&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Check your application by using the URL format given above&lt;/li&gt;
&lt;li&gt;Once you have verified the version has been uploaded, goto http://www.appspot.com, login and goto your application&#39;s main page&lt;/li&gt;
&lt;li&gt;Look for &quot;Application Versions&quot; and goto those settings&lt;/li&gt;
&lt;li&gt;Select the &quot;2&quot; to be your version to be the &quot;default&quot;&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
Congratulations, you have the necessary skills to create an application using Google App Engine and Spring 3.0!&lt;br /&gt;
&lt;br /&gt;
Later post will give more insights and tricks that I have learned while developing a full application exclusively hosted on Google App Engine.</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/4444453464675779671/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/4444453464675779671' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/4444453464675779671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/4444453464675779671'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2010/09/spring-3-maven2-google-app-engine-part.html' title='Spring 3 + maven2 + Google App Engine: Part 4 [Deployment]'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-922330013866621337</id><published>2010-04-08T23:25:00.000-07:00</published><updated>2011-06-27T23:27:05.369-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="annotations"/><category scheme="http://www.blogger.com/atom/ns#" term="Google App Engine"/><category scheme="http://www.blogger.com/atom/ns#" term="MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring 3"/><title type='text'>Spring 3 + maven2 + Google App Engine: Part 3 [Spring Setup]</title><content type='html'>This is a continuation of a multi-part series discussing how to get Spring 3 running on Google App Engine using maven.&amp;nbsp; This part discusses in more detail how to get Spring 3 MVC configured using annotations.&lt;br /&gt;
&lt;br /&gt;
If you have ever had to setup a typical J2EE Web Application you remember (or perhaps have suppressed) the massive amounts of XML needed to configure your app.&amp;nbsp; Spring 2.5 took great steps towards reducing the use of XML by introducing annotation based configuration.&amp;nbsp; Annotation based configuration is probably the best achievement towards  sustainable RAD.&amp;nbsp; For example, lets take your typical Spring web application.&amp;nbsp; You need a web.xml, dispatcher-servlet.xml, urlrewrite.xml (to have the greatest control of your URLs for SEO purposes), data-config xml files and a build.xml.&amp;nbsp; While you can not completely get rid of all of the XML, using annotations you can reduce the file size and best yet, remove dependencies to your business beans.&lt;br /&gt;
&lt;br /&gt;
To start setting up your application with annotations, create a file called &quot;dispatcher-servlet.xml&quot; and place it in your WEB-INF folder.&amp;nbsp; This file will need to have several namespaces defined.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;/src/main/webapp/WEB-INF/dispatcher-servlet.xml&lt;/i&gt;:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; 
       xmlns:p=&quot;http://www.springframework.org/schema/p&quot;
       xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
       xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd&quot;&amp;gt;

&amp;lt;/beans&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
After saving the skeleton file above, it is time to add the meat of the configuration.  First, we will tell Spring to wire Controllers to your POJOs that represent the &quot;C&quot; (controller) of MVC.  In order to do this, we will need to place our controllers inside of a package structure so Spring can scan the package looking for the @Controller annotation.  For our example, we setup our controller to be under &lt;b&gt;com.example.web.controllers&lt;/b&gt;.  Where you used to have to wire in a bean that used the class name to guess the controller, now we add the annotation to the class and that&#39;s it!&lt;br /&gt;
&lt;br /&gt;
Add this to your dispatcher-servlet.xml file:&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;context:component-scan base-package=&quot;com.example.web.controllers&quot; /&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
That&#39;s it!  Now we have the basics for setting up your first controller.  Let&#39;s build our first Controller.&amp;nbsp; Create a file called &lt;em&gt;HelloController.java&lt;/em&gt; under &lt;strong&gt;/src/main/java/com/example/web/controllers&lt;/strong&gt;&lt;br /&gt;
&lt;pre name=&quot;code&quot; class=&quot;Cpp&quot;&gt;package com.example.web.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.ui.ModelMap;

@Controller
public class HelloController {

    @RequestMapping(value = &quot;/hello&quot;, method = RequestMethod.GET)
    public String helloGet(ModelMap map) {
        // this is your model (in future post, I will show how to use the ModelAttribute and command objects)
        map.put(&quot;name&quot;, &quot;mike!&quot;);
        // for now, this is where your &quot;View&quot; is
        return &quot;hello&quot;;
    }
}
&lt;/pre&gt;&lt;br /&gt;
For now, we will go with just the basics. Save this file and let&#39;s create the &amp;quot;View&amp;quot; so we you can run your application.&lt;br /&gt;
&lt;br /&gt;
Create a file named &lt;em&gt;hello.jsp&lt;/em&gt; and place it in &lt;strong&gt;/src/main/webapp/WEB-INF/jsp/views&lt;/strong&gt; folder.&lt;br /&gt;
&lt;pre name=&quot;code&quot; class=&quot;Cpp&quot;&gt;&amp;lt;%@ page contentType=&quot;text/html; charset=UTF-8&quot; contentEncoding=&quot;UTF-8&quot; isELIgnored=&quot;false&quot; %&amp;gt;
&amp;lt;%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jsp/jstl/core&quot; %&amp;gt;
&amp;lt;%@ taglib prefix=&quot;fmt&quot; uri=&quot;http://java.sun.com/jsp/jstl/fmt&quot; %&amp;gt;
&amp;lt;%@ taglib prefix=&quot;fn&quot; uri=&quot;http://java.sun.com/jsp/jstl/functions&quot; %&amp;gt;
&amp;lt;-- it is recommended to take the preceding 
four lines and place them in a file to include on 
the top of each page --&amp;gt;
&amp;lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;
    &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&amp;gt;
        &amp;lt;title&amp;gt;Hello Controller&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;Hello ${name}!&amp;lt;/h1&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Lastly we must hook up our dispatcher servlet (front-loading servlet) so we can handle web request.  Open &lt;em&gt;/src/main/webapp/WEB-INF/web.xml&lt;/em&gt; file and add in the following:&lt;br /&gt;
&lt;pre name=&quot;code&quot; class=&quot;Cpp&quot;&gt;&amp;lt;servlet&amp;gt;
    &amp;lt;servlet-name&amp;gt;dispatcher&amp;lt;/servlet-name&amp;gt;
    &amp;lt;servlet-class&amp;gt;org.springframework.web.servlet.DispatcherServlet&amp;lt;/servlet-class&amp;gt;
    &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
&amp;lt;/servlet&amp;gt;

&amp;lt;servlet-mapping&amp;gt;
    &amp;lt;servlet-name&amp;gt;dispatcher&amp;lt;/servlet-name&amp;gt;
    &amp;lt;url-pattern&amp;gt;/movie/*&amp;lt;/url-pattern&amp;gt;
&amp;lt;/servlet-mapping&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Now we&#39;re ready to run our app!&lt;br /&gt;
&lt;pre name=&quot;code&quot; class=&quot;Cpp&quot;&gt;mvn clean gae:run&lt;/pre&gt;&lt;br /&gt;
&lt;blockquote class=&quot;note&quot;&gt;NOTE: If this is the first time you have run Google App Engine application using Maven2, then type the following to &amp;quot;unpack&amp;quot; Google App Engine&lt;/blockquote&gt;&lt;pre name=&quot;code&quot; class=&quot;Cpp&quot;&gt;mvn gae:unpack&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Navigate to &lt;a href=&quot;http://localhost:8080/movie/hello&quot; target=&quot;_blank&quot;&gt;http://localhost:8080/movie/hello&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now that you have have checked out your first controller, you can already see things that are static and probably be changed.  For example, take a look at your &amp;quot;helloGet&amp;quot; method.  The String being returned points directly to the view.  Rather than hard-code the entire path, we can setup a &lt;em&gt;ViewResolver&lt;/em&gt; so you only need a small part of the view name.&lt;br /&gt;
&lt;br /&gt;
Open &lt;em&gt;/src/main/webapp/WEB-INF/dispatcher-servlet.xml&lt;/em&gt; and add in the following:&lt;br /&gt;
&lt;pre name=&quot;code&quot; class=&quot;Cpp&quot;&gt;&amp;lt;bean id=&quot;viewResolver&quot;
&amp;nbsp;&amp;nbsp;class=&quot;org.springframework.web.servlet.view.InternalResourceViewResolver&quot;
&amp;nbsp;&amp;nbsp;p:prefix=&quot;/WEB-INF/jsp/views/&quot; 
&amp;nbsp;&amp;nbsp;p:suffix=&quot;.jsp&quot; 
&amp;nbsp;&amp;nbsp;p:viewClass=&quot;org.springframework.web.servlet.view.JstlView&quot;
&amp;nbsp;&amp;nbsp;/&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Now in your &lt;em&gt;HelloController.java&lt;/em&gt; file, simply return &amp;quot;hello&amp;quot; (see how the strings concatenated together create the entire path?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You now have the basics of Spring MVC setup and so therefore this concludes this portion of the series on how to get Spring and Maven2 running on Google App Engine</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/922330013866621337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/922330013866621337' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/922330013866621337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/922330013866621337'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2010/04/spring-3-maven2-google-app-engine-part_08.html' title='Spring 3 + maven2 + Google App Engine: Part 3 [Spring Setup]'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-1935110441424434740</id><published>2010-04-06T23:52:00.000-07:00</published><updated>2010-05-18T10:24:44.387-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ant"/><category scheme="http://www.blogger.com/atom/ns#" term="DataNucleus"/><category scheme="http://www.blogger.com/atom/ns#" term="GAE"/><category scheme="http://www.blogger.com/atom/ns#" term="Google App Engine"/><category scheme="http://www.blogger.com/atom/ns#" term="JUnit"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><category scheme="http://www.blogger.com/atom/ns#" term="POM"/><category scheme="http://www.blogger.com/atom/ns#" term="project"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring 3"/><title type='text'>Spring 3 + maven2 + Google App Engine: Part 2 [POM Setup]</title><content type='html'>In this post, we will look at the POM file and the dependencies for  not only a solid web application using Spring 3, but the dependencies  specific to Google App Engine. This is not meant to be a comprehensive overview of Maven and may or may not use best practices for Maven (ie, I&#39;ll ignore comments about your maven file, grab a maven book, hopefully off the links to the right!)&lt;br /&gt;
&lt;br /&gt;
Now, let&#39;s take a look at the POM file and setup our project.&amp;nbsp; We need to add the Google App Engine and the related dependencies, DataNucleus for enhancing domain objects (though, I am investigating how to use Spring persistence through Annotations to replace this dependency), JUnit and various other utilities needed to construct a working web-app.&lt;br /&gt;
&lt;br /&gt;
Most of the POM file generated from part 1 will be sufficient, but we need to start adding dependencies.  We&#39;ll start with the Spring 3.&lt;br /&gt;
&lt;br /&gt;
Inside of your &amp;lt;dependencies&amp;gt; section, lets add the following dependencies:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Project Dependencies&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;b&gt;Spring 3&lt;/b&gt;&lt;/div&gt;&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;nbsp;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupid&amp;gt;org.springframework&amp;lt;/groupid&amp;gt;
            &amp;lt;artifactid&amp;gt;spring-webmvc&amp;lt;/artifactid&amp;gt;
            &amp;lt;version&amp;gt;3.0.1.RELEASE&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupid&amp;gt;org.springframework&amp;lt;/groupid&amp;gt;
            &amp;lt;artifactid&amp;gt;spring-test&amp;lt;/artifactid&amp;gt;
            &amp;lt;version&amp;gt;3.0.1.RELEASE&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;b&gt;Google App Engine &lt;/b&gt;&lt;/div&gt;&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;nbsp;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.google.appengine&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;datanucleus-jpa&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.1.5&amp;lt;/version&amp;gt;
            &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.google.appengine&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;geronimo-jpa_3.0_spec&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.1.1&amp;lt;/version&amp;gt;
            &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.google.appengine&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;appengine-api-1.0-sdk&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.3.2&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.google.appengine&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;appengine-api-labs&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.3.2&amp;lt;/version&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.google.appengine&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;appengine-api-stubs&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.3.2&amp;lt;/version&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.google.appengine&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;appengine-testing&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.3.2&amp;lt;/version&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.google.appengine&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;appengine-local-runtime&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.3.2&amp;lt;/version&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;

&lt;/pre&gt;&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;b&gt;Google App Engine Data Store&lt;/b&gt;&lt;/div&gt;&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;nbsp;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;javax.jdo&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;jdo2-api&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;2.3-eb&amp;lt;/version&amp;gt;
            &amp;lt;exclusions&amp;gt;
                &amp;lt;exclusion&amp;gt;
                    &amp;lt;groupId&amp;gt;javax.transaction&amp;lt;/groupId&amp;gt;
                    &amp;lt;artifactId&amp;gt;transaction-api&amp;lt;/artifactId&amp;gt;
                &amp;lt;/exclusion&amp;gt;
            &amp;lt;/exclusions&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;javax.servlet&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;jstl&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.2&amp;lt;/version&amp;gt;
            &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;
            &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;javax.transaction&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;jta&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.1&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.google.appengine.orm&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;datanucleus-appengine&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.0.5.final&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.datanucleus&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;datanucleus-core&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.1.5&amp;lt;/version&amp;gt;
            &amp;lt;exclusions&amp;gt;
                &amp;lt;exclusion&amp;gt;
                    &amp;lt;groupId&amp;gt;javax.transaction&amp;lt;/groupId&amp;gt;
                    &amp;lt;artifactId&amp;gt;transaction-api&amp;lt;/artifactId&amp;gt;
                &amp;lt;/exclusion&amp;gt;
            &amp;lt;/exclusions&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Now you have the default minimum dependencies for GAE (still not there quite yet, we need to add the necessary plugins). If you are more familiar with Maven, you might want to add in Ant, Apache Commons Collections and any other libraries you typically use.&lt;br /&gt;
&lt;br /&gt;
&lt;b style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Plugins&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
Once you have the needed libraries it is time to setup the plugins to build and run your project.&amp;nbsp; Add the following to the &lt;plugins&gt; section:&lt;/plugins&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.1-alpha-2&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;webAppConfig&amp;gt;
            &amp;lt;contextPath&amp;gt;/movie&amp;lt;/contextPath&amp;gt;
            &amp;lt;scanIntervalSeconds&amp;gt;10&amp;lt;/scanIntervalSeconds&amp;gt;
        &amp;lt;/webAppConfig&amp;gt;
        &amp;lt;webResources&amp;gt;
            &amp;lt;resource&amp;gt;
                &amp;lt;directory&amp;gt;src/main/webapp&amp;lt;/directory&amp;gt;
                &amp;lt;filtering&amp;gt;true&amp;lt;/filtering&amp;gt;
                &amp;lt;includes&amp;gt;
                    &amp;lt;include&amp;gt;**/appengine-web.xml&amp;lt;/include&amp;gt;
                &amp;lt;/includes&amp;gt;
            &amp;lt;/resource&amp;gt;
        &amp;lt;/webResources&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;

&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt;
        &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;

&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;cobertura-maven-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${cobertura-version}&amp;lt;/version&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;clean&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;

&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.datanucleus&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-datanucleus-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.1.4&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;!-- Make sure this path contains your persistent classes! --&amp;gt;
        &amp;lt;mappingIncludes&amp;gt;**/model/*.class&amp;lt;/mappingIncludes&amp;gt;
        &amp;lt;!-- */This is where your domain objects will be located --&amp;gt;
        &amp;lt;verbose&amp;gt;true&amp;lt;/verbose&amp;gt;
        &amp;lt;enhancerName&amp;gt;ASM&amp;lt;/enhancerName&amp;gt;
        &amp;lt;api&amp;gt;JDO&amp;lt;/api&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;phase&amp;gt;compile&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;enhance&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.datanucleus&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;datanucleus-core&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.1.5&amp;lt;/version&amp;gt;
            &amp;lt;exclusions&amp;gt;
                &amp;lt;exclusion&amp;gt;
                    &amp;lt;groupId&amp;gt;javax.transaction&amp;lt;/groupId&amp;gt;
                    &amp;lt;artifactId&amp;gt;transaction-api&amp;lt;/artifactId&amp;gt;
                &amp;lt;/exclusion&amp;gt;
            &amp;lt;/exclusions&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.datanucleus&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;datanucleus-rdbms&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.1.5&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.datanucleus&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;datanucleus-enhancer&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.1.4&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;
&amp;lt;/plugin&amp;gt;

&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${maven-surefire-plugin-version}&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*Spec.java&amp;lt;/include&amp;gt;
            &amp;lt;include&amp;gt;**/*Test.java&amp;lt;/include&amp;gt;
        &amp;lt;/includes&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-jxr-plugin&amp;lt;/artifactId&amp;gt;
&amp;lt;/plugin&amp;gt;

&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;net.kindleit&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-gae-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;0.5.2&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;unpackVersion&amp;gt;1.3.2&amp;lt;/unpackVersion&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;

&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-release-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;goals&amp;gt;gae:deploy&amp;lt;/goals&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;

&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-antrun-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;phase&amp;gt;compile&amp;lt;/phase&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;tasks&amp;gt;

                    &amp;lt;!--
                        This creates the META-INF folder inside of classes, then
                        copies over the jdoconfig.xml required for GAE
                    --&amp;gt;
                    &amp;lt;mkdir dir=&quot;${project.build.directory}/classes/META-INF&quot;/&amp;gt;
                    &amp;lt;copy file=&quot;${project.build.directory}/classes/jdoconfig.xml&quot;
                          todir=&quot;${project.build.directory}/classes/META-INF&quot; /&amp;gt;
                    &amp;lt;echo message=&quot;Copy:${project.build.directory}/classes/jdoconfig.xml to &quot; /&amp;gt;
                    &amp;lt;echo message=&quot;${project.build.directory}/classes/META-INF&quot;/&amp;gt;
                &amp;lt;/tasks&amp;gt;
            &amp;lt;/configuration&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;run&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;

&lt;/pre&gt;&lt;br /&gt;
&lt;a href=&quot;https://docs.google.com/leaf?id=0B1vwPdChHbDcM2FmZWE3NTYtZTc3OC00MjY1LTkzODEtOTViNDZlYjZkOWM0&amp;hl=en&quot;&gt;Click here to get the full pom.xml file&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/1935110441424434740/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/1935110441424434740' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/1935110441424434740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/1935110441424434740'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2010/04/spring-3-maven2-google-app-engine-part.html' title='Spring 3 + maven2 + Google App Engine: Part 2 [POM Setup]'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2531455513819948701.post-8845483809546046217</id><published>2010-04-01T08:00:00.000-07:00</published><updated>2010-04-08T23:26:49.233-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="GAE"/><category scheme="http://www.blogger.com/atom/ns#" term="Google App Engine"/><category scheme="http://www.blogger.com/atom/ns#" term="MVC"/><category scheme="http://www.blogger.com/atom/ns#" term="project"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring 3"/><title type='text'>Spring 3 + maven2 + Google App Engine: Part 1 [Initial Project Setup]</title><content type='html'>Recently a co-worker started down the path of Spring 3, Spring MVC and Google App Engine.  After hearing him talk about it, I decided it was time for me to figure out what the hype was and figure out how to program something using the &quot;cloud&quot;.&lt;br /&gt;
&lt;br /&gt;
This series of post will discuss one approach to getting my favorite Java web-app stack of Spring 3, Spring MVC (both with annotations), maven2 and all developed on Google App Engine.&amp;nbsp; Since unit testing is a corner stone of Agile development, JUnit test will also be included to show how to test your code prior to deployment to GAE servers.&lt;br /&gt;
&lt;br /&gt;
This series assumes that you have and know how to use the following: Google login (Gmail or iGoogle for example), Java 1.6, some IDE (Eclipse, NetBeans, InteliJ, Notepad++, etc) though you do not need to install the suggested &quot;Plugins&quot;, maven2, Ant 1.7+, web browser, command line&lt;br /&gt;
&lt;br /&gt;
We will be building a simple &quot;Movie Listing&quot; web application where you can enter a movie, add a comment (single user, for now), add &quot;Actors&quot; to that movie.  The model and idea is very simple and easy to define so we can focus on the technology.&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;b&gt;Step 1: Sign up for a Google App Engine&lt;/b&gt;&lt;/div&gt;First off, you will need to sign up for a Google App Engine account before you can do anything else.&amp;nbsp; Visit &lt;a href=&quot;http://code.google.com/appengine/&quot;&gt;http://code.google.com/appengine/&lt;/a&gt; and click on &quot;Sign Up&quot; under &quot;Getting Started&quot; on the right side navigation.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Note: Remember the URL you fill out as the name of your application, this will be used later in the POM file&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Step 2: Setup the project&lt;/b&gt;&lt;br /&gt;
Once you have your GAE account setup, you need to setup your web application.&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
Suggested directory structure and project layout:&lt;br /&gt;
pom.xml&lt;br /&gt;
src&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; - main&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - resources&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - site&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - img&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - javascript&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - css&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - webapp&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - WEB-INF&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - java&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - com&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - example&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - controllers&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; - test&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - resources&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - java&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - com&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - example&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; - controllers&lt;br /&gt;
&lt;br /&gt;
This is just a standard Spring Web App, nothing special here.&amp;nbsp; As a shortcut, you can use the maven command: (this will create most of the folder structure and default files)&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;mvn archetype:create -DgroupId=com.example.app -DartifactId=movie-app -DarchetypeArtifactId=maven-archetype-webapp
&lt;/pre&gt;&lt;br /&gt;
At this point, you should be able to &quot;clean&quot; and &quot;install&quot; the application.&amp;nbsp; Nothing will happen since we have not setup the project, which is in the next post.&lt;br /&gt;
&lt;br /&gt;
Run the project with:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;Cpp&quot; name=&quot;code&quot;&gt;mvn clean install&lt;/pre&gt;&lt;br /&gt;
Depending on how your maven usage, different plugins may need to download but ultimately you should see &quot;Build Successful&quot; in the output.</content><link rel='replies' type='application/atom+xml' href='http://www.ensor.cc/feeds/8845483809546046217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2531455513819948701/8845483809546046217' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/8845483809546046217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2531455513819948701/posts/default/8845483809546046217'/><link rel='alternate' type='text/html' href='http://www.ensor.cc/2007/12/welcome-to-my-blog.html' title='Spring 3 + maven2 + Google App Engine: Part 1 [Initial Project Setup]'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/08005723041154179130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>