<?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-457071854377599320</id><updated>2025-11-12T18:33:37.385+01:00</updated><category term="java"/><category term="test"/><category term="Lotus Connections"/><category term="connections"/><category term="customization"/><category term="development"/><category term="howto"/><category term="lotus"/><category term="jcr"/><category term="navigation"/><category term="cdi"/><category term="code"/><category term="junit"/><category term="lc25"/><category term="mutation testing"/><category term="quickr"/><category term="scribble"/><category term="unit test"/><category term="web20"/><category term="WebAppIntegrator"/><category term="best-practices"/><category term="developer diary"/><category term="fake testing"/><category term="framework"/><category term="library"/><category term="maven"/><category term="opensource"/><category term="personal"/><category term="security"/><category term="siconbus"/><category term="sidebar"/><category term="social software"/><category term="testing"/><category term="troubleshooting"/><category term="2.5"/><category term="activity"/><category term="agile"/><category term="dependency injection"/><category term="diagram"/><category term="eech"/><category term="helios"/><category term="inkstand"/><category term="jee"/><category term="junt"/><category term="kpi"/><category term="metrics"/><category term="pit"/><category term="programming"/><category term="prototype"/><category term="prototyping"/><category term="quality"/><category term="release"/><category term="script"/><category term="service"/><category term="service locator"/><category term="simulation"/><category term="tab"/><category term="twitter"/><category term="uml"/><category term="2008"/><category term="2009"/><category term="5in5"/><category term="9.10"/><category term="Amsterdam"/><category term="Dublin"/><category term="London"/><category term="Portal"/><category term="Portal Awareness"/><category term="Prague"/><category term="RSA"/><category term="Riga"/><category term="Stockholm"/><category term="acceptance testing"/><category term="access"/><category term="application"/><category term="appserver"/><category term="barriers"/><category term="bdd"/><category term="behavior driven"/><category term="best practices"/><category term="best-practice"/><category term="blog"/><category term="bomber"/><category term="bookmark"/><category term="bookmarking"/><category term="bratislava"/><category term="build"/><category term="business use"/><category term="ch"/><category term="cheese"/><category term="chrome"/><category term="cloud"/><category term="cmis overview"/><category term="cockpit"/><category term="collaboration"/><category term="communities"/><category term="comparison"/><category term="configuration"/><category term="connector"/><category term="content"/><category term="convert"/><category term="converter"/><category term="coverage"/><category term="creation"/><category term="css"/><category term="cucumber"/><category term="db2"/><category term="decision"/><category term="delicious"/><category term="deltaspike"/><category term="devicelink"/><category term="diagrams"/><category term="diigo"/><category term="dom"/><category term="eclipse"/><category term="ecm"/><category term="encode"/><category term="error"/><category term="export"/><category term="facebook"/><category term="failed"/><category term="fired"/><category term="firefox"/><category term="fix"/><category term="flying"/><category term="fondue"/><category term="framwork"/><category term="functional credit"/><category term="functional debt"/><category term="future"/><category term="gathering"/><category term="get2gether"/><category term="gif"/><category term="git"/><category term="goals"/><category term="gothic"/><category term="gps"/><category term="gpx"/><category term="graphics"/><category term="hack"/><category term="holiday"/><category term="hotkey"/><category term="ibm"/><category term="images"/><category term="installation"/><category term="instconffailed"/><category term="integration"/><category term="integration test"/><category term="internet"/><category term="ireland"/><category term="issl"/><category term="issues"/><category term="jacoco"/><category term="javascript"/><category term="jawr"/><category term="job"/><category term="keyconfig"/><category term="kml"/><category term="label"/><category term="latvia"/><category term="libstdc++5"/><category term="links"/><category term="linux"/><category term="live"/><category term="log4j"/><category term="log4j2"/><category term="logging"/><category term="login"/><category term="lookup"/><category term="meet-greet"/><category term="microservice"/><category term="missing"/><category term="mock"/><category term="modelling"/><category term="mp3"/><category term="multi-module"/><category term="multilingual"/><category term="music"/><category term="mutation"/><category term="nls"/><category term="node"/><category term="notifications"/><category term="opencmis"/><category term="opinion"/><category term="pattern"/><category term="pdf"/><category term="pervasive"/><category term="png"/><category term="prediction"/><category term="privacy"/><category term="processing"/><category term="profile"/><category term="protection"/><category term="quickr81"/><category term="rasterize"/><category term="repository"/><category term="rock"/><category term="satire"/><category term="sax"/><category term="scalable"/><category term="scm"/><category term="scrum master"/><category term="seamless"/><category term="search"/><category term="selenium"/><category term="selfmade"/><category term="server"/><category term="setup"/><category term="show"/><category term="singleton"/><category term="slf4j"/><category term="social"/><category term="sonar"/><category term="spnego"/><category term="sso"/><category term="stupidity"/><category term="stylesheet"/><category term="subscribe"/><category term="svg"/><category term="svn"/><category term="sweden"/><category term="switzerland"/><category term="technical credit"/><category term="technical debt"/><category term="technote"/><category term="template"/><category term="terror"/><category term="tiff"/><category term="tips"/><category term="tools"/><category term="tracking"/><category term="travelling"/><category term="twhirl"/><category term="twitterbar"/><category term="uat"/><category term="ubuntu"/><category term="ui"/><category term="vacation"/><category term="value-add"/><category term="was"/><category term="waste"/><category term="wav"/><category term="websphere"/><category term="xml"/><category term="xpath"/><title type='text'>whoopdicity</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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>58</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-4509335445327098614</id><published>2016-06-29T17:51:00.002+02:00</published><updated>2016-06-29T18:05:41.462+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="mutation testing"/><category scheme="http://www.blogger.com/atom/ns#" term="pit"/><category scheme="http://www.blogger.com/atom/ns#" term="quality"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><category scheme="http://www.blogger.com/atom/ns#" term="unit test"/><title type='text'>How to detect fake tests - Introduction to Mutation Testing</title><content type='html'>In the last posts (&lt;a href=&quot;http://whoopdicity.blogspot.com/2016/05/how-to-fake-tests-part-1.html&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;http://whoopdicity.blogspot.ch/2016/06/how-to-fake-tests-part-2.html&quot;&gt;2&lt;/a&gt;, &lt;a href=&quot;http://whoopdicity.blogspot.ch/2016/06/how-to-fake-tests-part-3.html&quot;&gt;3&lt;/a&gt;) I showed various ways for producing fake tests. Of course, good developers won&#39;t fake their tests, and the chances to encounter a test suite purely made of fake tests in real life is rather low. Nevertheless, in certain environments it may occasionally happen that metrics are polished for various reasons. But it&#39;s more likely, that the quality of a test suites deteriorates over time because of various reasons, i.e. project pressure, sloppy moments during coding, wrong assumptions, etc. And typically we rely on metrics to determine whether our project is in good shape.&lt;br /&gt;
&lt;br /&gt;
My intention for the last three posts was to show, how easy the common metrics - test count, line and condition coverage - can be tricked and are of very low value without the proper context. They are as good for determining the health of a software project as lines of codes are. They might be an weak indicator but nothing more.&lt;br /&gt;
&lt;br /&gt;
The main question is, how could we determine the actual value of our tests and test suites? How would others do it? Firebrigades test their procedures and techniques on a real fire. Military is holding maneuvers, martial arts fighters test their skills in championships, NetFlix is letting the &lt;a href=&quot;https://github.com/Netflix/SimianArmy/wiki/Chaos-Monkey&quot;&gt;Chaos Monkey&lt;/a&gt; terminate instances to detect holes in the recovery procedures.&lt;br /&gt;
&lt;br /&gt;
What is the main reason to have automated tests? To detects bugs that slipped into existing code unintentionally. It doesn&#39;t matter if you wrote the tests beforehand by practicing Uncle Bob style TDD or afterwards to create a safepoint for your code. The base assumption is, once you&#39;ve written your code and your tests, it&#39;s free of errors. But it&#39;s called &lt;i&gt;Software&lt;/i&gt; for a reason: it may change over time. The once written, error-free code will eventually be changed. To ensure, it is still functional, the test suites are run and if it&#39;s all green, nothing was broken. But how can you be sure of that?&lt;br /&gt;
&lt;br /&gt;
The only thing to verify your test suite is capable of detecting bugs is to induce bugs in your code.&lt;br /&gt;
&lt;br /&gt;
The technique of altering your code and re-run your test suite to verify the test suite detects the code change is called &lt;i&gt;Mutation Testing&lt;/i&gt;. The concept is known for quite a while and was mostly subject to academic research with the tools being somewhat theoretical and less practical to use. But since the arrival of &lt;a href=&quot;http://pitest.org/&quot;&gt;Pitest.org&lt;/a&gt; a practical, stable and well integrated tool has been around that should be in every developer&#39;s toolbox.&lt;br /&gt;
&lt;br /&gt;
Pitest mutates bytecode and runs highly parallel making it the fastest mutation testing tool for the JVM. Pitest offers a set of &lt;i&gt;Mutation Operators&lt;/i&gt; that modify bytecode according to a defined ruleset and thus creates a modified version of the code, a &lt;i&gt;Mutation&lt;/i&gt;. The test suite is run again and if at least one test fails, the Mutation is &lt;i&gt;killed&lt;/i&gt;. In the end, the &lt;i&gt;Mutation Score&lt;/i&gt; is calculated from the number of killed mutations vs the total number of mutations.&lt;br /&gt;
&lt;br /&gt;
Different to line or branch coverage, which can be determined with a single test suite execution, Pitest requires one test suite execution per mutation. With larger code-bases the execution time increases exponentially due to the sheer number of combinations of mutations. Although Pitest offers a variety of settings and options to limit execution time - i.e. delta execution, selection of mutation operators, exclusion of classes, to name a few - it requires some thorough planning how this technique should be incorporated into the CI/CD pipeline. The value it delivers, comes with a price.&lt;br /&gt;
&lt;br /&gt;
In the next post of this series, I will provide examples of how to setup and run pitest with practical examples, so stay tuned.</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/4509335445327098614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/4509335445327098614' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/4509335445327098614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/4509335445327098614'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2016/06/how-to-detect-fake-tests.html' title='How to detect fake tests - Introduction to Mutation Testing'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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-457071854377599320.post-3799652058072673777</id><published>2016-06-22T17:17:00.003+02:00</published><updated>2016-06-22T17:17:49.382+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fake testing"/><category scheme="http://www.blogger.com/atom/ns#" term="junit"/><category scheme="http://www.blogger.com/atom/ns#" term="mutation testing"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><category scheme="http://www.blogger.com/atom/ns#" term="unit test"/><title type='text'>How to fake tests (Part 3)</title><content type='html'>In this 3rd part of the series I want to show how assertions can be faked, so that not only lines and branches get covered but the test themselves also contain some assertions.&lt;br /&gt;
Faking Assertions only makes sense if a metric such as &quot;assertions/test&quot; is computed at all. Otherwise you may skip that part, because every proper code review would reveal your test as fake.
&lt;br /&gt;
Test libraries such as Junit or TestNG contain various means for expressing assertions. In addition to this, some frameworks exist for that sole purpose, i.e. Hamcrest, Truth, to name a few. Basic approach for all is, to invoke the system under test (generating coverage information) and to verify outcomes against assertions. 
&lt;br /&gt;
But the outcomes doesn’t have to be related to what is declared as expected for the test to succeed. So all of the following assertions might do the trick

&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;code prettyprint&quot;&gt;assertTrue(true);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;code prettyprint&quot;&gt;assertNotNull(new Object());&lt;/code&gt; (a real life example I’ve encountered during a code review)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;code prettyprint&quot;&gt;assertEquals(&quot;2&quot;,&quot;2&quot;);&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
After having applied fake assertions and fake coverage, our testsuite satisfies the following criteria

&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Big, lots of tests for all the methods&lt;/li&gt;
&lt;li&gt;100% Line Coverage&lt;/li&gt;
&lt;li&gt;100% Condition Coverage&lt;/li&gt;
&lt;li&gt;Tests contain assertions (maybe 1 assertion/method as a metric)&lt;/li&gt;
&lt;/ul&gt;
This would make every project manager happy, because the quality of the product is so good and there is proof for that.... &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Not!&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;You’ve probably produced the most sophisticated test suite with best quality ratings with minimum effort to create that has &lt;i&gt;no value at all&lt;/i&gt; (Achievement unlocked).&lt;br /&gt;
&lt;br /&gt;
In the next post I&#39;ll show how all these fakes described in this and the earlier posts can be revealed as such -&amp;nbsp; and more important, how the effectiveness of a test suite can be determined and gaps in a sensible test suite be found. So stay tuned.</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/3799652058072673777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/3799652058072673777' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/3799652058072673777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/3799652058072673777'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2016/06/how-to-fake-tests-part-3.html' title='How to fake tests (Part 3)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-872174228586405521</id><published>2016-06-09T17:27:00.001+02:00</published><updated>2016-06-09T17:27:11.639+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fake testing"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="junt"/><category scheme="http://www.blogger.com/atom/ns#" term="kpi"/><category scheme="http://www.blogger.com/atom/ns#" term="metrics"/><category scheme="http://www.blogger.com/atom/ns#" term="mutation testing"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><category scheme="http://www.blogger.com/atom/ns#" term="unit test"/><title type='text'>How to fake tests (Part 2) </title><content type='html'>In the &lt;a href=&quot;http://whoopdicity.blogspot.ch/&quot;&gt;last post&lt;/a&gt; I described how to write fake tests to statisfy number-of-tests KPI. Apparently this is not a good practice for software craftsmen. Unfortunately some organisation do value KPIs more than good craftsmenship and may be simply tricked by fake tests. So in today&#39;s post I&#39;d like to show you how to fake line and condition coverage of tests. This is a call to action for decision makers who base their decisions on such numbers: don&#39;t trust them. And for developers: if encouter things like the following (or like in the last post): fix them. So let&#39;s start with line coverage.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Faking Line Coverage&lt;/h4&gt;
Line Coverage is a metric that measures how many and which lines have been covered during execution. There are various tools to measure coverage.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Jacoco – Measuring on ByteCode level which has the advantage that you can test your actual artifacts, but bytecode can be different to its source at times.&lt;/li&gt;
&lt;li&gt;ECobertura, Clover – Measuring on SourceCode level which is more precise than byte-code measuring but injects additional code before compilation, ending up in different artifacts than you want to deliver.&lt;/li&gt;
&lt;/ul&gt;
When running your tests with line coverage enabled, all lines touched are recorded to produce the metric. If you have 0% line coverage, you didn’t run any code. So let’s extend our test to get some coverage:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;java prettyprint&quot;&gt;
@Test
public void test() {
  subject.invokeSomeMethod();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Obviously this test is broken because in cannot fail – unless the code itself produces an exception. But with tests like these you may achieve quite easily a high line coverage and a stable test suite. &lt;br /&gt;
But typical programs are rarely linear and have some sort of loop or branch constructs. So it’s unlikely you achieve 100% line coverage. So we have to fake branch coverage, too.&lt;br /&gt;
&lt;h4&gt;
&amp;nbsp;&lt;/h4&gt;
&lt;h4&gt;
Faking Condition Coverage&lt;/h4&gt;
Lets assume our simple program consists of the following code&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;java prettyprint&quot;&gt;
Object compute(Object input) {
  if(&quot;left&quot;.equals(input) {
    return &quot;right&quot;;
  } 
  return &quot;left&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
It has one condition with two branches. With a single test, you may get 66% Line Coverage and 50% Condition Coverage. I’ve experiences several times that branch coverage is perceived as “better” or of “more value” because it’s harder to achieve. If “harder” means “more code” it’s certainly true, but branch coverage suffers the same basic problem as line coverage does: it’s just a measure for which code is executed and not how good your tests are. It also depends on the code base, what is harder to achieve. If the happy-flow you test covers only a minor part of the code, you may have 50% branch-coverage but only 10% line coverage. Given the above example, assume the “left”-branch contains 10 lines of code, but you only test for the “right”-branch.&lt;br /&gt;
&lt;br /&gt;
But as we are developers who want to make happy managers, let’s fake branch coverage!&lt;br /&gt;
Given, we only test a single flow in a single test, we need two tests:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;java prettyprint&quot;&gt;
@Test
public void testLeft() {
 String output = compute(&quot;left&quot;);
}
@Test
public void testRight() {
 String output = compute(&quot;right&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
This test will produce 100% branch- and line coverage and is very unlikely to fail, ever. &lt;br /&gt;But again: it’s worthless, because we don’t check any output of the operation. So the operation may return anything without failing the test. But still in terms of KPI metrics we achieved:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;2 tests for 1 method (great ratio!)&lt;/li&gt;
&lt;li&gt;100% line coverage&lt;/li&gt;
&lt;li&gt;100% condition coverage&lt;/li&gt;
&lt;/ul&gt;
What we missed to have is an assertion. Assertion postulate expected outcomes of an operation. If the actual outcome is different than expected, the test fails. Theoretically it would would be possible to count assertions per test in static code analysis. But I’ve never seen such metric although it’s value would be similar to line- or condition coverage. Nevertheless: we can fake it!&lt;br /&gt;
&lt;br /&gt;
So in the next post, I&#39;ll show you how to fake assertions.</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/872174228586405521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/872174228586405521' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/872174228586405521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/872174228586405521'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2016/06/how-to-fake-tests-part-2.html' title='How to fake tests (Part 2) '/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-2896198661296970950</id><published>2016-05-31T17:23:00.000+02:00</published><updated>2016-05-31T17:36:46.507+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fake testing"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="junt"/><category scheme="http://www.blogger.com/atom/ns#" term="kpi"/><category scheme="http://www.blogger.com/atom/ns#" term="metrics"/><category scheme="http://www.blogger.com/atom/ns#" term="mutation testing"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><category scheme="http://www.blogger.com/atom/ns#" term="unit test"/><title type='text'>How to fake tests (Part 1)</title><content type='html'>In most projects, metrics play an important role to determine the status, health, quality etc. of the project. Not rarely the common metrics for quality have been&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Number of Unit Tests (Total, Failed, Successful)&lt;/li&gt;
&lt;li&gt;Line Coverage&lt;/li&gt;
&lt;li&gt;Branch Coverage&lt;/li&gt;
&lt;/ul&gt;
Usually those “KPI” (Key Performance Indicators) were used by “managers” to steer the project to success. The problem with these metrics is: they are totally useless if taken out of context - and the context is usually not that well defined in terms of metrics, but often requires knowledge and insight into the system that’s been measured.&lt;br /&gt;
&lt;br /&gt;
This post is about to show how to game the system and life-hack those KPIs to fake good quality. It’s NOT a best practice but a heads up to those who make decision based on those metrics to look behind the values.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Faking Number of Unit Tests &lt;/h3&gt;
Most (if not all?) frameworks count the number of tests executed, which failed and which succeeded. A high number of tests is usually perceived as a good indicator of quality. The increase of the amount of tests should correlate with the increase in lines of code (another false-friend KPI). But what is counted as a test?&lt;br /&gt;
&lt;br /&gt;
Let’s look at the Junit which is the de-facto standard for developing and executing Java based unit tests, but other frameworks such as TestNG follow similar concepts. &lt;br /&gt;
&lt;br /&gt;
In Junit 3 it was every parameterless public void method starting with “test” in a class extending TestCase. Since Junit 4 every method annotated with @Test counts as a Test.&lt;br /&gt;
&lt;br /&gt;
That’s it. Just a name convention or an Annotation and you have your test, so let’s fake it!&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;code prettyprint&quot;&gt;
@Test
public void test() {

}
&lt;/pre&gt;
&lt;br /&gt;
This is pure gold: a stable and ever succeeding Unit Test!&lt;br /&gt;
&lt;br /&gt;
Copy and paste or even generate those and you produce a test suite satisfying the criteria:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Big, tons of tests, probable even more than you have LoCs&lt;/li&gt;
&lt;li&gt;Stable, none of these tests is failing. Ever.&lt;/li&gt;
&lt;li&gt;Fast, you have feedback about the success within seconds.&lt;/li&gt;
&lt;/ul&gt;
The downside: it’s worthless (surprise, surprise!). There are basically two primary reasons, why its worthless:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;It doesn’t run any code&lt;/li&gt;
&lt;li&gt;It doesn’t pose any assertion about the outcome&lt;/li&gt;
&lt;/ul&gt;
Good indicators to check the first one are line or condition coverage analysis. The latter is more difficult to check.&lt;br /&gt;
&lt;br /&gt;
In the upcoming posts we&#39;ll have a look into both.</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/2896198661296970950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/2896198661296970950' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/2896198661296970950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/2896198661296970950'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2016/05/how-to-fake-tests-part-1.html' title='How to fake tests (Part 1)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-3528179132886981383</id><published>2015-12-19T22:31:00.000+01:00</published><updated>2015-12-19T22:31:18.277+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cdi"/><category scheme="http://www.blogger.com/atom/ns#" term="framework"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jcr"/><category scheme="http://www.blogger.com/atom/ns#" term="library"/><category scheme="http://www.blogger.com/atom/ns#" term="opensource"/><category scheme="http://www.blogger.com/atom/ns#" term="scribble"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Scribble 0.3.0</title><content type='html'>&lt;div class=&quot;wiki-content&quot;&gt;
        I am proud to announce a new version of the the &lt;a href=&quot;https://inkstand.atlassian.net/wiki/display/SCRIB/0.3.0&quot;&gt;Scribble &lt;/a&gt;testing library! The biggest changes are the new modularization and 
documentation. For every functional aspect there is now a separate 
module so that not a whole load of unused dependencies have to be 
included in your project if you only require just a single functional 
aspect. In addition to this, the entire project documentation is now 
kept in the source and be generated using maven&#39;s site support. This 
includes this wiki documentation as well, although the publishing 
process is not yet part of the release build jobs.&lt;br /&gt;
As new features
 for testing I introduce a http server as a TestRule that can be set up
 in various ways to server static content. It&#39;s still rather limited, 
but will be contiuously improved in future releases. Further features 
are the possibility to create temporary zip files, record system out and
 err via a TestRule and capture and restore System Properties - a simple
 rule that helps keeping the test environment clean, and finally a 
matcher for matching date strings against a data format.&lt;br /&gt;
&lt;br /&gt;
For more information, have a look at the &lt;a href=&quot;https://inkstand.atlassian.net/wiki/display/SCRIB/Documentation&quot;&gt;wiki&lt;/a&gt; or find the source code on &lt;a href=&quot;https://github.com/inkstand-io/scribble&quot;&gt;GitHub&lt;/a&gt;.&amp;nbsp; &lt;br /&gt;
&lt;h2 id=&quot;ReleaseScribble0.3.0-Task&quot;&gt;
Task&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-55&quot; rel=&quot;nofollow&quot;&gt;SCRIB-55&lt;/a&gt;] - Modularize Scribble&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;ReleaseScribble0.3.0-Story&quot;&gt;
Story&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-35&quot; rel=&quot;nofollow&quot;&gt;SCRIB-35&lt;/a&gt;] - Embedd static HTTP content as a rule&lt;/li&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-43&quot; rel=&quot;nofollow&quot;&gt;SCRIB-43&lt;/a&gt;] - Build documentation as part of the release&lt;/li&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-49&quot; rel=&quot;nofollow&quot;&gt;SCRIB-49&lt;/a&gt;] - Create zipped temp file from resources&lt;/li&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-50&quot; rel=&quot;nofollow&quot;&gt;SCRIB-50&lt;/a&gt;] - Date Format Matcher&lt;/li&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-52&quot; rel=&quot;nofollow&quot;&gt;SCRIB-52&lt;/a&gt;] - Rule for capturing System.out and System.err&lt;/li&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-53&quot; rel=&quot;nofollow&quot;&gt;SCRIB-53&lt;/a&gt;] - Rule for setting and restoring System Properties&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;ReleaseScribble0.3.0-Bug&quot;&gt;
Bug&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-39&quot; rel=&quot;nofollow&quot;&gt;SCRIB-39&lt;/a&gt;] - ConfigPropertyInjection#isMatching sets default value&lt;/li&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-51&quot; rel=&quot;nofollow&quot;&gt;SCRIB-51&lt;/a&gt;] - TemporaryFile not usable as ClassRule&lt;/li&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-57&quot; rel=&quot;nofollow&quot;&gt;SCRIB-57&lt;/a&gt;] - ApacheDS all prevents exclusion of modules&lt;/li&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-58&quot; rel=&quot;nofollow&quot;&gt;SCRIB-58&lt;/a&gt;] - Remove SLF4J Binding dependencies&lt;/li&gt;
&lt;li&gt;[&lt;a class=&quot;external-link&quot; href=&quot;https://inkstand.atlassian.net/browse/SCRIB-59&quot; rel=&quot;nofollow&quot;&gt;SCRIB-59&lt;/a&gt;] - DirectoryServer/DirectoryService not working as ClassRule&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/3528179132886981383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/3528179132886981383' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/3528179132886981383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/3528179132886981383'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2015/12/scribble-030.html' title='Scribble 0.3.0'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-5028466362589457754</id><published>2015-07-08T21:51:00.002+02:00</published><updated>2015-07-08T21:51:59.582+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cdi"/><category scheme="http://www.blogger.com/atom/ns#" term="framework"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jcr"/><category scheme="http://www.blogger.com/atom/ns#" term="library"/><category scheme="http://www.blogger.com/atom/ns#" term="opensource"/><category scheme="http://www.blogger.com/atom/ns#" term="scribble"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Scribble Release 0.2.0</title><content type='html'>I am proud to announce a new version of the the Scribble testing library! The new version has support for an embedded ldap server which allows to write tests against an ldap server without having to rely on existing infrastructure. Further, the JCR support has been improved, now it&#39;s possible to pre-initialize a JCR repository with content from a descriptor file and to create a security-enabled in-memory repository. Some additional improvements have been made in the CDI injection support and the matchers have been extended for availability checks for URLs.&lt;br /&gt;
&lt;br /&gt;
For more information, have a look at the &lt;a href=&quot;https://inkstand.atlassian.net/wiki/display/SCRIB/Documentation&quot;&gt;wiki&lt;/a&gt; or find the source code on &lt;a href=&quot;https://github.com/inkstand-io/scribble&quot;&gt;GitHub&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
&lt;h1&gt;
Release Notes - Scribble - Version 0.2.0&lt;/h1&gt;
&lt;h2&gt;
        Bug
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-31&quot;&gt;SCRIB-31&lt;/a&gt;] -         Primitive types not support for ConfigProperty injection
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-32&quot;&gt;SCRIB-32&lt;/a&gt;] -         String to Number conversion of default values in ConfigProperty injection fails
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-41&quot;&gt;SCRIB-41&lt;/a&gt;] -         LDAP Rules are not properly applied
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-42&quot;&gt;SCRIB-42&lt;/a&gt;] -         ResourceAvailabilityMatcher is not compatible with URL
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-48&quot;&gt;SCRIB-48&lt;/a&gt;] -         Directory Rules can not be used as ClassRules
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
        Story
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-1&quot;&gt;SCRIB-1&lt;/a&gt;] -         Builder support for LDAP Server and Service
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-2&quot;&gt;SCRIB-2&lt;/a&gt;] -         Make LDAP Port configurable
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-5&quot;&gt;SCRIB-5&lt;/a&gt;] -         Matchers for availability of an URL
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-10&quot;&gt;SCRIB-10&lt;/a&gt;] -         Support for prepared JCR Content
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-12&quot;&gt;SCRIB-12&lt;/a&gt;] -         Support security enabled content repositories
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-14&quot;&gt;SCRIB-14&lt;/a&gt;] -         Add Convenience method for admin login
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-33&quot;&gt;SCRIB-33&lt;/a&gt;] -         Convenience Methods for Directory creation
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-34&quot;&gt;SCRIB-34&lt;/a&gt;] -         Convenience Method for anonymous login
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-38&quot;&gt;SCRIB-38&lt;/a&gt;] -         Supply package-info.java
&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/5028466362589457754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/5028466362589457754' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/5028466362589457754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/5028466362589457754'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2015/07/scribble-release-020.html' title='Scribble Release 0.2.0'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-2235965212693601879</id><published>2015-05-29T09:41:00.001+02:00</published><updated>2015-05-29T09:41:51.134+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="coverage"/><category scheme="http://www.blogger.com/atom/ns#" term="integration test"/><category scheme="http://www.blogger.com/atom/ns#" term="jacoco"/><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="multi-module"/><category scheme="http://www.blogger.com/atom/ns#" term="sonar"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><title type='text'>Multi-Module Integration Test Coverage with Jacoco and Sonar</title><content type='html'>&lt;ul&gt;
&lt;/ul&gt;
Yesterday I have struggled to capture IT coverage results in a multi-module project setup, which I eventually solved.&lt;br /&gt;
&lt;br /&gt;
So lets assume, I have the following setup:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;rootModule&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;+Module1&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;+Module2&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;| +SubModule2-1&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;|&amp;nbsp;&amp;nbsp;&amp;nbsp; +SubModule2-1-1&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;|&amp;nbsp;+SubModule2-2&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;+ITModule&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;+ITModule1&lt;/span&gt;
&lt;br /&gt;
&lt;br /&gt;
The ITModule contains only integration tests, where ITModule1 is a special scenario, that requires a single module. Module2 consists of nested submodules. There are several examples out there to use a path like &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;../target/jacoco-it.exec&lt;/span&gt; but that&#39;s obviously not working if you more than one nesting level.&lt;br /&gt;
&lt;br /&gt;
To know how to solve it, you must understand, how sonar is doing the analysis. When analysing the coverage information sonar checks the code of each module against the coverage file that is specified in the &lt;code&gt;sonar.jacoco.itReportPath&lt;/code&gt; property which defaults to &lt;code&gt;target/jacoco-it.exec&lt;/code&gt;. So when analyzing &lt;code&gt;Module1&lt;/code&gt; it check for coverage info in &lt;code&gt;Module1/target/jacoco-it.exec&lt;/code&gt;.
 But as the coverage data is captured in the ITModule, respectively ITModule1, I have to 
point sonar to the file generated in the IT 
module.&lt;br /&gt;
So the best location to gather the coverage data is to the use rootModule, i.e. &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;rootModule/target/jacoco-it.exec&lt;/span&gt; and append the results of all IT tests to that file.&lt;br /&gt;
&lt;br /&gt;
I use the following plugin configuration that uses separate files for unit-test coverage (don&#39;t forget the append flag otherwise overall coverage will be incorrect) and the central file for IT covergage.&lt;br /&gt;
&lt;pre class=&quot;code prettyprint&quot;&gt;&amp;lt;plugin&amp;gt;
  &amp;lt;groupId&amp;gt;org.jacoco&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;jacoco-maven-plugin&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;0.7.4.201502262128&amp;lt;/version&amp;gt;
  &amp;lt;executions&amp;gt;
    &amp;lt;execution&amp;gt;
      &amp;lt;id&amp;gt;prepare-agent&amp;lt;/id&amp;gt;
      &amp;lt;goals&amp;gt;
        &amp;lt;goal&amp;gt;prepare-agent&amp;lt;/goal&amp;gt;
      &amp;lt;/goals&amp;gt;
      &amp;lt;configuration&amp;gt;
        &amp;lt;destFile&amp;gt;target/jacoco.exec&amp;lt;/destFile&amp;gt;
        &amp;lt;append&amp;gt;true&amp;lt;/append&amp;gt;
        &amp;lt;propertyName&amp;gt;surefireArgLine&amp;lt;/propertyName&amp;gt;
      &amp;lt;/configuration&amp;gt;
    &amp;lt;/execution&amp;gt;
    &amp;lt;execution&amp;gt;
      &amp;lt;id&amp;gt;prepare-it-agent&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;prepare-agent&amp;lt;/goal&amp;gt;
      &amp;lt;/goals&amp;gt;
      &amp;lt;configuration&amp;gt;
        &amp;lt;destFile&amp;gt;${session.executionRootDirectory}/target/jacoco-it.exec&amp;lt;/destFile&amp;gt;
        &amp;lt;append&amp;gt;true&amp;lt;/append&amp;gt;
        &amp;lt;propertyName&amp;gt;failsafeArgLine&amp;lt;/propertyName&amp;gt;
      &amp;lt;/configuration&amp;gt;
    &amp;lt;/execution&amp;gt;
  &amp;lt;/executions&amp;gt;
 &amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
The &lt;code&gt;${session.executionRootDirectory}&lt;/code&gt; property is the root 
of execution, when I build the entire project, it will point to the rootModule. So this is the best path to use, when you have 
multi-module with more than one level of nesting.&lt;br /&gt;
&lt;br /&gt;
For the analysis, I need to point sonar to use that file when analyzing IT coverage. So I have to set the &lt;code&gt;sonar.jacoco.itReportPath&lt;/code&gt; to that file. Unfortunately, this does not work with the &lt;code&gt;session.executionRootDirectory&lt;/code&gt;
 property and I have to set the absolute path to the file manually. I 
do not recommend to specify the absolute path in the &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;pom.xml&lt;/span&gt; as this 
path is specific to the build environment. So either set the path in 
Sonar or as System property of your build environment. I set it directly
 in the Sonar Project Settings (Java &amp;gt; Jacoco), for example &lt;code&gt;/opt/buildroot/myProject/target/jacoco-it.exec&lt;/code&gt;.
Now sonar will check that file for the IT coverage analysis of each module.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/2235965212693601879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/2235965212693601879' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/2235965212693601879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/2235965212693601879'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2015/05/multi-module-integration-test-coverage.html' title='Multi-Module Integration Test Coverage with Jacoco and Sonar'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-1237954793893270725</id><published>2015-05-27T18:00:00.000+02:00</published><updated>2015-05-27T18:00:28.529+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="release"/><category scheme="http://www.blogger.com/atom/ns#" term="scribble"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><title type='text'>Scribble 0.1.3</title><content type='html'>&amp;nbsp;While working on the next release of Inkstand, I had to fix some bugs in the Scribble test framework&#39;s injection support which just got released.&lt;br /&gt;
&lt;h4&gt;
Release Notes - Scribble - Version 0.1.3
        
&lt;/h4&gt;
&lt;h2&gt;
        Bug
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-26&quot;&gt;SCRIB-26&lt;/a&gt;] -         Check for null injection target
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-27&quot;&gt;SCRIB-27&lt;/a&gt;] -         TcpPort has no proper toString() representation
&lt;/li&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-30&quot;&gt;SCRIB-30&lt;/a&gt;] -         Field candidates are not collected for null-values
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
        Story
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;[&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-29&quot;&gt;SCRIB-29&lt;/a&gt;] -         Injection does not fail if no target is found
&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/1237954793893270725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/1237954793893270725' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/1237954793893270725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/1237954793893270725'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2015/05/release-scribble-013.html' title='Scribble 0.1.3'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-122861300631097542</id><published>2015-05-26T11:33:00.001+02:00</published><updated>2015-05-26T11:33:17.569+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="dom"/><category scheme="http://www.blogger.com/atom/ns#" term="issues"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="processing"/><category scheme="http://www.blogger.com/atom/ns#" term="sax"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><category scheme="http://www.blogger.com/atom/ns#" term="xml"/><category scheme="http://www.blogger.com/atom/ns#" term="xpath"/><title type='text'>Java XML Processing Vulnerabilities</title><content type='html'>&lt;div style=&quot;line-height: 100%; margin-bottom: 0cm;&quot;&gt;
Last week I was
fixing issues for my pet project Scribble. I use Sonar for capturing
issues in my code. Since April this year, the Findbugs plugin for
Sonar includes rules for finding security bugs. Two of the bugs found
were related to XML processing using Java&#39;s XML APIs for Xpath and
DOM parsing. The security issue themselves were not new, both of them
were discovered some years ago. But to me they were new as I was not
aware of them at all. For my pet project they are not that critical
as it is just a framework for writing tests and no one using that
framework is kept from writing vulnerable code themselves. But for me
it was a good case for studying the issues to avoid them when it
really matters. &lt;/div&gt;
&lt;div style=&quot;line-height: 100%; margin-bottom: 0cm;&quot;&gt;
&lt;/div&gt;
&lt;h2 class=&quot;western&quot;&gt;
&amp;nbsp;&lt;/h2&gt;
&lt;h4 class=&quot;western&quot;&gt;
Xpath Injection&lt;/h4&gt;
Xpath injection adheres to the same principle as SQL injection
were parameter values that are used in an Xpath expression contain
characters that are semantically bound to the Xpath syntax to break
out from the path defined by the expression.&lt;br /&gt;
&lt;br /&gt;
&lt;h3 class=&quot;western&quot;&gt;
The Attack&lt;/h3&gt;
Given, you have an XML document containing sensitive data&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;&amp;lt;technical-users&amp;gt;
  &amp;lt;user id=”reader”&amp;gt;
  &amp;lt;privateKey&amp;gt;ABC&amp;lt;/privateKey&amp;gt;
  &amp;lt;/user&amp;gt;
  &amp;lt;user id=”writer”&amp;gt;
  &amp;lt;privateKey&amp;gt;123&amp;lt;/privateKey&amp;gt;
  &amp;lt;/user&amp;gt; 
&amp;lt;/technical-users&amp;gt;
&lt;/pre&gt;
and an Xpath expression with a parameter that is filled in at
runtime:&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;//technical-users/user[@id=&#39;”+userId+”&#39;]/privateKey
&lt;/pre&gt;
Lets assume, the attacker has authenticated successfully as reader
and now tries to query for the private key, manipulating it&#39;s own
user id to that value:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;reader&#39;]/../user[@id=&#39;writer
&lt;/pre&gt;
&lt;div class=&quot;code-western&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
The injected value leaves the reader-user subpaths, traverses
one level up and down into the writer-users subpath and thereby
delivering the privateKey of that user.

A variation of this attack is if the authentication data of a
webapp is stored in xml, i.e. an XML database. With a forged userId
the system can be tricked to authenticate without a proper password&lt;br /&gt;
&lt;br /&gt;
&lt;h3 class=&quot;western&quot;&gt;
The Defense&lt;/h3&gt;
The only effective defense is to sanitize the user input!
Typically, a regex-pattern could help with allowing only input of a
certain pattern, i.e. allowing only alphanumeric characters and
within a specific length range (5 to 15 characters):&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;if(!userId.matches([a-zA-Z0-9]{5,15}) { 
  throw new Exception(“Invalid Input“); 
}
&lt;/pre&gt;
If reserved characters should be allowed, you may escape them:&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;String escapedUserId = userId.replaceAll(“&#39;“, “\\&#39;“);
&lt;/pre&gt;
&lt;div class=&quot;code-western&quot;&gt;
&lt;/div&gt;
Although that may be prone to further injection to circumvent
the escaping, so it should be thoroughly tested if self-implemented.

Both pattern matching and escaping could be encapsulated in a
javax.xml.xpath.XpathVariableResolver that is registered at the Xpath
instance. The following example shows a sanitizing variable resolver
that accepts a set of regular expressions to check the parameters
that should be resolved&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public class SanitizingVariableResolver implements XPathVariableResolver {
   //create a map to contain the variable values
  private Map&amp;lt;QName, String&amp;gt; variables = new HashMap&amp;lt;&amp;gt;();
  //keep a list of all valid patterns
  private final List&amp;lt;Pattern&amp;gt; validationPatterns;

  //constructor accepting regular expression patterns
  public SanitizingVariableResolver(String... regexPatterns){
    this.validationPatterns = new ArrayList&amp;lt;&amp;gt;();
    for(String regexPattern : regexPatterns) {
      this.validationPatterns.add(Pattern.compile(regexPattern));
    }
  }
  //method to add variable value on which the sanity check is applied
  public void addVariable(String name, String value) {
    for(Pattern pattern : validationPatterns){
      if(pattern.matcher(value).matches()){
        variables.put(new QName(name), value);
        return;
      }
    }
    //don&#39;t accept invalid values
    throw new IllegalArgumentException(&quot;The value &#39;&quot; + value + &quot;&#39; is not 
      allowed for a variable&quot; );
  }
  @Override
  public Object resolveVariable(QName variableName) {
    return this.variables.get(variableName);
  }
}
&lt;/pre&gt;
Next, you&#39;ll have to apply this resolver to your Xpath instance
and use an Xpath expression with a variable placeholder:&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;//create new xpath instance
final XPath xp = XPathFactory.newInstance().newXPath();

//instantiate the resolver with an alpahnumeric pattern
final SanitizingVariableResolver resolver = 
  new SanitizingVariableResolver(&quot;[a-zA-Z0-9]{4,15}&quot;);

//add the user id value
resolver.addVariable(&quot;userId&quot;, userId);

//assign the resolver to the xpath instance
xp.setXPathVariableResolver(resolver);

//apply the xpath expression with variable
xp.evaluate(&quot;//technical-users/user[@id=$userId]/privateKey&quot;,source);
&lt;/pre&gt;
&lt;br /&gt;
An
alternative to sanitizing the input yourself, you may use alternative
libraries such as Xquery that provides an abstraction layer on top of
the Xpath API that provides means to sanitize parameter input.&lt;br /&gt;
&lt;br /&gt;
&lt;h3 class=&quot;western&quot;&gt;
References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href=&quot;https://www.owasp.org/index.php/Top_10_2013-A1-Injection&quot;&gt;OWASP:
 Top 10 2013-A1-Injection&lt;/a&gt;&lt;br /&gt;

 &lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;http://cwe.mitre.org/data/definitions/643.html&quot;&gt;CWE-643:
 Improper Neutralization of Data within XPath Expressions (&#39;XPath
 Injection&#39;)&lt;/a&gt;&lt;br /&gt;

 &lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=61407250&quot;&gt;CERT:
 IDS09-J. Prevent XPath Injection (archive)&lt;/a&gt;&lt;br /&gt;

 &lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;http://media.blackhat.com/bh-eu-12/Siddharth/bh-eu-12-Siddharth-Xpath-WP.pdf&quot;&gt;Black
 Hat Europe 2012: Hacking XPath 2.0&lt;/a&gt;&lt;br /&gt;

 &lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;http://www.balisage.net/Proceedings/vol7/html/Vlist02/BalisageVol7-Vlist02.html&quot;&gt;Balisage:
 XQuery Injection&lt;/a&gt;&amp;nbsp; &lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 class=&quot;western&quot;&gt;
&amp;nbsp;&lt;/h2&gt;
&lt;h4 class=&quot;western&quot;&gt;
XML External Entity (XXE) 
&lt;/h4&gt;
XML document have to be well-formed and may be validated. For
validation, there are two options for declaring a structure against
which the document is validated: Doctype Definition (DTD) or XML
Schema. A DTD may be embedded in the document itself. For XML the
concepts of entities exist to describe characters or values that are
parsed and replaced by the XML processor. A common example is the
&amp;amp;-entity for describing an ampersand character (&#39;&amp;amp;&#39;)
because the &#39;&amp;amp;&#39; is a reserved character in Xml. Within a DTD
custom entities can be declared. Values for those entities could be
characters but also the content external resources indicated by an
URI.&lt;br /&gt;
&lt;br /&gt;
&lt;h3 class=&quot;western&quot;&gt;
The Attack&lt;/h3&gt;
In an XXE atttack, the attacker sends a perpared XML file
containing a malicious entity. The entity points to an external
resource containing a secret, i.e. /etc/passwd. Depending on what the
service actually does, the attacker may easily read the secret from
the parsed document.&lt;br /&gt;
A prepared XML document may be&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;!DOCTYPE document [
    &amp;lt;!-- placeholder for the attacked file url --&amp;gt;
    &amp;lt;!ENTITY xxe SYSTEM &quot;/etc/passwd&quot; &amp;gt;
]&amp;gt;
&amp;lt;document&amp;gt;
    &amp;lt;!-- the external entity is replaced with the injected value --&amp;gt;&amp;gt;
    &amp;lt;property&amp;gt;&amp;amp;xxe;&amp;lt;/property&amp;gt;
&amp;lt;/document&amp;gt;
&lt;/pre&gt;
When being processed by DocumentBuilder, the &amp;amp;xxe; is
resolved to the content of /etc/passwd and accessible as text content
of the &lt;property&gt; element.

The attack is also valid for processing XML with the SAX parser.&lt;/property&gt;&lt;br /&gt;
&lt;property&gt;&amp;nbsp;&lt;/property&gt;
&lt;br /&gt;
&lt;h3 class=&quot;western&quot;&gt;
The Defense&lt;/h3&gt;
There are several options to fix this vulnerability. Probably the
easiest one is to use XML-Schemas only for XML validation and disable
the Doctype Declaration feature by setting the &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;DocumentBuilderFactory&lt;/span&gt;
Feature &lt;span style=&quot;font-family: Liberation Mono, monospace;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;http://apache.org/xml/features/disallow-doctype-decl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;to true:&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
f.setFeature(&quot;http://apache.org/xml/features/disallow-doctype-decl&quot;, true);
&lt;/pre&gt;
&lt;br /&gt;
&lt;div class=&quot;code-western&quot;&gt;
&lt;br /&gt;
This feature however is only supported by Xerces2. If you&#39;re
on Xerces 1 or you can not disable Doctype declaration, you could
disable the features&lt;/div&gt;
&lt;br /&gt;
Xerces 1&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;http://xerces.apache.org/xerces-j/features.html#external-general-entities&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;
&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;http://xerces.apache.org/xerces-j/features.html#external-parameter-entities&lt;/span&gt;&lt;br /&gt;
Xerces 2&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;http://xerces.apache.org/xerces2-j/features.html#external-general-entities&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities&lt;/span&gt;&lt;br /&gt;
Sax in general&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;http://xml.org/sax/features/external-general-entities&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;http://xml.org/sax/features/external-parameter-entities &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
and set on the DocumentBuilderFactory the flags&lt;br /&gt;
&lt;div style=&quot;line-height: 100%; margin-bottom: 0cm;&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;dbf.setXIncludeAware(false);&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace; font-size: small;&quot;&gt;dbf.setExpandEntityReferences(false);&lt;/span&gt;&lt;br /&gt;
&amp;nbsp;
&lt;br /&gt;
Oracle proposes two alternative approaches. The first is to
perform the parse operation in a privileged context with a
no-permission ProtectionDomain where the java security policy is
effective, preventing access to restricted system files. The second
is to use an EntityResolver and allow only entities that match a
certain pattern.&lt;br /&gt;
Further attacks against DTD, Schema and Entities and how to defend
against are discussed in XML &quot;&lt;a href=&quot;http://www.vsecurity.com/download/papers/XMLDTDEntityAttacks.pdf&quot;&gt;Schema, DTD, and Entity Attacks&lt;/a&gt;&quot;(pdf).&lt;br /&gt;
&lt;br /&gt;
&lt;h3 class=&quot;western&quot;&gt;
References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href=&quot;http://cwe.mitre.org/data/definitions/611.html&quot;&gt;CWE-611:
 Improper Restriction of XML External Entity Reference (&#39;XXE&#39;)&lt;/a&gt;&lt;br /&gt;

 &lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=61702260&quot;&gt;CERT:
 IDS10-J. Prevent XML external entity attacks&lt;/a&gt;&lt;br /&gt;

 &lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;https://www.owasp.org/index.php/XML_External_Entity_%28XXE%29_Processing&quot;&gt;OWASP.org:
 XML External Entity (XXE) Processing&lt;/a&gt;&lt;br /&gt;

 &lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;http://www.ws-attacks.org/index.php/XML_Entity_Expansion&quot;&gt;WS-Attacks.org:
 XML Entity Expansion&lt;/a&gt;&lt;br /&gt;

 &lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;http://www.ws-attacks.org/index.php/XML_External_Entity_DOS&quot;&gt;WS-Attacks.org:
 XML External Entity DOS&lt;/a&gt;&lt;br /&gt;

 &lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;http://www.ws-attacks.org/index.php/XML_Entity_Reference_Attack&quot;&gt;WS-Attacks.org:
 XML Entity Reference Attack&lt;/a&gt;&lt;br /&gt;

 &lt;/li&gt;
&lt;li&gt;
&lt;a href=&quot;http://xerces.apache.org/xerces2-j/features.html&quot;&gt;Xerces2
 complete features list&lt;/a&gt;&lt;br /&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
All examples, including JUnit tests that can be used as template to tests your own code can be found on &lt;a href=&quot;https://github.com/gmuecke/whoopdicity/tree/master/examples&quot;&gt;https://github.com/gmuecke/whoopdicity/tree/master/examples&lt;/a&gt;&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/122861300631097542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/122861300631097542' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/122861300631097542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/122861300631097542'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2015/05/java-xml-processing-vulnerabilities.html' title='Java XML Processing Vulnerabilities'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-444392668824589287</id><published>2015-05-26T11:10:00.000+02:00</published><updated>2015-05-26T11:10:02.702+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="framework"/><category scheme="http://www.blogger.com/atom/ns#" term="inkstand"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="microservice"/><category scheme="http://www.blogger.com/atom/ns#" term="release"/><title type='text'>Inkstand Release 0.1.3</title><content type='html'>&lt;div class=&quot;wiki-content&quot; id=&quot;main-content&quot;&gt;
                                                                
        &lt;div class=&quot;wiki-content&quot;&gt;
Yesterday I released 0.1.3 of the &lt;a href=&quot;http://inkstand.io/&quot;&gt;Inkstand &lt;/a&gt;microservice framework fixing some bugs and added some minor improvements.&lt;br /&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;wiki-content&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;wiki-content&quot;&gt;
&lt;h3&gt;
Bug&lt;/h3&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-31&quot;&gt;INK-31&lt;/a&gt;] - Sonar Issue - Security - XML Parsing Vulnerable to XXE (SAXParser) in JCRContentLoader&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-17&quot;&gt;INK-17&lt;/a&gt;] - Apply Apache Licence to code base&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-29&quot;&gt;INK-29&lt;/a&gt;] - Findings in Code Inspection&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-32&quot;&gt;INK-32&lt;/a&gt;] - remove log4j2.xml from core&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-41&quot;&gt;INK-41&lt;/a&gt;] - Wrong Logging Statements in ServiceLauncher&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;
Task&lt;/h3&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-4&quot;&gt;INK-4&lt;/a&gt;] - Document Inkstand in wiki&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-5&quot;&gt;INK-5&lt;/a&gt;] - Set up Test Quality Assessment&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-6&quot;&gt;INK-6&lt;/a&gt;] - Set up Build for master branch&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-34&quot;&gt;INK-34&lt;/a&gt;] - Update to Apache Jackrabbit 2.10.1&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-35&quot;&gt;INK-35&lt;/a&gt;] - Update Apache DS to 2.0.0-M20 and LDAP API to 1.0.0-M30&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-36&quot;&gt;INK-36&lt;/a&gt;] - Update Undertow to 1.2.6.Final&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-37&quot;&gt;INK-37&lt;/a&gt;] - Update Apache Deltaspike to 1.4.0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/INK-40&quot;&gt;INK-40&lt;/a&gt;] - Update Scribble to 0.1.2&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/444392668824589287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/444392668824589287' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/444392668824589287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/444392668824589287'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2015/05/inkstand-release-013.html' title='Inkstand Release 0.1.3'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-7984699975986068070</id><published>2015-05-19T21:07:00.000+02:00</published><updated>2015-05-19T21:11:27.536+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="framwork"/><category scheme="http://www.blogger.com/atom/ns#" term="inkstand"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jcr"/><category scheme="http://www.blogger.com/atom/ns#" term="opensource"/><category scheme="http://www.blogger.com/atom/ns#" term="scribble"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><title type='text'>Scribble 0.1.2</title><content type='html'>Today I released version 0.1.2 of the Scribble testing framwork. Beside some bugifxes, the main improvement was the added support for initializing the JCR ContentRepository test rules with nodetype definitions from a CND file.&lt;br /&gt;
&lt;h3&gt;
&amp;nbsp;Bug&lt;/h3&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-16&quot;&gt;SCRIB-16&lt;/a&gt;] - @Inject Annotations is not considered&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-19&quot;&gt;SCRIB-19&lt;/a&gt;] - InjectableHolders are not recognized properly when injecting&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-23&quot;&gt;SCRIB-23&lt;/a&gt;] - Sonar Issue: The use of XPath.evaluate() is vulnerable to XPath injection&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-24&quot;&gt;SCRIB-24&lt;/a&gt;] - Sonar Issue: The usage of /DocumentBuilder.parse(...) is vulnerable to XML External Entity attacks&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-25&quot;&gt;SCRIB-25&lt;/a&gt;] - Sonar Issue: Use a cryptographically strong random number generator (RNG) like &quot;java.security.SecureRandom&quot; in place of this PRNG&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Story&lt;/h3&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-11&quot;&gt;SCRIB-11&lt;/a&gt;] - Convenience Methods for InMemory and StandaloneRepository creation&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-20&quot;&gt;SCRIB-20&lt;/a&gt;] - Initialize Repository with CND node types&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Task&lt;/h3&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-17&quot;&gt;SCRIB-17&lt;/a&gt;] - Set up Build for master branch&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-18&quot;&gt;SCRIB-18&lt;/a&gt;] - Set up Test Quality Assesment&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-21&quot;&gt;SCRIB-21&lt;/a&gt;] - Update Apache DS Dependency to 2.0.0-M20&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;a href=&quot;https://inkstand.atlassian.net/browse/SCRIB-22&quot;&gt;SCRIB-22&lt;/a&gt;] - Fix &quot;Copyright and license headers should be defined&quot; Rule configuration</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/7984699975986068070/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/7984699975986068070' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/7984699975986068070'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/7984699975986068070'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2015/05/scribble-012.html' title='Scribble 0.1.2'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-1652535535458383994</id><published>2015-05-12T11:39:00.003+02:00</published><updated>2015-05-13T09:20:32.048+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fired"/><category scheme="http://www.blogger.com/atom/ns#" term="job"/><category scheme="http://www.blogger.com/atom/ns#" term="scrum master"/><category scheme="http://www.blogger.com/atom/ns#" term="search"/><title type='text'>Off to new horizons</title><content type='html'>April 30th was a weird day. It started like a normal day and ended in me being fired out of blue 20 minutes before I had to leave to pickup my kids from childcare. The reason I was told was that I don&#39;t fit into the company&#39;s culture, which is kind of weird after 2.5years of hard working making customers happy and having a proven track record of outstanding results.&lt;br /&gt;
&lt;br /&gt;
What happened?&lt;br /&gt;
&lt;br /&gt;
Well, I don&#39;t know, but I can only speculate. With the last project I was involved in, the company tried to enter the market of software vendors. The company itself has a long history of being successful in consulting, but had no experience so far in producing software themselves. We adopted Scrum as method and I had the role of Solution Architect or Architecture Owner (you name it) and Scrum Master. We made good progress having to tackle lots of obstacles especially as the stack we used was new to us, same as the persistence layer. &lt;br /&gt;
&lt;br /&gt;
My personal goals as scrum master were to pave the way for bringing the product to it&#39;s first go-live, second aiming for high quality as a small company cannot afford producing crappy software and third, increase transparency of the project&#39;s progress as a lot of the stakeholders were working at customers and were not located in the office. I also stood up for protecting the team from unnecessary overtime as the effect on declining quality is well known. And I tried to mitigate unrealistic expectations from wishful thinking to what&#39;s realizable, always embracing challenges. I really took my job seriously and diligently. But I assume it was too much for a company that not fully embraced the agile idea. I guess in the end it was a personal conflict that grew on one end, 
totally hidden from me, and no one ever made attempts to solve it in a 
professional way. Stories about scrum master&#39;s being fired for taking their job seriously are not unknown, and now it was my turn. Bad luck I&#39;d say.&lt;br /&gt;
&lt;br /&gt;
My advice for other scrum masters, if your stakeholder are not available physically most of the time find ways for effective communication rather sooner than later. And if your stakeholders are detached, try to re-connect them with the project and what&#39;s actually going on. Though that might just reduce but not remove the risk. &lt;br /&gt;
&lt;br /&gt;
Anyway, so now it&#39;s official, I&#39;m looking for a new Job!&lt;br /&gt;
So if you have or hear of an open position as Scrum Master, Software Engineer or Architect, drop me a message.&lt;br /&gt;
&lt;br /&gt;
And while I&#39;m on job search, I&#39;ll spent some time on my new pet project, a microservice framework named &lt;a href=&quot;http://inkstand.io/&quot;&gt;Inkstand&lt;/a&gt;! If you&#39;re interested, I&#39;ll invite you come around, have look, drop a comment or join!</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/1652535535458383994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/1652535535458383994' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/1652535535458383994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/1652535535458383994'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2015/05/off-to-new-horizons.html' title='Off to new horizons'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-2278233358363740024</id><published>2015-02-03T17:38:00.000+01:00</published><updated>2015-02-03T17:38:44.862+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="development"/><category scheme="http://www.blogger.com/atom/ns#" term="junit"/><category scheme="http://www.blogger.com/atom/ns#" term="mutation"/><category scheme="http://www.blogger.com/atom/ns#" term="pit"/><category scheme="http://www.blogger.com/atom/ns#" term="quality"/><category scheme="http://www.blogger.com/atom/ns#" term="testing"/><title type='text'>Mutation Testing</title><content type='html'>End of January I attended the &lt;a href=&quot;http://www.oop-konferenz.de/&quot;&gt;OOP2015 &lt;/a&gt;conference in Munich. Among the load of interesting sessions was one that left a mark. It was the workshop conducted by Filip van Laenen and Markus Schirp about &lt;i&gt;Mutation Testing&lt;/i&gt; (slides &lt;a href=&quot;http://www.slideshare.net/filipvanlaenen/oop-2015-mutation-testing&quot;&gt;here&lt;/a&gt;), which I&#39;d like to summarize in this post.&lt;br /&gt;
&lt;h4&gt;
What is Mutation Testing?&lt;/h4&gt;
Mutation testing is a method to ensure the quality of your Test. With mutations testing you verify if your tests not only invokes your product code pretending to cover lines and branches but that the tests actually reflects the semantics of your code. While your tests guard your product code from bugs, mutation testing guards your tests suite from critical gaps. &lt;br /&gt;
&lt;h4&gt;
How does it work?&lt;/h4&gt;
Mutation testing is available for a set of languages. The implementation for Java is the &lt;a href=&quot;http://pitest.org/&quot;&gt;PIT&lt;/a&gt;. PIT modifies the compiled byte code by applying a set of predefined rules, so call Mutators. Each change to the byte code is called a &lt;i&gt;Mutant&lt;/i&gt;. Against the altered byte code your unit tests are executed, resulting in three outcomes:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;The tests fails. This proves, that your tests detects the changes to the byte code correctly and reports an error. This outcome is called a &lt;i&gt;Killed Mutant&lt;/i&gt;.&lt;/li&gt;
&lt;li&gt;The test does not fail, but the line of code is covered by the test execution. This proves, that your test does not cover the full semantics of the product. This outcome is called a &lt;i&gt;Survived Mutant&lt;/i&gt; (I call them Survivors). &lt;/li&gt;
&lt;li&gt;The product code is not covered by a test at all but contains a mutant. This is outcome is an &lt;i&gt;Uncovered Mutant&lt;/i&gt; (I call them Lurker), which can also be indicated by a Code Coverage tool such as Cobertura or jacoco.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
What&#39;s the use of it?&lt;/h4&gt;
Every mutant not killed by a test is a blind spot of your test suite and may become an actual bug in the long run. With mutation testing you can determine, whether your Unit Test - the detail specification - covers all the semantics of your product code. For every uncovered mutant you may either decide if your specification (test) is incomplete or your product code contains unneeded semantics which should be removed. That way mutation testing leads to smaller and simpler code and further is an indicator, when you are &lt;i&gt;done &lt;/i&gt;with testing.&lt;br /&gt;
&lt;h4&gt;
Its no silver bullet&lt;/h4&gt;
Mutation testing is no silver bullet as it does not replace the need for properly designed tests in the first place. Testing for all combinations of Mutations may become a quite resource consuming operation, requiring to reduce the scope of mutation testing in larger projects on the crucial parts. &lt;br /&gt;
Further, some survived mutants may have to be accepted. Survived mutants may easily occur and may not necessarily be an indicator that your coverage is insufficient. For a simple example, think about logging code or the equality in some comparison cases, like ( a &amp;gt; b ? a : b) which in Java is equal to (a &amp;gt;=b ? a : b).&lt;br /&gt;
&lt;h4&gt;
How to use it?&lt;/h4&gt;
To use it on a maven project, an official &lt;a href=&quot;http://pitest.org/quickstart/maven/&quot;&gt;maven plugin&lt;/a&gt; is avaible (see link for a good documentation how to use it). There are options for command line or Ant as well. This will create a report in html or xml. You may narrow the scope of the mutation testing using include and exclude parameter. The report itself run on a regular basis is already a good source of information for conduction code reviews.&lt;br /&gt;
For using it with SonarQube, a plugin is available, but its current version 0.5 is only compatible with SonarQube prior to version 4.2. There is a &lt;a href=&quot;https://github.com/gvsmirnov/sonar-pitest&quot;&gt;fork &lt;/a&gt;on github, making it compatible with Sonar API version 4.3 and I am working on a &lt;a href=&quot;https://github.com/gmuecke/sonar-pitest&quot;&gt;version for SonarQube 5.0&lt;/a&gt; with some more rules. Both have to be compiled and deployed manually to Sonar.&lt;br /&gt;
&lt;h4&gt;
TL;DR&lt;/h4&gt;
Mutation Testing alters your product code in a deterministic way and verifies if your test suite finds the induced bug. This leads to smaller and simpler source code and you can tell when your&#39;re done with testing.</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/2278233358363740024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/2278233358363740024' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/2278233358363740024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/2278233358363740024'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2015/02/mutation-testing.html' title='Mutation Testing'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-2549516004975071736</id><published>2014-09-23T07:58:00.002+02:00</published><updated>2014-09-23T08:00:09.437+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="build"/><category scheme="http://www.blogger.com/atom/ns#" term="convert"/><category scheme="http://www.blogger.com/atom/ns#" term="gif"/><category scheme="http://www.blogger.com/atom/ns#" term="graphics"/><category scheme="http://www.blogger.com/atom/ns#" term="howto"/><category scheme="http://www.blogger.com/atom/ns#" term="images"/><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="pdf"/><category scheme="http://www.blogger.com/atom/ns#" term="png"/><category scheme="http://www.blogger.com/atom/ns#" term="rasterize"/><category scheme="http://www.blogger.com/atom/ns#" term="scalable"/><category scheme="http://www.blogger.com/atom/ns#" term="svg"/><category scheme="http://www.blogger.com/atom/ns#" term="tiff"/><title type='text'>Rasterizing scalable images during build</title><content type='html'>&lt;br /&gt;
In most web projects your content does not only include code, html or css but also images. Those images are typically delivered as non-scalable graphics to the clients (i.e. jpg, png, gif). But ususally those images are created from a scalable image that allows to &quot;design&quot; the actual image and produce versions of various sizes from the scalable image. The process of transforming a scalable graphic to a non-scalable graphic is called rasterization and fortunately the process can be automated when you&#39;re running your build with Maven.&lt;br /&gt;
&lt;br /&gt;
The&amp;nbsp;&lt;a href=&quot;http://mojo.codehaus.org/batik-maven-plugin/&quot;&gt;Batik Maven plugin&lt;/a&gt; allows you to convert your svg (Scalable Vector Graphics) images to non-scalable images, supported types are &lt;code&gt;png&lt;/code&gt;,
&lt;code&gt;jpeg&lt;/code&gt;, &lt;code&gt;tiff&lt;/code&gt; or &lt;code&gt;pdf&lt;/code&gt;. The plugin can be added to your build lifecycle. The plugin documentation states that adding the following snippet to your pom.xml&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint 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;batik-maven-plugin&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;1.0-beta-1&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;rasterize&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;
Unfortunately that&#39;s not sufficient as not all dependencies seem to be satisfied. But the following snippet worked for me (see also &lt;a href=&quot;https://jira.codehaus.org/browse/MOJO-1670&quot;&gt;https://jira.codehaus.org/browse/MOJO-1670&lt;/a&gt; )&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;&amp;lt;build&amp;gt;
  &amp;lt;plugins&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;batik-maven-plugin&amp;lt;/artifactId&amp;gt;
      &amp;lt;version&amp;gt;1.0-beta-1&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;rasterize&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;batik&amp;lt;/groupId&amp;gt;
          &amp;lt;artifactId&amp;gt;batik-rasterizer&amp;lt;/artifactId&amp;gt;
          &amp;lt;version&amp;gt;1.6&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
          &amp;lt;groupId&amp;gt;org.axsl.org.w3c.dom.svg&amp;lt;/groupId&amp;gt;
          &amp;lt;artifactId&amp;gt;svg-dom-java&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;org.w3c.css&amp;lt;/groupId&amp;gt;
          &amp;lt;artifactId&amp;gt;sac&amp;lt;/artifactId&amp;gt;
          &amp;lt;version&amp;gt;1.3&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
      &amp;lt;/dependencies&amp;gt;
      &amp;lt;/plugin&amp;gt;
    &amp;lt;/plugins&amp;gt;
&amp;lt;/build&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
With that snippet I could place my svg files into &lt;code&gt;/src/main/svg&lt;/code&gt; and during the build those files are rasterized to png files in the &lt;code&gt;/target/generated-resources/images&lt;/code&gt; (locations and type are default settings and can be configured). From now on it&#39;s quite easy to &quot;compile&quot; your images during the build and you never have to paint your images by pixel anymore.&lt;br /&gt;
&lt;br /&gt;
If you&#39;re looking for a free and powerful SVG &quot;editor&quot;, try &lt;a href=&quot;http://www.inkscape.org/&quot;&gt;Inkscape&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/2549516004975071736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/2549516004975071736' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/2549516004975071736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/2549516004975071736'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/09/compile-your-images-during-build.html' title='Rasterizing scalable images during build'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-4723937783516312886</id><published>2014-08-26T17:53:00.002+02:00</published><updated>2014-08-26T18:17:00.216+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="acceptance testing"/><category scheme="http://www.blogger.com/atom/ns#" term="bdd"/><category scheme="http://www.blogger.com/atom/ns#" term="behavior driven"/><category scheme="http://www.blogger.com/atom/ns#" term="cucumber"/><category scheme="http://www.blogger.com/atom/ns#" term="development"/><category scheme="http://www.blogger.com/atom/ns#" term="howto"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="junit"/><category scheme="http://www.blogger.com/atom/ns#" term="selenium"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><category scheme="http://www.blogger.com/atom/ns#" term="uat"/><title type='text'>User Acceptance Testing with Selenium and Cucumber</title><content type='html'>In the last implementation project I participated in we applied the &lt;a href=&quot;http://en.wikipedia.org/wiki/Behavior-driven_development&quot;&gt;Behavior Driven Development &lt;/a&gt;approach where the user stories are defined in Given-When-Then style. In this article I want to describe how I combined &lt;a href=&quot;http://cukes.info/&quot;&gt;Cucumber&lt;/a&gt; with &lt;a href=&quot;http://www.seleniumhq.org/&quot;&gt;Selenium &lt;/a&gt;in order to automate our User-Acceptance Tests using Behavior Driven Development.&lt;br /&gt;
&lt;br /&gt;
For running automated BDD tests there are some free frameworks available (a brief comparison of &lt;a href=&quot;http://java.dzone.com/articles/brief-comparison-bdd&quot;&gt;BDD frameworks&lt;/a&gt;). We decided to go for &lt;a href=&quot;http://cukes.info/&quot;&gt;Cucumber&lt;/a&gt; because it served all our requirements, has a good documentation with good examples and is pretty easy to get it up and running&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Cucumber JUnit Test&lt;/h3&gt;
The following listing shows a simple example that is practically the archetype for all our Cucumber tests.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;@RunWith(Cucumber.class)
@CucumberOptions(
  features = { &quot;classpath:features/example/&quot; },
  glue = { &quot;my.project.uat.&quot; },
  tags = { &quot;@Example&quot; })
public class ExampleCucumberTest {
  //empty
}
&lt;/pre&gt;
The annotations of the example in detail are:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;@RunWith declares the TestRunner for this test, which is the Cucumber class. The test won&#39;t run without it.&lt;/li&gt;
&lt;li&gt;@CucumberOptions define various options for this tests. The options are optional but are quite helpful in controlling the behavior of the test&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;features: declares a path were the BDD feature files (text files) are found. The example points to a location in the classpath. All feature files (.feature extension) below that location are considered. Multiple locations can be defined as an array.&lt;/li&gt;
&lt;li&gt;glue: defines the packages where Steps and Hooks are located. Steps and Hooks contain the actual code for the tests. Multiple packages can be defined as an array.&lt;/li&gt;
&lt;li&gt;tags: defines which stories should be executed. If you omit this option, all Stories are executed, otherwise only those that have one of the tags set will be run.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
Of course there are more options available (see &lt;a href=&quot;http://cukes.info/api/cucumber/jvm/javadoc/cucumber/api/CucumberOptions.html&quot;&gt;Cucumber apidoc&lt;/a&gt;)&amp;nbsp; but these are the options I use most. As soon as you have your first story written, you can start right away with this simple test.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
BDD Feature&amp;nbsp; &lt;/h3&gt;
The following exaple story is taken from the &lt;a href=&quot;https://github.com/cucumber/cucumber/wiki&quot;&gt;Cucumber documentation&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;@Example
Feature: Search courses
  Courses should be searchable by topic
  Search results should provide the course code

Scenario: Search by topic
    Given there are 240 courses which do not have the topic &quot;biology&quot;
    And there are 2 courses, A001 and B205, that each have &quot;biology&quot; as one of the topics
    When I search for &quot;biology&quot;
    Then I should see the following courses:
      | Course code |
      | A001        |
      | B205        |
&lt;/pre&gt;
&lt;br /&gt;
With that feature in the right location you can run the above test with JUnit. Of course it will not be successful. Actually, with the default settings it will ignore all the steps unless you use the @CucumberOption(strict=true) which is recommended when you run the test as part of a quality gate.&lt;br /&gt;
The Cucumber documentation provides some good descriptions on &lt;a href=&quot;https://github.com/cucumber/cucumber/wiki/Feature-Introduction&quot;&gt;Features and their syntax&lt;/a&gt;. You can define &lt;a href=&quot;https://github.com/cucumber/cucumber/wiki/Background&quot;&gt;Backgrounds &lt;/a&gt;that are executed for each scenario of the feature (similar to JUnit 4 @BeforeClass) or &lt;a href=&quot;https://github.com/cucumber/cucumber/wiki/Scenario-Outlines&quot;&gt;Scenario Outlines&lt;/a&gt; to run the feature against a set of data. It is even possible to write your BDDs in different languages. Therefore you have to start the feature with the line following line and have all the keywords in the according language.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;#language: de
Funktionalität: ...
&lt;/pre&gt;
&lt;br /&gt;
But you have to be careful with the encoding of the Feature files and special characters. It&#39;s best to use UTF-8 as default encoding. A complete list of the keywords in other languages can be found in the &lt;a href=&quot;http://cukes.info/api/cucumber/jvm/javadoc/&quot;&gt;Cucumber apidoc&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Cucumber Steps &lt;/h3&gt;
When the test for the feature is run and the steps or part of it are not yet implemented, it will produce an output like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;You can implement missing steps with the snippets below:

@Given(&quot;^there are (\\d+) courses which do not have the topic \&quot;([^\&quot;]*)\&quot;$&quot;)
public void there_are_courses_which_do_not_have_the_topic(int arg1, String arg2) throws Throwable {
    // Express the Regexp above with the code you wish you had
    throw new PendingException();
}

@Given(&quot;^there are (\\d+) courses, A(\\d+) and B(\\d+), that each have \&quot;([^\&quot;]*)\&quot; as one of the topics$&quot;)
public void there_are_courses_A_and_B_that_each_have_as_one_of_the_topics(int arg1, int arg2, int arg3, String arg4) throws Throwable {
    // Express the Regexp above with the code you wish you had
    throw new PendingException();
}
...
&lt;/pre&gt;
&lt;br /&gt;
The test prints out skeletons for unimplemented steps. What you do now is to create a new step which is a simple Java class and put in one of the packages defined in the glue. Copy the skeletons into the class and implement it.&lt;br /&gt;
So the steps are basically what is executed for each line. It is possible to pass parameters to the steps that are extracted and converted so that steps can be reused with different values. Its also possible to define entire tables as input.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Hooks&lt;/h3&gt;
Hooks are basically the same as steps but fulfill a similar role like the JUnit&amp;nbsp;@Before and @After annotated methods, the even use the similar annotations (actually, the are named the same but are in a &lt;a href=&quot;http://cukes.info/api/cucumber/jvm/javadoc/cucumber/api/java/package-summary.html&quot;&gt;different package&lt;/a&gt;). You can trigger certain hooks using tags like shown in the following example:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;@WithFirefox
Scenario: Response times with 10 users
...
&lt;/pre&gt;
&lt;br /&gt;
and the according hook in Java will be&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;@Before(&quot;@WithFirefox&quot;)
public class BrowserHook {
 ...
  public void setupScenario_Firefox() {
   ...
  }
 ...
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Dependencies between Hooks and Steps&lt;/h3&gt;
In order to reuse existing code or to access the state of a particular Hook or Step instance you can create a dependency between the classes by defining a constructor that accepts a particular Hook or Step. The Cucumber JUnit runner will create instances of the according classes and inject them in classes that are dependent.&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public class MyBrowserSteps {

  private BrowserHook browserHook;

  public MyBrowserSteps(final BrowserHooks browserHook) {
    this.browserHook = browserHook;
  }
&lt;/pre&gt;
The same applies to Steps so you can make one set of steps dependent on other steps.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Selenium Steps&lt;/h3&gt;
So far I only described how to write any test with Cucumber, but for User Acceptance Testing you might want to test the actual solution. For web application that is the deployed application that is accessed by a browser. For browser automation the &lt;a href=&quot;http://docs.seleniumhq.org/&quot;&gt;Selenium framework&lt;/a&gt; is widely known and framework of choice for most cases. It provides a recording tool (a plugin to Firefox) to record user interactions with the browser. It provides a model to access elements of the website using Java and various methods of locating elements in the browser.&lt;br /&gt;
For automated user-acceptance tests with Selenium and Cucumber the basic approach would be to&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Record actions with the Selenium Recorder&lt;/li&gt;
&lt;li&gt;Copy them to Steps classes that match your BDD&lt;/li&gt;
&lt;li&gt;Define assertions in &lt;i&gt;Then&lt;/i&gt; step implementations&lt;/li&gt;
&lt;/ol&gt;
A step implemented with Selenium will look like in the following example&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;@When(&quot;^I push the button$&quot;)
public void i_push_the_button() throws Throwable {
  driver.findElement(By.cssSelector(&quot;div.v-select-button&quot;)).click();
}
&lt;/pre&gt;
&lt;br /&gt;
In order to reuse steps for different browsers, I used the BrowserHook shown in on of the example on above and set-up the browser using a specific tag for each browser. The driver is first initialized upon the first call to getDriver(). In the step itself I retrieve the driver from the BrowserHook that got injected. The BrowserHook may be implemented like this&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public final class BrowserHooks {
  private enum DriverType {
    headless,
    firefox,
    ie,
    chrome, ;
  }
  
  private WebDriver driver;

  public WebDriver getDriver() {
    if (driver == null) {
      switch (driverType) {
 case ie:
   driver = new InternetExplorerDriver();
   break;
        case firefox:
          driver = new FirefoxDriver();
          break;
        ...
    }
    return driver;
  }

  @Before(&quot;@WithFirefox&quot;)
  public void setupScenario_Firefox() {
    driverType = DriverType.firefox;
  }
  
  @Before(&quot;@WithIE&quot;)
  public void setupScenario_InternetExplorer() {
    driverType = DriverType.ie;
  }
  ...
}
&lt;/pre&gt;
And the step definition that uses it may look like &lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public class MyBrowserSteps {

  private BrowserHook browserHook;

  public MyBrowserSteps(final BrowserHooks browserHook) {
    this.browserHook = browserHook;
  }

  @When(&quot;^I push the button$&quot;)
  public void i_push_the_button() throws Throwable {
    this.browserHook.getDriver().findElement(By.cssSelector(&quot;div.v-select-button&quot;)).click();
  }
...
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Aggregate Steps&lt;/h3&gt;
One of the big advantages of a BDD framework like Cucumber is, that you can define steps that aggregate multiple steps. A good example for this is the Login Story. Although this is a point of typical discussions whether &quot;Login User&quot; is a valid Use Case or User Story (with regards to its business value) the requirement to allow a user to login does exists and its parameters need to be defined (whether it is via Single Sign On, Smartcard, Username/Password, Two-Factor or whatever else).&lt;br /&gt;
So let&#39;s assume you define a login user story such as&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt; Given the login screen is being displayed
 When I enter my username &quot;xxx&quot; and my password &quot;yyy&quot;
  And I push the login button
 Then I see the main screen of the application
  And I see my name being displayed in the user info box
&lt;/pre&gt;
Now you don&#39;t want to describe all these steps over and over again because the rest of the application under test requires a logged in user. So you could begin the other stories with&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;When the user &quot;xxx&quot; is logged in&lt;/li&gt;
&lt;/ul&gt;
Or even better by using a hook/tag before the story like&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;@Authenticated &lt;/li&gt;
&lt;/ul&gt;
Now, what you do in your code is to define a dependency to the steps class that contains the login step definitions and invoke each of them in the correct order either in a hook definition or in a step definition. The advantage of a hook is that you could combine it with other hooks to set up the test user or even persona.&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public class LoginSteps {

  private BrowserHook browserHook;

  public LoginSteps (final BrowserHooks browserHook) {
    this.browserHook = browserHook;
  }


  @Given(&quot;^the login screen is being displayed$&quot;)
  public the_login_screen_is_being_displayed() {
    this.browserHook.getDriver().get(baseURL);
  }
  @When(&quot;^I enter my username \&quot;([^\&quot;]*)\&quot; and my password \&quot;([^\&quot;]*)\&quot;$&quot;)
  public void I_enter_my_username_and_my_password(String arg1, String arg2) throws Throwable {
    //with Selenium, put in the values in the login form
  }
  @When(&quot;^I push the login button$&quot;)
  public void I_push_the_login_button() throws Throwable {
    // with Selenium, locate the submit/login button and click it
  }
  ...
}

public class LoginHook {

  private LoginSteps loginSteps;
  private String testUser;
  private String testPassword;

  public LoginHook (final LoginSteps loginSteps) {
    this.loginSteps= loginSteps;
   
  }

  @Before(value=&quot;@PersonaXY&quot;, order=1)
  public void selectPersonaXY() {
     this.testUser = ...;
     this.testPassword = ...;
  }

  @Before(value=&quot;@Authenticated&quot;, order=2)
  public void login() {
    this.loginSteps.the_login_screen_is_being_displayed();
    this.loginSteps.I_enter_my_username_and_my_password(testUser, testUserPassword);
    this.loginSteps.I_push_the_login_button();
    ...
  }
}
&lt;/pre&gt;
&lt;br /&gt;
And how it is used in a story&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt; @Authenticated @PersonaXY
 Given I see the meaningful screen
 When I do something purposeful
 Then I get a sensible result
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
&amp;nbsp;Conclusion&lt;/h3&gt;
In this article I gave a brief introduction into Cucumber and how to write testcases with it. I showed how to define steps with Selenium to create meaningful, browser-based user acceptance testing and I showed how to combine thereby reuse steps and hook to create a rich user acceptance testing suite.</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/4723937783516312886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/4723937783516312886' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/4723937783516312886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/4723937783516312886'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/08/user-acceptance-testing-with-cucumber.html' title='User Acceptance Testing with Selenium and Cucumber'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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-457071854377599320.post-1524036320486709669</id><published>2014-08-22T17:22:00.002+02:00</published><updated>2014-08-22T17:22:40.131+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cdi"/><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="deltaspike"/><category scheme="http://www.blogger.com/atom/ns#" term="dependency injection"/><category scheme="http://www.blogger.com/atom/ns#" term="howto"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jee"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="service"/><category scheme="http://www.blogger.com/atom/ns#" term="service locator"/><title type='text'>Developing a dynamic JEE service client with CDI (part 2)</title><content type='html'>In &lt;a href=&quot;http://whoopdicity.blogspot.ch/2014/07/developing-dynamic-jee-service-client.html&quot;&gt;the previous blog entry&lt;/a&gt; I described how to develop an JEE service client that performs lazy lookups and is injectable to satisfy a service dependency. In this article I want to describe how to extend this service client to allow client-side service call interception.&lt;br /&gt;
&lt;br /&gt;
Before I dive into the details of the interception, I want to outline the reasons why client-side call interception might be useful.&lt;br /&gt;
&lt;h4&gt;
Background &lt;/h4&gt;
In our current project we aspired a RESTful component-based architecture. For each of the components it should be possible to integrate them in a service oriented architecture via WebService, deploy them in a JEE environment accessing it as JNDI-locateable services or access them via a RESTful lightweight interface. Each component should be deployable standalone and should be operational as long as their lower-level component dependencies are satisfied. To be RESTful, our architecture followed the seven principles of REST, described in the famous &lt;a href=&quot;https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm&quot;&gt;thesis of Roy Fielding&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
With JEE we could easily add caching behavior on the service side of a service consumer-provider relationship by adding an interceptor that serves a call with data from a cache and therefore reducing processing resource usage on the service side.&lt;br /&gt;
&lt;br /&gt;
On the consumer side there is no such mechanism as to transparently intercept a service call before it is actually sent to the service. Such a client-side call interception could be of use for a range of use-cases&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;caching, to reduce network resource usage&lt;/li&gt;
&lt;li&gt;error handling and fault tolerance&lt;/li&gt;
&lt;li&gt;logging&lt;/li&gt;
&lt;li&gt;security&lt;/li&gt;
&lt;/ul&gt;
&amp;nbsp;The following description uses the service client I described in &lt;a href=&quot;http://whoopdicity.blogspot.ch/2014/07/developing-dynamic-jee-service-client.html&quot;&gt;a previous blog post&lt;/a&gt;.&lt;br /&gt;
&lt;h4&gt;
Adding Interceptor support&lt;/h4&gt;
In order to add call interceptors to the service client, we have to extend the invocation handler that delegates the service method invocation to the actual service by adding a stack of interceptors that are invoked consecutively.&lt;br /&gt;
&lt;br /&gt;
When a JEE interceptors is invoked an InvocationContext is passed to the interceptor. The interceptor may decide to fully intercept the request and not proceeding the invocation further. This is behavior is needed for caching or security concern. Alternatively, interceptors may execute some additional operations before or after proceeding with the invocation which is useful for logging or error handling.&lt;br /&gt;
&lt;br /&gt;
The &lt;a href=&quot;http://docs.oracle.com/javaee/6/api/javax/interceptor/InvocationContext.html&quot;&gt;InvocationContext &lt;/a&gt;is an interface introduced by JEE6. I used my own implementation of this interface where the getter methods defined by the interface simply return the values that are passed to the &lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/InvocationHandler.html&quot;&gt;InvocationHandler &lt;/a&gt;of the dynamic proxy (see the ProxyServiceInvocationHandler of the &lt;a href=&quot;http://whoopdicity.blogspot.ch/2014/07/developing-dynamic-jee-service-client.html&quot;&gt; previous blog post&lt;/a&gt;), the getTimer() method returns null, as I don&#39;t really need it. The main functionality of the InvocationContext however resides in the proceed() method. I used a stack (&lt;a href=&quot;http://docs.oracle.com/javase/7/docs/api/java/util/Deque.html&quot;&gt;Deque&lt;/a&gt;) to maintain a list of registered interceptors of which each is checked whether it may intercept the method invocation or not.&lt;br /&gt;
&lt;br /&gt;
The check is done in the method isInterceptedBy and does check the class of the interceptor instance as well as the method whether they both are annotated with the same the &lt;a href=&quot;http://docs.oracle.com/javaee/6/api/javax/interceptor/InterceptorBinding.html&quot;&gt;InterceptorBinding&lt;/a&gt; annotation. I deviated a bit from the JEE6 standard as I allowed an interceptor without an explicit interceptor binding to intercept any method invocation, but that is up to you. &lt;br /&gt;
The main method of my InvocationContext implementation are shown in the next listing&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;class ProxyInvocationContext implements InvocationContext {

  ...

  @Override
  public Object proceed() 
    throws IllegalAccessException, 
           IllegalArgumentException, 
           InvocationTargetException {
    if (!interceptorInvocationStack.isEmpty()) {
      final Object interceptor = interceptorInvocationStack.removeFirst();
      if (isInterceptedBy(interceptor)) {
        final Method aroundInvoke = interceptorMethods.get(interceptor);
        return aroundInvoke.invoke(interceptor, this);
      }
    }
    return this.method.invoke(target, this.parameters);
  }
  
  private boolean isInterceptedBy(final Object interceptor) {
    boolean hasNoBinding = true;
    for (final Annotation an : interceptor.getClass().getAnnotations()) {
      if (an.annotationType().getAnnotation(InterceptorBinding.class) != null) {
        hasNoBinding = false;
        if (getMethod().getAnnotation(an.annotationType()) != null) {
          return true;
        }
      }
    }
    return hasNoBinding;
  }
}
&lt;/pre&gt;
&lt;h4&gt;
Instantiating Interceptors in CDI Context using DeltaSpike&lt;/h4&gt;
Now we want to create interceptors and put them into the interceptor stack. The JEE 6 standard already defines interceptors so we could simply re-use this specification. JEE6 compliant interceptors may be used in a CDI lifecycle, that means lifecycle methods annotated with @PostConstruct or @PreDestroy are executed as well as injection of dependencies.&lt;br /&gt;
With the implementation of the InvocationContext described above, we need a collection of interceptor instances. In our project I used a configuration file (similar to the beans.xml where you have to define which interceptors should be loaded) where I defined the interceptor classes that should be loaded.&lt;br /&gt;
&lt;br /&gt;
Creating an instance of a class by the fully qualified name of the class is trivial using reflection (i.e. Class.forName(&quot;...&quot;).newInstance()). But when you have a CDI container you want to let the container do the creation and further process the lifecycle of the the instance including dependency injection.&lt;br /&gt;
&lt;br /&gt;
JEE6 itself does not provide the means for that but it defines an SPI. The &lt;a href=&quot;https://deltaspike.apache.org/&quot;&gt;Apache DeltaSpike&lt;/a&gt; project offers an implementation for that SPI (btw. it is developed by the same guys behind CDI in JEE6 itself). DeltaSpike allows to interact directly with the CDI container.&lt;br /&gt;
&lt;br /&gt;
The following code snippet assumes, that you have already loaded the interceptor class and verified it is annotated with the @Interceptor annotation. It first checks, if a CDI environment is active, if not, the interceptor is instantiated the traditional way. If it is active, a BeanManager reference is obtained, an injection target is created using the interceptor class.  This is needed to create the instance and inject dependencies to the instance. With the injection target, an interceptor Bean is created using the BeanBuilder of DeltaSpike. The Bean is a Contextual instance that is required by the manager to create a creational context. Having this context we can create a managed instance using the create method. DeltaSpikes contribution to the snippet is the BeanManagerProvider , the BeanBuilder and the DelegatingContextualLifecycle.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;private &amp;lt;I&amp;gt; I createInterceptor(final Class&amp;lt;I&amp;gt; interceptorClass) 
  throws InstantiationException, IllegalAccessException {
  
  final I interceptor;
  
  if (BeanManagerProvider.isActive()) {
    final BeanManager manager = BeanManagerProvider.getInstance().getBeanManager();
    final InjectionTarget&amp;lt;I&amp;gt; target = manager.createInjectionTarget(
                                            manager.createAnnotatedType(interceptorClass));
            
    final Bean&amp;lt;I&amp;gt; interceptorBean = 
      new BeanBuilder&amp;lt;I&amp;gt;(manager)
          .beanClass(interceptorClass)
          .beanLifecycle(new DelegatingContextualLifecycle&amp;lt;I&amp;gt;(target))
          .create();
    interceptor = interceptorBean.create(
                     manager.createCreationalContext(interceptorBean));

  } else {
    interceptor = interceptorClass.newInstance();
  }
  return interceptor;
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;h4&gt;
Conclusion&lt;/h4&gt;
In this article I described how the &lt;a href=&quot;http://whoopdicity.blogspot.ch/2014/07/developing-dynamic-jee-service-client.html&quot;&gt;Dynamic Service Client&lt;/a&gt; can be extended in order to provide client-side service call interception and how Interceptors (or Beans in general) can be instantiated in a CDI context using &lt;a href=&quot;https://deltaspike.apache.org/&quot;&gt;Apache DeltaSpike&lt;/a&gt;.&lt;a href=&quot;http://whoopdicity.blogspot.ch/2014/07/developing-dynamic-jee-service-client.html&quot;&gt;&lt;/a&gt;  </content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/1524036320486709669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/1524036320486709669' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/1524036320486709669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/1524036320486709669'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/08/developing-dynamic-jee-service-client.html' title='Developing a dynamic JEE service client with CDI (part 2)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-6179966634087419877</id><published>2014-07-23T07:23:00.000+02:00</published><updated>2014-07-23T07:23:04.783+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cdi"/><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="dependency injection"/><category scheme="http://www.blogger.com/atom/ns#" term="howto"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jee"/><category scheme="http://www.blogger.com/atom/ns#" term="lookup"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><category scheme="http://www.blogger.com/atom/ns#" term="service"/><category scheme="http://www.blogger.com/atom/ns#" term="service locator"/><title type='text'>Developing a dynamic JEE service client with CDI (part 1)</title><content type='html'>With JEE6 CDI was introduced in and standardized for the Java Enterprise world. The main scope for the CDI extension was for enterprise services as it simplified various mechanisms in the JEE world such as EJB lookup or invocation interception. Unfortunately the new features fall a bit short on the consumer side of services implemented with CDI, in particular the lookup or service locator pattern, and &lt;i&gt;client side &lt;/i&gt;invocation interception.&lt;br /&gt;
In this first article I want to describe a dynamic service client that performs lazy service dependency resolution (lookup) and that can be injected into a CDI injection point.&lt;br /&gt;
It is a good base for being extended to use sophisticated configuration or error handling mechanisms.&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;
Defining a Dynamic Service Locator&lt;/h4&gt;
In JEE6 its quite easy to perform a JNDI lookup for an EJB using the @EJB annotation. Unfortunately this is done during construction of the service consumers.  When you have a multi-module project where each module should be deployable independently from the others, deployment will fail if the dependencies defined by the&amp;nbsp;@EJB annotation could not be satisfied, that is, the EJB lookup fails.&lt;br /&gt;
The key to this problem is a lazy lookup, that is done first time the dependency is actually needed. But that is not supported by the&amp;nbsp;@EJB annotation.&lt;br /&gt;
In our current project we solved the problem by implementing a dynamic service proxy that implements the interface of the service and performs the lookup using a JNDI lookup or another strategy on the first actual service call.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Creating a Proxy&lt;/h3&gt;
Creating a dynamic proxy is relatively simple, you need a custom implementation of an InvocationHandler that performs the actual method invocation and need to specify the interfaces the dynamic proxy should implement. A factory method is used to create such a proxy instance. The the following code example shows such a factory method:&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public abstract class DynamicServiceClient {

  public static &amp;lt;T&amp;gt; T newInstance(final Class T serviceInterface) {
    return (T) java.lang.reflect.Proxy.newProxyInstance(
      getClassLoader(),
      new Class[] { serviceInterface }, 
      new ProxyServiceInvocationHandler T(config));
    }
 
  private static ClassLoader getClassLoader(){
     ...
  }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Invocation Handler&lt;/h3&gt;
The invocation handler delegates all service call to an instance of the actual service. The service is kept as an instance field of the invocation handler that is initialized upon the first service call using a Service Locator. The invoke method of the Invocation Handler delegates the call to the service instance.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;class ProxyServiceInvocationHandler&amp;lt;T&amp;gt; 
  implements InvocationHandler {
 /**
  * The service reference that is lazily initialized
  */
  private T service; 

 /**
  * The service locator that performs the actual lookup
  */
  private final ServiceLocator&amp;lt;T&amp;gt; locator;

    ...

  @Override
  public Object invoke(final Object proxy, final Method method, final Object[] args) 
    throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    //do the lookup if not already done
    if (this.service == null) {
      this.service = this.locator.locate();
    }
    //do the actual service call and return the result
    return method.invoke(this.service, args);
  }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Service Locator&lt;/h3&gt;
The service locator that is used in the the above listing performs the actual lookup. In our project I used an implementation that allowed to define a location strategy in a configuration, with the JNDI lookup being implemented in one of the strategies. The following example however shows a simple implementation that performs a straightforward JNDI lookup using a lookupName. &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public class ServiceLocator&amp;lt;T&amp;gt;{
 /**
  * the name for the JNDI lookup
  */
  private String lookupName;

    ...

  public T locate() {
    final Context context = new InitialContext();
    T service = (T)context.lookup(this.lookupName);
    return service;
  }
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;h4&gt;
Service Injection&lt;/h4&gt;
In order to use the dynamic service shown above and inject it via CDI, I used a producer method that creates instances of the dynamic service and a qualifier to distinguish the dynamic service client from the actual service implementation that might be available in the CDI container as well.&lt;br /&gt;
The creation of the instance itself is done by the static factory method shown in the first listing. The producer extends the DynamicServiceClient I described earlier and uses its static factory method. In order to keep the producer class simple, we need to extend some methods to the DynamicServiceClient.&lt;br /&gt;
&lt;br /&gt;
The extended DynamicServiceClient that is shown in the following listing contains the logic for the actual service proxy instantiation and an abstract method returning the interface class of the service to be instantiated that has to be implemented by the producer.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public abstract class DynamicServiceClient&amp;lt;T&amp;gt;{
  /**
   * Instance of the service client
   */
  private T serviceInstance;

  /**
   * The method has to return the interface of the service 
   */
  protected abstract Class&amp;lt;T&amp;gt; getServiceInterface();

  /**
   * Creates a new instance of the service client. 
   */
  protected T getInstance() {
   if (serviceInstance == null) {
       serviceInstance = newInstance(getServiceInterface());
   }
   return serviceInstance;
 }

  /**
   * The factory method to create a new service instance
   */
  public static &amp;lt;T&amp;gt; T newInstance(final Class&lt;t&gt; serviceInterface) {
    return (T) Proxy.newProxyInstance(
        getClassLoader(),
        new Class[] { serviceInterface }, 
        new ProxyServiceInvocationHandler&lt;t&gt;());
    }
  }

  private static ClassLoader getClassLoader(){
     ...
  }
}
&lt;/t&gt;&lt;/t&gt;&lt;/pre&gt;
&lt;br /&gt;
To qualify an injection point and the producer method to create and inject instances of the service client that implement the service interface and not instances of the actual service, I used a qualifier as shown in the next listing.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;@Qualifier
@Retention(RUNTIME)
@Target({ METHOD, FIELD, PARAMETER })
public @interface ServiceClient {}
&lt;/pre&gt;
&lt;br /&gt;
Now we&#39;re ready to define a producer using the DynamicServiceClient as base class. The producer is relatively simple as it only contains two simple methods.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public class MyServiceClientProducer 
  extends DynamicServiceClient&amp;lt;MyBusinessService&amp;gt; {

  @Produces @ServiceClient 
  public MyBusinessService getInstance() {
    return super.getInstance();
  }

  protected Class&amp;lt;MyBusinessService&amp;gt; getServiceInterface() {
    return MyBusinessService.class;
  }
}
&lt;/pre&gt;
To inject the dynamic service client into an injection point we simply have to define the Service interface class and use the qualifier. That&#39;s it.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public class MyServiceConsumer {

  @Inject @ServiceClient
  private MyBusinessService service;

  ... 
}
&lt;/pre&gt;
&lt;br /&gt;
Instead of
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;public class MyServiceConsumer {

  @EJB(lookup=&quot;...&quot;)
  private MyBusinessService service;

  ... 
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;h3&gt;
Conclusion&lt;/h3&gt;
In this article I described how to implement a dynamic service locator that can be used in a CDI container. The service locator performs a lookup upon the first call of a service method and therefore provides a mechanism for fault tolerant dependency resolving and further a foundation for implementing client-side service call interception - which I will a describe in a future post.</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/6179966634087419877/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/6179966634087419877' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/6179966634087419877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/6179966634087419877'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/07/developing-dynamic-jee-service-client.html' title='Developing a dynamic JEE service client with CDI (part 1)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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-457071854377599320.post-6849347572347849602</id><published>2014-04-29T10:36:00.002+02:00</published><updated>2014-04-29T10:36:20.279+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="code"/><category scheme="http://www.blogger.com/atom/ns#" term="development"/><category scheme="http://www.blogger.com/atom/ns#" term="howto"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jcr"/><category scheme="http://www.blogger.com/atom/ns#" term="junit"/><category scheme="http://www.blogger.com/atom/ns#" term="mock"/><category scheme="http://www.blogger.com/atom/ns#" term="setup"/><category scheme="http://www.blogger.com/atom/ns#" term="test"/><title type='text'>JUnit Testing with Jackrabbit</title><content type='html'>Writing unit tests for your code is not only best practices, it&#39;s essential for writing quality code. In order to write good unit tests, you should use mocking of code not under test. But what if you&#39;re using a technology or an API that would require quite a lot of complicated mocks?&lt;br /&gt;
In this article I&#39;d like to describe how you write unit tests for code that accesses a JCR repository. &lt;br /&gt;
&lt;br /&gt;
At first I really tried to mock the JCR API using Mockito, but stopped my attempt at the point where I had to mock the behavior of the Query Object Model. It became apparent, that writing mocks would outweigh the effort to write the actual production code by far. So I had to search for an alternative and found one.&lt;br /&gt;
&lt;br /&gt;
The reference implementation of JCR is the &lt;a href=&quot;http://jackrabbit.apache.org/&quot;&gt;Apache Jackrabbit&lt;/a&gt; project. This implementation comes with a set of JCR &lt;a href=&quot;http://www.day.com/maven/jsr170/javadocs/jcr-2.0/javax/jcr/Repository.html?is-external=true&quot;&gt;Repository &lt;/a&gt;implementations, one of these is the &lt;a href=&quot;http://jackrabbit.apache.org/api/2.4/org/apache/jackrabbit/core/TransientRepository.html&quot;&gt;TransientRepository&lt;/a&gt;. The TransientRepository starts the repository on first login and shuts it down on the last session being closed. The repository is created in memory which works pretty fast and makes it the best solution for unit testing. But nevertheless, a directory structure is created for the repository and unless not specified a config file is created as well.&lt;br /&gt;
&lt;br /&gt;
For writing unit tests against this repository, we need the following:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;a temporary directory to locate the directory structure of the repository&lt;/li&gt;
&lt;li&gt;a configuration file (unless you want one created on every startup)&lt;/li&gt;
&lt;li&gt;the repository instance &lt;/li&gt;
&lt;li&gt;a CND content model description to initialize the repository data model (optional)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;an admin session to perform administrator operations &lt;/li&gt;
&lt;li&gt;a cleanup operation to remove the directory structure&lt;/li&gt;
&lt;li&gt;the maven dependencies to satisfy all dependencies&lt;/li&gt;
&lt;/ul&gt;
Let&#39;s start with the Maven dependencies. You need the JCR Spec, the Jackrabbit core implementation and the Jackrabbit commons for setting up the repository.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;&amp;lt;properties&amp;gt;
  &amp;lt;!-- JCR Spec --&amp;gt;
  &amp;lt;javax.jcr.version&amp;gt;2.0&amp;lt;/javax.jcr.version&amp;gt;
  &amp;lt;!-- JCR Impl --&amp;gt;
  &amp;lt;apache.jackrabbit.version&amp;gt;2.6.5&amp;lt;/apache.jackrabbit.version&amp;gt;
&amp;lt;/properties&amp;gt;
...
&amp;lt;dependencies&amp;gt;
&amp;lt;!-- The JCR API --&amp;gt;
  &amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;javax.jcr&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jcr&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${javax.jcr.version}&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;!-- Jackrabbit content repository --&amp;gt;
  &amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.jackrabbit&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jackrabbit-core&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${apache.jackrabbit.version}&amp;lt;/version&amp;gt;
    &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;!-- Jackrabbit Tools like the CND importer --&amp;gt;
  &amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.jackrabbit&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jackrabbit-jcr-commons&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${apache.jackrabbit.version}&amp;lt;/version&amp;gt;
    &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
  &amp;lt;/dependency&amp;gt;
&amp;lt;/dependencies&amp;gt; 
&lt;/pre&gt;
&lt;br /&gt;
Now let&#39;s create the directory for the repository. I recommend to locate it in a temporary folder so multiple test runs don&#39;t affect each other if cleanup failed. We use the Java TempDirectory facility for that:&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;//prefix for the repository folder
import java.nio.file.Files;
import java.nio.file.Path;
...
private static final String TEST_REPOSITORY_LOCATION = &quot;test-jcr_&quot;;
...
final Path repositoryPath = 
      Files.createTempDirectory(TEST_REPOSITORY_LOCATION);
&lt;/pre&gt;
&lt;br /&gt;
Next, you require a configuration file. If you already have a configuration file available in the classpath, i.e. in &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;src/test/resource&lt;/span&gt;, you should load it first:&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;final InputStream configStream = 
  YourTestCase.class.getResourceAsStream(&quot;/repository.xml&quot;);
&lt;/pre&gt;
&lt;br /&gt;
Knowing the location and the configuration, we can create the repository:&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;import org.apache.jackrabbit.core.config.RepositoryConfig;
import org.apache.jackrabbit.core.TransientRepository;
...
final Path repositoryLocation = 
      repositoryPath.toAbsolutePath();
final RepositoryConfig config = 
      RepositoryConfig.create(configStream, repositoryLocation.toString());
final TransientRepository repository = 
  new TransientRepository(config);
&lt;/pre&gt;
&lt;br /&gt;
If you ommit the &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;config &lt;/span&gt;parameter, the repository is created in the working directory including the &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;repository.xml&lt;/span&gt; file, which is good for a start, if you have no such file.&lt;br /&gt;
&lt;br /&gt;
Now that we have the repository, we want to login to create a session (admin) in order to populate the repository. Therefore we create the credentials (default admin user is admin/admin) and perform a login:&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;final Credentials creds = 
  new SimpleCredentials(&quot;admin&quot;, &quot;admin&quot;.toCharArray());
final Session session = repository.login(creds);
&lt;/pre&gt;
&lt;br /&gt;
With the repository running and an open session we can initialize the repository with our content model if require some extensions beyond the standard JCR/Jackrabbit content model. In the next step I import a model defined in the &lt;a href=&quot;https://jackrabbit.apache.org/node-type-notation.html&quot;&gt;Compact Node Definition&lt;/a&gt; (CND) Format, described in &lt;a href=&quot;http://www.day.com/specs/jcr/2.0/25_Appendix.html&quot;&gt;JCR 2.0&lt;/a&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;import org.apache.jackrabbit.commons.cnd.CndImporter;
...
private static final String JCR_MODEL_CND = &quot;/jcr_model.cnd.txt&quot;;
...
final URL cndFile = YourTestCase.class.getResource(JCR_MODEL_CND);
final Reader cndReader = new InputStreamReader(cndFile.openStream());
CndImporter.registerNodeTypes(cndReader, session, true);
&lt;/pre&gt;
&lt;br /&gt;
All the code examples above should be performed in the @BeforeClass annotated method so that the repository is only created once for the entire test class. Otherwise a lot of overhead will be generated. Nevertheless, in the @Before and @After annotated methods, you should create your node structures and erase them again (addNode() etc).&lt;br /&gt;
&lt;br /&gt;
Finally, after you have performed you test, you should cleanup the test environment again. Because a directory was created for the transient repository, we have to remove the directory again, otherwise the temp folder will grow over time.&lt;br /&gt;
There are three options for cleaning it up.&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Cleaning up in&amp;nbsp;@AfterClass annotated method&lt;/li&gt;
&lt;li&gt;Cleaning up using File::deleteOnExit()&lt;/li&gt;
&lt;li&gt;Cleaning up using shutdown hook &lt;/li&gt;
&lt;/ol&gt;
I prefer combining 1 and 3 for fail-safe deletion. For option 1 we require a method to destroy the repository and cleaning up the directory. For deleting the directory I use Apache Commons FileUtil as it allows deletion of directory structures containing files and subdirectories. The method could look like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;import org.apache.commons.io.FileUtils;
...
@AfterClass
public static void destroyRepository(){
  repository.shutdown();
  String repositoryLocation = repository.getHomeDir();
  try {
    FileUtils.deleteDirectory(new File(repositoryLocation));
  } catch (final IOException e) {
   ...
  }
  repository = null;
}
&lt;/pre&gt;
&lt;br /&gt;
As fail-safe operation I prefer to add an additional shutdown hook that is executed when the JVM shuts down. This will delete the repository even when the @AfterClass method is not invoked by JUnit. I do not use the deleteOnExit() method of File as it requires the directory to be empty while I could call any code in the shutdown hook using my own cleanup implementation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A shutdown hook can easily be added to the runtime by specifying a Thread to be executed on VM shutdown. We simply add a call to the destroy methode to the run() method.&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;Runtime.getRuntime().addShutdownHook(new Thread(&quot;Repository Cleanup&quot;) {
  @Override
  public void run() {
    destroyRepository();
  }
});
&lt;/pre&gt;
&lt;br /&gt;
Now you should have everything to set-up you Test JCR Repositoy and tear-down the test environment. Happy Testing!&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/6849347572347849602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/6849347572347849602' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/6849347572347849602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/6849347572347849602'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/04/junit-testing-with-jackrabbit.html' title='JUnit Testing with Jackrabbit'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-676388631399040630</id><published>2014-04-28T09:12:00.000+02:00</published><updated>2014-04-29T08:40:27.537+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="configuration"/><category scheme="http://www.blogger.com/atom/ns#" term="howto"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="log4j"/><category scheme="http://www.blogger.com/atom/ns#" term="log4j2"/><category scheme="http://www.blogger.com/atom/ns#" term="logging"/><category scheme="http://www.blogger.com/atom/ns#" term="maven"/><category scheme="http://www.blogger.com/atom/ns#" term="slf4j"/><title type='text'>Configuring SLF4J with Log4J2 using Maven</title><content type='html'>In our current project we had to decide for a logging framework. As it apears to be a common standard to use the Simple Logging Facade for Java (SLF4J) on caller side, there were various options on the logging framework itself. In the end we decided to use Log4J 2 as logging framework, mainly for reasons of better performance in comparison to other frameworks (see &lt;a href=&quot;http://www.takipiblog.com/2013/12/18/the-logging-olympics-a-race-between-todays-top-5-logging-frameworks/&quot;&gt;The Logging Olympics&lt;/a&gt;). &lt;br /&gt;
The setup of this combination is fairly ease, and there are good examples how to add a SLF4J binding to your Maven project as in &lt;a href=&quot;http://www.captaindebug.com/2011/09/adding-slf4j-to-your-maven-project.html&quot;&gt;this good blog article&lt;/a&gt;. But as Log4J is rather new and no final release has been announced yet (current is release candidate 1), it&#39;s hard to find a definitive configuration example, so I decided to put down ours.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;&amp;lt;properties&amp;gt;
  &amp;lt;slf4j.version&amp;gt;1.7.6&amp;lt;/slf4j.version&amp;gt;
  &amp;lt;!-- current log4j 2 release --&amp;gt;
  &amp;lt;log4j.version&amp;gt;2.0-rc1&amp;lt;/log4j.version&amp;gt; 
&amp;lt;/properties&amp;gt;
...
&amp;lt;dependencies&amp;gt;
  &amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.slf4j&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;slf4j-api&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${slf4j.version}&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;!-- Binding for Log4J --&amp;gt;
  &amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.logging.log4j&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;log4j-slf4j-impl&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${log4j.version}&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;!-- Log4j API and Core implementation required for binding --&amp;gt;
  &amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.logging.log4j&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;log4j-api&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${log4j.version}&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
  &amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.logging.log4j&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;log4j-core&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${log4j.version}&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
&amp;lt;/dependencies&amp;gt; &lt;/pre&gt;
&lt;br /&gt;
And a basic log4j configuration (located at your &lt;code&gt;src/main/resources&lt;/code&gt; path) could look like this
&lt;br /&gt;
&lt;pre class=&quot;prettyprint code&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;configuration status=&quot;OFF&quot;&amp;gt;
 &amp;lt;appenders&amp;gt;
  &amp;lt;Console name=&quot;Console&quot; target=&quot;SYSTEM_OUT&quot;&amp;gt;
   &amp;lt;PatternLayout pattern=&quot;%d{HH:mm:ss} [%t] %-5level %logger{36} - %msg%n&quot; /&amp;gt;
  &amp;lt;/Console&amp;gt;
 &amp;lt;/appenders&amp;gt;
 &amp;lt;Loggers&amp;gt;
  &amp;lt;Logger name=&quot;yourLogger&quot; level=&quot;debug&quot; additivity=&quot;false&quot;&amp;gt;
   &amp;lt;AppenderRef ref=&quot;Console&quot; /&amp;gt;
  &amp;lt;/Logger&amp;gt;
  &amp;lt;Root level=&quot;error&quot;&amp;gt;
   &amp;lt;AppenderRef ref=&quot;Console&quot; /&amp;gt;
  &amp;lt;/Root&amp;gt;
 &amp;lt;/Loggers&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/676388631399040630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/676388631399040630' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/676388631399040630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/676388631399040630'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/04/configuring-slf4j-with-log4j2-using.html' title='Configuring SLF4J with Log4J2 using Maven'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-9044872349847792552</id><published>2014-04-01T23:26:00.001+02:00</published><updated>2014-04-01T23:26:14.850+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="activity"/><category scheme="http://www.blogger.com/atom/ns#" term="decision"/><category scheme="http://www.blogger.com/atom/ns#" term="diagram"/><category scheme="http://www.blogger.com/atom/ns#" term="node"/><category scheme="http://www.blogger.com/atom/ns#" term="uml"/><title type='text'>Guard Conditions of UML Decision Nodes</title><content type='html'>In the beginning of the year I attended a requirements engineering class where we discussed - among other topics - activity diagrams. One element of an activity diagram is the decision node, the diamond shape, where you can branch the flow of activities depending on guarding condition for each outgoing edge. There we stumbled upon one - at least to me - completely new aspect on the guard conditions.&lt;br /&gt;
&lt;br /&gt;
According to the UML specification the guard condition protects the entry of an edge. If the condition is not fulfilled, the edge is no entered. Before the above mentioned discussion I always assumed that an edge without a condition always evaluates to true and is always evaluated at last of all outgoing edged and is therefore entered only if none of the other edges&#39; condition applies. &lt;i&gt;But that is wrong&lt;/i&gt;!&lt;br /&gt;
&lt;br /&gt;
The truth is, that according to the UML specification the order of the &quot;processing&quot; of the edges is not determined and therefore may be completely random. So if you define an outgoing edge of a decision node &lt;i&gt;without &lt;/i&gt;a guarding condition, it may be the case, the edge is entered although another edge&#39;s condition may have been met but would be evaluated after the edge without a condition.&lt;br /&gt;
&lt;br /&gt;
Conclusion is, if you want to have a determined behavior of your activities, always define all of the guard conditions of your outgoing edges of decision nodes.</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/9044872349847792552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/9044872349847792552' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/9044872349847792552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/9044872349847792552'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/04/guard-conditions-of-uml-decision-nodes.html' title='Guard Conditions of UML Decision Nodes'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-1943417875282409329</id><published>2014-03-24T19:13:00.001+01:00</published><updated>2014-03-24T19:13:37.281+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cmis overview"/><category scheme="http://www.blogger.com/atom/ns#" term="content"/><category scheme="http://www.blogger.com/atom/ns#" term="ecm"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="jcr"/><category scheme="http://www.blogger.com/atom/ns#" term="opencmis"/><category scheme="http://www.blogger.com/atom/ns#" term="repository"/><title type='text'>Some interesting points about JCR</title><content type='html'>While I was doing research about Java Content Repository (&lt;a href=&quot;http://www.day.com/day/en/products/jcr.html&quot;&gt;JCR&lt;/a&gt;, specified in &lt;a href=&quot;https://jcp.org/en/jsr/detail?id=283&quot;&gt;JSR 283&lt;/a&gt;) for our current project I stumbled upon various interesting fact worth mentioning besides the actual specification details, which I like to share.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;JCR was specified by Day Software, a company based in Bale, Switzerland which is especially interesting to me, as I live in Switzerland. Day Software has been bought by Adobe&lt;/li&gt;
&lt;li&gt;In comparison with CMIS, JCR seems to be a functional superset of CMIS, as various sources indicate (see &lt;a class=&quot;external-link&quot; href=&quot;http://dev.day.com/content/ddc/blog/2009/05/jcrcmiscomparison.html&quot; rel=&quot;nofollow&quot;&gt;here&lt;/a&gt;, &lt;a class=&quot;external-link&quot; href=&quot;http://stackoverflow.com/questions/6352030/how-much-does-cmis-specification-cover-jcr-specification/6357465#6357465&quot; rel=&quot;nofollow&quot;&gt;here,&lt;/a&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://nukleos.wordpress.com/2012/10/05/jcr-and-cmis-complementary-technologies/&quot; rel=&quot;nofollow&quot;&gt;here&lt;/a&gt; or &lt;a class=&quot;external-link&quot; href=&quot;http://stackoverflow.com/questions/2909788/jcr-vs-cmis-which-repository-api-should-i-use&quot; rel=&quot;nofollow&quot;&gt;here&lt;/a&gt;), which means, JCR offers more functionality than CMIS does. Nevertheless, both standards are hardly directly comparable, as they focus on disjunct fields of use. While CMIS is service oriented and aims at repository interoperability, JCR is a standard and model for accessing hierarchical content. JCR seems to be easier to implement that CMIS.&lt;/li&gt;
&lt;li&gt;JCR and CMIS are compatible to each other.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;It&#39;s possible to access JCR repositories via CMIS. The JCR reference implementation (Jackrabbit) offers a service provider interface (SPI) implementation towards CMIS as well as there is a CMIS-JCR Bridge as part of the OpenCMIS implementation Apache Chemistry (for an overview, see &lt;a class=&quot;external-link&quot; href=&quot;http://www.slideshare.net/uncled/cmis-jackrabbit-sandbox-presentation&quot; rel=&quot;nofollow&quot;&gt;her&lt;/a&gt;e). The only restriction ist, that some of the JCR mixin types are not visible via CMIS.&lt;/li&gt;
&lt;li&gt;An access via JCR to CMIS repositories should be a programmer&#39;s exercise as they are directly mappable.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://www.jboss.org/modeshape&quot; rel=&quot;nofollow&quot;&gt;JBoss ModeShape&lt;/a&gt; is an alternative open source implementation of the JCR that is not based on Jackrabbit. Although it does not implement the standard as complete as Jackrabbit does regarding optional elements (the mandatory elements are fully implemented), it offers various functionalities beyond Jackrabbit, such as Administration, configuration and enterprise readiness. The documentation is much more useful.&lt;/li&gt;
&lt;li&gt;Both, &lt;a class=&quot;external-link&quot; href=&quot;https://jackrabbit.apache.org/&quot; rel=&quot;nofollow&quot;&gt;Apache Jackrabbit&lt;/a&gt; and &lt;a class=&quot;external-link&quot; href=&quot;http://www.jboss.org/modeshape&quot; rel=&quot;nofollow&quot;&gt;JBoss ModeShape&lt;/a&gt; are implementations of the JCR standard and form only the data management component of a content management system. Typically, CMS define their own data model and define workflows for dealing with the data.&lt;/li&gt;
&lt;li&gt;Content Management Systems that are built upon a JCR Repository are&lt;br /&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://www.magnolia-cms.com/&quot; rel=&quot;nofollow&quot;&gt;Magnolia CMS&lt;/a&gt; (support both ModeShape and Jackrabbit), it&#39;s a swiss product, by the way!&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://www.jahia.com/company/open-source&quot; rel=&quot;nofollow&quot;&gt;Jahia&lt;/a&gt; (Jackrabbit)&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://www.onehippo.com/en&quot; rel=&quot;nofollow&quot;&gt;Hippo-CMS&lt;/a&gt; (Jackrabbit)&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://www.exoplatform.com/&quot; rel=&quot;nofollow&quot;&gt;exo Platform&lt;/a&gt; (is more of a Social/Collaboration Portal product, but offers it&#39;s own JCR implementation)&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://www.adobe.com/de/solutions/web-experience-management.html&quot; rel=&quot;nofollow&quot;&gt;Adobe Exprience Manager&lt;/a&gt;
 (former CQ5, uses ContentRepositoryExtreme (CRX) which is&amp;nbsp; a commercial, enterprise-ready JCR implementation, based on Jackrabbit),&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Other implementations that supportJCR&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://www.oracle.com/de/products/middleware/beehive/index.html&quot; rel=&quot;nofollow&quot;&gt;Oracle Beehive&lt;/a&gt;&lt;ul&gt;
&lt;/ul&gt;
&lt;a class=&quot;external-link&quot; href=&quot;http://jackalope.github.io/&quot; rel=&quot;nofollow&quot;&gt;Jackalope&lt;/a&gt; - a PHP (!) implementation of the JCR standard&lt;ul&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Day Software (now part of Adobe) offers various JCR connectors for other commercial repositories:&lt;ul&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://dev.day.com/docs/en/crx/connectors/sharepoint/current.html&quot; rel=&quot;nofollow&quot;&gt;MS Sharepoint Connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://dev.day.com/docs/en/crx/connectors/documentum/current.html&quot; rel=&quot;nofollow&quot;&gt;EMC Documentum Connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://dev.day.com/docs/en/crx/connectors/livelink/current.html&quot; rel=&quot;nofollow&quot;&gt;OpenText LiveLink Connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://dev.day.com/docs/en/crx/connectors/jdbc/current.html&quot; rel=&quot;nofollow&quot;&gt;Database Connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://dev.day.com/docs/en/crx/connectors/vignette/current.html&quot; rel=&quot;nofollow&quot;&gt;Vignette Connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://dev.day.com/docs/en/crx/connectors/interwoven/current.html&quot; rel=&quot;nofollow&quot;&gt;Interwoven Connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://dev.day.com/docs/en/crx/connectors/filenet_p8/current.html&quot; rel=&quot;nofollow&quot;&gt;FileNet P8 Connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://dev.day.com/docs/en/crx/connectors/domino/current.html&quot; rel=&quot;nofollow&quot;&gt;IBM Lotus Notes Domino Connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;http://dev.day.com/docs/en/crx/connectors/fast2jcr/current.html&quot; rel=&quot;nofollow&quot;&gt;Fast to JCR Adapter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;https://sling.apache.org/&quot; rel=&quot;nofollow&quot;&gt;Apache Sling&lt;/a&gt; is a framework allowing to access JCR repositories via REST and to create repository-oriented web applications.&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external-link&quot; href=&quot;https://stanbol.apache.org/index.html&quot; rel=&quot;nofollow&quot;&gt;Apache Stanbol&lt;/a&gt; is a framework combining the elements of semantic web with structured repository data of content management systems (JCR, CMIS)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;A good overview of available CM Repositories is shown here &lt;a class=&quot;external-link&quot; href=&quot;http://stackoverflow.com/questions/1174131/looking-for-a-good-programmable-java-cms-content-management-system&quot; rel=&quot;nofollow&quot;&gt;http://stackoverflow.com/questions/1174131/looking-for-a-good-programmable-java-cms-content-management-system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Looking at the Jackrabbit team you might stumble upon the name &#39;Roy Fielding&#39;. Doesn&#39;t ring a bell? Maybe have a look at his must-read &lt;a class=&quot;external-link&quot; href=&quot;https://www.ics.uci.edu/%7Efielding/pubs/dissertation/top.htm&quot; rel=&quot;nofollow&quot;&gt;thesis&lt;/a&gt; (tl;dr: its about defining REST architectural style)&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/1943417875282409329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/1943417875282409329' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/1943417875282409329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/1943417875282409329'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/03/some-interesting-points-about-jcr.html' title='Some interesting points about JCR'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-2899420111800661106</id><published>2014-01-14T19:17:00.000+01:00</published><updated>2014-01-14T19:17:00.056+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="agile"/><category scheme="http://www.blogger.com/atom/ns#" term="best-practices"/><category scheme="http://www.blogger.com/atom/ns#" term="functional credit"/><category scheme="http://www.blogger.com/atom/ns#" term="functional debt"/><category scheme="http://www.blogger.com/atom/ns#" term="prototype"/><category scheme="http://www.blogger.com/atom/ns#" term="prototyping"/><category scheme="http://www.blogger.com/atom/ns#" term="technical credit"/><category scheme="http://www.blogger.com/atom/ns#" term="technical debt"/><category scheme="http://www.blogger.com/atom/ns#" term="waste"/><title type='text'>Prototyping in Agile Environments</title><content type='html'>In my blog post a couple of days ago I wrote about &lt;a href=&quot;http://whoopdicity.blogspot.ch/2014/01/technical-debt-and-prototyping.html&quot;&gt;prototyping and technical debt&lt;/a&gt;. After some discussions with my colleagues about the value of prototyping I want to refine my statements a bit further.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
What is a prototype? &lt;/h2&gt;
First of all, what is a prototype? &lt;a href=&quot;http://en.wikipedia.org/wiki/Prototype&quot;&gt;Wikipedia states&lt;/a&gt; &quot;A &lt;b&gt;prototype&lt;/b&gt; is an early sample, model or release of a product 
built to test a concept or process or to act as a thing to be replicated
 or learned from&quot;. There are several types of prototypes which basically breaks down to the two dimensions:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Horizontal vs. Vertical Prototype&lt;/li&gt;
&lt;li&gt;Evolutionary vs. Throwaway Prototype&lt;/li&gt;
&lt;/ul&gt;
&amp;nbsp;To help understand the relations and implications of the various kinds of prototypes, have a look at the following diagram. (The diagram assumes, that front-end (UI) aspects are on the upper side while backend aspects (logic, processing, persistence, etc) are on the lower side and time flows from left to right.)&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/AVvXsEhjkz6irWH1mekxnIyTz3jrLkYMrZ-44MhEGrGYB6lEoNMqisX2x7ll5V_Ug6qsUeVDTdyFPQfMZTFe0oOrKmNgseE6mqaxTDHxonbFjhLlsA8bMdoPHXU_lVgru-LDWje59-Z3xqx3cMlE/s1600/Prototype.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;265&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjkz6irWH1mekxnIyTz3jrLkYMrZ-44MhEGrGYB6lEoNMqisX2x7ll5V_Ug6qsUeVDTdyFPQfMZTFe0oOrKmNgseE6mqaxTDHxonbFjhLlsA8bMdoPHXU_lVgru-LDWje59-Z3xqx3cMlE/s400/Prototype.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Basically, a prototype should answer questions to the solution to be built. Therefore, an intrinsic value of a prototype is to help reduce a kind of risk by giving those answers.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Horizontal and Vertical Prototypes &lt;/h3&gt;
A horizontal prototype may help to reduce functional risk, so the customer can validate if the solution to be developed meets her requirements. A vertical prototype may help to reduce technical risks as it proves that certain architectural or technical decisions are viable. A prototype may also be combination horizontal and vertical aspects, but typically should focus only one of these, for example verifying if certain UI components can be integrated together in the UI framework focuses more on vertical than horizontal aspects.&lt;br /&gt;
&lt;br /&gt;
Nevertheless, in the lean world, most types of a prototype are waste (throwaway prototypes) or potential waste (horizontal, evolutionary prototypes). In order to reduce waste, efforts of producing a prototype that will not become part of the solution should be minimized. The prototype should focus only on reducing risks and giving answers to a predefined set of questions. In other words it should have a narrow and defined goal.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Technical Debt and Technical Credit&amp;nbsp;&lt;/h3&gt;
Two aspects of prototyping in agile environments are technical debt and technical credit.&amp;nbsp; The latter being a concept you do not read often in the agile literature, but which exists if you think the concept of technical debt to the end.&lt;br /&gt;
&lt;br /&gt;
The following diagram depicts the concept of technical credit and is a variation of the first diagram.&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/AVvXsEg4RSJuRGxYtK7m5l914waAgEraPpVYWk2-6tGwypcxcYLBoQ1Egix7-rMDylKhchQlUs0Irr42J4fee5yBkBp3cZuKAqVpIQv9UmXU6DCVnY68f3sQsUaQPdNljt0PcSv7QP_SgLOghXlZ/s1600/Prototype_2.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;266&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4RSJuRGxYtK7m5l914waAgEraPpVYWk2-6tGwypcxcYLBoQ1Egix7-rMDylKhchQlUs0Irr42J4fee5yBkBp3cZuKAqVpIQv9UmXU6DCVnY68f3sQsUaQPdNljt0PcSv7QP_SgLOghXlZ/s400/Prototype_2.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
It differs from the first one in three areas:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;a vertical 
throwaway prototypes does not necessarily have to start at the 
front-end. It could actually cover any part of the technical stack.&lt;/li&gt;
&lt;li&gt;a horizontal evolutionary prototype may also cover other layers of the software, not only UI, and therefore may produce &quot;Technical Credit&quot; as the opposite of technical debt.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;h3&gt;
Technical Debt &lt;/h3&gt;
As it is obvious, a horizontal prototype that is part of the solution produces &lt;i&gt;a lot &lt;/i&gt;of technical debt in the first place, especially if the prototype targets at the UI. The customer perceives the solution as finished, but it is dysfunctional from a technical perspective, and most of the feature promises are broken until the technical debt is worked off.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Technical Credit&lt;/h3&gt;
The opposite of technical debt is technical credit. Technical credit is generated, when something is developed and delivered in advance, that does not provide any immediate and perceivable business value. An example could be an architecture refactoring that provides a simple extension mechanism so that business functionalities can be developed more rapidly. This could cost more in advance than is perceived as returned business value but could cost less afterwards compared with the business values additional functionalities provide. But still there is a great risk of producing waste, for example if the requirements change.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Functional Debt and Functional Credit&lt;/h3&gt;
The other dimension of debt and credit is the functional. A project starts with a certain amount of functional debt - the product backlog, which is worked off continuously. Further, the requirements engineering discipline refers to the &lt;a href=&quot;http://en.wikipedia.org/wiki/Kano_model&quot;&gt;Kano model&lt;/a&gt; of success factors:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Basic or Threshold Attributes - if they are missing, the solution is not accepted at all&lt;/li&gt;
&lt;li&gt;Performance Attributes - some attributes could be missing, but the more are implemented the better&lt;/li&gt;
&lt;li&gt;Excitement Attributes - the customer does not even know they want those. They could compensate for missing performance attributes and may help to exceed the customer expectations (making her a more happy customer).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
Functional Debt &lt;/h3&gt;
Functional debt are features that are implicitly or explicitly (Basic and Performance Attributes) required but are not yet delivered. Working off the functional debt of the backlog is exactly the concept of
 a vertical, evolutionary prototype, and therefore an intrinsic 
mitigation strategy in agile processes to reduce functional risks of 
overall project and maximize the work not done according to &lt;a href=&quot;http://agilemanifesto.org/principles.html&quot;&gt;the principles of the agile manifesto&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Functional Credit &lt;/h3&gt;
Functional credit on the other hand is generated, when Excitement Attributes are delivered. Functional credit may help to compensate for functional debt (missing Performance Attributes) or even more help to exceed the customer expectation by raising your functional balance above 0.&lt;br /&gt;
&lt;br /&gt;
Nevertheless, concentrating on generating functional credit - in the meaning of developing something that is not implicitly or explicitly required - poses the risk of producing waste. For example, you cannot guarantee for sure the developed feature is an Excitement Attribute. The customer may even get upset that you do not provide what has was agreed on, but still it could be a risk worth to be taken - depends on the situation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
Theory applied&lt;/h3&gt;
How will all this theory impact our daily work? Basically, it should help you to make informed decisions and know of the implications of using one concept to your project.&lt;br /&gt;
&lt;br /&gt;
The following diagram depicts a possible situation in a project where the above discussed aspects have been taken into consideration. &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/AVvXsEjTL62E2IpVknVP4woVeh3B7UAHH7Kpooe4BKNxzgvntwbILHV72djlLCdQKlWdutKKT4HFII3g6IvRqzF4NEa0bvCcIoiZ5GwA17x9Z8lEY0gzV9XrZXzkt1hFZls7yHkUPINJQbVU0xeB/s1600/Prototypes_in_Iterations.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;266&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTL62E2IpVknVP4woVeh3B7UAHH7Kpooe4BKNxzgvntwbILHV72djlLCdQKlWdutKKT4HFII3g6IvRqzF4NEa0bvCcIoiZ5GwA17x9Z8lEY0gzV9XrZXzkt1hFZls7yHkUPINJQbVU0xeB/s400/Prototypes_in_Iterations.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
The diagram shows:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;a limited horizontal evolutionary prototype with a limited scope that anticipates what has to be developed in the next iteration. This could support marketing operations by showing what the customer could expect soon and prove that it&#39;s vaporware.&lt;/li&gt;
&lt;li&gt;a lightweight horizontal throwaway prototype (the bar smaller than in the diagrams above) to support the vision (using a wireframe) that goes beyond the evolutionary horizontal prototype to mitigate functional risks&lt;/li&gt;
&lt;li&gt;maximized amount of work not done&lt;/li&gt;
&lt;li&gt;several proof-of-concept lightweight vertical throwaway prototypes (bars are more narrow) that cover combined the entire technical stack to mitigate technical risks.&lt;/li&gt;
&lt;/ul&gt;
Further, the diagram shows several iteration increments with growing perceivable value but also with growing technical debt (which might occur in every project). The next diagram depict how the iteration scope may have looked like (yellow), how it should look in an ideal world (green) and how it should look to reduce the technical debt again (red). The latter effectively depicts to the approach of producing only something of little business value but with a big (estimated) effort. &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/AVvXsEjoj7r3sTAogMVx-Hm3CWBz77Et11k-2fRqauXkCCK1y6gLZhk0i-hR0Fg3ydManszDtTXzJ-6uvys45xAOWRuuq0xT-hs80gynA0BoMAd4SZ5Azbu0J25bBd7RrbnyR-8eqazYij_VpHil/s1600/Prototypes_in_Iterations_2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;266&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoj7r3sTAogMVx-Hm3CWBz77Et11k-2fRqauXkCCK1y6gLZhk0i-hR0Fg3ydManszDtTXzJ-6uvys45xAOWRuuq0xT-hs80gynA0BoMAd4SZ5Azbu0J25bBd7RrbnyR-8eqazYij_VpHil/s400/Prototypes_in_Iterations_2.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Of course it&#39;s better to avoid technical debt in the first place, but 
when you have created it you have to deal with it. The Disciplined Agile
 Delivery framework lists &lt;a href=&quot;http://disciplinedagiledelivery.wordpress.com/2013/11/10/technical-debt/&quot;&gt;11 strategies of dealing with technical debt&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Concluding Thoughts&lt;/h2&gt;
There might be occasions where any kind of prototype
 has it&#39;s value and helps the project. But if you choose a certain type 
of prototyping approach in your project, keep the implications in mind. 
Always try to reduce waste and technical debt and maximize the work not 
done, while minimizing the risks. &lt;br /&gt;
&lt;br /&gt;
Good practices for prototyping should include:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Reduce functional risk without producing technical debt with a wireframe mockup (horizontal, throwaway prototype)&lt;/li&gt;
&lt;li&gt;Reduce high technical risks with a limited proof-of-concept throwaway prototype (horizontal or vertical). Define a set of questions to be answered by the prototype to limit the production of waste. (i.e. &quot;is the architecture feasible and matches our criteria?&quot;, &quot;does the framework to be used matches our needs?&quot;, &quot;are the performance criteria achievable?&quot;, &quot;does the solution integrate into the environment?&quot; etc.). Such a prototype is always a tradeoff between waste and risk reduction and requires thorough considerations.&lt;/li&gt;
&lt;li&gt;Avoid producing a horizontal, evolutionary prototype. But if you do it, limit it&#39;s scope to limit production of technical waste. Anticipate only a small and manageable number of iterations (i.e. 1-3) and define a strategy along with the prototype creation how to work off the technical debt. Make it transparent.&lt;/li&gt;
&lt;li&gt;Do vertical, evolutionary prototyping whenever possible.&lt;/li&gt;
&lt;li&gt;Have a strategy to deal with technical debt. &lt;/li&gt;
&lt;/ul&gt;
tl;dr&lt;br /&gt;
The world of prototyping is not black and white, it all depends on the situation. &lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/2899420111800661106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/2899420111800661106' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/2899420111800661106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/2899420111800661106'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/01/prototyping-in-agile-environments.html' title='Prototyping in Agile Environments'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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/AVvXsEhjkz6irWH1mekxnIyTz3jrLkYMrZ-44MhEGrGYB6lEoNMqisX2x7ll5V_Ug6qsUeVDTdyFPQfMZTFe0oOrKmNgseE6mqaxTDHxonbFjhLlsA8bMdoPHXU_lVgru-LDWje59-Z3xqx3cMlE/s72-c/Prototype.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-485234412264066185</id><published>2014-01-13T18:44:00.000+01:00</published><updated>2014-01-13T18:44:00.205+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bookmarking"/><category scheme="http://www.blogger.com/atom/ns#" term="collaboration"/><category scheme="http://www.blogger.com/atom/ns#" term="delicious"/><category scheme="http://www.blogger.com/atom/ns#" term="diigo"/><category scheme="http://www.blogger.com/atom/ns#" term="social"/><category scheme="http://www.blogger.com/atom/ns#" term="tools"/><category scheme="http://www.blogger.com/atom/ns#" term="web20"/><title type='text'>Social Bookmarking</title><content type='html'>Over the holiday season I sought for a solution to keep my bookmarks between my private and my working computer in sync. Although Firefox comes with a synchronization feature, I aimed more to a solution based on social bookmarking. Back in the days when working for IBM Software Services for Lotus I used social bookmarking on the internal platform - guess what - Lotus Connections (now IBM Connections), which had a good browser integration (an IBM internally available extension, I don&#39;t know if that&#39;s now part of the product or a free or paid asset). However, the combination of persisting my bookmarks and sharing my (tagged) links with the community was a great added value to my work as it significantly decreased the time to find specific information, especially in the field I was working in and in the network of colleagues that worked in the same field.&lt;br /&gt;
So the requirements for my sought-for social bookmarking solution were set:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Browser integration being a substitute for Browser Bookmarks&lt;/li&gt;
&lt;li&gt;Synchronization between different working stations&lt;/li&gt;
&lt;li&gt;Support for Tagging, to ease search for information&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Possibility to share links with colleagues and friends&lt;/li&gt;
&lt;li&gt;Possibility to have private links&lt;/li&gt;
&lt;/ul&gt;
I remembered, that there had been a social bookmarking site, if not THE social bookmarking site, called del.icio.us that had a good browser integration. So I started using it. But my experience with it was not that good and I guess it has its origin in the history of the site. &lt;a href=&quot;https://delicious.com/&quot;&gt;Delicious &lt;/a&gt;was bought by yahoo, went through years of stagnation before it was sold again to AVOS, the company of the founders of youtube. The browser integration developed by yahoo doesn&#39;t seem well supported anymore (or at the moment?), especially the synchronization between browser and website brakes frequently and you have to sign out, delete the local bookmarks and sign in again (the sign-in of the browser extension is done via the website previous.delicious.com, that says everything). So I ended multiple times with editing bookmarks in the extension that were not persisted on the website or editing bookmarks on the websites that were not only not synchronized to the browser, but overwritten again with the data from the browser. On top of that, I don&#39;t find the web UI not very user friendly, it&#39;s overly simplistic and not very intuitive. So I sought for an alternative.&lt;br /&gt;
&lt;br /&gt;
I took StumbleUpon into consideration, but it&#39;s poor browser integration (incompatible with NoScript plugin) was a no-go. Further it focuses more on news than knowledge sharing and has no concept of private links - everything is public. Though I find the idea behind stumble upon generally intriguing, it&#39;s not what I was looking for.&lt;br /&gt;
Google Bookmarks fell short a good browser integration and Evernote although allowing to capture merely everything is not really a social bookmarking site and therefore lacks some basic functionality.&lt;br /&gt;
&lt;br /&gt;
After reading the good blog post regarding &quot;&lt;a href=&quot;http://searchengineland.com/10-alternatives-to-delicious-com-bookmarking-59058&quot;&gt;10 Alternatives to Delicious.com&lt;/a&gt;&quot; I tried out &lt;a href=&quot;https://www.diigo.com/&quot;&gt;Diigo&lt;/a&gt;. And I must admit, that&#39;s exactly what I was looking for, even more. It comes with a browser plugin that allows to easily capture new bookmarks and also display your bookmarks in the bookmarks toolbar based on custom filters on the captured bookmarks. Bookmarks can also be organized into lists that can be filtered too. Further, the plugin has a sidebar to quickly search all your captured bookmarks. For me Diigo is a complete replacement for the browser bookmark management and helps me easily to keep in sync with different computer, including smart phones, as it also provides a neat app. &lt;br /&gt;
But Diigo is not only a social bookmarking tool. It goes well beyond that, its a &lt;i&gt;knowledge working&lt;/i&gt; tool. With Diigo you can add sticky notes to web pages, highlight passages, comment on them, capture images, capture parts of a web page as image and share everything of that with the public or a group of people, and of course keep them private as well. So whenever I capture a bookmark, I can also highlight what was important for me from that page or why I looked up a certain information. When working in a group it helps, sharing certain information with each other. &lt;br /&gt;
&lt;br /&gt;
There may be other alternatives in the web as well, but having found Diigo, I found a solution that works for me, so I stick with that.&lt;br /&gt;
&lt;br /&gt;
tl;dr&lt;br /&gt;
Want to do social bookmarking and looking for an alternative to delicious? Try &lt;a href=&quot;https://www.diigo.com/&quot;&gt;Diigo&lt;/a&gt;. It&#39;s a knowledge working tool.&lt;br /&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/485234412264066185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/485234412264066185' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/485234412264066185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/485234412264066185'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/01/social-bookmarking.html' title='Social Bookmarking'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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><entry><id>tag:blogger.com,1999:blog-457071854377599320.post-1155337855267147723</id><published>2014-01-07T23:25:00.000+01:00</published><updated>2014-01-13T07:46:59.325+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="agile"/><category scheme="http://www.blogger.com/atom/ns#" term="best-practice"/><category scheme="http://www.blogger.com/atom/ns#" term="development"/><category scheme="http://www.blogger.com/atom/ns#" term="prototype"/><category scheme="http://www.blogger.com/atom/ns#" term="prototyping"/><title type='text'>Technical Debt and Prototyping</title><content type='html'>&lt;br /&gt;
Currently I am preparing for my IREB Requirements Engineering Certification and I read (and already knew before) that in Requirements Engineering creating a prototype is a method and tool to validate requirements.&lt;br /&gt;
A prototype should always answer a beforehand defined set of questions. Further, there are two basic types of prototypes.&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Throwaway Prototype - the prototype is not used further in the development process apart from being a technical example. &lt;/li&gt;
&lt;li&gt;Evolutionary Prototype - the prototype itself is continuously developed further until it becomes the final (or a shippable) product.&lt;/li&gt;
&lt;/ol&gt;
The question is, what role does prototyping play in agile development?&lt;br /&gt;
&lt;br /&gt;
Let&#39;s first have a look at the dimensions of a prototype. The &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_prototyping&quot;&gt;wikipedia article about prototyping&lt;/a&gt; describes the two dimensions of a prototype as &lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;vertical (in german also known as &quot;Durchstichprototyp&quot;), in the meaning of a slice of the system to be developed, including frontend, business logic and persistent. &lt;/li&gt;
&lt;li&gt;horizontal, in the meaning of an almost complete implementation of a single layer of a multi-layered architecture. I guess, the most common example of a horizontal prototype is a UI prototype. Also common are interface stubs.&lt;/li&gt;
&lt;/ul&gt;
I would assume, that vertical prototypes are closer to the principles of agile development, as they are more &quot;something that is done&quot; than a horizontal prototype.&lt;br /&gt;
&lt;br /&gt;
Why is that?&lt;br /&gt;
&lt;br /&gt;
In agile the concept of &quot;&lt;a href=&quot;http://en.wikipedia.org/wiki/Technical_debt&quot;&gt;technical debt&lt;/a&gt;&quot;
 is known as a measure of design or software quality, or better, the 
lack of it. There are some strategies to deal with it, as described in 
the DAD&#39;s &quot;&lt;a href=&quot;http://disciplinedagiledelivery.wordpress.com/2013/11/10/technical-debt/&quot;&gt;11 Strategies to deal with technical debt&lt;/a&gt;&quot;.&amp;nbsp; Further, agile or scrum, aims at producing increments that provide value to the customer, in most of the cases, the &quot;value&quot; reflects some additions or changes to the UI, that the customer can validate relatively easy.&lt;br /&gt;
&lt;br /&gt;
A vertical prototype is a potentially shippable or consumable piece of 
software in the meaning of agile. It is functional and it is &lt;i&gt;done&lt;/i&gt;.
 Maybe it needs some refactoring, but basically the amount of technical 
debt is relatively low. One could even say, that producing an 
evolutionary, vertical prototype &lt;i&gt;is&lt;/i&gt; doing agile (if done right). &lt;br /&gt;
&lt;br /&gt;
On the opposite, a horizontal prototype produces only an artifact on one single layer of the software, which is in most cases the UI. The customer can validate, if the prototype reflects the requirements. But, the prototype itself provides no real value, as it is a dysfunctional piece of software, as all the stuff behind the UI is not implemented. In other words, &lt;i&gt;a horizontal UI prototype is a huge pile of technical debt&lt;/i&gt;. The more complete the prototype is, the higher is the debt.&lt;br /&gt;
If a evolutionary, horizontal prototype is the starting point of the implementation (i.e. the product of a pre-project or the first iterations), it is relatively difficult to plan backlog entries for the further iterations with increments that &quot;provide value&quot; from a customer perspective. Ways to deal with it could be:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;deliver only small increments that add value (i.e. slight adjustments to the UI) but that take more time than one would assume they would take. For example changing the background color takes a week.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;define the disabling of elements of the UI as added value and focus on only one element that is actually implemented, and the continue as ususal. This means actually to make the evolutionary prototype a throwaway or least major parts of it. &lt;/li&gt;
&lt;li&gt;call a spade a spade and track it as chores that provide no actual value but a reduction of the technical debt and the stakeholders have to bite the bullet for getting several iterations with no added value&lt;/li&gt;
&lt;/ul&gt;
My suggestion would be to use either horizontal throwaway or vertical evolutionary prototypes.&lt;br /&gt;
&lt;br /&gt;
The throwaway protoype - especially UI 
prototypes - could enrich the requirements descriptions as it provides a clearer vision, how the system should look like and partially how it behaves. Creating this prototype should be the job of the product owner or her assistant&#39;s. Wireframe models are a good example of such a
 prototype. The prototype can be decomposed into smaller user stories or
 tasks the development team implements, while keeping the entire 
prototype as a detailed version of a vision. &lt;br /&gt;
&lt;br /&gt;
The evolutionary prototype is actually developed during iterations of the development process and it should always be of the vertical dimension which ensures, that every iterations produces something that is done.&lt;br /&gt;
&lt;br /&gt;
Concluding, I would make the three suggestions:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;if using a prototype as part of the requirements definition (job of the PO), use a horizontal throwaway prototype. I&#39;d recommend a wireframe model.&lt;/li&gt;
&lt;li&gt;creating a vertical evolutionary prototype is developing the product in an agile or at least iterative way&lt;/li&gt;
&lt;li&gt;avoid creating horizontal evolutionary or vertical throwaway prototypes as they produce high technical debt or are unfinished work, which is bad.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
tl;dr &lt;br /&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;horizontal prototype&lt;/th&gt;&lt;th&gt;vertical prototype&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;throwaway prototype&lt;/th&gt;&lt;td style=&quot;background-color: #7fff7f; color: black;&quot;&gt;&lt;b&gt;good&lt;/b&gt;&lt;br /&gt;
done by PO as part of requirements&lt;/td&gt;&lt;td style=&quot;background-color: #ff7f7f; color: black;&quot;&gt;&lt;b&gt;bad&lt;/b&gt;,&lt;br /&gt;
use only to demonstrate general feasibility to reduce high risks (proof-of-concept), produces waste&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt;evolutionary prototype&lt;/th&gt;&lt;td style=&quot;background-color: #ff7f7f; color: black;&quot;&gt;&lt;b&gt;bad&lt;/b&gt;,&lt;br /&gt;
produces high technical debt, avoid if possible&lt;/td&gt;&lt;td style=&quot;background-color: #7fff7f; color: black;&quot;&gt;&lt;b&gt;good&lt;/b&gt;,&lt;br /&gt;
actual potentially shippable increment, done by development team&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/1155337855267147723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/1155337855267147723' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/1155337855267147723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/1155337855267147723'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2014/01/technical-debt-and-prototyping.html' title='Technical Debt and Prototyping'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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-457071854377599320.post-8000680808220317107</id><published>2013-12-19T18:47:00.000+01:00</published><updated>2013-12-19T18:47:00.549+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="5in5"/><category scheme="http://www.blogger.com/atom/ns#" term="future"/><category scheme="http://www.blogger.com/atom/ns#" term="ibm"/><category scheme="http://www.blogger.com/atom/ns#" term="opinion"/><category scheme="http://www.blogger.com/atom/ns#" term="prediction"/><title type='text'>5 in 5</title><content type='html'>IBM recently published their recent &lt;a href=&quot;http://www.ibm.com/smarterplanet/us/en/ibm_predictions_for_future/ideas/&quot;&gt;5in5&lt;/a&gt; predictions for the near future (5 predictions for the next 5 years). The predictions look to me like logic consequences of the current technologies and approaches applied to a broader areas of use. The key principle is, that computer become smarter, cognitive and more adaptive to their context.&lt;br /&gt;
I&#39;d like to share you my view on these five predictions.&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;i&gt;The classroom will learn you&lt;/i&gt;. Probably a good way of using the potential of a learner and supporting them in the best way possible. Applied to public schools this would be of great help to give our kids the best chances. But when I look at the current and past state the schools are in, I doubt this will become a reality at least for public schools in 5 years as cost pressure and strong conservative forces prevented major innovations in the public education system. At least physical punishment is forbidden in schools nowadays :). Best chances I see for private schools or even more adult education.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Buying local will beat online&lt;/i&gt;. I doubt this will happen. The major constraint is time and the biggest advantage of online shopping is the separation of the process of buying from your location and 
time, allowing even customers with stuffed schedules to make purchases of whatever they want. Another downside of computerized shopping, as we could see with existing online shops like Amazon are the tailored offerings matching customer interests, needs and behaviors to maximize the probability to sell something in order to maximize the profit (because that&#39;s the basic intent), and people get used to that (because they obviously like it), might lead to a (consumer)life that&#39;s totally dictated by computers. People might trust, the computer is always right, and stop scrutinize decisions. Today, going to a local shop allows us to flee from computerized proposals and simply explore. &lt;/li&gt;
&lt;li&gt;&lt;i&gt;Doctors will routinely use your DNA to keep you well&lt;/i&gt;. Might be great to detect and treat certain diseases. But what is is value of Death? That we value life. The question (even today) is, what should be treated because it preserves life and what not because it preserves dignity. The other constraint is, as long as there is the effective danger that state authorities capture and analyze these data and possibly derive executive actions from that, I doubt anyone will seriously put their personal &quot;blueprint&quot; into the cloud. An example of what real consequences a simple but erroneous computerized decision could create shows a case I read about recently. A harmless money transaction to pay a bill was blocked as its payment reason contained &quot;Südanflug&quot; (Landing Approach from South) which the banking computer systems - not being able to deal with umlauts - interpreted as &quot;Sudan-Flug&quot; (Flight to/from Sudan) and a raised a terror warning.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;A digital guardian will protect you online&lt;/i&gt;. Key question is, which decision has priority. Who may overrule whom? Some recent cases from the aviation industry are good examples, what could happen, when computer decides based on algorithms and sensor inputs, but does not capture the overall situation completely. One of those cases was a &lt;a href=&quot;http://www.youtube.com/watch?v=nNR0a4TMxeA&quot;&gt;landing approach at the aiport in hamburg during stormy weather with heavy cross winds&lt;/a&gt;. On touchdown of one of the wheels, the computer switched to ground mode, limiting the maximum angle of the rudder, but that was needed to compensate the strong cross winds. The result was, one of the wingtips touched ground, but the pilots could resolve the situation by going to full throttle and take off again. If computers could ever capture the entirety of the users context, it might be possible to really help. But again, I fear the dangers of digitally capturing the entirety of your life as long as state authorities are able to misuse them.&lt;/li&gt;
&lt;li&gt;&lt;div class=&quot;ibm-alternate&quot;&gt;
&lt;i&gt;The city will help you live in it&lt;/i&gt;. Surely, the computer might propose things I might not find easily. The main driver however is still - pretty similar to point 2 - money, to maximize profits, i.e. by sending the people to places where it&#39;s most likely to spent a lot of money. So the computer will most certainly make suggestions based on my habits, location and probably my network. This might result in proposing the same bar over and over again. But I could have that even without a computer, and sometime I simply want to try something different. The goal should be to broaden the ken, not limit it, then it will serves a purpose.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
Don&#39;t get me wrong, I&#39;m quite looking forward of what the future will bring with all the existing and upcoming technological possibilities. But I&#39;m also skeptic, what of it will really serve a purpose - to help the humans being better humans (which is desirable), and not what will maximize profits (which is the real driver behind A LOT).&lt;br /&gt;
So the key question is and will be, what roles will humans and machines play in the world. What is the value of an individual&#39;s life? When will the machines really serve us, freeing most of us from having to be &quot;worker drones&quot; and allowing everyone a life of self-determination, that is not constrained by the (un)availability of wealth?&lt;br /&gt;
I believe these question won&#39;t be answered by computers, but by society. So if computers get smarter and more able to learn, we should strive to make the same progress for humans, and we will achieve a lot more.</content><link rel='replies' type='application/atom+xml' href='http://whoopdicity.blogspot.com/feeds/8000680808220317107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/457071854377599320/8000680808220317107' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/8000680808220317107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/457071854377599320/posts/default/8000680808220317107'/><link rel='alternate' type='text/html' href='http://whoopdicity.blogspot.com/2013/12/5-in-5.html' title='5 in 5'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/09897975984597806156</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>