tag:blogger.com,1999:blog-68592550457660415912024-03-09T18:46:49.422-08:00Java, Web and ITThis blog is about Java (advanced Java topics like Reflection, Byte Code transformation, Code Generation), Maven, Web technologies, Raspberry Pi and IT in general.Unknownnoreply@blogger.comBlogger26125tag:blogger.com,1999:blog-6859255045766041591.post-1389389985403384662018-05-05T08:23:00.001-07:002018-05-05T08:23:09.749-07:00Ubuntu VM with Hyper-V on a UDH displayUntil now I used VirtualBox for VMs. However Docker for Windows requires Hyper-V to be enabled and VirtualBox doesn't work with this setting. Therefore I switched to Hyper-V for VMs. After installing Ubuntu I noticed that the font was blurry and the clipboard wasn't shared between guest and host. To fix both issues it's required to enable the Enhanced Session Mode. To do that run following commands on the Ubuntu VM:<br />
<br />
<div class="code">
$ git clone https://github.com/jterry75/xrdp-init.git ~/xrdp-init<br />
$ cd ~/xrdp-init/ubuntu/18.04/<br />
$ sudo chmod +x install.sh<br />
$ sudo ./install.sh
</div>
<br />
Install.sh will need to be run twice in order for the script to execute fully (it must perform a reboot mid-script). That is, once your VM reboots, you’ll need to change directory into the location of the script and run again.
After you’ve run your scripts, shut down your VM. On your host machine in a admin PowerShell prompt, execute this command:<br />
<br />
<div class="code">
Set-VM -VMName <your_vm_name> -EnhancedSessionTransportType HvSocket
</your_vm_name></div>
<br />
After that the Enhanced Session Mode works with the Ubuntu VM and the front isn't blurry anymore and the clipboard is shared. The only annoying thing is that per default you can only choose between 100% and 200% scale in Ubuntu's display setting. To set it it to 150% just execute this command:<br />
<br />
<div class="code">
gsettings set org.gnome.desktop.interface text-scaling-factor 1.5</div>
<br />
<br />
Source: <a href="https://blogs.technet.microsoft.com/virtualization/2018/02/28/sneak-peek-taking-a-spin-with-enhanced-linux-vms/" target="_blank">Sneak Peek: Taking a Spin with Enhanced Linux VMs</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6859255045766041591.post-24115363303203769672016-01-17T14:11:00.000-08:002016-01-17T14:11:48.333-08:00How to set the encoding of a Powershell console windowI created some Unix like Java console programs. One program reads the stdin, writes to the stdout and then the next program reads the output and processes it. This worked very well with Cygwin or a Unix shell. The whole thing looks like this:<br />
<br />
<div class="code">
> java -jar prog1.jar | java -jar prog2.jar<br />
</div>
<br />
The Java code is quite simple a well:<br />
<br />
<div class="prettyprint lang-java code">
Scanner scanner = new Scanner(System.in);<br />
while (scanner.hasNextLine()) {<br /> String line = scanner.nextLine();<br /> System.out.println(doSomething(line));<br />}<br />
</div>
<br />
My problem was that this example broke special characters if I did the same thing in the Windows Powershell. The reason is that a Powershell console window doesn't use the default system encoding, but some strange encoding. In my case it's IBM850. However my default system encoding is window-1252. My Java programs expected windows-1252 and therefore the encoding of special chars was broken. Why the hell uses a Powershell window IBM850? I have no idea. But I cost my several hours to figure it out and to figure out how to change the encoding. To change the encoding to the default system encoding you need to run this three commands:<br />
<br />
<div class="code">
$OutputEncoding = [system.text.encoding]::GetEncoding([System.Text.Encoding]::Default.CodePage)<br />[console]::InputEncoding = [system.text.encoding]::GetEncoding([System.Text.Encoding]::Default.CodePage)<br />[console]::OutputEncoding = [system.text.encoding]::GetEncoding([System.Text.Encoding]::Default.CodePage)<br />
</div>
<br />
Again i have no idea why you need to set the encoding three times. After this point I just did it and I was happy that it worked. Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6859255045766041591.post-37118290623044683622016-01-17T13:50:00.000-08:002016-01-17T13:51:21.877-08:00How to get the boot time of a Windows 7 or Windows 10 system with PowershellI must admit that i have a quite bad memory. Most of the time I can't remember when I arrived at work. But there is a quite easy way to figure it out, if the first thing you do is to turn on the computer. With this little Powershell command you see the time of the first system event. Because if you turn on the computer and login will generate system events this method is quite accurate.<br />
<br />
<div class="code">
> Get-EventLog System -After (Get-Date -F 'yyyy-MM-dd') | select -Last 1 | % {$_.TimeGenerated.ToString("HH:mm")}</div>
Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-6859255045766041591.post-90701373899032381672015-08-09T13:48:00.000-07:002015-08-09T13:48:43.192-07:00Microservices with Spring Boot, Netflix OSS and Maven - Log Configuration<span lang="EN-US" style="mso-ansi-language: EN-US;">This is a follow up post to the <a href="http://blog.rseiler.at/2015/06/microservices-with-spring-boot-netflix.html">microservice overview post</a></span><span lang="EN-US" style="mso-ansi-language: EN-US;">. In this post I will explain the log configuration.</span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span>
<span lang="EN-US" style="mso-ansi-language: EN-US;">The basis of the configuration is the default <a href="https://github.com/spring-projects/spring-boot/tree/master/spring-boot/src/main/resources/org/springframework/boot/logging/logback" rel="nofollow" target="_blank">Spring Boot configuration</a>. I just adapted as I needed. The two important changes are:</span><br />
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Added <i>[%mdc]</i> to the<i> CONSOLE_LOG_PATTERN</i> and the <i>FILE_LOG_PATTERN</i></span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">The log file is only written if the <i>LOG_FILE</i> variable (system variable or environment variable) is set. With the system variable it's possible to have several microservices running on the same machine, which will write the output into the specified log file.</span></li>
</ul>
<span lang="EN-US" style="mso-ansi-language: EN-US;">The <a href="http://logback.qos.ch/manual/mdc.html" rel="nofollow" target="_blank">Mapped Diagnostic Context</a> (MDC) is filled in the <a href="https://github.com/rseiler/concept-microservice/blob/master/common/common-mvc/src/main/java/at/rseiler/concept/microservice/common/mvc/RequestContextInterceptor.java" rel="nofollow" target="_blank">RequestContextInterceptor</a>#preHandle method with the <i>uuid </i>and the <i>caller</i>. It's possible to put even more data into the MDC. The MDC data will be printed as <i>key1=value1, key2=value2, ...</i> in the <i>%mdc</i> part. So it's great to fill the MDC at the beginning of the request and clear the data at the end of the request. Thereby you always have the meta data logged within your log output.</span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span>
<span lang="EN-US" style="mso-ansi-language: EN-US;">For example if you call <i>http://localhost:9090/shopping-cart/3</i> following output will be generated distributed over 3 processes:</span><br />
<br />
<div class="code">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"># frontend-service </span></i><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;">2015-08-09 21:46:03.337 INFO 10868 --- [nio-9090-exec-2] a.r.c.m.f.c.ShoppingCartController : [caller=/shopping-cart/3 <- 127.0.0.1, uuid=23badb29-6cb3-4f02-a786-2c15cbcaf302] getShoppingCart(3)</span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"></span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><i># shopping-cart-service</i><br />2015-08-09 21:46:03.340 INFO 17732 --- [o-auto-1-exec-1] a.r.c.m.user.rest.ShoppingCartService : [caller=frontend-service <- /shopping-cart/3 <- 127.0.0.1, uuid=23badb29-6cb3-4f02-a786-2c15cbcaf302] getShoppingCart(3)</span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"></span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><i># product-service</i><br />2015-08-09 21:46:03.360 INFO 20148 --- [o-auto-1-exec-4] a.r.c.m.product.rest.ProductService : [caller=frontend-service <- /shopping-cart/3 <- 127.0.0.1, uuid=23badb29-6cb3-4f02-a786-2c15cbcaf302] getproduct(3)</span>
</div>
<br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span>
<span lang="EN-US" style="mso-ansi-language: EN-US;">This output makes two things very easy:</span><br />
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Find all log output which belongs </span><span lang="EN-US" style="mso-ansi-language: EN-US;">together. Just find all log entries with the same uuid.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">See the flow of the initial request through the microservices.</span></li>
</ul>
<span lang="EN-US" style="mso-ansi-language: EN-US;">To make this possible it's necessary to pass the data (uuid, caller) from one microservice to the next microservice. This is quite easy to accomplish with HTTP headers. The implementation of it is quite simple, too. It's handled in </span><span lang="EN-US" style="mso-ansi-language: EN-US;">the <a href="https://github.com/rseiler/concept-microservice/blob/master/common/common-mvc/src/main/java/at/rseiler/concept/microservice/common/mvc/RequestContextInterceptor.java" rel="nofollow" target="_blank">RequestContextInterceptor</a></span> and the <a href="https://github.com/rseiler/concept-microservice/blob/master/common/common-feign/src/main/java/at/rseiler/concept/microservice/common/feign/ServiceNameInterceptor.java" rel="nofollow" target="_blank">ServiceNameInterceptor</a>. Given that a ThreadLocal is used in the implementation and that Hystrix uses it's own threads it's necessary to configure Hystrix correctly. See <a href="https://github.com/rseiler/concept-microservice/blob/master/common/common-feign/src/main/java/at/rseiler/concept/microservice/common/feign/ServiceNameInterceptor.java" rel="nofollow" target="_blank">this three files</a>.<br />
<br />
Last but not least it's nice that you don't have to copy the <a href="https://github.com/rseiler/concept-microservice/blob/master/common/common-configuration/classes/logback.xml" rel="nofollow" target="_blank">logback.xml</a><a href="https://github.com/rseiler/concept-microservice/blob/master/common/common-configuration/classes/logback.xml" rel="nofollow" target="_blank"></a> file into each service. With Maven it's possible to pack the logback.xml file into an artifact and then unpack it into the microservices. If you change the log configuration you just need to change the file once. Depending on your setup it might be required to change the version of the artifact so that the new version is unpacked.Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-6859255045766041591.post-14819968933335888122015-06-28T14:29:00.000-07:002015-06-28T14:33:56.440-07:00Microservices with Spring Boot, Netflix OSS and Maven - Monolithic Build<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:HyphenationZone>21</w:HyphenationZone>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>DE</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Normale Tabelle";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"Times New Roman";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]--><span lang="EN-US" style="mso-ansi-language: EN-US;">In the
<a href="http://blog.rseiler.at/2015/06/microservices-with-spring-boot-netflix.html">overview post</a> I mentioned that it's possible to pack all microservice into one
application. This application is fully functionally, without the need of any
change, without Eureka and without remote calls. In the demo the module
all-in-one showcases this monolithic application. In this short blog entry I
will describe how it works.</span>
<br />
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Actually
it's very simple. It's done with the dependency injection of Spring.
Nevertheless is a quite cool setup.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b>Microservice Setup and Configuration</b></span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Let's
look into the <i><a href="https://github.com/rseiler/concept-microservice/blob/master/frontend-service/src/main/java/at/rseiler/concept/microservice/frontend/controller/UserController.java" target="_blank">UserController</a></i> of the <i><a href="https://github.com/rseiler/concept-microservice/tree/master/frontend-service" target="_blank">frontend-service</a></i> module and take a look
what's normally happens if you start the <i><a href="https://github.com/rseiler/concept-microservice/blob/master/frontend-service/src/main/java/at/rseiler/concept/microservice/frontend/FrontendApplication.java" target="_blank">FrontendApplication</a></i>.</span></div>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">the <i>UserController
</i>requires the <i><a href="https://github.com/rseiler/concept-microservice/blob/master/user-domain/user-client/src/main/java/at/rseiler/concept/microservice/client/UserHystrixClient.java" target="_blank">UserHystrixClient</a></i></span><span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">the <i>UserHystrixClient
</i>requires the <i><a href="https://github.com/rseiler/concept-microservice/blob/master/user-domain/user-client/src/main/java/at/rseiler/concept/microservice/client/UserClient.java" target="_blank">UserClient</a></i></span><span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">the <i>UserClient
</i>has the <i>@FeignClient</i> annotation</span><span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></li>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">thereby a Spring service is
created, given that the <i>FrontendApplication </i>has this configuration: <i>@EnableFeignClients({"at.rseiler.concept.microservice.client"})</i></span><span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">this Spring service is then
injected into the <i>UserHystrixClient</i></span><span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></li>
</ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">=>
that's it. It's this simple.</span>
</li>
</ul>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b>Monolithic Setup and Configuration</b> </span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Now the
explanation what happens if the <a href="https://github.com/rseiler/concept-microservice/blob/master/all-in-one/src/main/java/at/rseiler/concept/microservice/monolith/MonolithApplication.java" target="_blank"><i>MonolithApplication</i></a> is started.</span></div>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">the
<i>UserController </i>requires the <i>UserHystrixClient </i>(no difference)</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">the
<i>UserHystrixClient </i>requires the <i>UserClient </i>(no difference)</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">the <i>UserClient
</i>has the <i>@FeignClient </i>annotation, but no service is created. Because <i>MonolithApplication
</i>doesn't has the <i>@EnableFeignClients</i> annotation.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">the <i><a href="https://github.com/rseiler/concept-microservice/blob/master/user-domain/user-service/src/main/java/at/rseiler/concept/microservice/user/rest/UserService.java">UserService</a>
</i>of the <a href="https://github.com/rseiler/concept-microservice/tree/master/user-domain/user-service" target="_blank"><i>user-service</i></a> implements the <i>UserClient </i>and its annotated with <i>@RestController</i>.</span><span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></li>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">thereby a Spring service is
created</span><span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">this Spring service is then
injected into the <i>UserHystrixClient</i></span><span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></li>
</ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">=>
that's it. It's this simple.</span></li>
</ul>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">In the
end the "magic" is done with the Spring configuration. Because we
don't need the Feign clients in the monolithic application we don't need to
create them. However the REST endpoints are created, because of the
<i>@RestController</i> annotation. So it's if two microservices defines the same
endpoint then you get an exception at the startup.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b>Improved Setup</b></span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">It's
also possible to improve the setup so that the REST endpoints aren't created in
the monolithic application. To do that you need to improve the configuration.
Each <i>@RestController</i> annotated class needs additional a <i>@Service</i> annotation. In
the monolithic application only the <i>@Service</i> are defined as <a href="http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html#includeFilters--" target="_blank"><i>includeFilters</i></a> for
the <i>at.rseiler.concept.microservice.*.rest</i> package and the <i>@RestController
</i>annotation will be ignored. In a microservice configuration the configuration
is reversed. Only the <i>@RestController</i> is defined as <a href="http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html#includeFilters--" target="_blank"><i>includeFilters</i></a>.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Conclusion</span></b></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">By the expressive
Spring dependency injection configuration it's possible to do very cool things.
It's only necessary to think outside of the box and use the power of the
configuration options. The only downside could be that it's probably confusing
for others if an class has a <i>@RestController</i> annotation and a <i>@Service</i> annotation.
So you either good documentation to explain this or keep it simple and don't do
both. I chose the second approach for the microservice example.</span></div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6859255045766041591.post-16928215086256659332015-06-21T09:52:00.001-07:002015-06-22T23:56:46.135-07:00Microservices with Spring Boot, Netflix OSS and Maven - Overview<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:HyphenationZone>21</w:HyphenationZone>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>DE</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Normale Tabelle";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"Times New Roman";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]--><br />
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;"></span><span lang="EN-US" style="mso-ansi-language: EN-US;">In my
last blog posts (<a href="http://blog.rseiler.at/2015/06/microservices-few-thoughts.html">Microservices: a few thoughts</a> and <a href="http://blog.rseiler.at/2015/06/the-importance-of-structuring.html">The Importance of structuring Microservices</a>) I wrote about microservices. Now it's time to go from theory to
practice and write some code. Based on <a href="http://projects.spring.io/spring-boot/" target="_blank">Spring Boot</a>, <a href="https://netflix.github.io/" target="_blank">Netflix OSS</a> (<a href="https://github.com/Netflix/eureka" target="_blank">Eureka</a>, <a href="https://github.com/Netflix/feign" target="_blank">Feign</a>,
<a href="https://github.com/Netflix/Hystrix" target="_blank">Hystrix</a> and <a href="https://github.com/Netflix/ribbon" target="_blank">Ribbon</a>) and <a href="https://maven.apache.org/" target="_blank">Maven </a>I created a setup for a microservice architecture.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I have put my <a href="https://github.com/rseiler/concept-microservice" target="_blank">example microservice project on GitHub</a>. </span><br />
<br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b>What the microservice example does</b></span><br />
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">It's a microservice system consists out of 3 microservices and one frontend microservice.</span></li>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>product service</i>: which just returns the data for a product (CPU, keyboard or mouse).</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>user service</i>: which just returns the data for a user.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>shopping cart service</i>: which stores for the users the products in their shopping carts.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>frontend service</i>: communicates with all microservices, aggregates the data and generates out of the data a simple HTML page.</span></li>
</ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">The microservices are grouped by domains.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Eureka is used to discover the microservices. Multiple instances can be started and new instances will automatically registered into the system and will be used from the existing microservices.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Ribbon is used transparently to do the load balancing on the client. So there is no need to have static IPs and a manually maintained load balancer.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">The REST clients for the microservices only consists out of interfaces. No cooding needed.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Hystrix REST clients are used to ensure resilience. The Hystrix REST clients are very effortless to write.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">The REST endpoints are done with Spring`s <i>@RestController</i> and implements the interface of the REST Client to ensure that the REST client and the REST endpoint matches each other.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Enhanced log output to make you life easier. It's done transparently with a Spring Interceptor and a Feign Interceptor.</span></li>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">The frontend microservice generates a UUID for each request. This UUID is put into the <a href="http://logback.qos.ch/manual/mdc.html" target="_blank">MDC</a> (Mapped Diagnostic Context) and will be printed out for each log entry. The UUID is passed as a header to the every called microservice - even if the called microservice calls another microservice the UUID is passed along too. Therefor it's possible to know which user request caused which log entry in any microservice.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Additional a calling stack is generated and logged. The calling stack looks like this: <i>ServiceB <- ServiceA <- /product/1 <- 127.0.0.1</i></span></li>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>/product/1 <- 127.0.0.1</i> is generated by the frontend microservice and shows the IP address of the request and the called endpoint</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>ServiceA</i>: the frontend microservice called the ServiceA</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>ServiceB</i>: the ServiceA<i> </i>called the ServiceB</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">=> Therefor you always know who called the microservice. Which isn't always a easy to answer question in a big microservice system. You could improve it furthermore if you would include <a href="https://twitter.github.io/zipkin/" target="_blank">zipkin</a>.</span></li>
</ul>
</ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">It's possible to pack all the microservices together into one monolithic application and this application works without the need to change anything. Therefor you have great flexibility. For example in development you probably don't want to start the complete microservice system on your machine. It's handy if you can just start up everything you need, which could be only a part of the system, packed into one application</span></li>
</ul>
</div>
<div class="MsoNoSpacing">
<br />
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Overview: Main Frameworks</span></b><br />
I give you an overview over the main frameworks/libraries and what they do.</div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Spring
Boot</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"><b>: </b>It saves
a lot of time for the setup. The auto configuration and the spring-cloud-starter-*
packages are awesome. In addition the Dependency Injection and the Spring Feign
abstraction are great, too.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Eureka</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"><b>: </b>It's a service
registry. Each service instance registers itself to Eureka. Afterwards all
instances of the services can be requested just with the name of the service.
So there is no need for IPs or ports. If another service instance is started
then it will be added into the corresponding service group or if a service
instance is shutdown then the instance will be removed from Eureka. </span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Ribbon</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"><b>: </b>It's a
client side load balancer working together with Eureka. Spring Boot
transparently integrates Ribbon. So you have to do nothing to use it. Ribbon
uses the round robin scheduling algorithms.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Hystrix:</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"><b> </b>It's a
latency and fault tolerance library designed to isolate points of access to
remote systems. I am using annotations to configure Hystrix. It's very easy to
use Hystrix and does only require a very little amount of effort. By all means
the programmatically side is very easy. The hard part is to react correctly to errors.
</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Feign:</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"><b> </b>It's a
REST client based on the <a href="https://hc.apache.org/httpcomponents-client-ga/" target="_blank">Apache HttpClient</a> which has a great level of
abstraction. With Spring the only thing you need to do is to write an interface
for you REST endpoint and annotate it with <i>@FeignClient</i>. You can use the Spring
MVC annotations instead of the Feign annotations. This has the advantage that
you reduce the complexity and the <i>@RestController</i> can implement the interface
to ensure that everything is compatible.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span></div>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">The top
level modules of the project</span></b></div>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>all-in-one</i>:
this module includes all microservices and it is fully functionally without any
change. Eureka isn't needed anymore and all remote calls will be done with standard
Java method calls.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>common</i>:
this module contains some common code and following </span><span lang="EN-US" style="mso-ansi-language: EN-US;"><span lang="EN-US" style="mso-ansi-language: EN-US;">micro</span>services: Eureka, Hystrix
Dashboard and Turbine Dashboard.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>frontend-service</i>:
this module generates the HTML and calls the other services to get the data.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>product-domain</i>:
this module represents the product domain and contains all product </span><span lang="EN-US" style="mso-ansi-language: EN-US;"><span lang="EN-US" style="mso-ansi-language: EN-US;">micro</span>services.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>user-domain</i>:
this module represents the user domain and contains all user microservices.</span></li>
</ul>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b>One repository to rule them all </b></span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I deliberately
put all microservices into a big project. The reason is that it makes
many things easier: </span></div>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">The need
to clone only one repository. Especially for this example no one would like to clone several repositories.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Refactoring,
searching, code navigation and so on works very well if you have everything in
one project. Especially if you run the <i>all-in-one monolithic application</i> then
it's very handy for debugging and coding.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Changes
can be done globally or locally. If you want to upgrade one library because of
a security issue then it's very nice if only one <i>pom.xml</i>
file needs to be changed. For example you could change the Spring version for all microservices. Otherwise you would need to clone and to open several projects and fix them all. Still
Maven allows you to change the version of a dependency only for a specific module. You
have the flexibility. Each module/microservice can be configured individual or mostly
everything can be configured globally.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Only one build is needed. Depending on the size you could build always everything. Or individual domain groups. Or individual microservices. Just execute <i>mvn install </i>wherever you need it.</span></li>
</ul>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I would
extract the common module into an own repository. This module shouldn't change
that often or is interesting to debug. Therefore it shouldn't be painful if
it's separated.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">With the current structure there is one problem: you can't
build the project directly after you have cloned it. It's necessary to build
the <i>common/common-configuration</i> module </span><span lang="EN-US" style="mso-ansi-language: EN-US;"><span lang="EN-US" style="mso-ansi-language: EN-US;">first</span>. Because it creates an artifact
which is needed and sadly Maven can't resolve this dependency correctly.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">If the
project begins to grow then </span><span lang="EN-US" style="mso-ansi-language: EN-US;"><span lang="EN-US" style="mso-ansi-language: EN-US;">possible </span> it makes sense to split the project
further more. For example you could create an own repository for each
domain-module. But it's up to you.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Microservice
Structure</span></b></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Each
microservice is located in a domain-module with the exception of the
frontend-service. Because the frontend-service aggregates all domains. In order to have a
consistent design and usability. In the frontend-service should only be very
little logic. It should only requests and aggregates data from the endpoints and prepares
the data to be displayed. But it shouldn't have any business logic.</span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span></div>
<div class="MsoNoSpacing">
</div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">A
microservice consists of two parts:</span></div>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>microservice-client</i>:
contains the Feign interface for the REST endpoint and the model/POJO classes.
Additional there is a Hystrix-REST-client which just wraps the Feign-client. Actual
everyone should use the Hystrix implementation instead of the Feign client.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>microservice-service</i>:
is the microservice itself with the business logic and the REST endpoints. It has a dependency to the <i>microservice-client</i>.
Since the model/POJO classes are needed and it implements the REST interface. Thereby
fewer mistakes can happen.</span></li>
</ul>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Maven</span></b></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I am
using my <a href="https://github.com/rseiler/pom-project" target="_blank">parent-pom</a> for this project. This POM file enables several useful
features like static code analysis. </span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;"> In <i>common-configuration</i> the <i>logback.xml</i> is
defined. The file will be packed into an Maven artifact and then extracted into each
service-module. Thereby it prevents to have several copies of that file. Probably
you could also move the<i> application.yml</i> and the <i>bootstrap.yml</i> into this module.
Otherwise there is nothing special to the Maven setup.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Scripts
and Execution</span></b></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">To make
it easier to build and run the project I provided some scripts. They are
located in the <i>scripts</i> folder and are very easy. So I think I don't need to
explain them. </span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The only
thing what is important to know is that it can take a little while until the microservices
are registered correctly and all microservices received the instances of the
other microservices. In the case of an error just try to reload the page a little
bit later.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b><span lang="EN-US" style="mso-ansi-language: EN-US;">Conclusion</span></b></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I think it's
a quite sophisticated setup and that it is very well suited to be the basis of production
microservices. One amazing thing is that it's possible to pack all the
microservices together - as long as the dependencies are compatible. This makes
supposedly the development easier. Instead of the need to start many
microservices you just need to start one application. In addition it can be a
quick fix for performance issues. If there are two very talkative microservices
just glue them together until you fixed the performance issue.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I hope
you like <a href="https://github.com/rseiler/concept-microservice" target="_blank">my setup</a> and my blog entry. I probably will write another blog post to
explain some details of the setup. This article is already so long that I didn't
want to include more details.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I am
always happy about comments and suggestions for improvements! :-)</span></div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6859255045766041591.post-41822138834250531522015-06-18T03:29:00.000-07:002015-06-18T07:06:07.843-07:00The Importance of structuring Microservices <!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:HyphenationZone>21</w:HyphenationZone>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>DE</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Normale Tabelle";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-fareast-language:EN-US;}
</style>
<![endif]--><span lang="EN-US" style="mso-ansi-language: EN-US;"></span><span lang="EN-US" style="mso-ansi-language: EN-US;">It's
very important to group microservices very well. Otherwise you will get a mess.
Several microservices should form a larger part of the functionality. </span>
<br />
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Example: Image Functionality in a Microservice System</span></b></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Lets
approach the problem by example. Assume we want to build an image processing functionality
for our system. Each microservice should do exactly one thing. So we will end
up in the following microservices:</span></div>
<br />
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">image
scaling</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">image
watermarking</span><span lang="EN-US" style="mso-ansi-language: EN-US;"></span> <span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">image
storing</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;"><span lang="EN-US" style="mso-ansi-language: EN-US;">image
retrieving</span> </span><span lang="EN-US" style="mso-ansi-language: EN-US;"></span></li>
</ul>
<br />
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">All
these image services are very tightly coupled - the storing microservice and
the retrieving microservice uses the same database and the same files. Of
course it should be possible to use each of them in another context or by
itself. However in your own system you will consider it as an image-sub-system.
Therefore this sub-system should have its own abstraction. Its own API - this API
is an own microservice. </span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">All non
image related microservices don't know anything about the individual image
microservices. They know only about the image API microservice. This API could group
together the typical use cases. For example to resize an image and watermark
it. </span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">You
don't want to have this code in any other place than in your image
microservices. Otherwise your complete microservice system is very tightly
interconnected. This is very bad. Imagine that all images will be scaled & watermarked
and that you have performance issues because of high network traffic. One
simple optimization is to merge the scaling microservice and the watermarking microservice
together. Then you have to send the image over the network one time less. If
you utilise an image API microservice then the code must be changed only once
and only one microservice needs to be redeployed. On the other hand if all other
microservices used the internal image microservices then you have to change the
code several times and several microservices need to be redeployed.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Abstraction like in a monolith</span></b></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">This
abstraction and grouping of functionality is nothing else like modules in
monoliths. In a monolith all the image functionality would be in a package
"image". This package would have following sub packages:
"scaling", "watermarking", "storing" and "retrieving".
Likewise in the microservice architecture you don't want other parts of the
monolith use these sub packages directly. Otherwise you have interconnected modules
and it will be hard to change internal details of the image implementation.
Everything should be behind a high level interface and everything else should
be hidden and not be used anywhere else. Then it's possible to rewrite the
complete image package without the need to adapt code in other packages. The
only thing you need to take care of is to support the interface.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I think
it's very appealing that this concept of abstraction is assignable to a monolith
and to a microservice architectures. If the concepts were completely different then something is most likely wrong.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The module
abstraction is often violated in monoliths and the complete codebase is very interconnected.
It's bad, but it's manageable. Because you have the complete code in your IDE
with all the useful refactoring tools. But if you have separated code bases
it's very hard to refractor anything. So do it right in the first place and
don't move it to a later date.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Microservice grouped by Domains</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"></span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">One way
to group the system is to group it by domains. A domain is a (mostly) independent
part of the system. It's very important that you get your domains right.
Because if you don't then the problem is that for nearly every new feature
several domains must be changed. But this should be only an exceptional case.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">For example the user part of a system consists of: login, registration, password
reset mail, user profile and so on. All these basic user functions are more or
less equal for each system. Therefore the user-sub-system should be also usable
for any other system. This only works if this domain is completely independent.
The domain is not allowed to have any dependency to any other domain. Otherwise
you have to remove those dependencies to make the user-sub-system usable for
another system.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Another
domain could be the product-domain. In this domain all the data of a product is
saved: price, stock count, description and so on. The user-domain and the
product-domain must be independent of each other.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">How to deal with features that require two
domains</span></b></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Lets approach
the problem again with an example: a shopping cart. A shopping cart is
individual to each user. Therefore it must be in the user=domain. The problem
is now that you also need the data from the product-domain. Otherwise the
shopping cart is quite useless if you can't see the details of the stored
products. But since the user-domain isn't allowed to have a dependency to the product-domain
how to solve this problem?</span><br />
<br /></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Actually
it's quite simple: with an aggregation microservice. In the user-domain all
stored data is related to the user like added-date, user-id and so on. There is
only one exception: the product-id is also stored.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The user-domain
provides an API to get all items from a specific user. These API will be consumed
by an aggregation microservice. The product-ids will be collected from the
aggregation microservice and then the details of the products will be fetched
from the product-domain. The data will be merged and then the shopping cart can
be displayed or the data can be passed to the next microservice. By that you
can implement the shopping cart feature so that both domains are still independent.</span><br />
<br /></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The
aggregation microservice/layer is nothing else than a Lego™ block which connects two
other Lego™ blocks together. If you use third party APIs then you do exactly the
same. You create some kind of Lego™ block which aggregates the data from several
third party APIs. It helps to think if you treat your own microservice APIs
like they are third party APIs. Because then you will get the independence of
the microservices right. You won't violate the independency.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Performance Issue with the Aggregation layer</span></b></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Let's
assume that it's common that a shopping cart has thousands of items.
Additionally you need to support to sort the items in a shopping cart by price. Then the aggregation
microservice has to load thousands of items from the user-domain, load thousands of
product details from the product-domain, merge the data, sort them by price and
then throw away thousands of items except for 100 which will be showed to the
user (pagination). That's very inefficient.</span><br />
<br /></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The only
way to solve the problem is with data duplication. It's necessary to store the
price of the item in the shopping cart database as well. Then you can do the pagination
in the database and only get out the right 100 items. </span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">That means
that you have to supply the additional data if an item is stored into the
shopping cart. Additionally the data in the shopping cart database must be
updated if the price is changed in the product database. To do that you need
events. If a product is updated an event must be thrown. An event listener will
take this event and update the price in the shopping cart database.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Eventual Consistency</span></b></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">This
means that you have only an eventual consistency. Because the price could be
changed but the corresponding event could be still in the queue. Then the item
will sorted in a wrong way. The price itself is correct, because the price which
will be displayed will be loaded from the product-domain with the other product
details.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">There is
no way around this problem. Only if you use just one database, do distributed
transactions, or do the inefficient loading of thousand records. But that conflicts
with scalability and/or the microservice architecture mindset. Therefore it must
be alright for all data you duplicate that they are shortly out of sync. In
some cases you can't do it. For example payment data. But then don't duplicate
the data.</span></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Conclusion</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"></span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">You need
guidelines which microservices are allowed to talk to which microservices.
Structure the communication workflow and use grouping and abstraction.
Otherwise you will not know which microservices rely on a specific
microservice - directly or indirectly. That's a very bad spot to be in. Another
thing you probably need is a good monitoring. So that you can see what
microservice calls were made for a user request and how long they take. Because
if you don't have this data then you have a very hard time to find performance
issues. Consider to use <a href="https://twitter.github.io/zipkin/">Zipkin</a>.</span></div>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Design the
system very careful and have good high level documentation for each
microservice. </span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;">If you get all of the things right then you should be fine and have much fun with your microservice system :-)</span></div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-6859255045766041591.post-24558846410760456032015-06-01T21:44:00.004-07:002015-06-18T05:55:36.805-07:00Microservices: a few thoughts<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:HyphenationZone>21</w:HyphenationZone>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>DE</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Normale Tabelle";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-fareast-language:EN-US;}
</style>
<![endif]-->
<br />
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Microservices
are a hot topic right now. At work we are discussing if we should move to
microservices, too. In my opinion it would be the right choice. First of all our
current software is very old and has many flaws. Therefore we need to rewrite the
software anyway. Second the concept of microservices fits us very well and it's
in general a great concept. </span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Specialists versus Generalists</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"><br />
A problem we currently have is that everyone must know the complete project,
which is quite big. We don't have modules on which the developers could
specialize. This causes a lack of code ownership and deep knowledge and
understanding of the code. Therefore the code gets worse and worse. With
microservices you have strong "modules". So each team/person can focus
on a group of microservices and know only about the interfaces of the other
microservices.<br />
The disadvantage is that you have a more difficult time with the project
management. Because you have to align your features accordingly to the teams
and their knowledge. <br />
If you can handle that then the overall output and quality should be considerably
better with specialized teams. More features mean mostly more money and that's
a good thing. This is not really a microservice thing. It's just an argument
for a good architecture and for specialized teams.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Impact of changes</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"><br />
Another nice benefit is, that you can delimit the impact of a change</span><span lang="EN-US" style="mso-ansi-language: EN-US;"><span lang="EN-US" style="mso-ansi-language: EN-US;"> better</span>.
Since a change in a monolith can always have strange side effects. This shouldn't
happen with microservices.<br />
It's very important that the microservices are fault tolerant. So if one
microservice misbehaves then it must not poison the other microservices. The
outage of one microservice must be contained. Meaning that a part of the functionality
is missing or broken. But everything else must still work fine. With this
concept you can take better care of your core microservices. The not so
important microservices could have less quality. Thereby it's possible to optimize
the development output - invest only as much as needed.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Homogeneous </span></b><b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Stack versus Inhomogeneous Stack</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"><br />
Many people say that another benefit is that you could use different frameworks
or even other programming languages. But in my opinion this doesn't make sense.
At least if the team is not very big. Or you have very special requirements.
Because a homogeneous stack makes everything much easier. Even the build tools,
build configuration and the deploy pipelines should be the same. Otherwise you
violate the DRY (don't repeat yourself), because you have some kind of "code/configuration/script
duplication" and have to solve each problem for each programming/framework-stack.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Upgrades</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"><br />
You still have the benefit of upgrading the microservices independently. If a
microservice runs stable and doesn't change then there is no need to upgrade it.
With a monolith you don't have this option. If a library is upgraded then everything
is affected. Even the code you didn't touch for years and worked perfectly
until the upgrade. Because of that a library upgrade in a monolith is very
dangerous and is done rarely. Microservices can be upgraded one after the
other. So there is no big bang upgrade but many little upgrades. Furthermore
you shouldn't have a jar hell like in a monolith. This makes upgrading easier,
too.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Flexibility<br />
</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;">In general you have
much more flexibility with microservices. Because one huge monolith is very
hard to change. What would it mean to change a core library in a monolith? For
example to change a self written URL dispatcher to Spring MVC. Of course there
is way too much logic in this layer. For the current project this change would mean
a rewrite of a big part of the system. Which would be very error-prone. Like in
the "Upgrades" section the problem is, that you have to change
everything. It's not reasonable to change only a part of the monolith to Spring
MVC. In some cases a partly change is just impossible. The general problem
with partly changes are that you have to support still the old self written URL
dispatcher and Spring MVC. The whole system gets more complex. And in a few
years the next library will come that you will want to use.<br />
But this isn't only true for core libraries. It's also true for smaller
libraries. If there is a new major library upgrade, which breaks the old API,
then you have to migrate a huge code base to the new version. It's not possible to write only one new feature with the new library version. For this single feature this doesn't
pay out. So you don't do it and use the old library which forces you to write
more code. Now you have a technical dept. Because all other features in the future
are limited to the old library version too.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Reusability<br />
</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;">How does the reusability
go? First you have a class which uses the same method for the same task. The
next step is to have a package for a more complicate task. If it gets even
more complicated you write standalone and independent libraries and add them as
a dependency. Microservices are the next step of the reusability. <br />
If you have several systems which need to send emails, then you probably have
in each system an email library dependency. Furthermore code to use this
library and this code is most likely an code duplication. Because it doesn't pay off to create a library which will be used in each
system </span><span lang="EN-US" style="mso-ansi-language: EN-US;"><span lang="EN-US" style="mso-ansi-language: EN-US;">only for a few
lines of code</span>. In a microservice world you create a microservice which handles the
emails. Then in all other places you just have to do one remote call and you
are done. If you create a new system, for example a new batch job, then you
have to use the email-microservice and you are done. No need to integrate an email
library into the batch. If a new requirement comes in that all mails should be resent
after an hour if the initial delivery failed then you only have to take care of
this requirement once. Not several times - for each system which sends emails.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Scalability</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"> <br />
This is a controversial topic, because not every software system needs to be extremely
scalable. Many software systems work fine with just one big database (which is
hopefully redundant). Therefore it's not always an argument for a microservice
architecture. If you need scalability then microservices are great. There is
one condition: the microservices need to be stateless. Then it's very easy to
start up more instances of the microservices and scalethe system this way.</span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;">There is another kind of scalability besides of the technical scalability: the developer scalability. It most likely won't work to have hundreds of developers working on the same monolithic code base. But again not everyone has to face this challenge.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Conclusion</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"> <br />
Microservices don't solve everything. In contrast this concept introduces new challenges
and problems. Nevertheless I think that these challenges are manageable. The
benefits you get from the use of the microservice archtecture are huge. If the system is complicated
enough, you know that your team can handle the microservice-challenges and creates
a good microservice architecture then you should definitely consider a
microservice architecture. If one of the criterions aren't met then stick to
your monolith.</span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br />A word of warning: a good microservice architecture and microservice infrastructure is
very hard to create and you need many things: an excellent concept, a very good
understanding of your domain - so that you can split up your monolith in the
right way, excellent monitoring, continuous delivery, automatically deployments and fast deployments,
handle failures gracefully - so that failures don't create a ripple effect, be able
to handle your data if it is distributed over several databases, and so on. </span></div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6859255045766041591.post-77880679412114429382015-06-01T14:18:00.001-07:002015-06-04T13:47:20.483-07:00spBee - generate the model classesIf you don't know <a href="https://rseiler.github.io/spBee/" target="_blank">spBee</a> then please read my other <a href="http://blog.rseiler.at/2015/05/spbee-stored-procedure-bee.html">blog post</a> first. But if you are in hurry then here is a very short description of spBee: it generates the code to execute stored procedures and to map the result into your model classes. This is done by writing the model classes, interfaces and some annotations.<br />
<br />
It's cool and it works very well. But there's still one thing that bothered me because it's just boring: the creation of the model classes. Therefore I have written a <a href="https://github.com/rseiler/spBee/blob/master/spbee-model-gen/src/main/java/at/rseiler/spbee/generator/ModelGenerator.java" target="_blank">quite simple program</a>. This program will execute your stored procedure with the your arguments, read the result and then creates the model classes. It's basic, but it works fine. With a little work you could optimize it so that it generates the Java files which you can put into your project without any additional work.<br />
The program just uses the <a href="https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSetMetaData.html" target="_blank"><span class="pl-smi">ResultSetMetaData</span> </a>and the <span lang="EN-US" style="mso-ansi-language: EN-US;"><a href="https://codemodel.java.net/nonav/apidocs/com/sun/codemodel/JCodeModel.html">JCodeMode</a></span>. There is also an <a href="https://github.com/rseiler/spBee/blob/master/spbee-model-gen/src/test/java/at/rseiler/spbee/generator/ModelGeneratorTest.java" target="_blank">unit test</a> to demonstrate the usage of the program.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6859255045766041591.post-90350246122117081412015-05-31T00:57:00.000-07:002015-06-01T08:56:47.458-07:00spBee - Stored Procedure Bee: a database framework<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:HyphenationZone>21</w:HyphenationZone>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>DE</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]-->
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Normale Tabelle";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-fareast-language:EN-US;}
</style>
<![endif]-->
<br />
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b>The Background Story</b></span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;">At work
we use only stored procedures to access the database. First I was quite skeptical.
Why don't we use JAP/Hibernate? But there are some reasons for that:</span></div>
<ul>
<li><span lang="EN-US" style="font-family: Symbol; mso-ansi-language: EN-US; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span><span lang="EN-US" style="mso-ansi-language: EN-US;">Performance</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">It's
very easy. Three other projects at work are using Hibernate. All of them had
to fight with performance issues. It's quite complicate to make Hibernate work efficiently.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">It's
the interface to the database. As a developer I don't care about the database
tables. I just want the data I am interested in and the stored procedures give me the data in a very
easy way.</span></li>
</ul>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">There are
more reasons for and against them. But actually I don't want to discuss this in greater detail.</span><br />
<br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b>The Problem</b> </span></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">One thing
that always bothered me with our stored procedure implementation was the necessity to map the <span style="font-family: "Courier New",Courier,monospace;">Resultset </span>manually. It looks like this but with more
fields/columns:</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<pre class="prettyprint lang-java code">Pojo pojo = new Pojo();
pojo.setId(theResultSet.getInt(1));
pojo.setName(theResultSet.getString(2));
pojo.setEnum(SomeEnum.fromId(theResultSet.getInt(3)));
return pojo;
</pre>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I wanted a
more elegant solution. So I spent some of my free time to figure out a
solution. The solution I wanted should be very easy to use and the implementation
should be easy, too. Nowadays many things rely on in-memory-code-generation
and reflection. But the problem with that is that it's impossible to debug.
Furthermore it's not easy to implement.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">The Solution: spBee - how it works</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;"><br />
That is why I decided to generate Java code. It's easy to create Java code
with <a href="https://codemodel.java.net/nonav/apidocs/com/sun/codemodel/JCodeModel.html">JCodeModel</a>
and it gives you the opportunity to debug the code. The code is generated based
on the structure of the Java classes and on some Java annotations. To make the
integration smooth everything is done in the Pre-Compile-Phase. Since Java 1.6
it's possible to hook up an annotation processor before the code is compiled. In this step it's possible to generate Java code. The generated Java code will be compiled to
byte code together with the rest of the code. With Maven it's very easy to configure the
annotation processor. So every time you build the project the boring to write code
will be generated automatically.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The current
implementation depends heavily on Spring. The first dependency to Spring is
that the <a href="http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/object/StoredProcedure.html">StoredProcedure</a>
from Spring is used - because of that it saved me to write more code. The
second dependency to Spring is that it builds on top of the Dependency Injection
of Spring. This has the benefit that the source code is always clean. Because
in the code only the interfaces are used. The implementation of the interfaces,
which will be generated by <a href="https://github.com/rseiler/spBee">spBee</a>,
will be wired up correctly by Spring at runtime.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Example</span></b></div>
<br />
<pre class="prettyprint lang-java code">@Entity
public class User {
private int id;
private String name;
private User() {}
@MappingConstructor
public User(int id, String name) {
this(id, name);
}
public int getId() { return id; }
public String getName() { return name; }
}
@Dao
public interface UserDao {
// list of entities
@StoredProcedure("sp_get_users")
List<user> getUsers();
// single entity
@StoredProcedure("sp_get_user")
public User getUser(int id);
}
// execution
@Autowired UserDao userDao;
List<user> users = userDao.getUsers();
User user = userDao.getUser(1)
</user></user></pre>
<br />
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Explanation of the example<br />
</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;">The <span style="font-family: "Courier New",Courier,monospace;">UserDao</span>
interface just groups together all stored procedures which are related to the
user. The interface has two methods which call two different stored procedures.
The name of the stored procedure is declared within the <span style="font-family: "Courier New",Courier,monospace;">@StoredProcedure</span>
annotation. The <span style="font-family: "Courier New",Courier,monospace;">getUsers()</span> method will just call the <span style="font-family: "Courier New",Courier,monospace;">sp_ger_users</span> stored
procedures without any parameters. Then the result is mapped into a list of
User entities. How does <a href="https://github.com/rseiler/spBee">spBee</a> know
how to map the result? It just reads the <span style="font-family: "Courier New",Courier,monospace;">@MappingConstrutor</span>, looks at the types
of the parameters and generates the corresponding code. It's possible to have several
<span style="font-family: "Courier New",Courier,monospace;">@MappingConstructor</span>s - you just have to give them names. Actually, that's it!
The <span style="font-family: "Courier New",Courier,monospace;">getUser()</span> method will call the stored procedure with one <span style="font-family: "Courier New",Courier,monospace;">int </span>value. The
list is automatically unpacked into a single element. If there is not exactly
one row returned from the database then an exception is thrown. But you can
configure it so that it returns <span style="font-family: "Courier New",Courier,monospace;">null</span>. Or you could wrap it into an <span style="font-family: "Courier New",Courier,monospace;">Optional </span>type.</span></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">There are more
features like multiple result sets and so on. If you are interested then please
take a look at the <a href="https://rseiler.github.io/spBee/">spBee documentation</a>.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b style="mso-bidi-font-weight: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">Conclusion<br />
</span></b><span lang="EN-US" style="mso-ansi-language: EN-US;">For me it was fun to
write this framework. I believe that the framework is stable and others can benefit
from it, too. Furthermore take a look at the <a href="https://github.com/rseiler/spBee/blob/master/spbee-core/src/main/java/at/rseiler/spbee/core/SPBeeAnnotationProcessor.java">SPBeeAnnotationProcessor</a>.
It's a very powerful but quite unknown feature of Java. In combination with
Dependency Injection it integrates very well. That's because nowhere in your code you are
using the generated code - no errors occur, if the code wasn't generated yet. Just
one warning: it's a little bit troublesome to write an annotation processor and
you can't use reflection at this point. You need to read the code with the help of the
AST API.<br />
Nevertheless it's great fun and it's awesome if it works in the end!</span></div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6859255045766041591.post-35741647707090116102015-03-14T13:52:00.001-07:002015-03-16T10:45:41.164-07:00Tutorial: How to push / upload artifacts into the Maven Central RepositoryI have several GitHub repositories and that's great. It's so easy to share the projects. But for some projects it's not enough. I created a POM, which I'm using as parent POM for all my projects. So if you want to checkout a project which depends on the POM then it's necessary to checkout the <a href="https://github.com/rseiler/pom-project/" target="_blank">pom-project</a> first and do a <span style="font-family: "Courier New",Courier,monospace;">$ mvn install</span>. That's quite annoying. The second example is my <a href="https://github.com/rseiler/spBee" target="_blank">spBee library</a>. I think most users aren't interested to checkout that project and to contribute to it - they just want to use it. Therefore it's necessary in such cases to put the artifacts on the Maven Central Repository. Then the user can add the library to the Maven dependencies and everything works. So I faced the question: how to push my artifacts to the Maven Central Repository?<br />
<br />
<b>A short overview over all steps</b><br />
<ol>
<li>install PGP - that's necessary to sign the artifacts - and upload your public key </li>
<li>prepare the POM file to satisfy all requirements</li>
<li>create an Sonatype account</li>
<li>create a New Project ticket</li>
<li>wait for a comment. </li>
<li>perform a stating release and comment the ticket that you have successfully done the stating release and the artifacts are ready to be released.</li>
<li>wait until the sync to the Maven Central Repository will be activated and now you can do the releases yourself.</li>
<ol>
<li>do another staging release</li>
<li>release your artifacts on this site <a href="https://oss.sonatype.org/">https://oss.sonatype.org/</a></li>
<li>or drop your staging release </li>
</ol>
<li>enjoy your artifacts on the Maven Central Repository </li>
</ol>
It seems to be quite complicated. But actually it's not that bad. Hopefully it's very easy with the help of this post!<br />
<br />
<b>1. Install PGP and upload your public key</b><br />
<b> </b>On <a href="http://central.sonatype.org/pages/working-with-pgp-signatures.html" target="_blank">this site</a> everything is explained. In short:<br />
<ul>
<li>download and install <a href="http://www.gnupg.org/download/" target="_blank">GPG</a></li>
<li><span style="font-family: "Courier New",Courier,monospace;">$ gpg --version</span></li>
<li><span style="font-family: "Courier New",Courier,monospace;">$ gpg --gen-key</span></li>
<ul>
<li>enter the required information</li>
</ul>
<li><span style="font-family: "Courier New",Courier,monospace;">$ gpg --list-keys</span></li>
<ul>
<li>in the output you will see the keyid of the public certificate</li>
<li><span style="font-family: "Courier New",Courier,monospace;">pub 1024D/C6EED57A 2010-01-13</span></li>
<li>the <span style="font-family: "Courier New",Courier,monospace;">C6EED57A </span>string is the keyid</li>
</ul>
<li>distribute the public key so that the signed files can be verified</li>
<ul>
<li><span style="font-family: "Courier New",Courier,monospace;">$ gpg --keyserver hkp://pool.sks-keyservers.net --send-keys C6EED57A</span></li>
</ul>
</ul>
<b>2. Prepare the POM file to satisfy all requirements</b><br />
On <a href="https://maven.apache.org/guides/mini/guide-central-repository-upload.html" target="_blank">this site</a> and <a href="http://central.sonatype.org/pages/requirements.html" target="_blank">that site</a> everything is explained. In short:<br />
<ul>
<li>the groupId </li>
<ul>
<li>if the groupId is at.rseiler.spbee then you need to own rseiler.at.</li>
<li>if you don't have an own domain, but use GitHub then the groupId must be: github.com/rseiler => com.github.rseiler</li>
</ul>
<li>the javadoc.jar must be generated</li>
<li>the sources.jar must be generated</li>
<li>all files must be signed with PGP</li>
<li>following meta data must be provided</li>
<ul>
<li>project name, description and URL </li>
<li>license information </li>
<li>developer information </li>
<li>scm (the repository URL) </li>
</ul>
<li>the nexus-staging-maven-plugin must be setup</li>
<li><span class="pl-ent">the distributionManagement (snapshotRepository and </span><br /><span class="pl-ent">repository) must be setup</span></li>
</ul>
Take a look at these both small POM files, which satisfies all requirements: <a href="https://github.com/rseiler/spBee/blob/master/pom.xml" target="_blank">spBee POM</a> <a href="https://github.com/rseiler/pom-project/blob/master/pom.xml" target="_blank">pom-project POM</a> <br />
The <span style="font-family: "Courier New",Courier,monospace;">release </span>profile will create the javadoc.jar sources.jar and signs the artifacts. So if you do a release you need to activate the profile with: <span style="font-family: "Courier New",Courier,monospace;">$ mvn clean deploy -P release</span><br />
<br />
To upload the artifacts you need to <a href="http://central.sonatype.org/pages/apache-maven.html" target="_blank">setup the settings.xml</a> (.m2/settings.xml).<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;"><settings><br /> <servers><br /> <server><br /> <id>ossrh</id><br /> <username>your-jira-id</username><br /> <password>your-jira-pwd</password><br /> </server><br /> </servers><br /></settings></span></blockquote>
<b>3. Create an Sonatype account</b><br />
Go to <a href="https://issues.sonatype.org/secure/Signup!default.jspa" target="_blank">this site</a> and create an account.<br />
<br />
<b>4. Create a New Project ticket</b><br />
<ul>
<li>go to <a href="https://issues.sonatype.org/secure/CreateIssue.jspa?issuetype=21&pid=10134" target="_blank">this site</a> and create a ticket - see <a href="https://issues.sonatype.org/browse/OSSRH-14402" target="_blank">mine as an example</a></li>
<li>enter the root groupId</li>
<ul>
<li>at.rseiler - even if your first artifact uses at.rseiler as groupId</li>
<li>com.github.rseiler - if you don't have an own domain</li>
</ul>
<li>fill out the rest of the fields</li>
</ul>
<b>6. Preform a stating release </b><br />
<ul>
<li>check if everything is setup correctly</li>
<li>I recommend to set <span style="font-family: "Courier New",Courier,monospace;"><<span class="pl-ent">autoReleaseAfterClose</span>>true</<span class="pl-ent">autoReleaseAfterClose</span>></span> to <span style="font-family: "Courier New",Courier,monospace;">false </span>so you can check the output first</li>
<li>notice that there aren't allowed any JavaDoc errors. If there are errors than the javadoc.jar file won't be created and then the requirements are missed. </li>
<li><span style="font-family: "Courier New",Courier,monospace;">$ mvn clean deploy -P release</span></li>
<li>check on <a href="https://oss.sonatype.org/" target="_blank">this site</a> under <span style="font-family: "Courier New",Courier,monospace;">Build Promation => Repositories => Content</span> your uploaded artifacts</li>
<li>if everything is fine then use: <span style="font-family: "Courier New",Courier,monospace;">$ mvn nexus-staging:release</span> to do a stating release</li>
<li>otherwise <span style="font-family: "Courier New",Courier,monospace;">$ mvn nexus-staging:drop</span> to drop the stating release</li>
<li>both commands can be executed on the website, too</li>
<li>comment the ticket</li>
</ul>
<b>7. Release yourself</b> <br />
After the sync is activated you can release your stating-releases yourself to the Maven Central Repository.<br />
<br />
<b>8. Enjoy your artifacts on the Maven Central Repository </b><br />
You have done it! Congratulation! :)<br />
<br />
<br />
I hope that my blog post helped you and gave you a good overview over all required steps.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6859255045766041591.post-64426242406935482692015-02-16T20:30:00.001-08:002015-03-06T19:27:08.102-08:00Publish Maven Site Documentation automatically to the GitHub Pages<style>.code { margin: 0 20px 0 20px; border: 1px solid silver; background-color: #EEE; border-radius:3px; padding: 5px; overflow: auto; }</style>
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:HyphenationZone>21</w:HyphenationZone>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>DE</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]-->
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Normale Tabelle";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"Times New Roman";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;}
</style>
<![endif]-->
<br />
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Maven site
is a great tool as well as GitHub. The coolest thing about those tools is that
they play together very well. Only a little Maven configuration is needed. But let
me explain shortly what both tools do.</span><br />
<br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b>Maven Site:
</b>generates automatically a nice documentation website for your Maven project.
Many Apache projects uses this generated site as their main website. So probably
you have already seen such generated websites. An nice example is the my (parent)
<a href="https://rseiler.github.io/pom-project/pom/index.html">POM project</a>
or the <a href="https://maven.apache.org/plugins/maven-site-plugin/">maven-site-plugin</a>.
Mainly the documentation consists of three parts:</span></div>
<div class="MsoNormal">
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">Project information
like dependencies, license, source repository and so on.</span> </li>
<li>Project reports like unit tests reports, static code analysis reports, JavaDocs
and so on.<span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">The documentation written by the developers. With an additional Maven Plugin
it's possible to write the documentation with Markdown.</span></li>
</ul>
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b>GitHub Pages: </b>GitHub
doesn't only provide a GIT repository but also can be used as webhost for
static website. Which is ideal for a project website. The GitHub Pages concept
is very cool. It's just a branch, called gh-pages, in you project repository.
All the files that are pushed into this branch will be served from GitHub`s
webserver. An nice example is the documentation for my (parent) <a href="https://rseiler.github.io/pom-project/pom/index.html">POM project</a>.<br />
Before you start with the Maven configuration you should read <a href="https://help.github.com/articles/creating-project-pages-manually/">Creating
Project Pages manually</a> for a better understanding.</span><br />
<br />
<span lang="EN-US" style="mso-ansi-language: EN-US;">Before we
can start with the GitHub Pages integration into Maven we firstly need to correctly
build the website. For multi module projects it's necessary to deploy (locally
is sufficient) the website first. Otherwise the references between modules
won't work. To do so you just need to configure the distribution management
like this:</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div class="code">
<distributionManagement><br />
<site><br />
<id>site-docs</id><br />
<url>file://${env.HOME}/sitedocs/pom-project</url><br />
</site><br />
</distributionManagement></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">How to
fully configure the generation of the Maven Site is too much for this blog
post. Look at the <a href="https://github.com/rseiler/pom-project/blob/master/pom/pom.xml">POM</a> for
some good basic configuration or just us it as parent POM for your project. The
minimum of configuration is:</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<div class="code">
<build><br />
<plugins><br />
<plugin><br />
<groupId>org.apache.maven.plugins</groupId><br />
<artifactId>maven-site-plugin</artifactId><br />
<version>3.4</version><br />
<executions><br />
<!-- used for multiproject builds --><br />
<execution><br />
<id>attach-descriptor</id><br />
<goals><br />
<goal>attach-descriptor</goal><br />
</goals><br />
</execution><br />
</executions><br />
<dependencies><br />
<!-- To use the Markdown format --><br />
<dependency><br />
<groupId>org.apache.maven.doxia</groupId><br />
<artifactId>doxia-module-markdown</artifactId><br />
<version>1.6</version><br />
</dependency><br />
</dependencies><br />
</plugin><br />
</plugins><br />
</build><br />
<br />
<reporting><br />
<plugins><br />
<plugin><br />
<groupId>org.apache.maven.plugins</groupId><br />
<artifactId>maven-project-info-reports-plugin</artifactId><br />
<version>2.7</version><br />
<configuration><br />
<dependencyLocationsEnabled>false</dependencyLocationsEnabled><br />
</configuration><br />
<reportSets><br />
<reportSet><br />
<reports><br />
<report>index</report><br />
<!--<report>cim</report>--><br />
<report>dependencies</report><br />
<!--<report>dependency-convergence</report>--><br />
<report>dependency-info</report><br />
<report>dependency-management</report><br />
<!--<report>distribution-management</report>--><br />
<!--<report>issue-tracking</report>--><br />
<report>license</report><br />
<!--<report>mailing-list</report>--><br />
<report>modules</report><br />
<report>plugin-management</report><br />
<report>project-team</report><br />
<report>scm</report><br />
<report>summary</report><br />
</reports><br />
</reportSet><br />
</reportSets><br />
</plugin><br />
</plugins><br />
</reporting></div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">To build
the Maven Site just use: <i style="mso-bidi-font-style: normal;">mvn clean</i> <i>site site:deploy</i></span><br />
</div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The
integration into the GitHub pages is very easy and looks like this:</span></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span></div>
<div class="MsoNormal">
<div class="code">
<build><br />
<plugins><br />
<plugin><br />
<groupId>org.apache.maven.plugins</groupId><br />
<artifactId>maven-scm-publish-plugin</artifactId><br />
<version>1.1</version><br />
<inherited>true</inherited><br />
<configuration><br />
<checkoutDirectory>${project.basedir}/github.com</checkoutDirectory><br />
<checkinComment>publishing site documentation</checkinComment><br />
<content>${env.HOME}/sitedocs/pom-project</content><br />
<pubScmUrl>scm:git:https://github.com/rseiler/pom-project.git</pubScmUrl><br />
<scmBranch>gh-pages</scmBranch><br />
</configuration><br />
</plugin><br />
</plugins><br />
</build></div>
</div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Additional
you need to configure your username and password in the .m2/settings.xml. It
should look like this:</span></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span></div>
<div class="MsoNormal">
<div class="code">
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"<br />
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0<br />
http://maven.apache.org/xsd/settings-1.0.0.xsd"><br />
<servers><br />
<server><br />
<id>github.com</id><br />
<username>github-username</username><br />
<password>github-password</password><br />
</server><br />
</servers><br />
</settings></div>
</div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><br /></span></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">If
everything is done just type: </span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<i style="mso-bidi-font-style: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">mvn clean site site:deploy
scm-publish:publish-scm -Dscmpublish.dryRun=true</span></i></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The <i>scmpublish.dryRun</i>
flag prevents the plugin to commit anything and just outputs what changes it
would commit. Check it and if everything works than rerun the command without
this flag: </span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><i style="mso-bidi-font-style: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">mvn clean site site:deploy </span></i><i style="mso-bidi-font-style: normal;"><span lang="EN-US" style="mso-ansi-language: EN-US;">scm-publish:publish-scm</span></i></b></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">That's it! It's
Very simple :)</span></div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6859255045766041591.post-47813606655166469052014-09-06T13:05:00.000-07:002014-11-28T13:18:06.300-08:00Class Transformation with ASM<style>.code { margin: 0 20px 0 20px; border: 1px solid silver; background-color: #EEE; border-radius:3px; padding: 5px; overflow: auto; }</style>
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:HyphenationZone>21</w:HyphenationZone>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>DE</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]-->
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Normale Tabelle";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-fareast-language:EN-US;}
</style>
<![endif]--><span lang="EN-US" style="mso-ansi-language: EN-US;">Have you
ever asked yourself how class transformation works? Great, then you are reading
the right blog post ;-)</span><br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Probably not
everybody knows what class transformation is. Therefore I will start to explain
it before I will explain how it works.</span><span lang="EN-US" style="mso-ansi-language: EN-US;"> </span></div>
<div class="MsoNormal">
<br /></div>
<h3 class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">What is
class transformation?</span></h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Actually it's there is a quite simple answer to this question: the <a href="https://en.wikipedia.org/wiki/Java_bytecode" target="_blank">Java bytecode</a>
will be modified in some kind. But let me explain it more detailed. If you
compile a Java file a class file will be generated. The class file represents
the Java source file as Java binary code. So it's much smaller and optimized
for execution. The methods consists of the <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html" target="_blank">Java opcodes</a>. These opcodes will
pushed sequentially onto the Java stack and will be executed. Class
transformation means that the Java byte code, which represents a Java class,
will be modified. So opcodes can be inserted or removed. But not only the
opcodes inside of a method can be modified. Everything can be changed - any
program can be transformed in anything else! At least as it is still valid Java
byte code. Otherwise the <a href="https://en.wikipedia.org/wiki/Java_virtual_machine#Bytecode_verifier" target="_blank">Java Bytecode Verifier</a> will reject the class if the class will
be loaded.</span></div>
<div class="MsoNormal">
<br /></div>
<h3 class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">W</span><span lang="EN-US" style="mso-ansi-language: EN-US;">here is class
transformation used?</span></h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Why would you transform a class if you just could write the Java class like you
need it to be? Actually if you can accomplish your work without class transformation
than don't use class transformation. Just write the Java code accordingly. I
think the most commonly usage of class transformation is to instrument Java
code at runtime. Imagine if you have a big program which has performance
problems and there are no performance tools like <a href="http://visualvm.java.net/" target="_blank">VisualVM </a>or <a href="https://www.ej-technologies.com/products/jprofiler/overview.html" target="_blank">JProfiler</a>. What would
you do to find the methods which takes long to execute?<br />
You would have to insert at each method the code to measure the execution
duration of the method. If there are thousands of methods this would be a quite
boring work. E</span><span class="hps"><span lang="EN" style="mso-ansi-language: EN;">specially since</span> you need to remove the code for the production code
and probably add it again to do the analyze the execution durations again. With
class transformation you can do exactly this boring work. You don't write the duration
measurement code in you Java files. But you read the existing class file and insert
the needed opcodes to each class, to each method.<br />
Actually all performance tools work like this. Java allows to modify already loaded
classes, with some restrictions, too. So these tools gets the binary code of
the classes, rewrites the classes on a binary level and Java loads the modified
classes. Than the tools can generate analysis and pretty diagrams from the
instrumented classes.</span></div>
<div class="MsoNormal">
<br /></div>
<h3>
<span lang="EN-US" style="mso-ansi-language: EN-US;">ASM </span></h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">
<a href="http://asm.ow2.org/" target="_blank">ASM</a> is a great library which allows to transform classes. It consists of three
main parts</span></div>
<ul>
<li><span lang="EN-US" style="font-family: Symbol; mso-ansi-language: EN-US; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"> </span></span></span><span lang="EN-US" style="mso-ansi-language: EN-US;">ClassReader:
reads a binary class</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">ClassWriter:
writes a binary class</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">ClassVisitor:
transforms the binary class by calling the visit-methods of your implementation</span></li>
</ul>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">To be able
to create class transformations you need to understand the Java opcodes and how
a <a href="https://en.wikipedia.org/wiki/Stack-oriented_programming_language" target="_blank">stack based language</a> works. At least you need a rudimentary understanding.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">There are
tools which will show you the byte code of any class and generate the ASM code
to create this class with ASM. Therefore you don't need to write all the
opcodes by hand. Just write a Java class which should be the result of your
transformation. Than look at the generated code and adapt it to your needs. In
theory that sounds very easy. But at least I had to read the ASM documentation
and the Java opcodes documentation, too. To make a quite simple transformation
work. </span></div>
<div class="MsoNormal">
<br /></div>
<h3 class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;"> Example</span></h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">
This example, which can be found completely on <a href="https://github.com/rseiler/concept-class-transformation-with-asm" target="_blank">GitHub</a>, does two things. </span></div>
<ul>
<li><span class="cm"><span lang="EN-US" style="font-family: Symbol; mso-ansi-language: EN-US; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span></span><span lang="EN-US" style="mso-ansi-language: EN-US;">Wraps all static </span><span class="cm">Logger variables</span><span class="cm"><span lang="EN-US" style="mso-ansi-language: EN-US;"></span></span></li>
<li><span class="cm"><span lang="EN-US" style="font-family: Symbol; mso-ansi-language: EN-US; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span></span><span class="cm">Logs all method calls</span><span class="cm"><span lang="EN-US" style="mso-ansi-language: EN-US;"></span></span></li>
</ul>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">For more
details read the code. It's heavily documented and it makes more sense to read
than anything else. Have fun! :-)</span><br />
<br />
<span lang="EN-US" style="mso-ansi-language: EN-US;">The code on GitHub with syntax hilighting, yeah: <a href="https://github.com/rseiler/concept-class-transformation-with-asm/blob/master/src/main/java/at/rseiler/concept/Main.java">https://github.com/rseiler/concept-class-transformation-with-asm/blob/master/src/main/java/at/rseiler/concept/Main.java</a>!</span></div>
<div class="MsoNormal">
<br /></div>
<div class="code">
<code>
</code>
<br />
<pre><code>package at.rseiler.concept;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.AdviceAdapter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.Method;
import java.util.logging.Logger;
import static org.objectweb.asm.Opcodes.ASM4;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
/**
* A demo how to do byte code transformation with ASM.
*
* The program will load the HelloWorld class file and manipulate the byte code:
*
* 1. Wraps static {@link Logger} into the {@link LoggerWrapper#logger(Logger)}
* 2. Adds at the beginning of each method a call to {@link MethodLogger#log(String, Object...)}
*
* 1.
* private static final Logger logger1 = Logger.getLogger(HelloWorld.class.getName());
* will be transformed into:
* private static final Logger logger1 = LoggerWrapper.logger(Logger.getLogger(HelloWorld.class.getName()));
*
* 2.
* public String foo(String arg) {
* return bar("foo", arg);
* }
* will be transformed into:
* public String foo(String arg) {
* MethodLogger.log("foo", arg);
* return bar("foo", arg);
* }
*
*
* You shouldn't relay on the ASM version packed into the jdk for production code!
* Because if a new Java version will be shipped than it could contain a new version of AMS (or remove ASM) which will break your code.
* Therefor you must repackage ASM into your own namespace, to prevent version conflicts, and ship it with your library.
*
* Because this is non production code and I am lazy I didn't do it.
*
* IMPORTANT: If you try to run the program on a JMV other than the JDK8 it will probably fail.
*
* @author reinhard.seiler@gmail.com
*/
public class Main {
public static void main(String[] args) throws Exception {
// creates the ASM ClassReader which will read the class file
ClassReader classReader = new ClassReader(new FileInputStream(new File("HelloWorld.class")));
// creates the ASM ClassWriter which will create the transformed class
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
// creates the ClassVisitor to do the byte code transformations
ClassVisitor classVisitor = new MyClassVisitor(ASM4, classWriter);
// reads the class file and apply the transformations which will be written into the ClassWriter
classReader.accept(classVisitor, 0);
// gets the bytes from the transformed class
byte[] bytes = classWriter.toByteArray();
// writes the transformed class to the file system - to analyse it (e.g. javap -verbose)
new FileOutputStream(new File("HelloWorld$$Transformed.class")).write(bytes);
// inject the transformed class into the current class loader
ClassLoader classLoader = Main.class.getClassLoader();
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
defineClass.setAccessible(true);
Class helloWorldClass = (Class) defineClass.invoke(classLoader, null, bytes, 0, bytes.length);
// creates an instance of the transformed class
Object helloWorld = helloWorldClass.newInstance();
Method hello = helloWorldClass.getMethod("hello");
// class the hello method
hello.invoke(helloWorld);
}
private static class MyClassVisitor extends ClassVisitor {
public MyClassVisitor(int i, ClassVisitor classVisitor) {
super(i, classVisitor);
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (cv == null) {
return null;
}
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
// <clinit> defines the static block in which the assignment of static variables happens.
// E.g. private static final Logger logger = Logger.getLogger(HelloWorld.class.getName());
// The assignment of the logger variable happens in <clinit>.
if ("<clinit>".equals(name)) {
return new StaticBlockMethodVisitor(mv);
} else {
// all other methods (static and none static)
return new MethodLogger(mv, access, name, desc);
}
}
class StaticBlockMethodVisitor extends MethodVisitor {
StaticBlockMethodVisitor(MethodVisitor mv) {
super(ASM4, mv);
}
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
// checks for: putstatic // Field *:Ljava/util/logging/Logger;
if ("Ljava/util/logging/Logger;".equals(desc)) {
// adds before the putstatic opcode the call to LoggerWrapper#logger(Logger) to wrap the logger instance
super.visitMethodInsn(INVOKESTATIC, "at/rseiler/concept/LoggerWrapper", "logger", "(Ljava/util/logging/Logger;)Ljava/util/logging/Logger;");
}
// do the default behaviour: add the putstatic opcode to the byte code
super.visitFieldInsn(opcode, owner, name, desc);
}
}
class MethodLogger extends AdviceAdapter {
private final int access;
private final String name;
private final String desc;
protected MethodLogger(MethodVisitor mv, int access, String name, String desc) {
super(ASM4, mv, access, name, desc);
this.access = access;
this.name = name;
this.desc = desc;
}
@Override
protected void onMethodEnter() {
// checks if the method is static.
// The difference is that "this" is stored in ALOAD_0 and the arguments are stored in ALOAD_1, ALOAD_2, ...
// But there is no "this" for a static method call. Therefor the arguments are stored in ALOAD_0, ALOAD_1 ,...
// If we want to access the arguments we need to differentiate between static and non static method calls.
boolean isStatic = (access & ACC_STATIC) > 0;
int length = Type.getArgumentTypes(desc).length;
// pushes the method name on the stack
super.visitLdcInsn(name);
// pushes the count of arguments on the stack
// could be optimized if we would use iconst_0, iconst_1, ..., iconst_5 for 0 to 5.
super.visitIntInsn(BIPUSH, length);
// creates an object array with the count of arguments
super.visitTypeInsn(ANEWARRAY, "java/lang/Object");
// stores the arguments in the array
for (int i = 0; i < length; i++) {
// duplicates the reference to the array. Because the AASTORE opcode consumes the stack element with the reference to the array.
super.visitInsn(DUP);
// could be optimized
super.visitIntInsn(BIPUSH, i);
// puts the value of the current argument on the stack
super.visitVarInsn(ALOAD, i + (isStatic ? 0 : 1));
// stores the value of the current argument in the array
super.visitInsn(AASTORE);
}
// calls the MethodLogger#log(String, Object...) method with the corresponding arguments - which we created just before
super.visitMethodInsn(INVOKESTATIC, "at/rseiler/concept/MethodLogger", "log", "(Ljava/lang/String;[Ljava/lang/Object;)V");
}
}
}
}
</clinit></clinit></clinit></code></pre>
<code>
</code>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6859255045766041591.post-82682863923564241542014-06-29T11:37:00.000-07:002014-11-28T13:17:48.886-08:00Explanation how CGLIB proxies work<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:HyphenationZone>21</w:HyphenationZone>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>DE</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]-->
<br />
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;"> In my <a href="http://reinhard-seiler.blogspot.co.at/2014/06/mock-framework-vs-anonymous-class-for.html">lastblog entry</a> I explained how proxy based mock frameworks work and created my own
demo mock framework based on CGLIB. Now I will explain how exactly the CGLIB proxy
works. Because then you will understand why these things doesn't work with a
proxy:</span></div>
<ul>
<li><span lang="EN-US" style="font-family: Symbol; mso-ansi-language: EN-US; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span><span lang="EN-US" style="mso-ansi-language: EN-US;">intercept
static method calls</span></li>
<li><span lang="EN-US" style="font-family: Symbol; mso-ansi-language: EN-US; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span><span lang="EN-US" style="mso-ansi-language: EN-US;">intercept
private method calls</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">intercept
final method calls</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">build
a proxy for a final class</span></li>
</ul>
<h3>
<br />ASM</h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;"><a href="https://github.com/cglib/cglib" target="_blank">CGLIB </a>is
based on <a href="http://asm.ow2.org/" target="_blank">ASM</a>. ASM is a library to create class files, on bytecode level, on the
fly. So it's very low level and you need a good understanding of the bytecode
to use it. But it abstracts the bytecode and is much more comfortable to generate
bytecode with ASM than writing the bytecode itself. Because it takes care of
the common structures like classes, constructors, method definitions and so on.
One of the most helpful features is that it takes care about the <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html" target="_blank">constant pool</a>.
Because the constant pool holds many elements and you need to adapt it if you
change anything. E.g. if a new method is added than you have to add the needed
elements to the constant pool and increase the constant pool size. Or the
labels in ASM are quite nice, too. Or that there are constants for the <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html" target="_blank">opcodes</a>.
After the complete class is generated, you have the bytecode of the class. This
bytecode is passed into the ClassLoader which will load the class and then the
class can be used.</span></div>
<h3>
<br />How the generated CGLIB looks </h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Now you
know how the generation of the proxy works. The question is how the
generated proxy looks like. Actually it's quite simple. The proxy class extends
the original class. All classes which should be intercepted by the proxy will
be overridden. These methods will call the <a href="http://cglib.sourceforge.net/apidocs/net/sf/cglib/proxy/MethodInterceptor.html#intercept%28java.lang.Object,%20java.lang.reflect.Method,%20java.lang.Object[],%20net.sf.cglib.proxy.MethodProxy%29" target="_blank"><i>MethodInterceptor:: intercept</i></a> method
with the corresponding parameters. If the proxy callback is null than the super
method will be called. Here is the code snippet for a simple <i>echo(String)</i>
method:</span></div>
<blockquote class="tr_bq">
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">public
class at.rseiler.concept.mock.Foo$$EnhancerByCGLIB$$c0699eac</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>extends at.rseiler.concept.mock.Foo</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>implements org.mockito.cglib.proxy.Factory</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">{</span></i></div>
</blockquote>
<blockquote class="tr_bq">
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>private static final
org.mockito.cglib.proxy.MethodProxy CGLIB$echo$1$Proxy;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>private static final java.lang.reflect.Method
CGLIB$echo$1$Method;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>// ...</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>private
org.mockito.cglib.proxy.MethodInterceptor CGLIB$CALLBACK_0;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>// ...<span style="mso-spacerun: yes;"><br /><br /> </span>public final String echo(String arg0) {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>if(CGLIB$CALLBACK_0
== null) {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>CGLIB$BIND_CALLBACKS(this);</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>}</span></i></div>
<i>
</i><br />
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>if(CGLIB$CALLBACK_0
!= null) {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>// MethodInterceptor::intercept(Object obj,
Method method, Object[] args, MethodProxy proxy)</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>Object obj = CGLIB$CALLBACK_0.intercept(this,
GLIB$echo$0$Method, new Object[] {arg0}, CGLIB$echo$0$Proxy);</span></i></div>
<i>
</i><br />
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>if(!(obj instanceOf String)) {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>throw
new ClassCastException();</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>}</span></i></div>
<i>
</i><br />
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>return obj;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>}</span></i></div>
<i>
</i><br />
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>return
super.echo(arg0);</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>}</span></i></div>
</blockquote>
<blockquote class="tr_bq">
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>private static final void
CGLIB$BIND_CALLBACKS(java.lang.Object object) {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span>/*
compiled code */</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>}</span></i></div>
<i>
</i><br />
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-spacerun: yes;"> </span>// ...</span></i></div>
<i>
</i><br />
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">}</span></i></div>
</blockquote>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Now you
should understand the limits of the proxy (see above). The limits caused
because the proxy is a subclass of the original class. Therefore it's not
possible to extend a final class or final methods and so on. That's just basic Java
limitations.<br />
With code generation it's not possible to work around these limits. Sure it
would be possible to generate a proxy class without the relationship to the
original class. Than it would be possible to copy the whole class and insert
the <i>MethodInterceptor::intercept</i> calls. This new class could remove all final
keywords and make private methods public. The problem is that you
can't call any method of this class without reflection. Because you don't have
the type information of the "proxy" class at compile time - clearly
because the class is generated at runtime. Further you can't pass the
"proxy" object to any constructor or any method because it's not a
subclass.</span></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The only
way to break this limits is to do bytecode transformations of the original
class before the ClassLoader loads the class. Before the class is loaded
replace all private keywords with public keywords and to remove all final
keywords. To do so you need to create your own ClassLoader which will performs the
bytecode transformation. I don't know the code of PowerMock, but it must work
like this.</span></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">At last the
with <i><a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javap.html" target="_blank">javap</a> --verbose</i> decompiled bytecode of the <i>echo(String)</i> method from which
I created the Java code above: </span></div>
<blockquote class="tr_bq">
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">public
final java.lang.String echo(java.lang.String);</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">flags:
ACC_PUBLIC, ACC_FINAL</span></i></div>
<div class="MsoNoSpacing">
<br /></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">Code:</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">stack=7,
locals=2, args_size=2</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">0:
aload_0</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">1:
getfield<span style="mso-spacerun: yes;"> </span>#37<span style="mso-spacerun: yes;"> </span>// Field
CGLIB$CALLBACK_0:Lorg/mockito/cglib/proxy/MethodInterceptor;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">4: dup</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">5:
ifnonnull<span style="mso-spacerun: yes;"> </span>17</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">8: pop</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">9:
aload_0</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">10:
invokestatic<span style="mso-spacerun: yes;"> </span>#41<span style="mso-spacerun: yes;"> </span>// Method
CGLIB$BIND_CALLBACKS:(Ljava/lang/Object;)V</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">13:
aload_0</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">14:
getfield<span style="mso-spacerun: yes;"> </span>#37<span style="mso-spacerun: yes;"> </span>// Field
CGLIB$CALLBACK_0:Lorg/mockito/cglib/proxy/MethodInterceptor;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">17: dup</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">18:
ifnull<span style="mso-spacerun: yes;"> </span>45</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">21:
aload_0</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">22: getstatic<span style="mso-spacerun: yes;"> </span>#64<span style="mso-spacerun: yes;"> </span>// Field
CGLIB$echo$1$Method:Ljava/lang/reflect/Method;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">25:
iconst_1</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">26:
anewarray<span style="mso-spacerun: yes;"> </span>#66<span style="mso-spacerun: yes;"> </span>// class java/lang/Object</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">29: dup</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">30:
iconst_0</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">31:
aload_1</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">32:
aastore</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">33:
getstatic<span style="mso-spacerun: yes;"> </span>#68<span style="mso-spacerun: yes;"> </span>// Field
CGLIB$echo$1$Proxy:Lorg/mockito/cglib/proxy/MethodProxy;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">36:
invokeinterface #53,<span style="mso-spacerun: yes;"> </span>5<span style="mso-spacerun: yes;"> </span>// InterfaceMethod
org/mockito/cglib/proxy/MethodInterceptor.intercept:(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lorg/mockito/cglib/proxy/MethodProxy;)Ljava/lang/Object;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">41:
checkcast<span style="mso-spacerun: yes;"> </span>#55<span style="mso-spacerun: yes;"> </span>// class java/lang/String</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">44:
areturn</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">45:
aload_0</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">46:
aload_1</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">47:
invokespecial #62<span style="mso-spacerun: yes;"> </span>//
Method at/rseiler/concept/mock/Foo.echo:(Ljava/lang/String;)Ljava/lang/String;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">50:
areturn</span></i></div>
</blockquote>
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Normale Tabelle";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-fareast-language:EN-US;}
</style>
<![endif]--><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026"/>
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1"/>
</o:shapelayout></xml><![endif]-->Unknownnoreply@blogger.com25tag:blogger.com,1999:blog-6859255045766041591.post-64169401959569516972014-06-20T11:54:00.000-07:002018-05-05T08:25:36.734-07:00 Explanation how proxy based Mock Frameworks work<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:HyphenationZone>21</w:HyphenationZone>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>DE</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]-->
<br />
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Have you
ever wondered how these <a href="https://code.google.com/p/mockito/" target="_blank">Mockito </a>lines work?</span></div>
<blockquote class="tr_bq">
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">Foo foo
= Mockito.mock(Foo.class);</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">Mockito.when(foo.echo("foo")).thenReturn("foo");</span></i></div>
</blockquote>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Yes or you
are now interested? Great, then you should read this article. Otherwise you are
probably lost and I can't help you. Sorry.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The first
important thing to know is that there are two types of frameworks.</span></div>
<ol>
<li><span lang="EN-US" style="mso-ansi-language: EN-US; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span><span lang="EN-US" style="mso-ansi-language: EN-US;">the proxy based mock frameworks:
Mockito, EasyMock, jMock, ...</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">the mock frameworks based on bytecode
manipulation: PowerMock, ...</span></li>
</ol>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">There is a
big different between those both concepts. </span></div>
<ol>
<li><span lang="EN-US" style="mso-ansi-language: EN-US; mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span><span lang="EN-US" style="mso-ansi-language: EN-US;">are much easier to implement but
they are more restricted in the features they can support. </span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">bytecode manipulation should tell
you everything you should know about it: it's based on "very dark magic". It can
break on major Java releases. So be careful if you start to use such
frameworks, because they could prevent you from upgrade your Java version.
PowerMock for example builds on top of <a href="http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/" target="_blank">Javassist</a>. A framework which makes
bytecode manipulation more simple.</span></li>
</ol>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">In this
article I will explain only how the proxy based mock frameworks like Mockito
works. Because it's quite easy to understand how this kind of mock frameworks
work. The knowledge will probably help you to use those frameworks if you know
how they work and where the limits are. So you will never try to do anything
which is technically impossible.</span></div>
<div class="MsoNormal">
<br /></div>
<h3 class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">What is a Proxy? </span></h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;"></span></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">A proxy is
just an object which will be used instead of the original object. If a method
of the proxy object is called then the proxy object can decide what it will do
with this call:</span></div>
<ul>
<li><span lang="EN-US" style="font-family: "symbol"; mso-ansi-language: EN-US; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span><span lang="EN-US" style="mso-ansi-language: EN-US;">delegate
it to the original object </span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">handles
the call itself </span></li>
</ul>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Proxies can
be used to implement some kind of permission system. The proxy checks if the
user is allowed to call the method and if the user doesn't have the permission
then it throws an exception.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">A proxy
doesn't require an instance of an interface/class if the proxy handles all
method invocations itself. <i> </i></span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><i>Mockito.mock(Foo.class)</i> is now easily explained.
This code just creates a proxy object for the Foo class.</span></div>
<div class="MsoNormal">
<br /></div>
<h3>
<span lang="EN-US" style="mso-ansi-language: EN-US;">Limits of a Proxy</span></h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">There are a
few important restrictions to the proxies. It's not possible to:</span></div>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">intercept
static method calls</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">intercept
private method calls</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">intercept
final method calls</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">build
a proxy for a final class</span></li>
</ul>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">If you want to understand these limitations then read my other blog entry about: <a href="http://reinhard-seiler.blogspot.co.at/2014/06/explanation-how-cglip-proxies-work.html" target="_blank">Explanation how CGLIP proxies work</a> </span><br />
<span lang="EN-US" style="mso-ansi-language: EN-US;">Another
restriction is that you have always to create the proxy explicitly. So it's not
possible to say, that all Foo instances, created with <i>new Foo()</i>
should be automatically wrapped into a proxy object. With PowerMock such things
are possible. </span></div>
<div class="MsoNormal">
<br /></div>
<h3>
<span lang="EN-US" style="mso-ansi-language: EN-US;">How to create a Proxy</span></h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">If you look
into the Java API you will find the <i>java.lang.reflect.Proxy</i> class. </span></div>
<blockquote class="tr_bq">
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">/**</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">*
Returns an instance of a proxy class for the specified interfaces</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">* that
dispatches method invocations to the specified invocation</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">*
handler.</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">*</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">*
@param<span style="mso-spacerun: yes;"> </span>loader the class loader to
define the proxy class</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">*
@param<span style="mso-spacerun: yes;"> </span>interfaces the list of
interfaces for the proxy class to implement</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">*
@param<span style="mso-spacerun: yes;"> </span>h the invocation handler to
dispatch method invocations to<br />
Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler
h)</span></i></div>
</blockquote>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">It's quite
simple to use. To showcase the usage of this proxy we just build our own simple
mock framework - you find the complete source code at the end of the article. We create the static mock method which returns the proxy
object.</span></div>
<blockquote class="tr_bq">
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">public
class Mock {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"> public static <T> T
mock(Class<T> clazz) {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 2;"> </span>MockInvocationHandler
invocationHandler = new MockInvocationHandler();</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 2;"> </span>T proxy = (T)
Proxy.newProxyInstance(Mock.class.getClassLoader(), new Class[]{clazz},
invocationHandler);</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 2;"> </span>return proxy;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>}</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">}</span></i></div>
</blockquote>
<i>
</i><br />
<i>
</i><br />
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">This
creates a proxy object for the <i>clazz</i> and redirects all calls to the <i>MockInvocationHandler</i> which looks like this:</span></div>
<i>
</i><br />
<blockquote class="tr_bq">
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">private
static class MockInvocationHandler implements InvocationHandler {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>@Override</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>public Object invoke(Object
proxy, Method method, Object[] args) throws Throwable {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 2;"> </span>return null;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>}</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">}</span></i></div>
</blockquote>
<div class="MsoNoSpacing">
<span lang="EN-US" style="mso-ansi-language: EN-US;">So each
call to a method of the proxy object will return null. At this stage we have an proxy
object on which we can call methods. </span></div>
<div class="MsoNoSpacing">
<br /></div>
<h3>
<span lang="EN-US" style="mso-ansi-language: EN-US;">How to dynamically define
the Proxy?</span></h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">Now the
question is how to setup the proxy to return something else than just null. We
need to do something like: <i>Mock.when(foo.echo("foo")).thenReturn("foo")</i></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">But how
does this work? To understand how this work you have to analyze the one line of code
very carefully and think about what it actually does. </span></div>
<div class="MsoNormal">
<br /></div>
<h4>
<span lang="EN-US" style="mso-ansi-language: EN-US;">What does the <i>when(</i>)
method actually gets?</span></h4>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">In the case
of our example it would just gets a null object. In the
first step we created the foo object which is a proxy which always return null.
The <i>when()</i> method doesn't get the method <i>echo()</i> with a parameter. It's an common
method call. It's a call to the proxy which will return null and pass the null value to the <i>when()</i> method. That's it. </span></div>
<div class="MsoNormal">
<br /></div>
<h4>
<span lang="EN-US" style="mso-ansi-language: EN-US;">How the <i>thenReturn()</i>
method works?</span></h4>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">You have
learned that the <i>when()</i> method just got null. So how can the <i>thenReturn()</i> call
work? Think a few minutes about it. It's nothing special. It can be called at
most "a little trick".</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The
solution is simple: with static variables in which the state is stored.</span></div>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">in
the <i>MockInvocationHandler </i>we store the method and the arguments of the last call</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">in
the <i>Mock </i>class - </span><span lang="EN-US" style="mso-ansi-language: EN-US;"><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>Mock.when(foo.echo("foo")).thenReturn("foo")</i></span> - we store the reference to the <i>MockInvocationHandler </i>which was
called last</span></li>
</ul>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">These two
steps happens in the<i> invoke()</i> method of the proxy object - in the </span><span lang="EN-US" style="mso-ansi-language: EN-US;"><span lang="EN-US" style="mso-ansi-language: EN-US;"><i>MockInvocationHandler</i></span>. The <i>when()</i> method doesn't
have any logic. When <i>thenReturn()</i> is called then we store the return value for
the stored (remembered) <i>MockInvocationHandler </i>with it's last method and arguments. If the
proxy is called again then it will return the stored return value (if it's the
same method gets called with the same parameter).</span></div>
<div class="MsoNormal">
<br /></div>
<h4>
<span lang="EN-US" style="mso-ansi-language: EN-US;">Basically that's it</span></h4>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I hope you
could follow so far. I will summarize it again with other words</span></div>
<ul>
<li><span lang="EN-US" style="font-family: "symbol"; mso-ansi-language: EN-US; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span><span lang="EN-US" style="mso-ansi-language: EN-US;">create
a proxy</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">if
a proxy method is called then remember which method was called. This proxy
method call is normally located inside of the <i>Mock.when()</i> method - even if it has no relationship to the <i>when()</i> method.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">if
<i>thenReturn(value)</i> is called store the "<i>value</i>" to the stored/remembered method.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">the
proxy returns the "<i>value</i>" if the method is called again with the
correct arguments.</span></li>
</ul>
<div class="MsoListParagraphCxSpLast" style="mso-list: l0 level1 lfo6; text-indent: -18.0pt;">
<br /></div>
<h4>
<span lang="EN-US" style="mso-ansi-language: EN-US;">The genius behind this is</span></h4>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The very
simple API which makes the whole thing looks like very nice. Another great decision is that
the <i>when()</i> method uses generics so that the <i>thenReturn()</i> method is type safe.</span></div>
<div class="MsoNormal">
<br /></div>
<h4>
<span lang="EN-US" style="mso-ansi-language: EN-US;">But what's about classes?</span></h4>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">The current
solution only works for interfaces. Because <i>java.lang.reflect.Proxy</i> only
supports interfaces and not classes. So we need another mechanism to create the proxy. We have to dig a little be deeper and finally come to <a href="https://github.com/cglib/cglib" target="_blank">CGLIB </a>- Code
Generation Library. So we are back to magic. But it's by far not so dangerous
like bytecode manipulation. We just use bytecode generation to create the proxy which shouldn't fail.
In fact many tools are using CGLIB (e.g. Spring, Hibernate).</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">To create a proxy with CGLIB isn't any more difficult than with the Java`s Proxy class.</span></div>
<blockquote class="tr_bq">
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">public
static <T> T mock(Class<T> clazz) {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>Enhancer enhancer = new
Enhancer();</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>enhancer.setSuperclass(clazz);</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>enhancer.setCallback(new
MockMethodInterceptor());</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>return (T) enhancer.create();</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">}</span></i> </div>
</blockquote>
<blockquote class="tr_bq">
<i>
</i><br />
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">private
static class MockMethodInterceptor {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>@Override</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>public Object intercept(Object
obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>return
null;</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;"><span style="mso-tab-count: 1;"> </span>}</span></i></div>
<div class="MsoNoSpacing">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">}</span></i></div>
</blockquote>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">That's it.
Everything else stays the same. <br />
With this kind of proxy you can easily build something like</span></div>
<blockquote class="tr_bq">
<div class="MsoNormal">
<i><span lang="EN-US" style="mso-ansi-language: EN-US;">Foo foo =
new Foo();<br />
foo = Mockito.spy(foo);<br />
Mockito.when(foo.echo("foo")).thenReturn("bar");</span></i></div>
</blockquote>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">You can create a proxy for a real object. All calls will be delegated to the real
object expect if the method call is redefined. With CGLIB this is very easy to
build. If you want to know more just take a look at the source code. </span></div>
<div class="MsoNormal">
<br /></div>
<h3>
<span lang="EN-US" style="mso-ansi-language: EN-US;">Source Code</span></h3>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">A simple mock framework to demonstrate how the proxy based mock frameworks work. With two implementations:</span><br />
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">based on the java.lang.reflect.Proxy.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">based on CGLIB. The
CGLIB mock also implements the <i>spy </i>method.</span></li>
</ul>
<span lang="EN-US" style="mso-ansi-language: EN-US;">Checkout the code from <a href="https://github.com/rseiler/concept-of-proxy-based-mock-frameworks">https://github.com/rseiler/concept-of-proxy-based-mock-frameworks </a></span></div>
<div class="MsoNormal">
<br /></div>
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Normale Tabelle";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-fareast-language:EN-US;}
</style>
<![endif]-->Unknownnoreply@blogger.com11tag:blogger.com,1999:blog-6859255045766041591.post-6515064411992712182014-06-13T08:30:00.004-07:002014-06-21T00:58:44.713-07:00Mock Framework vs Anonymous Class for Unit Tests<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:HyphenationZone>21</w:HyphenationZone>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>DE</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Normale Tabelle";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-fareast-language:EN-US;}
</style>
<![endif]-->
<br />
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">I recently
discussed at work what to use for unit tests: a mock framework (e.g. Mockito) or
anonymous classes. Surprisingly for my only one person choose anonymous classes
and there where many votes for the mock framework. I prefer myself the mock framework. </span><br />
<br />
<span lang="EN-US" style="mso-ansi-language: EN-US;"><b>The benefits of a mock framework:</b> </span></div>
<ul>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">if
you mock an interface within multiple tests with anonymous classes and then you
change the interface you have to touch all of these test files. Even if the new
added method doesn't break the old tests.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">if
the interface has many methods but you need only a few of them, the anonymous
class still have to implement each method. So it's quite messy and doesn't
help to read the code.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">sure
your IDE will generate the anonymous class with all methods with one keystroke.
But if you want to make explicit which method is used in the test than you have
to rewrite all unnecessary methods to something like this: <i>throw new
RuntimeException("not implemented")</i>. Because otherwise you can't
decide if the test relies on the method to return null or it's not used for the
test.</span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">the
code navigation in the IDE (at least IntelliJ) gets messed up because of the anonymous
test classes. If you want to jump to the method implementation of an interface
and there is one class implementing the interface than IntelliJ will jump
directly to the correct code (ctrl+shift+b). But if in the test classes the
anonymous mock classes are defined than IntelliJ will show you all anonymous
classes which are in this case completely uninteresting. </span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">mocks
are cleaner to write. if you want different return values by different
parameters than you just define them in two lines. In an anonymous class you
have to use if/else. </span></li>
<li><span lang="EN-US" style="mso-ansi-language: EN-US;">mocks
are more powerful. You can verify if the methods got called with the right
parameters and are called exactly x times. </span></li>
</ul>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">There is
just one downside of mock frameworks: you have to learn one of them. </span></div>
<div class="MsoNormal">
<span lang="EN-US" style="mso-ansi-language: EN-US;">It pays off
to learn a mock framework and to use it because of all the benefits you get
from it (see above). I am currently using Mockito which has a very easy and clean API.</span></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6859255045766041591.post-41378132514869202382013-05-14T00:28:00.002-07:002013-05-14T00:49:26.629-07:00Tutorial: how to setup a torrent-box (torrent-tracker + seeding client) on a Raspberry Pi<style>.code { margin: 0 20px 0 20px; border: 1px solid silver; background-color: #EEE; border-radius:3px; padding: 5px }</style>
<br />
<h2>
Motivation</h2>
Most people use Dropbox and other cloud services to share their files. But if you want to be in control of your files - without any restrictions - than you need to setup your own share server. The simplest way to do so is to setup a FTP or HTTP server. I didn't want to use a FTP because the person you want to share your files with has first to setup the connection - too much work. Another problem with both options is that they don't handle a connection lost very well. So I decided to use a torrent network.<br />
<ul>
<li>it can handles a connection lost very well</li>
<li>the peers will upload too (important if you share you files with many people)</li>
<li>easy to use: just send a magnet link or a torrent file</li>
</ul>
<br />
<h2>
Setup a Torrent Tracker - opentracker</h2>
At first we setup our own torrent tracker using <a href="http://erdgeist.org/arts/software/opentracker/">opentracker</a>.<br />
<br />
<div class="code">
<code>
sudo apt-get install cvs<br />
cvs -d :pserver:cvs@cvs.fefe.de:/cvs -z9 co libowfat<br />
cd libowfat<br />
make<br />
cd ..<br />
cvs -d:pserver:anoncvs@cvs.erdgeist.org:/home/cvsroot co opentracker<br />
cd opentracker<br />
make<br />
chmod a+x opentracker
</code></div>
<br />
That's it. Just start the torrent tracker<br />
<br />
<div class="code">
<code>
./opentracker
</code></div>
<br />
<br />
<h2>
Setup a Torrent Client - rtorrent</h2>
The tracker connects the peers with each other but it doesn't seed (upload) anything. So we need a torrent client which will seed our shared files. Get the program<br />
<br />
<div class="code">
<code>
sudo apt-get install rtorrent
</code></div>
<br />
Configure rtorrent<br />
<br />
<div class="code">
<code>
wget http://libtorrent.rakshasa.no/export/1303/trunk/rtorrent/doc/rtorrent.rc<br />
mv rtorrent.rc ~/.rtorrent.rc<br />
nano ~/.rtorrent.rc
</code></div>
<br />
The most important configuration settings<br />
<br />
<div class="code">
<code>
# sure use udp <br />
use_udp_trackers = yes<br />
# encryption is always a good idea<br />
encryption = require<br />
# change it so it doesn't conflict with our torrent tracker which uses the port 6969<br />
port_range = 6890-6960 <br />
# where the files are saved<br />
directory = ~/downloads/torrents/ <br />
# load automatically all torrent files from the directory and start downloading or seeding<br />
schedule = watch_directory,5,5,load_start=/var/www/torrents/*.torrent<br />
# if the torrent files are removed stop downloading or seeding<br />
schedule = untied_directory,5,5,stop_untied=
</code></div>
<br />
Now you could start rtorrent and start downloading torrents.<br />
<br />
<br />
<h2>
Create a Torrent File - mktorrent</h2>
Now we need to create a torrent for the files we want to share.<br />
<br />
<div class="code">
<code>
sudo apt-get install mktorrent <br />
mktorrent -p -a http://${YOUR_IP_OR_DOMAIN}:6969/announce -a udp://${YOUR_IP_OR_DOMAIN}:6969/announce FILE_OR_DIRECTORY -o OUTPUT_FILE.torrent<br />
</code></div>
<br />
That's it. Put the torrent file in you torrent watch directory and start rtorrent. Rtorrent will read the file and start seeding. Don't forget the source file must be in the right directory (see the rtorrent setting directory=).<br />
<br />
<br />
<h2>
Setup your router and start sharing</h2>
You probably need to setup a port forwarding to your Raspberry Pi for the necessary ports.<br />
Then you can start sharing your files in your own private torrent network :)<br />
<h2>
<br />
<br />
<br />
Further reading</h2>
<a href="http://reinhard-seiler.blogspot.co.at/2013/05/tutorial-how-to-automatically-start.html">How to automatically start opentracker and rtorrent</a><br />
<a href="http://reinhard-seiler.blogspot.co.at/2013/05/tutorial-how-to-generate-magnetic-link.html">How to generate a magnetic link form a torrent file (convert torrent file to magnetic link)</a>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-6859255045766041591.post-13344307971041894392013-05-14T00:27:00.003-07:002013-05-17T23:36:54.542-07:00Tutorial: How to automatically start opentracker and rtorrent on a Raspberry Pi<style>.code { margin: 0 20px 0 20px; border: 1px solid silver; background-color: #EEE; border-radius:3px; padding: 5px }</style>
<br />
<h2>
Motivation</h2>
In my <a href="http://reinhard-seiler.blogspot.co.at/2013/05/tutorial-how-to-setup-torrent-box.html">last post</a> I explained how to setup a torrent-box on a Raspberry Pi. But there is still one important thing to do: automatically start <a href="http://erdgeist.org/arts/software/opentracker/">opentracker</a> and <a href="http://libtorrent.rakshasa.no/">rtorrent </a>so you needn't to do it yourself after each reboot. It's not that easy because rtorrent can't be started as deamon and you probably want to be able to get the background rtorrent process so you can change the setting (e.g. limit the upload speed). To solve this problem I used tmux.<br />
<br />
<h2>
Setup the autostart </h2>
<br />
The first thing is to put the opentracker executable into the <code class="code">/usr/bin</code><br />
Then install tmux<br />
<br />
<div class="code">
<code>
sudo apt-get install tmux
</code></div>
<br />
Now we have to write our init.d script which will be called at the startup<br />
<br />
<div class="code">
<code>
sudo nano /etc/init.d/torrent
</code></div>
<br />
With this content<br />
<br />
<div class="code">
<code>
# !/bin/sh<br /># /etc/init.d/torrent<br /><br />BIN="/usr/bin"<br /><br />case "$1" in<br /> start)<br /> echo "Starting torrent"<br /> start-stop-daemon --start --background --chuid=pi --exec $BIN/opentracker<br /> start-stop-daemon --start --background --chuid=pi --exec $BIN/tmux -- new-session -d -n rtorrent -s rtorrent rtorrent<br /> ;;<br /> stop)<br /> echo "Stopping torrent"<br /> killall opentracker<br /> killall rtorrent<br /> ;;<br /> *)<br /> echo "Usage: /etc/init.d/torrent {start|stop}:"<br /> exit 1<br /> ;;<br />esac<br /><br />exit 0
</code></div>
<br />
Make the file executable and embed it into the starting process<br />
<br />
<div class="code">
<code>
sudo chmod 755 /etc/init.d/torrent.sh<br />
sudo update-rc.d torrent.sh defaults<br />
</code></div>
<br />
Basically that's it.<br />
<br />
<h2>
tmux</h2>
To get your running rtorrent process write<br />
<br />
<div class="code">
<code>
tmux attach
</code></div>
<br />
To put it back into the background press ctrl+b and then press d (for deattch).<br />
<br />
<a href="http://www.dayid.org/os/notes/tm.html">tmux cheat cheet</a>.Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-6859255045766041591.post-73031568613862930242013-05-14T00:27:00.002-07:002013-05-14T00:51:52.812-07:00Tutorial: How to generate a magnet link form a torrent file (convert torrent file to magnetic link)<style>.code { margin: 0 20px 0 20px; border: 1px solid silver; background-color: #EEE; border-radius:3px; padding: 5px }</style>
<h2>
Motivation</h2>
It's easier to send just a link instead of a file if you want to share a torrent file. <br />
<br />
<h2>
Create the magic link</h2>
To create the magic link I used the <a href="https://pypi.python.org/pypi/bencode/1.0">bencode</a> library (python). To easily install it we need first easy_install. The first thing to to is to install <a href="https://pypi.python.org/pypi/setuptools#downloads">easy_install</a><br />
<br />
<div class="code">
<code>
wget http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg#md5=fe1f997bc722265116870bc7919059ea<br />
sudo chmod 755 setuptools-0.6c11-py2.7.egg<br />
sudo ./setuptools-0.6c11-py2.7.egg
</code></div>
<br />
Now it's very simple to install bencode<br />
<br />
<div class="code">
<code>
easy_install http://pypi.python.org/packages/2.7/b/bencode/bencode-1.0-py2.7.egg#md5=fa08025585d4cd7700bed503b6baf018
</code></div>
<br />
That's your preconditions. Now we can write our python script which will generate the magnic link.<br />
<br />
<div class="code">
<code>
nano createMagnetLink.py
</code></div>
<br />
Put following content into it<br />
<br />
<div class="code">
<code>
!/usr/bin/python<br /><br />import sys<br />import urllib<br />import bencode<br />import hashlib<br />import base64<br /><br />if len(sys.argv) == 0:<br />print("Usage: file")<br />exit()<br /><br />torrent = open(sys.argv[1], 'r').read()<br />metadata = bencode.bdecode(torrent)<br /><br />hashcontents = bencode.bencode(metadata['info'])<br />digest = hashlib.sha1(hashcontents).digest()<br />b32hash = base64.b32encode(digest)<br /><br />params = {'xt': 'urn:btih:%s' % b32hash,<br />'dn': metadata['info']['name']}<br /><br />announcestr = ''<br />for announce in metadata['announce-list']:<br />announcestr += '&' + urllib.urlencode({'tr':announce[0]})<br /><br />paramstr = urllib.urlencode(params) + announcestr<br />magneturi = 'magnet:?%s' % paramstr<br /><br />print(magneturi)
</code></div>
<br />
Make the file executable<br />
<br />
<div class="code">
<code>
sudo nano 755 createMagnetLink.py
</code></div>
<br />
And the just call it with a torrent file<br />
<br />
<div class="code">
<code>
./createMagnetLink.py file.torrent
</code></div>
<br />Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6859255045766041591.post-22657554801362926242013-05-11T08:56:00.000-07:002013-05-14T00:52:31.951-07:00Tutorial: How to install a Tiny Tiny RSS (tt-rss) server on a Raspberry Pi (nginx, php, mysql)<style>.code { margin: 0 20px 0 20px; border: 1px solid silver; background-color: #EEE; border-radius:3px; padding: 5px }</style>
<br />
<h3>
Motivation</h3>
I love the Google Reader (RSS reader) very much and I used it heavily. But sadly Google decided to shutdown this great service. So it was time to look for an alternative and I found <a href="http://tt-rss.org/">Tiny Tiny RSS</a> (tt-rss). It's an open source RSS reader written in PHP. It's quite nice but there is one big issue: the website (JavaScript) is slow. It's impossible to use it on a smartphone. But there are Android apps for tt-rss which are quite nice.<br />
<br />
<h3>
Install & configure nginx, php & mysql-server</h3>
<ul>
<li>get all the packages </li>
</ul>
<div class="code">
<code>
sudo apt-get update<br />
sudo apt-get install nginx php5-fpm php5-cli php5-curl php5-gd php5-mcrypt php5-mysql php5-cgi mysql-server<br />
</code></div>
<ul>
<li> create the web directory</li>
</ul>
<div class="code">
<code>
sudo mkdir /var/www<br />
sudo chown www-data:www-data /var/www/<br />
</code></div>
<ul>
<li> configure nginx</li>
<ul>
<li>open the config file</li>
</ul>
</ul>
<div class="code">
<code>
sudo nano /etc/nginx/sites-enabled/default <br />
</code></div>
<ul><ul>
<li>modify it so it looks like this</li>
</ul>
</ul>
<div class="code">
<code>
server {<br />
listen 80;
<br />
root /var/www;<br />
index index.html index.htm index.php;<br />
<br />
server_name localhost;<br />
<br />
location / {<br />
try_files $uri $uri/ /index.html;<br />
}<br />
<br />
location ~ \.php$ {<br />
fastcgi_pass unix:/var/run/php5-fpm.sock;<br />
fastcgi_index index.php;<br />
include fastcgi_params;<br />
}<br />
} <br />
</code></div>
<ul>
<li> configure php-fpm</li>
<ul>
<li>open the php.ini</li>
</ul>
</ul>
<div class="code">
<code>
sudo nano /etc/php5/fpm/php.ini <br />
</code></div>
<ul><ul><ul>
<li>set: <i class="code">cgi.fix_pathinfo = 0;</i></li>
</ul>
<li>open the www.conf</li>
</ul>
</ul>
<div class="code">
<code>
sudo nano /etc/php5/fpm/pool.d/www.conf <br />
</code></div>
<ul><ul><ul>
<li> set: <i class="code">listen = /var/run/php5-fpm.sock</i></li>
</ul>
</ul>
<li>restart nginx and php-fpm</li>
</ul>
<div class="code">
<code>
sudo service php5-fpm restart<br />
sudo service nginx restart<br />
</code></div>
<ul>
<li>create the mysql database for tt-rss</li>
</ul>
<div class="code">
<code>
mysql -u root -p <br />
</code></div>
<ul><ul>
<li>insert the password and execute those two commands </li>
</ul>
</ul>
<div class="code">
<code>
create database ttrss;<br />
exit</code></div>
<h3>
</h3>
<h3>
Install Tiny Tiny RSS (tt-rss)</h3>
It's quite simple. Just grab the .tar.gz file, unpack it move it to the web directory and set the permissions. It's done like this. But you probably want to check if there is a newer version.<br />
<br />
<div class="code">
<code>
wget https://github.com/gothfox/Tiny-Tiny-RSS/archive/1.7.8.tar.gz<br />
tar zxfv 1.7.8.tar.gz<br />
mv Tiny-Tiny-RSS-1.7.8/ ttrss<br />
sudo mv ttrss /var/www<br />
cd /var/www/ttrss<br />
chmod -R 777 cache/images && chmod -R 777 cache/export && chmod -R 777 cache/js && chmod -R 777 feed-icons && chmod -R 777 lock<br />
</code></div>
<br />
<br />
<h4>
Perform the tt-rss installation</h4>
<a href="http://localhost/ttrss/install">http://localhost/ttrss/install</a><br />
<br />
<h4>
Setup the crontab</h4>
<ul>
<li>Open the crontab</li>
</ul>
<div class="code">
<code>
crontab -e </code></div>
<ul><ul>
<li>Insert following line<br />
</li>
</ul>
</ul>
<div class="code">
<code>
*/15 * * * * cd /var/www/ttrss && /usr/bin/php update.php --feeds --quiet > /dev/null <br />
</code></div>
<br />
With this setup the Raspberry Pi will load every 15 minutes the RSS feeds and update them so you can read them.<br />
<br />
<h3>
Enjoy your Tiny Tiny RSS (tt-rss) installation</h3>
That's it. Now you can open your installation, configure it and read your feeds. Have fun! :)<br />
<br />Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-6859255045766041591.post-65731041354894248442012-09-22T09:45:00.000-07:002016-01-17T13:52:21.002-08:00Truecrypt benchmark for Raspberry Pi with Turbo<a href="http://www.raspberrypi.org/archives/2008">Introducing turbo mode: up to 50% more performance for free</a>. This benchmark was run on raspbian/wheezy with the overclock setting "Turbo". The buffer size was was 5MB. With turbo truecrypt is about 60% faster than <a href="http://reinhard-seiler.blogspot.co.at/2012/07/truecrypt-benchmark-for-raspberry-pi.html">without</a>.<br />
<br />
<br />
<table>
<tbody>
<tr>
<th>Algorithm</th>
<th>Encrypt</th>
<th>Decrypt</th>
<th>Mean</th>
</tr>
<tr>
<td>Twofish </td>
<td>14</td>
<td>12</td>
<td>13</td>
</tr>
<tr>
<td>Serpent </td>
<td>10</td>
<td>10</td>
<td>10</td>
</tr>
<tr>
<td>AES</td>
<td>7</td>
<td>5.3</td>
<td>6.1</td>
</tr>
<tr>
<td>Twofish-Serpent</td>
<td>5.9</td>
<td>5.5</td>
<td>5.7</td>
</tr>
<tr>
<td>Serpant-AES</td>
<td>4.1</td>
<td>4.0</td>
<td>4.1</td>
</tr>
<tr>
<td>AES-Twofish</td>
<td>4.6</td>
<td>4.2</td>
<td>4.4</td>
</tr>
<tr>
<td>Serpant-Twofish-AES</td>
<td>3.2</td>
<td>3.0</td>
<td>3.1</td>
</tr>
<tr>
<td>AES-Twofish-Serpent</td>
<td>3.2</td>
<td>3.0</td>
<td>3.1</td>
</tr>
</tbody></table>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6859255045766041591.post-16447931539315083412012-09-12T04:16:00.000-07:002013-05-14T00:52:44.236-07:00Java SimpleArchive with RandomAccessFile I had a quite simple problem. I want to read several hundred thumbnail images (movie posters) to display them in a Java program.<br />
<br />
<b>File system </b><br />
The simplest approach is to save the images directly in the file system. It's working fine if all images are cached from the OS. But if not it takes several seconds to load all images. Another downside is that most of the files have a size of 6kb - 7kb (in a range of 3kb - 10kb). So you loose some space because the block size is usually 4kb. In my case it was about 25%.<br />
<br />
<b>Zip</b> <br />
The next idea was to save all images in a Zip archive. The standard Java library supports Zip archives <a href="http://docs.oracle.com/javase/7/docs/api/java/util/zip/ZipEntry.html">directly</a>. It looked very promising. It was quite easy to use and it worked fine. But there is one big problem. It's not possible to add files to an existing archive. You had always to recreate the complete file. It's no problem if the archive is small but if it gets bigger than this could consume quite a long time. I looked for other libraries and archive formats. But it seemed that there is no easy to use archive library which supported to add files to an existing archive. So I wrote my own very simple archive library with the RandomAccessFile API.<br />
<br />
<b>SimpleArchive</b> (<a href="https://github.com/rseiler/SimpleArchive">github</a>)<br />
It's very simple and very fast. It can add files to an existing archive without the need to recreate the file. It just adds the file(s) and rewrite the file index which is located at the end of the file. So it will be much faster by adding files to an archive than the Zip implementation. In a very basic test it read the files ~3 times faster than the the Zip implementation. If you want to know more about it just visit the <a href="https://github.com/rseiler/SimpleArchive">github</a>.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-6859255045766041591.post-8003356665910765812012-07-20T06:04:00.001-07:002016-01-17T13:52:11.871-08:00Truecrypt benchmark for Raspberry PiThis benchmark was run on raspbian/wheezy. So it's used the armhf architecture. The buffer size was was 5MB. Checkout the truecrypt benchmark with the new <a href="http://reinhard-seiler.blogspot.co.at/2012/09/truecrypt-benchmark-for-raspberry-pi.html">turbo overclock</a> setting.<br />
<br />
<br />
<table>
<tbody>
<tr>
<th>Algorithm</th>
<th>Encrypt</th>
<th>Decrypt</th>
<th>Mean</th>
</tr>
<tr>
<td>Twofish </td>
<td>8.9</td>
<td>7.7</td>
<td>8.3</td>
</tr>
<tr>
<td>Serpent </td>
<td>6.8</td>
<td>6.9</td>
<td>6.9</td>
</tr>
<tr>
<td>AES</td>
<td>4.4</td>
<td>3.7</td>
<td>4.1</td>
</tr>
<tr>
<td>Twofish-Serpent</td>
<td>3.9</td>
<td>3.7</td>
<td>3.8</td>
</tr>
<tr>
<td>Serpant-AES</td>
<td>2.7</td>
<td>2.4</td>
<td>2.5</td>
</tr>
<tr>
<td>AES-Twofish</td>
<td>1.9</td>
<td>2.4</td>
<td>2.1</td>
</tr>
<tr>
<td>Serpant-Twofish-AES</td>
<td>2.1</td>
<td>1.8</td>
<td>2.0</td>
</tr>
<tr>
<td>AES-Twofish-Serpent</td>
<td>2.0</td>
<td>1.8</td>
<td>1.9</td>
</tr>
</tbody></table>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-6859255045766041591.post-56687951780377044552012-07-20T05:52:00.000-07:002016-01-17T13:51:48.761-08:00Truecrypt armhf executable for Raspberry Pi (raspbian/wheezy)Because Truecrypt it's a bit of a work and takes so long to compile I uploaded the <a href="https://skydrive.live.com/redir?resid=9042B08E4B64499C!2213&authkey=!AIpkJN9fI3yRzJc2213&authkey=!AIpkJN9fI3yRzJc">compiled binary file</a>Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-6859255045766041591.post-34693256726070407382012-07-20T03:50:00.001-07:002016-01-17T13:51:58.423-08:00Compile Truecrypt on Raspberry PiI wanted to run Truecrypt on my Raspberry Pi. But there is no precompiled package which you could simply install with apt-get. So you have to compile it yourself - which take a few hours. If you just want the truecrypt binary for Raspbian/Wheezy then you can download them <a href="http://reinhard-seiler.blogspot.co.at/2012/07/truecrypt-armhf-executable-for.html">here</a>. <br />
The first thing you need to do is to get all needed dependencies. Thereby you have to compile one dependency yourself. We start with this dependency.<br />
<br />
<br />
<b>How to compile wxWidgets</b><br />
First download the source code: <a href="http://www.wxwidgets.org/downloads/#latest_stable">http://www.wxwidgets.org/downloads/#latest_stable</a> I used wxAll 2.8.11. Unpack it, go into the directory and execute these commands.<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">sudo apt-get install libgtk2.0-dev</span><br />
<span style="font-family: "Courier New",Courier,monospace;">./configure</span><br />
<span style="font-family: "Courier New",Courier,monospace;">make</span></blockquote>
<br />
<b>How to setup PKCS11</b><br />
Truecrypt needs three header files (pkcs11.h, pkcs11f.h, pkcs11t.h) which you can download from this location: <a href="ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v211/">ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v211/</a><br />
Put them into a directory and then set the PKCS11_INC variable.<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">export PKCS11_INC=/home/pi/pkcs11</span></blockquote>
<br />
<b>How to compile Truecrypt</b><br />
First download the source code: <a href="http://www.truecrypt.org/downloads2">http://www.truecrypt.org/downloads2</a> I used 7.1a. Unpack it, go into the unpacked directory and execute these commands.<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">sudo apt-get install libfuse-dev nasm libwxgtk2.8-dev</span><br />
<span style="font-family: "Courier New",Courier,monospace;">make WX_ROOT=/home/pi/wxWidgets/ wxbuild</span><br />
<span style="font-family: "Courier New",Courier,monospace;">make WXSTATIC=1</span></blockquote>
<br />
There will be this warning<br />
<blockquote class="tr_bq">
<span style="font-family: Arial,Helvetica,sans-serif;">configure: WARNING: libSM not found; disabling session management detection</span></blockquote>
sadly I couldn't figure out how to fix it. But Truecrypt will work anyway.<br />
<br />
<br />
If you get this error message<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">In file included from Keyfile.cpp:10:0:</span><br />
<span style="font-family: "Courier New",Courier,monospace;">.../SecurityToken.h:43:21: fatal error: pkcs11.h: No such file or directory</span></blockquote>
then the PKCS11_INC variable isn't set correctly or you forgot to put the header files in the directory.<br />
<br />
<br />
Now you can use Truecrypt. The executable file will be created in Main/truecrypt. To mount a truecrypt volume just use<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">./truecrypt /path/to/truecrypt-volume /path/to/mount-point </span></blockquote>
or you can just execute ./truecrypt and use the graphical <span class="short_text" id="result_box" lang="en"><span class="hps atn">surface.</span></span>Unknownnoreply@blogger.com2