<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>AspectWorks &#187; Java</title>
	<atom:link href="http://www.aspectworks.com/category/java/feed" rel="self" type="application/rss+xml" />
	<link>http://www.aspectworks.com</link>
	<description>Vyvíjíme chytré webové aplikace pro střední a velké podniky</description>
	<lastBuildDate>Thu, 26 Jan 2012 14:25:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>Synchronizace scheduleru v clusteru</title>
		<link>http://www.aspectworks.com/2012/01/synchronizace-scheduleru-v-clusteru</link>
		<comments>http://www.aspectworks.com/2012/01/synchronizace-scheduleru-v-clusteru#comments</comments>
		<pubDate>Thu, 26 Jan 2012 13:48:48 +0000</pubDate>
		<dc:creator>Tomáš Holý</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=3123</guid>
		<description><![CDATA[Na našem projektu Starthead jsme potřebovali implementovat automatické provádění úkolu určeného ke zpracovávání dat v databázi. Ve frameworku Spring, který je pro vývoj použit, je tato úloha jednoduše řešitelná například<a href="http://www.aspectworks.com/2012/01/synchronizace-scheduleru-v-clusteru" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Na našem projektu <a href="http://www.starthead.com" title="Starthead">Starthead</a> jsme potřebovali implementovat automatické provádění úkolu určeného ke zpracovávání dat v databázi. Ve frameworku Spring, který je pro vývoj použit, je tato úloha jednoduše řešitelná například pomocí <a title="TaskScheduler" href="http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/scheduling/TaskScheduler.html">TaskScheduler</a>.<br />
Zajímavější situace nastává, pokud má aplikace bežet v clusterovém řešení. To znamená, že je potřeba řešit synchronizaci, aby nedocházelo k vícenásobnému spouštění jobů ve stejný čas. Snažili jsme se najít co nejjednodužší řešení, které by splňovalo danou podmínku a tím se v našem případě ukázalo využití Quartz scheduleru s patřičnou clusterovou konfigurací a synchronizováním pomocí ukládání do databáze.<span id="more-3123"></span><br />
Zde je uveden jednoduchý příklad vytvoření takového úkolu a jeho konfigurace ve Spring frameworku.</p>
<p><strong>Implementace jednoduchého jobu</strong></p>
<pre class="brush: java; title: ; notranslate">
package com.aspectworks;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.StatefulJob;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class TestJob extends QuartzJobBean implements StatefulJob {
	private TestService testService;
	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		//implementace úkolu
	}
	public void setTestService(TestService testService) {
		this.testService = testService;
	}
}
</pre>
<p><strong>Definice triggeru úkolu pomocí Cron definice</strong></p>
<pre class="brush: xml; title: ; notranslate">
&lt;bean id=&quot;testTrigger&quot; class=&quot;org.springframework.scheduling.quartz.CronTriggerBean&quot;&gt;
	&lt;property name=&quot;jobDetail&quot;&gt;
		&lt;bean class=&quot;org.springframework.scheduling.quartz.JobDetailBean&quot;&gt;
			&lt;property name=&quot;jobClass&quot; value=&quot;com.aspectworks.TestJob&quot; /&gt;
			&lt;property name=&quot;name&quot; value=&quot;TestJob&quot; /&gt;
		&lt;/bean&gt;
	&lt;/property&gt;
	&lt;property name=&quot;jobDataAsMap&quot;&gt;
		&lt;map&gt;
			&lt;entry key=&quot;testAttribute&quot; value=&quot;value &quot; /&gt;
		&lt;/map&gt;
	&lt;/property&gt;
	&lt;property name=&quot;cronExpression&quot; value=&quot;1 * * * * ?&quot; /&gt;
&lt;/bean&gt;
</pre>
<p><strong>Konfigurace scheduleru pro clusterové řešení</strong></p>
<pre class="brush: xml; title: ; notranslate">&lt;bean class=&quot;org.springframework.scheduling.quartz.SchedulerFactoryBean&quot;&gt;
&lt;property name=&quot;waitForJobsToCompleteOnShutdown&quot; value=&quot;true&quot; /&gt;
	&lt;property name=&quot;dataSource&quot; ref=&quot;dataSource&quot; /&gt;
	&lt;property name=&quot;overwriteExistingJobs&quot; value=&quot;true&quot; /&gt;
	&lt;property name=&quot;autoStartup&quot; value=&quot;true&quot; /&gt;
	&lt;property name=&quot;triggers&quot;&gt;
		&lt;list&gt;
			&lt;ref bean=&quot;testTrigger&quot; /&gt;
		&lt;/list&gt;
	&lt;/property&gt;
	&lt;property name=&quot;quartzProperties&quot;&gt;
		&lt;props&gt;
			&lt;prop key=&quot;org.quartz.scheduler.instanceName&quot;&gt;TestScheduler&lt;/prop&gt;
			&lt;prop key=&quot;org.quartz.scheduler.instanceId&quot;&gt;AUTO&lt;/prop&gt;
			&lt;prop key=&quot;org.quartz.jobStore.misfireThreshold&quot;&gt;60000&lt;/prop&gt;
			&lt;prop key=&quot;org.quartz.jobStore.class&quot;&gt;org.quartz.impl.jdbcjobstore.JobStoreTX&lt;/prop&gt;
			&lt;prop key=&quot;org.quartz.jobStore.driverDelegateClass&quot;&gt;org.quartz.impl.jdbcjobstore.StdJDBCDelegate&lt;/prop&gt;
			&lt;prop key=&quot;org.quartz.jobStore.tablePrefix&quot;&gt;QRTZ_&lt;/prop&gt;
			&lt;prop key=&quot;org.quartz.jobStore.isClustered&quot;&gt;true&lt;/prop&gt;
			&lt;prop key=&quot;org.quartz.threadPool.class&quot;&gt;org.quartz.simpl.SimpleThreadPool&lt;/prop&gt;
			&lt;prop key=&quot;org.quartz.threadPool.threadCount&quot;&gt;25&lt;/prop&gt;
			&lt;prop key=&quot;org.quartz.threadPool.threadPriority&quot;&gt;5&lt;/prop&gt;
		&lt;/props&gt;
	&lt;/property&gt;
	&lt;property name=&quot;schedulerContextAsMap&quot;&gt;
		&lt;map&gt;
			&lt;entry key=&quot;testService&quot; value-ref=&quot;testService&quot; /&gt;
		&lt;/map&gt;
	&lt;/property&gt;
&lt;/bean&gt;</pre>
<p>V dané konfiguraci je důležité nastavení atributů obsahujících <em>org.quartz.jobStore</em> a <em>org.quartz.impl.jdbcjobstore</em>. Ty říkají, že úkoly poběží v clusteru, a že se má provést jejich ukládání do tabulek s prefixem QRTZ_. Toto nastavení nám samo zajistí, že po inicializaci se úkol uloží do databáze s příslušnými parametry a ve chvíli vykonávání úkolu smí pouze jeden stroj v clusteru provést jeho spuštění. Právo na vykonání úkolu dostane první z běžících strojů v clusteru, který o to požádá.</p>
<p><strong>Vysvětlení nejdůležitějších atributů:</strong><br />
<strong>org.quartz.jobStore.isClustered</strong> – definování běhu úkolu v clusteru<br />
<strong>org.quartz.scheduler.instanceId</strong> – nastavení typu určování id instance (defaultně nastaveno na NON_CLUSTERED)<br />
<strong>org.quartz.jobStore.class</strong> – definování typu ukládání synchronizace úkolů (v našem případě definuje ukládání do databáze)<br />
<strong>org.quartz.jobStore.driverDelegateClass</strong> – definování driveru pro ukládání dat do databáze (v našem případě MySQL). Sql soubor pro založení tabulek můžete najít v adresáři doc v konkrétní verzi quartz implementace.<br />
<strong>org.quartz.jobStore.tablePrefix</strong> – nastavení prefixu Qartz tabulek pro ukládání synchronizace úkolů</p>
<p>Pokud se použije ukládání úkolů do databáze, ukládá se společně s JobDetailem i mapa jeho atributů jobDataAsMap. To znamená, že musí být možné je serializovat a také, že by to neměly být žádné objekty s aplikační logikou. Pokud je potřeba v úkolu využít nějakou service spravovanou Springem, je lepší ji předat do úkolu přes schedulerContextAsMap definovanou v SchedulerFactoryBeanu. Tento způsob uloží objekty do contextu Scheduleru a do úkolů je předá až při jejich inicializování, tedy bez nutnosti ukládání do databáze s ostatnímy atributy.</p>
<p>Více o Quartz schedulerech je možné najít na stránkách <a title="http://quartz-scheduler.org/overview" href="http://quartz-scheduler.org/overview">http://quartz-scheduler.org/overview</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2012/01/synchronizace-scheduleru-v-clusteru/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>IntelliJ Idea pro vývoj v Javě</title>
		<link>http://www.aspectworks.com/2011/12/intellij-idea-pro-vyvoj-v-jave</link>
		<comments>http://www.aspectworks.com/2011/12/intellij-idea-pro-vyvoj-v-jave#comments</comments>
		<pubDate>Wed, 14 Dec 2011 09:27:14 +0000</pubDate>
		<dc:creator>Jaroslav Kavalec</dc:creator>
				<category><![CDATA[Java]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=3048</guid>
		<description><![CDATA[Většina lidí si vývoj v Javě spojí s jedním ze dvou nejpoužívanějších IDE &#8211; Eclipse a Netbeans. Třetí, donedávna čistě komerční IDE je často neprávem přehlíženo. Před pár dny byla<a href="http://www.aspectworks.com/2011/12/intellij-idea-pro-vyvoj-v-jave" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Většina lidí si vývoj v Javě spojí s jedním ze dvou nejpoužívanějších IDE &#8211; Eclipse a Netbeans. Třetí, donedávna čistě komerční IDE je často neprávem přehlíženo. Před pár dny byla uvolněna nová verze IDE IntelliJ Idea s číslem 11. IntelliJ Idea (dále jen Idea), je vyvíjena firmou Jet Brains, která se zaměřuje na vývoj špičkových vývojových nástrojů pro různé programovací jazyky, mimo jiné IDE pro Ruby, Python nebo Objective C. V článku se budu snažit shrnout věci, které jsem si oblíbil a chybí nebo jsou v horším provedení u konkurence (především Eclipse).<span id="more-3048"></span></p>
<p>Idea je dodávána ve dvou edicích &#8211; Ultimate a Comunity, která je k dispozici zdarma. Comunity edici chybí pluginy na vývoj Java enterprise aplikací postavených na Springu, Hibernate, JPA, EJB, GWT a další a proto se v článku budu zabývat Ultimate edicí.</p>
<h2>Enterprise vývoj</h2>
<p>Idea má ve své Ultimate edici bohatou sadu pluginů podporujíchích vývoj enterprise aplikací běžících na široké škále aplikačních serverů, využívajících mnoho frameworků. Pojďme si tedy pžiblížit nějaké nástroje, kterí nám dá IDE k dispozici.</p>
<h3>Spring a Hibernate</h3>
<p>Idea si velmi dobře rozumí se Springem. Dokáže si sestavit model celé aplikace, vygenerovat diagram závislostí jednotlivých beanů, a jednotlive chyby, které se třeba v Eclipse zjistí až v runtime, se projeví okamžitě při psaní chybného kódu. Toto funguje jak s autowiringem, tak se Spring AOP. Dále je k dispozici mnoho dalších pomůcek jako generování kódu, podpora pro snadnou editaci xml konfuguračních souborů nebo snadný import beanů přímo do testů, nebo vygenerování diagramu který přehledně zobrazí závislosti jednotlivých beanů nakonfigurovaných Spring kontejnerem.</p>
<p><a href="http://www.aspectworks.com/wp-content/uploads/2011/12/IMG1.png" rel="lightbox[3048]"><img class="aligncenter size-large wp-image-3049" title="Intellij Idea" src="http://www.aspectworks.com/wp-content/uploads/2011/12/IMG1-1024x654.png" alt="" width="640" height="408" /></a></p>
<p>Třída je na outline editoru oanotována ikonkou značící, že se jedná o komponentu, při kliku na ikonu je možné se přesunout do konfiguračního xml souboru s deklarací komponenty. Další anotace značí komponenty, které jsou autowirovány Spring kontejnerem do komponenty. U komponenty TwitterServiceImpl byla odebrána anotace @Service, takže není registrována v kontejneru a je na první pohled vidět že něco není v pořádku, jelikož chybí ikona.</p>
<p>Podpora Hibernate a JPA je také na velmi vysoké úrovni. Idea opět sestaví model doménových tříd v aplikaci, dokáže z něj vygenerovat i ER diagram, s modelem jde dále pracovat. Velmi užitečné je, že má Idea podporu pro editaci Hibernate i JPA dotazů přímo v Java kódu, takže se jakákoli chyba v dotazech projevuje okamžitě a také je možné využít autocompletition jak pro jednotlivé entity tak pro různé funkce dotazovacího jazyka.</p>
<h3>Properties a lokalizace</h3>
<p>Velmi příjemná je práce s lokalizavanými zprávami a properties soubory obecně. Lokalizované zprávy mají speciální editor, v němž se všechny zprávy zobrazí pro editaci současně, v případě že zapomenete překlad tak je položka s chybějícím textem zvýrazněna. Idea dokonce vyznačí varování v případě, že nějakou property nelze najít v property souborech aplikace, takže není nutné čekat než se taková chyba projeví v runtime.</p>
<p>Velmi dobrá věc kterou je možné využít je propisování properties přímo do Java kódu.</p>
<div id="attachment_3050" class="wp-caption aligncenter" style="width: 650px"><a href="http://www.aspectworks.com/wp-content/uploads/2011/12/IMG2.png" rel="lightbox[3048]"><img class="size-large wp-image-3050" title="Idea" src="http://www.aspectworks.com/wp-content/uploads/2011/12/IMG2-1024x640.png" alt="" width="640" height="400" /></a><p class="wp-caption-text">Pohled na nastavení IDE - panel s inspekcemi</p></div>
<h2>Vývoj webu</h2>
<p>IntelliJ si velmi dobře dokáže poradit s HTML a CSS, a také velmi dobře si rozumí s JavaScriptem a mnoha JS knihovnami. Výborná je například podpora jQuery, různých technologií z rodiny HTML5 či pokročilých možností CSS3 a to včetně vendor prefixů. Pro příznivce CSS pre-procesorů je tu v základu podpora LESS, SASS a SCSS. Dokonce se prodává i samostatná verze, určená jen pro vývoj webu, bez podpory Javy, což svědčí o tom, že tato funkčnost není jen navíc ale, že dokáže stát i sama o sobě. K dispozici je i velmi dobrý JavaScript debugger. Java programátoři jistě ocení pohodlnou práci s JSP stránkami.</p>
<h2>Editace textu</h2>
<p>Toto je oblast v které Idea vyniká. Idea nabízí mnoho detailů které když se sečtou, tak vytvoří velmi silný nástroj na editaci textu:</p>
<p>- Autocompletition &#8211; jedna z důležitých vlastností moderních IDE, Idea má velmi mnoho možností jak doplňovat text i podle částí slov, podle prvních písmen camel-case identifikátorů, a také jsou možnosti nabízeny podle kontextu, v němž se nachází právě editovaný kód, takže většinou je nejvhodnější možnost jako první.</p>
<p>- Navigace &#8211; ve větších projektech je určitě důležité se velmi rychle navigovat v textu i mezi soubory. Idea má nepřeberné množství různých metod navigace jako je hledaní souborů, tříd, nebo symbolů. přecházení mezi třídou a testem k ní náležícímu, mezi rozhraními a implementacemi, navigace v hierarchii&#8230;</p>
<p>- Oblíbené položky a skupiny oblíbených položek</p>
<p>- Inkrementální výběr textu kdy se s každým výběrem rozšíří vybraný text obecně ve formátu slovo-&gt;camelCase-&gt;identifikátor-&gt;výraz-&gt;blok kódu-&gt;metoda</p>
<p>- Rozeznání camel case</p>
<p>- Obalení vybraného textu párovým symbolem</p>
<p>- Velmi dobře zpracované šablony na vkládání často používaných výrazů (opravdu značné vylepšení proti Eclipse, podrobnějčí popis je nad rámec článku)</p>
<p>- XML editace &#8211; velmi dobře funguje a editování xml už není utrpení (tady srovnávám s Eclipsem), navíc je možné použít různé transformace dokumentu, a využít vylepšenou podporu pro editaci specifických XML jako například Spring konfigurace</p>
<p>- Kontrola slov slovníkem &#8211; v praxi velmi užitečná věc, okamžitě se tak odhalí překlepy jak v kódu, tak v komentářích, čímž se předejde zbytečným opravám v budoucnu</p>
<p>- Zalamování řádků, na první pohled nevýznamná ale v praxi velmi užitečná funkčnost, zalamovat je možné jak v editoru tak i v konzoli (konzole nabízí navíc folding a filtrování textu)</p>
<p>- navigace v souborech v kódu &#8211; Idea ví o všech souborech v projektu, když se třeba v kódu odkazujete na soubor, který neexistuje tak vás na to upozorní.</p>
<h2>Analýza kódu</h2>
<p>IDE obsahuje velmi kvalitní nástroj na analýzu kódu &#8211; k dispozici je velmi rozsáhlá knihovna inspekcí, které je možno vypnout a zapnout, dle potřeby týmu. IDE pak vyznačí podezřelý kód v outline editoru. Je tak možné být varován před kódem, který povede ke špatnému výkonu, mrtvým kódem, místům, která mají potenciál způsobit NullPointerException a mnoho dalších problémů.</p>
<h2>JavaDoc</h2>
<p>Idea si velmi dobře vede i v práci s JavaDocem, dokáže generovat kostry JavaDoců, hledat chyby v pravopisu, ale hlavně upozorní na chyby, které vzniknou obvykle když programátor změní kód, ale zapomene provést náležité změny i v JavaDocu. Je to velmi pohodlné, a hlavně kód vypadá mnohem profesionálněji.</p>
<h2>Refaktoring a transformace kódu</h2>
<p>Idea má k dispozici mnoho různých refaktoringů, které pomohou zvýšit kvalitu kódu, bez zbytečných komplikací.</p>
<p>Velmi zajímavou vlastností jsou tzv Intention actions. Jedná se o akce, které je možné spustit v určitém kontextu, na určitém kódu.</p>
<p>Díky tomu lze například v testech transformovat boolean výrazy do asercí, optimalizovat logické výrazy, nahradit kontrolní struktury za jiné, přesunout inicializátor stojící mimo konstruktor do konstruktoru, uzavřít nejbližší výraz po !if! do závorek a velmi velké množství dalších věcí. Navíc v případě, že je možné na kódu nějakou akci vykonat, tak Idea zobrazí náležitou ikonu.</p>
<div id="attachment_3052" class="wp-caption aligncenter" style="width: 650px"><a href="http://www.aspectworks.com/wp-content/uploads/2011/12/IMG3.png" rel="lightbox[3048]"><img class="size-large wp-image-3052" title="IMG3" src="http://www.aspectworks.com/wp-content/uploads/2011/12/IMG3-1024x640.png" alt="" width="640" height="400" /></a><p class="wp-caption-text">Vyznačení inspekcí, chyb v JavaDocu, také taby jsou značeny dle toho jedná-li se o test, nový či změněný soubor atd. V pravém panelu je naznačeno použití intention akce.</p></div>
<h2>Verzovací systémy a Maven</h2>
<p>Idea má konzistentní systém pro práci s různými verzovacími systémy, takže přecházet například mezi SVN a Gitem není žádný problém.</p>
<p>Změny, které se provádějí jsou strukturovány do change setů, které je možné v případě potřeby schovat (shelve changes). Celkově je práce verzovacími systémy velmi pohodlná a komfortní, velmi dobře je řešeno i mergování souborů s  pěkně vyřešenou grafickou navigací.</p>
<p>Velmi pěkně je řešeno načení změn přímo v outline editoru, včetně snadného vyvolání předchozích verzí.</p>
<p>IDE má velmi dobrou podporu Mavenu, rozjet nový projekt z pomu je hračka. Z Maven panelu lze spouštět jednotlivé Maven goals, prohlížet závislosti a pluginy. Je možné jednoduše přepnout spouštění testu toggle tlačítkem.</p>
<p>Groovy &#8211; nemám zkušenost, ale kolegové si chváli velmi dobrou podporu Groovy.</p>
<h2>Nevýhody</h2>
<p>Kromě ceny je snad jediná částečná nevýhoda oproti Eclipsu menší množství dostupných pluginů. Na druhou stranu, v základním balíku IntelliJ je jich obrovské množství a jsou bezproblémové &#8211; fungují tak jak mají, takže tato nevýhoda není tak vážná.</p>
<p>Mezi nejzajímavější pluginy patří:</p>
<p>- IdeaVim &#8211; přidává editoru mnoho funkcí velmi efektivního Vim editoru</p>
<p>- Scala plugin &#8211; jednoznačně nejlepší IDE pro Scalu</p>
<p>- Clojure plugin &#8211; platí to stejné co u Scala pluginu</p>
<p>Celkově je velmi těžké hledat na tomto IDE nějaké nevýhody. Tým JetBrains jde velmi tvrdě za vývojem nejlepších vývojových nástrojů, a i když Ultimate verze jejich Java IDE není zdarma jako ostatní velká Java IDE, určitě stojí za zamyšlení, je možné vyzkoušet Comunity edition, která je open-source a zdarma, a nebo Ultimate, u které je trial verze na 30 dní. Neznám nikoho kdo zkusil IntelliJ Ideu a poté se dobrovolně vrátil k Eclipse, je tu hromada malých detailů, které však dohromady přispívají k mnohem příjemnější práci, hlavě dokáže odhalit mnoho chyb, které se při práci s jinými nástroji projeví až při spuštění aplikace.</p>
<p>Do článku se všechny možnosti, které Idea přináší nevlezou, k dalšímu studování doporučuji navštívit stránky <a href="http://www.jetbrains.com/idea/">JetBrains</a>, k dispozici je kompletní seznam vlastností, mapy klávesových zkratek, množství video tutoriálů a dalších informací.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/12/intellij-idea-pro-vyvoj-v-jave/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Získávání dat z HTML stránek</title>
		<link>http://www.aspectworks.com/2011/10/ziskavani-dat-z-html-stranek</link>
		<comments>http://www.aspectworks.com/2011/10/ziskavani-dat-z-html-stranek#comments</comments>
		<pubDate>Thu, 27 Oct 2011 10:22:03 +0000</pubDate>
		<dc:creator>Milan milan.cecrdle</dc:creator>
				<category><![CDATA[Java]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=2713</guid>
		<description><![CDATA[Na jednom projektu jsme potřebovali získávat informace z HTML stránek a využili jsme knihovnu jSoup. Její jednoduché použití si ukážeme na příkladu získání jednotlivých popisů volných pozic ze stránek Aspectworks. Pomocí<a href="http://www.aspectworks.com/2011/10/ziskavani-dat-z-html-stranek" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Na jednom projektu jsme potřebovali získávat informace z HTML stránek a využili jsme knihovnu <a title="jSoup" href="http://jsoup.org">jSoup</a>. Její jednoduché použití si ukážeme na příkladu získání jednotlivých popisů volných pozic ze stránek <a title="AspectWorks" href="http://www.aspectworks.com/volne-pozice">Aspectworks</a>. Pomocí metody connect a get() získáme načtenou stránkou</p>
<pre class="brush: java; title: ; notranslate">Document doc = Jsoup.connect(&quot;http://www.aspectworks.com/volne-pozice&quot;).get();</pre>
<p><span id="more-2713"></span></p>
<p>Stránka obsahuje &#8222;ul&#8220; element s class = &#8222;subPages&#8220;, ve které jsou pod elementy &#8222;li&#8220; uloženy jednotlivé pozice. Pomocí metody select nad daným dokumentem najdeme odpovídající pozice a vypíšeme pozici a URL kde získáme detail pozice</p>
<pre class="brush: java; title: ; notranslate">
Elements positions=doc.select(&quot;ul.subPages li a&quot;);
for (Element elem:positions) {
   System.out.printf(&quot;Pozice=%s,URL=%s\n&quot;,elem.text(),elem.absUrl(&quot;href&quot;));
}</pre>
<p>K vyhledání cílových informací lze použít syntaxy jquery případně CSS selektorů, <a href="http://jsoup.org/cookbook/extracting-data/selector-syntax" title="Příklady jak použít selektory">detailní popis najdete zde</a>. Užitečné jsou dále metody text(), která vrátí vnitřní obsah elementu a dále absUrl, která vrátí absolutní URL, tak abychom jej mohli přímo použít na další volání. Samozřejmostí je také automické vyplnění parametru stránky a odeslání např. metodou post</p>
<pre class="brush: java; title: ; notranslate">
Jsoup.connect(URL).data(&quot;název parametru&quot;,&quot;hodnota&quot;).post();
</pre>
<p>Knihovna funguje velmi intuitivně a její použití bylo bezproblémové. Jediný nedostatek je zatím nemožnost nastavit proxy. Výhodou knihovny je také to, že má minimun závislostí a lze ji tedy použít např. při vývoji Android aplikací.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/10/ziskavani-dat-z-html-stranek/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JTA v integračních testech bez aplikačního serveru</title>
		<link>http://www.aspectworks.com/2011/10/jta-v-integracnich-testech-bez-aplikacniho-serveru</link>
		<comments>http://www.aspectworks.com/2011/10/jta-v-integracnich-testech-bez-aplikacniho-serveru#comments</comments>
		<pubDate>Wed, 12 Oct 2011 07:27:26 +0000</pubDate>
		<dc:creator>Milan milan.cecrdle</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=2740</guid>
		<description><![CDATA[JTA tedy distribuované transakce se dost často použivájí v enterprise systémech, kde je potřeba přistupovat jak k více databázím, tak třeba v kombinaci databáze a messaging systém (např. Websphere MQ).<a href="http://www.aspectworks.com/2011/10/jta-v-integracnich-testech-bez-aplikacniho-serveru" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>JTA tedy distribuované transakce se dost často použivájí v enterprise systémech, kde je potřeba přistupovat jak k více databázím, tak třeba v kombinaci databáze a messaging systém (např. Websphere MQ). Mezi vývojáři obecně panuje představa, že pro jeho využítí potřebuji aplikační server ala Jboss či Websphere, případně také, že bez EJB JTA nelze použít. Toto není samozřejmě pravda a např. pokud použijeme Spring, situace se nám ještě velmi zjednoduší. V příkladu si ukážeme jak nakonfigurovat transakční manager pro test, který otestuje jednu komponentu, ve které je logika přístupu k více XA zdrojům.<span id="more-2740"></span></p>
<p>Takto vypadá šablona spring integračního testu, který naloaduje aplikační kontexty, jeden s konfigurací aplikace a jeden s konfigurací testovacího JTA manageru.</p>
<pre class="brush: java; title: ; notranslate">
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {&quot;/applicationTestContext.xml&quot;, &quot;/applicationContext.xml&quot;})
@TestExecutionListeners({TransactionalTestExecutionListener.class})
@Transactional
public class JTASampleIntegrationTest extends AbstractJUnit4SpringContextTests {
  @Test
  public void testComponenet() {
  }
}
</pre>
<p>Existuje více implementací JTA, například <a href="http://www.atomikos.com/">Atomikos</a> nebo <a href="http://jotm.ow2.org/xwiki/bin/view/Main/WebHome">Jotm</a>. Pro testy jsem se rozhodl použít Jotm implementace a dále implementaci XA pool datasource z projektu <a href="http://xapool.ow2.org/">Enhydra XAPool</a>.</p>
<p>Prvni co musíme je definovat JTATransactionManagera. Tomu musíme specifikovat referenci na factory, která vytvoří JOTM objekt, který implementuje UserTransaction interface. Pro JOTM je již factory součastí springu. V případě běhu v aplikačním server už má JTATransactionManager implementován automatický lookup do JNDI pro konkrétní objekt a není třeba specifikovat nic.</p>
<pre class="brush: xml; title: ; notranslate">
	&lt;bean id=&quot;jotm&quot; class=&quot;org.springframework.transaction.jta.JotmFactoryBean&quot; /&gt;
	&lt;bean id=&quot;transactionManager&quot;
		class=&quot;org.springframework.transaction.jta.JtaTransactionManager&quot;&gt;
		&lt;property name=&quot;userTransaction&quot; ref=&quot;jotm&quot; /&gt;
	&lt;/bean&gt;
</pre>
<p>Takto nadefinujeme &#8222;testDataSource1&#8243; s využitím XA datasource z Enhrydry, obdobně definuje i druhý datasource.</p>
<pre class="brush: xml; title: ; notranslate">
	&lt;bean id=&quot;testDataSource1&quot; class=&quot;org.enhydra.jdbc.pool.StandardXAPoolDataSource&quot;
		destroy-method=&quot;shutdown&quot;&gt;
		&lt;property name=&quot;dataSource&quot;&gt;
			&lt;bean class=&quot;org.enhydra.jdbc.standard.StandardXADataSource&quot;
				destroy-method=&quot;shutdown&quot;&gt;
				&lt;property name=&quot;transactionManager&quot;&gt;
					&lt;ref local=&quot;jotm&quot; /&gt;
				&lt;/property&gt;
				&lt;property name=&quot;driverName&quot;&gt;
					&lt;value&gt;com.informix.jdbc.IfxDriver&lt;/value&gt;
				&lt;/property&gt;
				&lt;property name=&quot;url&quot; value=&quot;jdbc:informix-sqli://.....&quot;/&gt;
			&lt;/bean&gt;
		&lt;/property&gt;
		&lt;property name=&quot;user&quot;&gt;
			&lt;value&gt;user&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name=&quot;password&quot;&gt;
			&lt;value&gt;password&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;
</pre>
<p>Pak už pouze spustíme test a ověříme, že změny v obou datasourcech při testech nebyly commitnuty.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/10/jta-v-integracnich-testech-bez-aplikacniho-serveru/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jak na mock HTTP serveru</title>
		<link>http://www.aspectworks.com/2011/09/jak-na-mock-http-serveru</link>
		<comments>http://www.aspectworks.com/2011/09/jak-na-mock-http-serveru#comments</comments>
		<pubDate>Mon, 05 Sep 2011 12:35:12 +0000</pubDate>
		<dc:creator>Roman Valina</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=2664</guid>
		<description><![CDATA[Pro jednoho z naších zákazníků dodáváme C2DM &#8211; zasílání notifikací na mobilní telefon s operačním systémem Android. Tato služba je implementována jako HTTP request, ve kterém pošlete zprávu, registrační identifikátor<a href="http://www.aspectworks.com/2011/09/jak-na-mock-http-serveru" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Pro jednoho z naších zákazníků dodáváme <a title="C2DM" href="http://code.google.com/android/c2dm/">C2DM</a> &#8211; zasílání notifikací na mobilní telefon s operačním systémem Android. Tato služba je implementována jako HTTP request, ve kterém pošlete zprávu, registrační identifikátor instance zařízení s androidem a C2DM server se postará o doručení.<span id="more-2664"></span></p>
<p>Narazil jsem ale na problém jak vytvořit unit test který ověří, správný formát odesílané notifikace. Problém je právě v tom, jak namockovat chování C2DM serveru bez toho, abych musel někde rozebíhat Jetty či nedejbože Tomcat.</p>
<p>Testovaný kód vypadá nějak takto:</p>
<pre class="brush: java; title: ; notranslate">
private static int sendMessage(String message, URL url) throws IOException {
   // create connection
   HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setDoInput(true);
    connection.setDoOutput(true);
    connection.setRequestMethod(&quot;POST&quot;);
    // post data
   DataOutputStream output = new DataOutputStream(connection.getOutputStream());
    output.writeBytes(&quot;message=&quot;message);
    output.flush();
    output.close();
    // establish connection
   connection.connect();
    // return errocode
   return connection.getResponseCode();
}
</pre>
<p>Umím vytvořit mock interfacu (viz. EasyMock , PowerMock ect.), dokonce i stub konkrétní třídy. Final třídu <a title="URL" href="http://download.oracle.com/javase/6/docs/api/java/net/URL.html">URL</a> zkrátka nepodědíte a testovanému kódu pak &#8222;nepředhodíte&#8220;.</p>
<p>Narazil jsem na knihovnu <a title="simple" href="http://www.simpleframework.org/">simple</a>, která velice jednoduše na několika řádcích na pár sekund rozběhne „webový server“. Vy pak můžete snadno nasimulovat chování protějšího serveru.</p>
<p>Vytvoříte třídu implementující interface org.simpleframework.http.core.Container</p>
<pre class="brush: java; title: ; notranslate">
public class MockC2dmServer implements Container {
  protected String capturedMessage;
  public void handle(Request request, Response response) {
     try {
       capturedMessage = request.getParameter(&quot;message&quot;);
     } catch (IOException e1) {
       capturedMessage = null;
     }
    if(capturedMessage != null) {
      response.setCode(HttpURLConnection.HTTP_OK);
    } else {
      response.setCode(HttpURLConnection.HTTP_BADREQUEST);
    }
  }
}
</pre>
<p>Samotné vytvoření serveru a test pak může vypadat nějak takto:</p>
<pre class="brush: java; title: ; notranslate">
@Test
public void basicSenderTest() throws Exception {
  MockC2dmServer mockServer = new MockC2dmServer();
   // binds server to socket on adress
  Connection connectionServer = new SocketConnection(mockServer);
  SocketAddress address = new InetSocketAddress(&quot;localhost&quot;,8080));
  connectionServer.connect(address);
   // test method
  String message = &quot;message text&quot;
  C2dmNotificationSender.sendNotification(message, new URL(&quot;http://localhost:8080&quot;);
  Assert.assertEquals(message, mockServer.capturedMessage);
}
</pre>
<p>Uznávám, že tento způsob testování má svá rizika, například vám nikdo nezaručí, že port 8080 bude volný, to však jde minimalizovat například metodou, která vám nějaký volný port najde, ale to už není tématem tohoto článku. Pokud někdo z vás přijde na jiné, lepší řešení rád si ho přečtu v diskuzi pod článkem.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/09/jak-na-mock-http-serveru/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Pokročilé integrační buildy</title>
		<link>http://www.aspectworks.com/2011/08/pokrocile-integracni-buildy</link>
		<comments>http://www.aspectworks.com/2011/08/pokrocile-integracni-buildy#comments</comments>
		<pubDate>Fri, 12 Aug 2011 12:12:21 +0000</pubDate>
		<dc:creator>Luboš Račanský</dc:creator>
				<category><![CDATA[ @cs]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[selenium]]></category>
		<category><![CDATA[soa]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=2610</guid>
		<description><![CDATA[Pevně veřím, že continuous integration je již zažitý standard na všech, nebo alespoň na těch jednodušších, projektech. Chtěl bych rozptýlit případné obavy z konfigurace složitějších projektů. Ukážeme si, jak pouhým<a href="http://www.aspectworks.com/2011/08/pokrocile-integracni-buildy" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Pevně veřím, že <em>continuous integration</em> je již zažitý standard na všech, nebo alespoň na těch jednodušších, projektech. Chtěl bych rozptýlit případné obavy z konfigurace složitějších projektů. Ukážeme si, jak pouhým <code>mvn clean verify</code> nastartujeme celou <a href="http://en.wikipedia.org/wiki/Service-oriented_architecture">SOA</a> platformu a nad ní spustíme selenium testy.<br />
<span id="more-2610"></span><br />
SOA je buzzword, ale principy, které oprášil <a href="http://www.dagblog.cz/2011_08_07_archive.html#5201938144742630731">Roman Pichlík v článku Aplikace kontra Služba kontra Knihovna</a>, stále platí. Jedním ze zmiňovaných aspektů je i <em>loose coupling</em> (volné provázání). To sice zjednodušuje deploy updatu, ale na druhou stranu kompletní rozchození prostředí na zelené louce, pokud byste ho snad prováděli ručně, vás rozhodně bavit nebude. Avšak lenost je matka pokroku a pro maven existuje <a href="http://cargo.codehaus.org/Maven2+plugin">plugin cargo</a>.</p>
<p>U zákazníka jsme implementovali webovou aplikaci, která volala další dva servery přes REST api a autentizace byla řešená přes <a href="http://en.wikipedia.org/wiki/Single_sign-on">SSO</a> (konkrétně <a href="http://www.jasig.org/cas">CAS</a> server). I takto komplexní platforma je snadno testovatelná. Konfiguraci popíši na zjednodušeném příkladu dvou serverů <em>Foo</em> a <em>Hoo</em>.</p>
<p>Možná máte někde v podvědomí zapsané, že na war souboru nelze záviset. Binárně nikoliv, ale pro potřeby našeho buildu ano. Přidejte tedy do závislostí servery potřebné pro test. Nezapomeňte, že tyto servery musí být nainstalované ve vaší maven repository (nejlépe, pokud spouštíte jejich integrační buildy s goalem <em>deploy</em>).</p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
	&lt;groupId&gt;com.aspectworks.examples&lt;/groupId&gt;
	&lt;artifactId&gt;foo&lt;/artifactId&gt;
	&lt;version&gt;${foo.version}&lt;/version&gt;
	&lt;type&gt;war&lt;/type&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
	&lt;groupId&gt;com.aspectworks.examples&lt;/groupId&gt;
	&lt;artifactId&gt;hoo&lt;/artifactId&gt;
	&lt;version&gt;${hoo.version}&lt;/version&gt;
	&lt;type&gt;war&lt;/type&gt;
&lt;/dependency&gt;
</pre>
<p>Samotný deploy serverů na tomcat zajistí cargo plugin, configurace viz níže. Pozor, tomcat si budete muset přidat do maven repository sami.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;plugin&gt;
	&lt;artifactId&gt;maven-failsafe-plugin&lt;/artifactId&gt;
	&lt;version&gt;2.8.1&lt;/version&gt;
	&lt;executions&gt;
		&lt;execution&gt;
			&lt;goals&gt;
				&lt;goal&gt;integration-test&lt;/goal&gt;
				&lt;goal&gt;verify&lt;/goal&gt;
			&lt;/goals&gt;
		&lt;/execution&gt;
	&lt;/executions&gt;
&lt;/plugin&gt;
&lt;plugin&gt;
	&lt;groupId&gt;org.codehaus.cargo&lt;/groupId&gt;
	&lt;artifactId&gt;cargo-maven2-plugin&lt;/artifactId&gt;
	&lt;version&gt;1.1.1&lt;/version&gt;
	&lt;executions&gt;
		&lt;execution&gt;
			&lt;id&gt;start-container&lt;/id&gt;
			&lt;phase&gt;pre-integration-test&lt;/phase&gt;
			&lt;goals&gt;
				&lt;goal&gt;start&lt;/goal&gt;
			&lt;/goals&gt;
		&lt;/execution&gt;
	&lt;/executions&gt;
	&lt;configuration&gt;
		&lt;container&gt;
			&lt;containerId&gt;tomcat6x&lt;/containerId&gt;
			&lt;artifactInstaller&gt;
				&lt;groupId&gt;org.apache&lt;/groupId&gt;
				&lt;artifactId&gt;tomcat&lt;/artifactId&gt;
				&lt;version&gt;6.0.32&lt;/version&gt;
			&lt;/artifactInstaller&gt;
			&lt;systemProperties&gt;
				&lt;foo.config.location&gt;file:etc/conf/&lt;/foo.config.location&gt;
				&lt;hoo.config.location&gt;file:etc/conf/&lt;/hoo.config.location&gt;
			&lt;/systemProperties&gt;
		&lt;/container&gt;
		&lt;configuration&gt;
			&lt;deployables&gt;
				&lt;deployable&gt;
					&lt;groupId&gt;com.aspectworks.examples&lt;/groupId&gt;
					&lt;artifactId&gt;foo&lt;/artifactId&gt;
					&lt;type&gt;war&lt;/type&gt;
					&lt;properties&gt;
						&lt;context&gt;foo&lt;/context&gt;
					&lt;/properties&gt;
				&lt;/deployable&gt;
				&lt;deployable&gt;
					&lt;groupId&gt;com.aspectworks.examples&lt;/groupId&gt;
					&lt;artifactId&gt;hoo&lt;/artifactId&gt;
					&lt;type&gt;war&lt;/type&gt;
					&lt;properties&gt;
						&lt;context&gt;hoo&lt;/context&gt;
					&lt;/properties&gt;
				&lt;/deployable&gt;
			&lt;/deployables&gt;
			&lt;properties&gt;
				&lt;cargo.servlet.port&gt;${cargo.port}&lt;/cargo.servlet.port&gt;
			&lt;/properties&gt;
		&lt;/configuration&gt;
	&lt;/configuration&gt;
&lt;/plugin&gt;
</pre>
<p>Je dobrým zvykem držet konfigurační soubory mimo war. Jediný build tak můžete nasadit v různých prostředích, pouze s jinou konfigurací. V předchozí ukázce pomu jste si mohli všimnout nastavení systémových properties. Tímto způsobem zadáme cestu právě k těmto konfiguračním souborům, které se v našem případě od produkčního prostředí liší například tím, že nastavují in memory <a href="http://hsqldb.org/">HSQL</a> databázi.</p>
<p>Spouštění selenium serveru pro integrační test nastavíme v pomu následujícím způsobem.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;plugin&gt;
	&lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
	&lt;artifactId&gt;selenium-maven-plugin&lt;/artifactId&gt;
	&lt;version&gt;1.1&lt;/version&gt;
	&lt;executions&gt;
		&lt;execution&gt;
			&lt;id&gt;start&lt;/id&gt;
			&lt;phase&gt;pre-integration-test&lt;/phase&gt;
			&lt;goals&gt;
				&lt;goal&gt;start-server&lt;/goal&gt;
			&lt;/goals&gt;
			&lt;configuration&gt;
				&lt;background&gt;true&lt;/background&gt;
			&lt;/configuration&gt;
		&lt;/execution&gt;
		&lt;execution&gt;
			&lt;id&gt;stop&lt;/id&gt;
			&lt;phase&gt;post-integration-test&lt;/phase&gt;
			&lt;goals&gt;
				&lt;goal&gt;stop-server&lt;/goal&gt;
			&lt;/goals&gt;
		&lt;/execution&gt;
	&lt;/executions&gt;
&lt;/plugin&gt;
</pre>
<p>A nyní můžete konečně spustit <code>mvn clean verify</code></p>
<p><strong>Závěr</strong><br />
Ukázali jsme si, že i testování rozsáhlejších projektů nemusí být složité. Doufám, že jsem inspiroval alespoň jeden projekt, kde již dnes zavedete integrační testy. Pokud by vás zajímalo, jak pro integrační testy a nightly buildy inicializujeme data, dejte nám vědět v komentářích, můžeme se tomuto tématu věnovat v nějakém z příštích příspěvků.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/08/pokrocile-integracni-buildy/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Spring Integration + WebSphere MQ</title>
		<link>http://www.aspectworks.com/2011/07/spring-integration-websphere-mq</link>
		<comments>http://www.aspectworks.com/2011/07/spring-integration-websphere-mq#comments</comments>
		<pubDate>Fri, 22 Jul 2011 08:46:04 +0000</pubDate>
		<dc:creator>jan.bumbala jan.bumbala</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=1096</guid>
		<description><![CDATA[Na projektu u zákazníka jsme řešili připojení k externímu systému na Websphere MQ. Bohužel na MQ nebylo z nějakého důvodu zpřístupněno JMS, takže bylo potřeba používat nativní API. Pokud by<a href="http://www.aspectworks.com/2011/07/spring-integration-websphere-mq" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Na projektu u zákazníka jsme řešili připojení k externímu systému na Websphere MQ. Bohužel na MQ nebylo z nějakého důvodu zpřístupněno JMS, takže bylo potřeba používat nativní API. Pokud by bylo možné použít JMS rozhraní, integrace do aplikace by byla triviální. Protože jsme používali Spring Integration, stačilo by nakonfigurovat springový JMS inbound channel adapter. Takto bylo potřeba vytvořit vlastní adapter a použít nativní MQ rozhraní.<br />
<span id="more-2563"></span><br />
Pro MQ existuje několik verzí java klienta, zdarma je ovšem pouze klient bez podpory transakcí, klient s podporou transakcí je součástí MQ instalace, a tak je potřeba licence k MQ. Knihovna pro zpřístupnění MQ pomocí JMS se nazývá &#8222;MQ classes for Java Message Service&#8220;, knihovna pro přístup k MQ pomocí nativního rozhraní, která nás nyní zajímá, se označuje jako “MQ classes for Java”. Ke knihovně existuje docela podrobná dokumentace pod názvem “WebSphere MQ, Using Java”, jen jsem měl trochu problém se k ní na stránkách IBM doklikat.</p>
<h3>MQ Inbound Channel Adapter</h3>
<p>Scénář pro naši implementaci byl jednoduchý: poslouchat na frontě a vybírat odtud všechny zprávy, tělo MQ zprávy se přečte jako String a pošle se do výstupního kanálu nakonfigurovaného ve Spring Integration pro další transformování a zpracování. Celou logiku pro přístup k MQ jsem zapouzdřil do nového inbound adapteru, který má za předka org.springframework.integration.endpoint.AbstractEndpoint a implementuje org.springframework.integration.core.MessageSource.</p>
<pre class="brush: java; title: ; notranslate">
public class MQAdapter extends AbstractEndpoint implements MessageSource{
...
}
</pre>
<p>Ve Spring konfiguraci lze potom adapter nadefinovat jednoduše takto:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!-- namespace http://www.springframework.org/schema/integration --&gt;
&lt;int:inbound-channel-adapter ref=&quot;mqAdapter&quot; channel=&quot;mqOutput&quot;&gt;
   &lt;int:poller fixed-rate=&quot;1000&quot; max-messages-per-poll=&quot;10&quot;/&gt;
&lt;/int:inbound-channel-adapter&gt;
&lt;bean name=&quot;mqAdapter&quot; class=&quot;example.MQAdapter&quot;&gt;
...
&lt;/bean&gt;
</pre>
<p>Takto se každou sekundu otestuje fronta, zda nepřišla nová zpráva, v našem příkladu se zpracuje maximálně deset zpráv za sekundu.</p>
<p>Co se týče implementace MQ adapteru, neobsahuje nic složitého. Nejprve se naváže spojení k MQ queue manageru které se udržuje po celou dobu životnosti adapteru. Podle nastavení polleru se pak periodicky zjišťuje, zda nepřišla nová zpráva. Spadlé spojení není potřeba nijak ošetřovat, adapter jednoduše naváže nové spojení při následujícím pokusu o čtení z fronty, není tedy nutný žádný daemon thread. Časově nejnáročnější bylo proniknout do nuancí MQ API, dále tedy následuje popis použití tohoto rozhraní.</p>
<h3>WebSphere MQ API</h3>
<p>Pro připojení k MQ je nejprve potřeba navázat spojení ke queue manageru který je reprezentovaný třídou com.ibm.mq.MQQueueManager. Pro tento účel je třeba znát a nastavit parametry připojení, jako je jméno queue managera, jméno fronty, IP adresa a port atd.. Toto lze udělat dvojím způsobem. Buď nastavit statická pole ve třídě com.ibm.mq.MQEnvironment (instance MQQueueManager si je načte při inicializaci), nebo parametry připojení naplnit do Hashtable a tu předat konstruktoru třídy MQQueueManager. Z nějakého důvodu mi druhý způsob nefungoval, takže jsem použil způsob první.</p>
<pre class="brush: java; title: ; notranslate">
//nastaveni statickych poli
MQEnvironment.hostname = hostname;
MQEnvironment.port     = port;
MQEnvironment.channel  = channel;
MQEnvironment.CCSID    = ccsid;
MQEnvironment.userID   = userId;
//konstruktor cte z MQEnvironment
MQQueueManager qMgr = new MQQueueManager(queueManagerName);
</pre>
<p>Dalším krokem je vytvoření samotného spojení na MQ frontu, tj. vytvořit instanci třídy com.ibm.mq.MQQueue. Frontu je možné otevřít v několika modech (zejména: sdílené nebo exkluzivní čtení, zápis, prohlížení obsahu fronty) a lze nastavit další různé detaily jak se fronta bude chovat. Všechny tyto parametry se nastavují jako bitová maska a předávají se konstruktoru MQQueue.</p>
<pre class="brush: java; title: ; notranslate">
int openOptions = MQC.MQOO_INQUIRE |= MQC.MQOO_INPUT_SHARED |= MQC.MQOO_BROWSE;
MQQueue queue = qMgr.accessQueue(this.queueName, openOptions);
</pre>
<p>Jakmile máme vytvořenou instanci MQQueue, můžeme číst zprávy z fronty. Pro čtení je opět potřeba nadefinovat sadu parametrů, které ovlivňují jak bude čtení probíhat; tyto parametry jsou reprezentovány třídou com.ibm.mq.MQGetMessageOptions. Původně jsem se snažil nastavit parametry tak, aby volání queue.get() klienta blokovalo do té doby, než se na frontě objeví zpráva, tudíž bez zbytečného pollingu, nějak takto:</p>
<pre class="brush: java; title: ; notranslate">
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.matchOptions = MQC.MQMO_NONE;
gmo.options  = MQC.MQGMO_WAIT;
gmo.waitInterval = MQC.MQWI_UNLIMITED;
</pre>
<p>Ovšem záhy se ukázalo, že potom není možné volání get() předčasně ukončit: interrupt na threadu nemá vliv, volat metodu close() na MQQueue také nelze, protože jak get() tak close() je synchronizováno na instanci MQQueue. Takže jsem se pollingu nevyhnul. Celý průbeh čtení z fronty vypadá následovně:</p>
<pre class="brush: java; title: ; notranslate">
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.matchOptions = MQC.MQMO_NONE; //nefiltrovat, cist vsechny zpravy ve fronte
gmo.options  = MQC.MQGMO_NO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
MQMessage messageBuffer = new MQMessage();
queue.get(messageBuffer, gmo);
</pre>
<p>Při takovéto konfiguraci se klient pokusí přečíst zprávu z fronty a pokud je fronta prázdná, volání neblokuje, ale vyhodí výjimku. Toto je nepříjemné, protože MQ klient loguje defaultně přímo do System.err, pak se v logu hromadí hlášení že nebyla nalezena zpráva: <em>MQJE001: Completion Code 2, Reason 2033</em><br />
Po delším googlování jsem nalezl dvě řešení, jak se vyhnout zahlcovaní logu. První způsob je přesměrovat logování nastavením statického pole com.ibm.mq.MQException.log (kdo má rád radikální řešení, lze nastavit na null a potlačit logování úplně). Ale více mi vyhovoval druhý způsob, filtrovat error kódy, které nechceme logovat:</p>
<pre class="brush: java; title: ; notranslate">
MQException.logExclude(MQException.MQRC_NO_MSG_AVAILABLE);
</pre>
<p>Posledním krokem v implementaci adapteru je čtení těla zprávy, což už je jednoduchá věc.</p>
<pre class="brush: java; title: ; notranslate">
byte[] buffer = new byte[messageBuffer.getDataLength()]; //MQMessage messageBuffer
messageBuffer.readFully(buffer, messageBuffer.getDataOffset(), messageBuffer.getDataLength());
String payload = new String(buffer, charset);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/07/spring-integration-websphere-mq/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Custom Spring Namespace + Embedded Groovy pre Business DSL</title>
		<link>http://www.aspectworks.com/2011/05/custom-spring-namespace-embedded-groovy-pre-business-dsl</link>
		<comments>http://www.aspectworks.com/2011/05/custom-spring-namespace-embedded-groovy-pre-business-dsl#comments</comments>
		<pubDate>Mon, 30 May 2011 16:48:51 +0000</pubDate>
		<dc:creator>Martin Tibenský</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=1088</guid>
		<description><![CDATA[Spring umožňuje pre svoju xml konfiguráciu okrem hromady dodávaných namespacov (jdbc, context, tx&#8230;) zaregistrovať aj vlastný namespace handler a tým používať custom xml tagy pre vytváranie bean, prípadne iné zasahovanie<a href="http://www.aspectworks.com/2011/05/custom-spring-namespace-embedded-groovy-pre-business-dsl" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Spring umožňuje pre svoju xml konfiguráciu okrem hromady dodávaných namespacov (jdbc, context, tx&#8230;) zaregistrovať aj vlastný namespace handler a tým používať custom xml tagy pre vytváranie bean, prípadne iné zasahovanie do contextu. V AspectWorks to používame napríklad pre konfiguráciu validátorov atp. Sila tohoto prístupu je však omnoho väčšia, v dnešnom článku si ukážeme malý príklad z praxe.<span id="more-2562"></span></p>
<p>Boilerplate kód pre vlastný spring namespace pozostáva zo súborov META-INF/spring.handlers</p>
<pre class="brush: plain; title: ; notranslate">http://www.company.com/schema/ourSchema=com.company.OurNamespaceHandler</pre>
<p>a META-INF/spring.schemas</p>
<pre class="brush: plain; title: ; notranslate">http://www.company.com/schema/ourSchema.xsd=META-INF/schema/ourSchema.xsd</pre>
<p>V súbore META-INF/schema/ourSchema.xsd definujme štandardným spôsobom XML schému:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;xsd:schema xmlns=&quot;http://www.company.com/schema/ourSchema&quot; xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot; xmlns:beans=&quot;http://www.springframework.org/schema/beans&quot; targetNamespace=&quot;http://www.hypotecnibanka.cz/schema/scoreProc&quot;
 elementFormDefault=&quot;qualified&quot; attributeFormDefault=&quot;unqualified&quot;&gt;
 &lt;xsd:import namespace=&quot;http://www.springframework.org/schema/beans&quot; /&gt;
 &lt;xsd:element name=&quot;expr&quot;&gt;
   &lt;xsd:complexType&gt;
     &lt;xsd:simpleContent&gt;
       &lt;xsd:extension base=&quot;xsd:string&quot;&gt;
         &lt;xsd:attribute name=&quot;result&quot; use=&quot;required&quot; type=&quot;xsd:token&quot; /&gt;
         &lt;xsd:attribute name=&quot;id&quot; type=&quot;xsd:ID&quot; /&gt;
         &lt;xsd:attribute name=&quot;name&quot; type=&quot;xsd:string&quot; /&gt;
       &lt;/xsd:extension&gt;
     &lt;/xsd:simpleContent&gt;
   &lt;/xsd:complexType&gt;
 &lt;/xsd:element&gt;
 &lt;xsd:element name=&quot;foo&quot;&gt;
   &lt;xsd:complexType&gt;
     &lt;xsd:sequence minOccurs=&quot;1&quot; maxOccurs=&quot;1&quot;&gt;
       &lt;xsd:element ref=&quot;expr&quot; minOccurs=&quot;1&quot; maxOccurs=&quot;unbounded&quot; /&gt;
     &lt;/xsd:sequence&gt;
   &lt;/xsd:complexType&gt;
 &lt;/xsd:element&gt;
</pre>
<p>V jave je potrebné implementovať dva interfacei: NamespaceHandler a BeanDefinitionParser. Spring framework nám samozrejme poskytuje potrebné abstraktné implementácie, ktoré je jednoduché upraviť:</p>
<pre class="brush: java; title: ; notranslate">public class OurNamespaceHandler extends NamespaceHandlerSupport {
 public void init() {
   ScoreBeanDefinitionParser parser = new OurBeanDefinitionParser();
   registerBeanDefinitionParser(&quot;foo&quot;, parser);
 }</pre>
<p>Väčšinu práce vykonáva BeanDefinitionParser:</p>
<pre class="brush: java; title: ; notranslate">public class ScoreBeanDefinitionParser extends AbstractBeanDefinitionParser {
 @Override
 protected AbstractBeanDefinition parseInternal(Element scoring, ParserContext parserContext) {
   BeanDefinitionBuilder factory = BeanDefinitionBuilder.genericBeanDefinition(FooServiceImpl.class);
   factory.addPropertyValue(&quot;exprs&quot;, processExprs(DomUtils.getChildElementsByTagName(scoring, &quot;expr&quot;)));
   return factory.getBeanDefinition();
 }
 private ManagedList&lt;BeanDefinition&gt; processExpressions(List&lt;Element&gt; expressions) {
   ManagedList&lt;BeanDefinition&gt; ret = new ManagedList&lt;BeanDefinition&gt;(expressions.size());
   for (Element element : expressions) {
     BeanDefinitionBuilder factory = BeanDefinitionBuilder.genericBeanDefinition(ExpressionProcessor.class);
     factory.addPropertyValue(&quot;expression&quot;, element.getTextContent());
     factory.addPropertyValue(&quot;result&quot;, CredScore.valueOf(element.getAttribute(&quot;result&quot;)));
     ret.add(factory.getBeanDefinition());
   }
   return ret;
 }</pre>
<p>Z kódu je zrejmé, že Spring kontajner vytvorí beany dvoch tried, FooServiceImpl a ExpressionProcessor.</p>
<p>Implementácii ExpressionProcessora sa bude venovať druhá časť článku. Pre samotné vyhodnocovanie expressionov môže dobre poslúžiť akýkoľvek expression language (SPEL, MVEL, &#8230;). V našom konkrétnom prípade použijeme groovy, keďže má k expression jazykom blízko ale jeho syntax umožňuje silnejiše vyjadrovanie. ExpressionProcessor v základe implementujeme:</p>
<pre class="brush: java; title: ; notranslate">public class ExpressionProcessor {
  private String result;
  private String expr;
  public String getResult() {
     GroovyShell groovy = new GroovyShell();
     //priklad nastavenia premennej
     groovy.setVariable(&quot;foo&quot;, &quot;bar&quot;);
     Boolean eval = (Boolean) groovy.evaluate(expr);
     if (eval) {
       return result;
     }
     log.debug(&quot;Evaluated to false, returning null&quot;);
     return null;
 }</pre>
<p>V príklade je viditeľné využitie embedded Groovy, pomocou GroovyShell, nastavenie premennej do kontextu a vyhodnotenie expressionu. DSL jazyk v celej svojej paráde potom môže vyzerať nasledovne:</p>
<pre class="brush: xml; title: ; notranslate">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot; xmlns:proc=&quot;http://www.company.com/schema/ourSchema&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
 xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.company.com/schema/ourSchema http://www.company.com/schema/scoreProc/ourSchema.xsd&quot;&gt;
 &lt;proc:foo&gt;
   &lt;proc:expr result=&quot;L&quot;&gt;foo == bar&lt;/proc:expr&gt;
   &lt;proc:expr result=&quot;M&quot;&gt;foo != bar&lt;/proc:expr&gt;
 &lt;/proc:foo&gt;
&lt;/beans&gt;</pre>
<p>Toto je už napríklad pre business analytika pochopiteľný formát a jednoducho do neho pridá ďalšie pravidlá atď.</p>
<p>Oproti vytváraniu DSL napríklad v čistom Groovy (postup je popísaný napríklad v knihe Groovy for Domain-Specific Languages) má tento postup výhodu v tom, že je relatívne nenáročný najmä pre vývojára, ktorý je Spring zručný a možnosť nasadiť ľubovoľný expression language zvyšuje flexibilitu.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/05/custom-spring-namespace-embedded-groovy-pre-business-dsl/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Konečně profily ve Springu 3.1</title>
		<link>http://www.aspectworks.com/2011/04/konecne-profily-ve-springu-3-1</link>
		<comments>http://www.aspectworks.com/2011/04/konecne-profily-ve-springu-3-1#comments</comments>
		<pubDate>Thu, 14 Apr 2011 15:20:09 +0000</pubDate>
		<dc:creator>Pavel Müller</dc:creator>
				<category><![CDATA[Homepage]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=1041</guid>
		<description><![CDATA[Před časem vyšel nový Spring 3.1 M1 a krom jiného zavádí novinku v podobě profilů pro Spring beany. Na něco takového čekáme už od prvních verzí a dosud jsme to<a href="http://www.aspectworks.com/2011/04/konecne-profily-ve-springu-3-1" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Před časem vyšel nový Spring 3.1 M1 a krom jiného zavádí novinku v podobě profilů pro Spring beany. Na něco takového čekáme už od prvních verzí a dosud jsme to obcházeli neelegantními způsoby. Ale je to konečně tady! Podívejme se na to, jak to funguje.<span id="more-2561"></span></p>
<p>Základní problém je, když potřebujete různé konfigurace pro různá prostředí (vývojové vs. produkční), nebo když potřebujete svůj produkt konfigurovat odlišně pro každého vašeho zákazníka. A přitom to nejde vyřesit nějak jednoduše třeba pomocí properties (<code>PropertyPlaceholderConfigurer</code>). Potřebujete úplně jinou konfiguraci pro jiné prostředí. V jednom bude aplikace nasazená na Tomcatu, v druhém na IBM WebSphere. Transakční konfigurace budou úplně odlišné. Nebo chcete do produktu implementovat autentizaci pomocí databáze i LDAPu, ale potom pro zákazníka jenom zvolit tu vhodnou.</p>
<p>Ve Springu 3.1 tedy existují profily. Pomocí nich můžete označit jednotlivé beany nebo celé konfigurační soubory, že budou aktivovány pouze pro daný profil. V XML může podpora pro dva způsoby autentizace ve Spring Security vypadat nějak takto:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
	xmlns:xsi=&quot;...&quot;
	xsi:schemaLocation=&quot;...&quot;&gt;
 &lt;beans profile=&quot;auth-db&quot;&gt;
   &lt;bean id=&quot;authProvider&quot; class=&quot;org.spring...DaoAuthenticationProvider&quot;&gt;
    ...
   &lt;/bean&gt;
 &lt;/beans&gt;
 &lt;beans profile=&quot;auth-ldap&quot;&gt;
   &lt;bean id=&quot;authProvider&quot; class=&quot;org.spring...LdapAuthenticationProvider&quot;&gt;
      ...
   &lt;/bean&gt;
 &lt;/beans&gt;
&lt;/beans&gt;
</pre>
<p>Pokud ke konfiguraci používáte anotace, existuje nová anotace <code>@Profile</code>, pomocí níž můžete opět řídit v jakém profilu se komponenta použije.</p>
<pre class="brush: java; title: ; notranslate">
@Service
@Profile(&quot;google&quot;)
public class GoogleStockLoader implements StockLoader {
</pre>
<p>Profily se aktivují několika způsoby. Buď pomocí API přímo na <code>ApplicationContext</code> nebo pro většinu projektů spíše ve <code>web.xml</code> nebo pomocí systémové proměnné <code>spring.profiles.active</code>.</p>
<pre class="brush: java; title: ; notranslate">
ClassPathXmlApplicationContext ctx =
    new ClassPathXmlApplicationContext();
ctx.setConfigLocation(&quot;orinoco-security.xml&quot;);
ctx.getEnvironment().setActiveProfiles(&quot;auth-ldap&quot;);
ctx.refresh();
</pre>
<p>Doporučuji se podívat na <a href="http://blog.springsource.com/category/spring/31/">SpringSource blog</a>, kde je více informací o profilech a novinkách ve Springu 3.1. Doufám, že tahle verze vyjde brzo, abychom to mohli co nejdřív začít používat.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/04/konecne-profily-ve-springu-3-1/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Proč psát javovské testy v Groovy II</title>
		<link>http://www.aspectworks.com/2011/03/proc-psat-javovske-testy-v-groovy-ii</link>
		<comments>http://www.aspectworks.com/2011/03/proc-psat-javovske-testy-v-groovy-ii#comments</comments>
		<pubDate>Tue, 22 Mar 2011 10:28:18 +0000</pubDate>
		<dc:creator>Tomáš Piňos</dc:creator>
				<category><![CDATA[Homepage]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Testování]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/cs/blog/?p=982</guid>
		<description><![CDATA[Druhá část blogu o psaní javovských testů v Groovy přinese méně slov a více kódu. Témata: Deklarace testovacích metod s JUnit Implementace rozhranní “mapou” Capture Libovolné řetězce jako názvy metod<a href="http://www.aspectworks.com/2011/03/proc-psat-javovske-testy-v-groovy-ii" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<div>
<p>Druhá část blogu o <a href="http://www.aspectworks.com/cs/blog/2011/02/proc-psat-javovske-testy-v-groovy-i/">psaní javovských testů v Groovy</a> přinese méně slov a více kódu.<br />
<span id="more-2560"></span><br />
Témata:</p>
<ul>
<li><a href="#deklarace">Deklarace testovacích metod s JUnit</a></li>
<li><a href="#rozhranni">Implementace rozhranní “mapou”</a></li>
<li><a href="#capture">Capture</a></li>
<li><a href="#nazvy_metod">Libovolné řetězce jako názvy metod</a></li>
<li><a href="#shouldFail">shouldFail?</a></li>
<li><a href="#test_xml">Testování XML výstupů</a></li>
<li><a href="#dalsi">A další&#8230;</a></li>
<li><a href="#maven">Konfigurace Mavenu</a></li>
</ul>
<p>Zkusili jste už psát testy v Groovy? K čemu dalšímu Groovy používáte? Podělte se o své zkušenosti v diskuzi pod článkem.</p>
<h3><a name="deklarace">Deklarace testovacích metod s JUnit</a></h3>
<p>Testovací metody můžeme označit @Test anotací tak, jak to zavedla JUnit 4. Druhou možností je psát testovací třídy jako potomky <a href="http://groovy.codehaus.org/api/groovy/util/GroovyTestCase.html">GroovyTestCase</a> a testovací metody začínat prefixem “test”.</p>
<pre class="brush: groovy; title: ; notranslate">
class Test1 {
  @Test
  void &quot;notification message handling&quot;() {
    Assert.fail()
  }
}
class Test2 extends GroovyTestCase {
  void test1() {
    fail(&quot;notification message not handled&quot;)
  }
}
</pre>
<p>GroovyTestCase dědí z třídy junit.framework.TestCase a přidává pár šikovných drobností navíc (<a href="#shouldFail">shouldFail</a>).</p>
<h3><a name="rozhranni">Implementace rozhranní “mapou”</a></h3>
<p>V Groovy můžeme rozhranní implementovat pomocí <a href="http://groovy.codehaus.org/Groovy+way+to+implement+interfaces">closures a map</a>. Pomocí closure:</p>
<pre class="brush: groovy; title: ; notranslate">
def accountDao = { new Account(number: “AX001”, balance: 999G) } as AccountDao
</pre>
<p>Tato closure implementuje všechny metody AccountDao pomocí jednoho kódu (akademický, ale někdy užitečný příklad). Pokud bych chtěl brát v úvahu parametry metod, mohu je v closure deklarovat jako pole &#8211; Object[] params.</p>
<p>Implementace pomocí mapy:</p>
<pre class="brush: groovy; title: ; notranslate">
def accountDao = [ get: { new Account(number: “AX001”, balance: 999G) } ] as AccountDao
</pre>
<p>Mapa implementuje jen metodu get. Rozhranní takto můžeme implementovat i jen částečně &#8211; volání neimplementovaných metod skončí NPE. Je to výborná zkratka pro implementaci různých testovacích stubů (nebo mocků, chcete-li).</p>
<h3><a name="capture">Capture</a></h3>
<p>Implementace rozhranní za pomoci map nebo closures může výrazně zjednodušit situace, kde bychom jinak v Javě museli použít např. EasyMock a jeho metodu <a href="http://easymock.org/api/easymock/2.4/org/easymock/Capture.html">capture</a>. Jako příklad uvedu zjednodušený test z našeho blogu o <a href="http://www.aspectworks.com/cs/blog/2011/02/test-metody-tvorici-objekty/">testech metod tvořících objekty</a>.</p>
<pre class="brush: groovy; title: ; notranslate">
class UserServiceTest {
  @Test
  public void createUser() {
    def userService = new UserServiceImpl()
    userService.userDao = { User user -&gt; assert &quot;tomas&quot; == user.username } as UserDao
    userService.createUser(&quot;tomas&quot;)
  }
}
</pre>
<p>Test ověří, že metoda UserService.createUser správně vytvoří instanci třídy User. Zkuste výsledný kód porovnat s implementací pomocí EasyMocku a capture (převzato z <a href="http://www.aspectworks.com/cs/blog/2011/02/test-metody-tvorici-objekty/">citovaného blogu</a>).</p>
<pre class="brush: java; title: ; notranslate">
public class UserServiceTest {
  private UserServiceImpl userService;
  private UserDao userDao;
  @Before
  public void setUp() {
    userService = new UserServiceImpl();
    userDao = createMock(UserDao.class);
    userService.setUserDao(userDao);
  }
  @Test
  public void createUser() {
    Capture&lt;User&gt; capturedUser = new Capture&lt;User&gt;();
    userDao.save(capture(capturedUser));
    replay(userDao);
    userService.createUser(&quot;pavel&quot;);
    User user = capturedUser.getValue();
    assertEquals(&quot;pavel&quot;, user.getUsername());
    verify(userDao);
  }
}
</pre>
<p>Java dobrý, Groovy lepší?</p>
<h3><a name="nazvy_metod">Libovolné řetězce jako názvy metod</a></h3>
<p>Pěknou možností je nazývat metody libovolnými řetězci.</p>
<pre class="brush: groovy; title: ; notranslate">
@Test void &quot;notification message handling&quot;() {
  // ...
}
</pre>
<p>Maven potom zobrazí výsledek běhu testu následujícím způsobem.</p>
<pre>Failed tests:
  notification message handling(test.NotificationTest)</pre>
<p></p>
<h3><a name="shouldFail">shouldFail?</a></h3>
<p>Metody <a href="http://groovy.codehaus.org/api/groovy/util/GroovyTestCase.html#shouldFail(groovy.lang.Closure)">shouldFail</a> třídy GroovyTestCase slouží pro přehledné řešení situací s výjimkami a elegantně obchází obvyklou konstrukci s try &#8211; catch blokem.</p>
<pre class="brush: groovy; title: ; notranslate">
shouldFail(NullPointerException) {
  new Hashtable()[&quot;key&quot;] = null
}
shouldFail(IllegalArgumentException) {
  new HashMap(-1)
}
</pre>
<p>A co jsem myslel obvyklou konstrukcí s try &#8211; catch blokem?</p>
<pre class="brush: java; title: ; notranslate">
    try {
      Hashtable ht = new Hashtable();
      ht.put(&quot;key&quot;, null);
      fail();
    } catch (NullPointerException e) {
      // ok
    }
    try {
      new HashMap(-1);
      fail();
    } catch (IllegalArgumentException e) {
      // ok
    }
</pre>
<p>První příklad testuje vložení null hodnoty pod určitým klíčem do Hashtable &#8211; očekáváme, že pokus skončí výjimkou NPE (jinak fail). Podobně v druhém příkladu by vytvoření HashMap velikosti -1 mělo skončit výjimkou IAE.</p>
<h3><a name="test_xml">Testování XML výstupů</a></h3>
<p>Častým předmětem testů je ověření, jestli nějaký XML výstup odpovídá očekávanému tvaru. Groovy nabízí pro parsing XML mimojiné třídu <a href="http://groovy.codehaus.org/Reading+XML+using+Groovy%27s+XmlSlurper">XmlSlurper</a>. Její použití znamená, že nepíšete XPath výrazy, neiterujete přes DOM, ale přistupujete k obsahu XML stále prostředky Groovy jazyka.</p>
<p>Příklad z dokumentace:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;records&gt;
    &lt;car name='HSV Maloo' make='Holden' year='2006'&gt;
        &lt;country&gt;Australia&lt;/country&gt;
        &lt;record type='speed'&gt;Production Pickup Truck with speed of 271kph&lt;/record&gt;
    &lt;/car&gt;
    &lt;car name='P50' make='Peel' year='1962'&gt;
        &lt;country&gt;Isle of Man&lt;/country&gt;
        &lt;record type='size'&gt;Smallest Street-Legal Car at 99cm wide and 59 kg in weight&lt;/record&gt;
    &lt;/car&gt;
&lt;/records&gt;
</pre>
<p>Použití třídy XmlSlurper:</p>
<pre class="brush: groovy; title: ; notranslate">
def records = new XmlSlurper().parseText(...)
assert 2 == records.car.size()
def firstRecord = records.car[0]
assert 'car' == firstRecord.name()
assert 'Holden' == firstRecord.@make.text()
assert 'Australia' == firstRecord.country.text()
</pre>
<p>Co se čte lépe &#8211; //car[1][@name='HSV Maloo'] nebo car[0].@name.text() == “HSV Maloo”?</p>
<h3><a name="dalsi">A další&#8230;</a></h3>
<p>Mezi další killer vlastnosti Groovy patří vytváření nových instancí, <a href="http://groovy.codehaus.org/Builders">buildery</a> pro vytváření stromových struktur objektů nebo podpora pro práci s <a href="http://groovy.codehaus.org/Collections">kolekcemi</a>. Pěkně akční český přehled lze nalézt třeba v článku <a href="http://java.cz/article/8020">Groovy je žůžo</a>.</p>
<p>Groovy má v arzenálu i podporu pro vytváření mock objektů. <a href="http://docs.codehaus.org/display/GROOVY/Groovy+Mocks">Standardní přístup</a> mě jako uživatele EasyMocku nepřesvědčil, ale <a href="http://gmock.org/">GMock </a>stojí za to. A nezapomínejme na <a href="#rozhranni">mapy</a>, ty vyřeší mnoho potřeb.</p>
<p>I když toho Groovy nabízí hodně a ještě víc, rozhodnout se psát testy v Groovy neznamená opustit skvělou testovací infrastrukturu z Javy. Knihovny jako EasyMock, PowerMock, Hamcrest, … a libovolné jiné můžete stejným způsobem používat dál.</p>
<h3><a name="maven">Konfigurace Mavenu</a></h3>
<p>Podporu Groovy začleníme do projektu jednoduše jako závislost na Groovy artefaktu.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
    &lt;groupId&gt;org.codehaus.groovy&lt;/groupId&gt;
    &lt;artifactId&gt;groovy&lt;/artifactId&gt;
    &lt;version&gt;1.7.5&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>Pro správný běh testů je ještě třeba nakonfigurovat build plugin pro kompilaci testů v Groovy.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;plugin&gt;
    &lt;groupId&gt;org.codehaus.gmaven&lt;/groupId&gt;
    &lt;artifactId&gt;gmaven-plugin&lt;/artifactId&gt;
    &lt;version&gt;1.3&lt;/version&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;id&gt;testCompile&lt;/id&gt;
            &lt;goals&gt;&lt;goal&gt;testCompile&lt;/goal&gt;&lt;/goals&gt;
            &lt;configuration&gt;
                &lt;sources&gt;
                    &lt;fileset&gt;
                        &lt;directory&gt;${pom.basedir}/src/test/java&lt;/directory&gt;
                        &lt;includes&gt;&lt;include&gt;**/*.groovy&lt;/include&gt;&lt;/includes&gt;
                    &lt;/fileset&gt;
                &lt;/sources&gt;
            &lt;/configuration&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;
</pre>
<p>Příklad popisuje možnost, kdy jsou .groovy zdrojáky ve stejném adresáři jako testy v Javě. Pokud bychom testy umístili do adresáře src/test/groovy, nebylo by třeba v konfiguraci zahrnovat uvedený fileset.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2011/03/proc-psat-javovske-testy-v-groovy-ii/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

