<?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, 17 May 2012 10:01:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>DB žurnál pomocí Hibernate interceptoru</title>
		<link>http://www.aspectworks.com/2012/04/db-zurnal-pomoci-hibernate-interceptoru</link>
		<comments>http://www.aspectworks.com/2012/04/db-zurnal-pomoci-hibernate-interceptoru#comments</comments>
		<pubDate>Tue, 10 Apr 2012 07:33:34 +0000</pubDate>
		<dc:creator>Jan Pacek</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=3543</guid>
		<description><![CDATA[Na mnoha projektech je třeba řešit databázový žurnál aplikace, který zaznamenává události v systému včetně dat, která při těchto událostech byla změněna či jen čtena. Zákazníci často požadují u událostí,<a href="http://www.aspectworks.com/2012/04/db-zurnal-pomoci-hibernate-interceptoru" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Na mnoha projektech je třeba řešit databázový žurnál aplikace, který zaznamenává události v systému včetně dat, která při těchto událostech byla změněna či jen čtena. Zákazníci často požadují u událostí, které mění data, žurnálovat jak staré tak i nové hodnoty záznamu.</p>
<p>Implementace takového mechanismu přímo na DAO vrstvě by byla pracná a hlavně složitě konfigurovatelná. Řešení žurnálování na úrovni databázových procedur a triggerů by zase zrušilo nezávislost aplikace na konkrétním typu databáze. Hibernate pro žurnálování nabízí zajímavou funkčnost <strong>interceptor</strong> pro zachycení a zpracování různých událostí, jako například databázové CRUD operace.<br />
<span id="more-3543"></span></p>
<p>Vycházím z <a title="http://www.mkyong.com/hibernate/hibernate-interceptor-example-audit-log/" href="http://www.mkyong.com/hibernate/hibernate-interceptor-example-audit-log/">příkladu použití interceptoru na audit log (žurnál)</a> a samozřejmě ze samotné dokumentace <a title="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/events.html" href="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/events.html">http://docs.jboss.org/hibernate/core/3.3/reference/en/html/events.html</a></p>
<p>Po menší modifikaci lze uvedený příklad použít i na žurnálování starých a nových hodnot. Vytvořímě si entitu <strong>AuditLogData</strong> pro ukládání změněných hodnot a přidáme ji do entity <strong>AuditLog</strong>.</p>
<pre class="brush: java; title: ; notranslate">
@Entity @Table(name = &quot;auditlog&quot;, catalog = &quot;mkyong&quot;)
public class AuditLog implements java.io.Serializable {
private Long auditLogId;
private String action;
private String detail;
private Date createdDate;
private Long entityId;
private String entityName;
@OneToMany() @JoinColumn (name = &quot;auditLogId&quot;) @OrderBy(&quot;propertyName&quot;)
privateList auditLogData;
...
}
</pre>
<p>&nbsp;</p>
<pre class="brush: java; title: ; notranslate">
@Entity @Table(name = &quot;auditlogdata&quot;, catalog = &quot;mkyong&quot;)
public class AuditLogData implements java.io.Serializable {
private Long auditLogDataId;
private String propertyName;
private String oldValue;
private String newValue;
...
}
</pre>
<p>Při ukládání záznamu budeme pracovat přímo se záznamem AuditLog třídy a ne pouze s entity.</p>
<pre class="brush: java; title: ; notranslate">
public boolean onFlushDirty(Object entity,Serializable id,
                Object[] currentState,Object[] previousState,
                String[] propertyNames,Type[] types)
                throws CallbackException {
                ...
   if (entity instanceof IAuditLog){
       AuditLog auditRecord = new AuditLog(&quot;Updated“,entity.getLogDeatil(), new Date(),entity.getId(), entity.getClass().toString());
       fillChangedData(auditRecord, previousState,  currentState, propertyNames, entity);
	 //Add the auditLog to be saved as update after commit of transaction
       updates.add(auditRecord);
   }
   return false;
}
</pre>
<p>Kde plnění změněných dat by mohlo vypadat přibližně následovně:</p>
<pre class="brush: java; title: ; notranslate">
private void fillChangedData(AuditLog auditLog, Object[] startState, Object[] endState, String[] propertyNames, Object newObject, Long persistedObjectId)
           throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        //check input parameters
        …
        for (int i = 0; i &lt; propertyNames.length; i++) {
            //check if the property has been changed
            if (propertyValueChanged(startState[i], endState[i])) {
                // property changed, add it to auditLog.auditLogData list
                final String pn = propertyNames[i];
                String valueOld = propertyValueToString(startState[i]);
                String valueNew = propertyValueToString(endState[i]);
                addDataToAuditLog(auditLog, pn, valueOld, valueNew);
            }
        }
    }
</pre>
<p>Jak je na příkladu vidět, Hibernate interceptor je mohutný nástroj, který umožňuje na aplikační úrovni nejen odchytávat operace nad databází, ale i dále zpracovávat jejich data.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2012/04/db-zurnal-pomoci-hibernate-interceptoru/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Quartz Scheduler a dynamické plánování úloh</title>
		<link>http://www.aspectworks.com/2012/03/quartz-scheduler-a-dynamicke-planovani-uloh</link>
		<comments>http://www.aspectworks.com/2012/03/quartz-scheduler-a-dynamicke-planovani-uloh#comments</comments>
		<pubDate>Tue, 27 Mar 2012 09:24:13 +0000</pubDate>
		<dc:creator>Jan Bumbala</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[quartz]]></category>
		<category><![CDATA[scheduler]]></category>
		<category><![CDATA[spring]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=3416</guid>
		<description><![CDATA[Na zákaznickém projektu bylo potřeba umožnit asynchronní spouštění různých handlerů, registrovaných jako Spring bean. Typicky jde o případ, kdy uživatel iniciuje vykonání nějaké činnosti, která může trvat desítky sekund nebo<a href="http://www.aspectworks.com/2012/03/quartz-scheduler-a-dynamicke-planovani-uloh" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Na zákaznickém projektu bylo potřeba umožnit asynchronní spouštění různých handlerů, registrovaných jako Spring bean. Typicky jde o případ, kdy uživatel iniciuje vykonání nějaké činnosti, která může trvat desítky sekund nebo dokonce minut. Zároveň jsme potřebovali, aby řešení bylo persistentní, a tedy aby se naplánované úlohy neztrácely při pádu serveru.<br />
Protože jsme již na projektu využívali Quartz Scheduler pro spouštění pravidelných úloh, použili jsme ho i pro účel tohoto asynchronního zpracování.<br />
<span id="more-3416"></span><br />
Scénář použití Quartz Scheduleru, se kterým jsem se nejčastěji setkal, je takový, že v systému jsou předem nakonfigurované joby, které chceme spouštět, a více či méně složité triggery. Každý job je jednoúčelový a spouští předem definovanou business logiku. Pokud chceme umožnit vyvolávat nějaký nový handler, je potřeba přidat a nakonfigurovat nový Quartz job.</p>
<p>Zde popisované řešení je trochu jiné v tom, že je definované obecné API pro naplánování asynchronního zpracování. Motivací bylo umožnit asynchronní procesing handleru bez nutnosti statické konfigurace Quartz jobu pro každý takový handler. Pro každou naplánovanou úlohu je použit společný Quartz job, který v okamžiku vyvolání vyhledá požadovaný handler ve Spring contextu a spustí jej. Přidání nového handleru, nového typu úlohy kterou chceme asynchronně spouštet, pak nevyžaduje žádné další konfigurační změny Quartz scheduleru, pouze konfiguraci nového beanu ve Spring kontextu.</p>
<p>Pro vyvolání metody na Spring beanu již existuje <code><a title="MethodInvokingJobDetailFactoryBean" href="http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/scheduling/quartz/MethodInvokingJobDetailFactoryBean.html">MethodInvokingJobDetailFactoryBean</a></code>, jenže tento způsob neumožňuje předat metodě parametry. Navíc i zde je potřeba mít pro každý bean nakonfigurovaný vlastní trigger. V našem scénáři nechceme pro každý springový bean definovat nový trigger, pouze definujeme a nakonfigurujeme univerzální scheduler vrstvu. Popsané řešení je sice závislé na Springu, nicméně klientský kód je oddělený interfacem, takže není až takový problém vytvořit implementaci, která Spring používat nebude.</p>
<h3>Implementace</h3>
<p><a href="http://www.aspectworks.com/wp-content/uploads/2012/03/Scheduler-schema.gif" rel="lightbox[3416]"><img src="http://www.aspectworks.com/wp-content/uploads/2012/03/Scheduler-schema.gif" alt="" title="Scheduler-schema" width="696" height="244" class="size-full wp-image-3549" /></a></p>
<p>Celý mechanismus je skrytý za API, které tvoří 2 třídy:<br />
-<em><code>SchedulerDAO</code></em> &#8211; určeno pro přístup z business logiky, pomocí tohoto interfacu se naplánuje asynchronní zpracování<em></em><br />
-<em><code>Task</code></em> &#8211; rozhraní, které musí naimplementovat handler, který chceme asynchronně spouštět</p>
<pre class="brush: java; title: ; notranslate">
public interface SchedulerDAO {
    /**
     * Schedule task for asynchronous processing.
     * @param taskClass task that is about to be executed asynchronously
     * @param properties data to be passed to the task
     */
    &lt;T extends Task&gt; void schedule(Class&lt;T&gt; taskClass, Properties properties);
}
</pre>
<pre class="brush: java; title: ; notranslate">
public interface Task {
    /**
	 * run scheduled action
	 * @param properties data the task was scheduled with
	 */
	void run(Properties properties);
}
</pre>
<p>Jednoduchá implementace SchedulerDAO může vypadat takto:</p>
<pre class="brush: java; title: ; notranslate">
public class SimpleSchedulerDAO implements SchedulerDAO {
	//...instance variables omitted..
    public SimpleSchedulerDAO(Scheduler scheduler, String jobName, String jobGroup, String classNameProperty) {
        this.scheduler = scheduler;
        this.jobName = jobName;
        this.jobGroup = jobGroup;
        this.classNameProperty = classNameProperty;
    }
    public &lt;T extends Task&gt; void schedule(Class&lt;T&gt; taskClass, Properties properties) {
        JobDataMap jobDataMap = new JobDataMap(properties);
        //todo validation that classNameProperty not present in passed properties
        jobDataMap.put(classNameProperty, taskClass.getName());
        try {
            scheduler.triggerJob(jobName, jobGroup, jobDataMap);
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }
}
</pre>
<p>Navržená implementace naplánuje jeden univerzální job, společný pro všechny <code>Task</code> implementace. Pokaždé je vytvořen nový trigger, který je okamžitě naplánován ke spuštění. Složitější implementace může např. získávat instanci triggeru pomocí trigger factory, kde bude vyřešena různá konfigurace triggeru pro různé typy handlerů.<br />
Důležité je, že do persistentních dat daného triggeru (jobDataMap) se uloží název třídy/interface, který chceme asynchronně spustit. Tj. název třídy, která byla jako parametr předána metodě <code>schedule(..)</code>. V okamžiku, kdy Quartz vyvolá takto vytvořený trigger, se podle uloženého názvu třídy vyhledá Springový bean, který chceme zavolat (viz dále). Třída jobu je konfigurovatelná, stejně jako název skupiny a klíč, pod kterým je uložený persistovaný název třídy.</p>
<p>Ukázková konfigurace Spring contextu:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;bean id=&quot;simpleSchedulerDAO&quot; class=&quot;com.aspectworks.example.scheduler.impl.SimpleSchedulerDAO&quot;&gt;
   &lt;constructor-arg index=&quot;0&quot; ref=&quot;scheduler&quot;/&gt;
   &lt;constructor-arg index=&quot;1&quot; value=&quot;taskExecutorJob&quot;/&gt;
   &lt;constructor-arg index=&quot;2&quot; value=&quot;taskGroup&quot;/&gt;
   &lt;constructor-arg index=&quot;3&quot; value=&quot;@className&quot;/&gt;
&lt;/bean&gt;
&lt;bean name=&quot;taskExecutorJob&quot; class=&quot;org.springframework.scheduling.quartz.JobDetailBean&quot;&gt;
   &lt;property name=&quot;jobClass&quot; value=&quot;com.aspectworks.example.scheduler.impl.TaskExecutorJob&quot;/&gt;
   &lt;property name=&quot;group&quot; value=&quot;taskGroup&quot;/&gt;
&lt;/bean&gt;
&lt;bean id=&quot;scheduler&quot; class=&quot;org.springframework.scheduling.quartz.SchedulerFactoryBean&quot; destroy-method=&quot;destroy&quot;&gt;
   &lt;property name=&quot;jobFactory&quot;&gt;
      &lt;bean class=&quot;org.springframework.scheduling.quartz.SpringBeanJobFactory&quot;/&gt;
   &lt;/property&gt;
   &lt;property name=&quot;applicationContextSchedulerContextKey&quot; value=&quot;applicationContext&quot;/&gt;
   &lt;property name=&quot;schedulerContextAsMap&quot;&gt;
      &lt;map&gt;
	     &lt;entry key=&quot;classNameProperty&quot; value=&quot;@className&quot;/&gt;
	  &lt;/map&gt;
   &lt;/property&gt;
   &lt;property name=&quot;jobDetails&quot;&gt;
      &lt;list&gt;
	     &lt;ref bean=&quot;taskExecutorJob&quot;/&gt;
      &lt;/list&gt;
   &lt;/property&gt;
&lt;/bean&gt;
</pre>
<p>V konfiguraci je vidět název třídy společného Quartz jobu &#8211; <code>TaskExecutorJob</code>, který je spouštěn všemi triggery. Job se chová tak, že podle názvu interface uloženého v persistentních datech triggeru nalezne Springový bean, a na něm spustí metodu run(). Za zmínku stojí ještě čtvrtý parametr konstruktoru <code>SimpleSchedulerDAO</code>, jedná se o název klíče, pod kterým bude v persistentních datech triggeru uložen název třídy Spring beanu, zde tedy hodnota <code>"@className"</code>. V implementaci <code>SimpleSchedulerDAO</code> je vhodné dodělat kontrolu, že předané properties neobsahují klíč, který by kolidoval s hodnotou <code>classNameProperty</code>, a ještě lépe tuto hodnotu pevně stanovit a zdokumentovat v API.<br />
Na závěr tedy ještě implementace samotného jobu, zde se vyhledá a spustí naplánovaný handler.</p>
<pre class="brush: java; title: ; notranslate">
public class TaskExecutorJob implements Job{
    private String classNameProperty;
    private ApplicationContext applicationContext;
    public void execute(JobExecutionContext context) throws JobExecutionException {
	    //read class from persisted data
        Class taskClass = readClass(context, classNameProperty);
		//lookup bean instance
        Task task = lookupJobBean(taskClass);
        if (task != null) {
            Properties properties = new Properties();
            properties.putAll(context.getTrigger().getJobDataMap());
            properties.remove(classNameProperty);
			//finally execute the target task
            task.run(properties);
        }
    }
    /**
     * read persisted Task class name from trigger's jobDataMap
     */
    protected  Class readClass(JobExecutionContext context, String beanClassKey) {
        String beanClassName = context.getTrigger().getJobDataMap().getString(beanClassKey);
        try {
            if (beanClassName != null){
                return (Class) Class.forName(beanClassName);
            }
        } catch (ClassNotFoundException e) {
            //log error
        }
        return null;
    }
    /**
     * lookup Task implementation from Spring context
     */
    protected  T lookupJobBean(Class clazz){
        if (clazz != null){
            try {
                return applicationContext.getBean(clazz);
            } catch (BeansException e) {
                //log error
            }
        }
        return null;
    }
}
</pre>
<h3>Možné nevýhody</h3>
<p>Existuje zde ovšem také jeden nedostatek. Klientský kód je sice oddělený dvěma rozhraními (<code>Task</code> a <code>SchedulerDAO</code>), nicméně popsané řešení je orientované na Spring framework a toto má jeden dopad: je potřeba, aby handler, který chceme asynchronně spouštět, definoval <em>nové rozhraní</em> rozšiřující interface <code>Task</code>. Například takto:</p>
<pre class="brush: java; title: ; notranslate">
public interface TestingTask extends Task{
}
public class TestingTaskImpl implements TestingTask {
    public void run(Properties properties) {
      //do something..
    }
}
</pre>
<p>Nelze definovat přímo implementaci interface <code>Task</code> a tuto se snažit naplánovat přes <code>SchedulerDAO</code>. Jde o to, jak funguje Springový lookup <code>BeanFactory.getBean(Class requiredType)</code>: pokud Spring pro AOP používá jdk proxy, nebude možné provést lookup Spring beanu podle jeho implementace, pouze podle interface. Dále je nutné, aby v kontextu byla registrovaná od každého tohoto rozhraní pouze jedna implementace. Popsané řešení by bylo možné změnit např. tak, že scheduling nebude probíhat na základě rozhraní handleru, ale pomocí jména beanu. Toto by ovšem do kódu zaneslo mnohem větší závislosti na Spring frameworku.</p>
<p>Budu rád, pokud se podělíte se svými názory, či jste třeba řesili něco podobného, nebo zda v tom vidíte nějaké problémy.</p>
<p>Ukázkový funkční příklad si můžete stáhnout zde: <a href="http://www.aspectworks.com/wp-content/uploads/2012/03/quartz-example.zip">quartz-example.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2012/03/quartz-scheduler-a-dynamicke-planovani-uloh/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Eclipse efektivně (4.)</title>
		<link>http://www.aspectworks.com/2012/02/eclipse-efektivne-4</link>
		<comments>http://www.aspectworks.com/2012/02/eclipse-efektivne-4#comments</comments>
		<pubDate>Fri, 24 Feb 2012 10:07:51 +0000</pubDate>
		<dc:creator>Luboš Račanský</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Eclipse]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=3219</guid>
		<description><![CDATA[K psaní seriálu Eclipse efektivně nás motivuje pozorování, že někteří (i zkušení) vývojáři nejsou dostatečně efektivní při práci s Eclipse&#160;IDE. Možná, že některé tipy, které našim stážistům vtloukáme do hlavy,<a href="http://www.aspectworks.com/2012/02/eclipse-efektivne-4" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>K psaní seriálu <em>Eclipse efektivně</em> nás motivuje pozorování, že někteří (i zkušení) vývojáři nejsou dostatečně efektivní při práci s Eclipse&nbsp;IDE. Možná, že některé tipy, které našim <a href="http://www.aspectworks.com/2011/10/v-aspectworks-uspesne-odstartovala-podzimni-java-staz">stážistům</a> vtloukáme do hlavy, se budou hodit i vám.</p>
<p>Tentokrát se zaměřím na to, jak získat přehledný výpis chyb. Dále nastavení generování metod equals a hashCode. Nechybí vám, že content assist nenabízí statické importy? Víte, že find dialog dokáže hledat zároveň jak píšete? Nakonec se naučíme kouzlit s řádky.</p>
<p><span id="more-3219"></span></p>
<h3>Problems View</h3>
<p><a href="http://www.aspectworks.com/wp-content/uploads/2012/02/Errors_highlighted.png" rel="lightbox[3219]"><img src="http://www.aspectworks.com/wp-content/uploads/2012/02/Errors_highlighted-1024x401.png" alt="" title="Errors" width="640" height="250" class="alignnone size-large wp-image-3225" /></a></p>
<p>V ideálním případě by měl být workspace bez jakýchkoliv chyb a varování, jenže v praxi se vám dostane pod ruku všelijaký kód. V záplavě chyb pak potřebujete rozeznat, která chyba je ještě „dobrá“. Osobně mám <em>Problems view</em> zapnuté na <em>Group By -> Java Problem Type</em>.</p>
<p>Kdy naposledy jste měli ve workspace otevřený jen jeden projekt? Na přehlednosti nepřidá, když se chyby sesypou na jednu hromadu. Pomůže zapnout <em>Show -> Error/Warnings on Project</em>, což umožní zobrazit chyby pouze z aktuálního projektu.</p>
<h3>Checkstyle &#8211; Need Braces</h3>
<p><a href="http://www.aspectworks.com/wp-content/uploads/2012/02/Generate_hashCode_equals_hightlighted.png" rel="lightbox[3219]"><img src="http://www.aspectworks.com/wp-content/uploads/2012/02/Generate_hashCode_equals_hightlighted-267x300.png" alt="" title="Generate hashCode equals" width="267" height="300" class="alignnone size-medium wp-image-3226" /></a></p>
<p>Jistě každý blok za <em>if</em> výrazem dáváte do složených závorek. O to víc vás pak musí rozzlobit, že <a href="http://checkstyle.sourceforge.net/">Checkstyle</a> v <a href="http://www.sonarsource.org/">Sonaru</a> hlásí: </p>
<p><em>Checkstyle Need Braces (&#8216;if&#8217; construct must use &#8216;{}&#8217;s.)</em></p>
<p>Příčinou bude s největší pravděpodobností automaticky generovaný kód (kdo by ho kontroloval) metod <em>equals</em> a <em>hashCode</em>. Přitom stačí zaškrtnout volbu <em>Use blocks in &#8216;if&#8217; statements</em></p>
<h3>Content assist &#8211; Import static members</h3>
<p><a href="http://www.aspectworks.com/wp-content/uploads/2012/02/imports.png" rel="lightbox[3219]"><img src="http://www.aspectworks.com/wp-content/uploads/2012/02/imports-300x283.png" alt="" title="Content assist will propose those static members even if the import is missing" width="300" height="283" class="alignnone size-medium wp-image-3227" /></a></p>
<p>Nevím jak vás, ale mě při psaní testů v Eclipse vytáčelo, že mi <em>ctrl + mezerník</em> (content assist) nenabízí <em>assertXXX</em>. Musíte si ručně nastavit oblíbené statické importy, které má <em>content assist</em> nabízet. Někteří kolegové mají sice proti konstruktu statických importů námitky, ale zdá se mi, že kód je pak méně ukecaný.</p>
<h3>Find/Replace</h3>
<p><a href="http://www.aspectworks.com/wp-content/uploads/2012/02/search_highlighted.png" rel="lightbox[3219]"><img src="http://www.aspectworks.com/wp-content/uploads/2012/02/search_highlighted-217x300.png" alt="" title="Find/Replace" width="217" height="300" class="alignnone size-medium wp-image-3228" /></a></p>
<p>Občas vídám programátory, jak ve <em>Find</em> dialogu napíšou hledaný řetězec, kliknou na tlačítko Find. Následně zjistí, že se přepsali, tak řetězec opraví a opět kliknout na tlačítko. Hrůza! Téměř stále mám zaškrtnutou volbu <em>Incremental</em>, což znamená, že se řetězec vyhledává zároveň jak píšu. Find dialog má ještě jednu šikovnou volbu a to <em>Wrap search</em>, která způsobí, že když hledání dojde na konec stránky, tak pokračuje opět od začátku.</p>
<h3>Kouzla s řádky</h3>
<p>Někdy se mi zdá, že se programátoři chtějí klávesovými zkratkami <em>ctrl + C</em>, <em>ctrl + X</em> a <em>ctrl + V</em> uklikat k smrti. Za domácí úkol doučit.</p>
<dl>
<dt>Duplikovat řádek</dt>
<dd>ctrl + alt + šipka nahoru/dolů</dd>
<dt>Posunout řádek</dt>
<dd>alt + šipka nahoru/dolů</dd>
<dt>Smazat řádek</dt>
<dd>ctrl + D</dd>
</dl>
<h3>Závěr</h3>
<p>Věřím, že pokud jste výše zmíněné postupy neznali, tak si je rychle oblíbíte. Mohly by vás zajímat i předchozí díly seriálu Eclipse efektivně.</p>
<ul>
<li><a href="http://www.aspectworks.com/2009/09/eclipse-efektivne-1-content-assist/">Eclipse efektivně (1.) – Content Assist</a></li>
<li><a href="http://www.aspectworks.com/2009/10/eclipse-efektivne-2-quick-fix/">Eclipse efektivně (2.) – Quick Fix</a></li>
<li><a href="http://www.aspectworks.com/2010/10/eclipse-efektivne-3-team-synchronizing">Eclipse efektivně (3.) – Team Synchronizing</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2012/02/eclipse-efektivne-4/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Od Sysdeo v Eclipse k tc Serveru v STS</title>
		<link>http://www.aspectworks.com/2012/02/od-sysdeo-v-eclipse-k-tc-serveru-v-sts</link>
		<comments>http://www.aspectworks.com/2012/02/od-sysdeo-v-eclipse-k-tc-serveru-v-sts#comments</comments>
		<pubDate>Tue, 07 Feb 2012 08:53:37 +0000</pubDate>
		<dc:creator>Luboš Račanský</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Java]]></category>
		<guid isPermaLink="false">http://www.aspectworks.com/?p=3165</guid>
		<description><![CDATA[Při vývoji webových aplikací používáme Eclipse IDE. Z workspace dostáváme Maven závislosti na Tomcat pomocí pluginu Sysdeo. Toto řešení funguje, ale není ideální. Nastavení aplikace lze ovšem jednoduše upravit tak,<a href="http://www.aspectworks.com/2012/02/od-sysdeo-v-eclipse-k-tc-serveru-v-sts" class="moreLink">více&#160;»</a>]]></description>
			<content:encoded><![CDATA[<p>Při vývoji webových aplikací používáme Eclipse IDE. Z workspace dostáváme Maven závislosti na Tomcat pomocí pluginu <a href="http://mojo.codehaus.org/sysdeo-tomcat-maven-plugin/">Sysdeo</a>. Toto řešení funguje, ale není ideální. Nastavení aplikace lze ovšem jednoduše upravit tak, aby šla spouštět na tc Serveru přímo z <a>STS (SpringSource Tool Suite)</a>.<br />
<span id="more-3165"></span></p>
<p>Proč měnit Sysdeo za tc Server v STS? Kromě toho, že se Sysdeo musíte myslet na ruční spouštění buildu (sysdeo-tomcat:generate), tak je navíc potřeba nahrát do Tomcat lib <a href="http://www.eclipsetotale.com/tomcatPlugin.html">DevLoader.jar</a> a modifikovat konfiguraci <code>/conf/Catalina/localhost/myApp.xml</code>. To je důvod, proč někteří <a href="http://www.aspectworks.com/2011/12/intellij-idea-pro-vyvoj-v-jave">kolegové přešli na IntelliJ Idea</a>. V neposlední řadě STS přináší, což pro mě je největší lákadlo, profiler <a href="http://www.springsource.org/insight">Spring Insight</a>.</p>
<p>Nejprve potřebujete zpřístupnit volbu <code>Run As -&gt; Run on Server</code>. Toho docílíte tím, že v nastavením projektu (<code>Properties -&gt; Project Facets</code>) přidáte facet <strong>Dynamic Web Modul</strong> (vyžaduje Java facet). Jste-li dítětem štěstěny, tak již nyní se vám podaří spustit aplikaci na tc&nbsp;Serveru.</p>
<p>S největší pravděpodobností se ale aplikace nejspíš nebude správně deployovat do <code>/home/user/springsource/vfabric-tc-server-developer-2.6.1.RELEASE/spring-insight-instance/wtpwebapps/myApp</code> (výchozí instalace na Linuxu, uživatel <code>user</code>, aplikace <code>myApp</code>).</p>
<p>Překontrolujte soubor <code>org.eclipse.wst.common.project.facet.core.xml</code> v adresáři <code>.settings</code></p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;faceted-project&gt;
  &lt;fixed facet=&quot;wst.jsdt.web&quot;/&gt;
  &lt;installed facet=&quot;java&quot; version=&quot;1.6&quot;/&gt;
  &lt;installed facet=&quot;jst.web&quot; version=&quot;2.4&quot;/&gt;
  &lt;installed facet=&quot;wst.jsdt.web&quot; version=&quot;1.0&quot;/&gt;
&lt;/faceted-project&gt;
</pre>
<p>Dále soubor org.eclipse.wst.common.component tamtéž</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project-modules id=&quot;moduleCoreId&quot; project-version=&quot;1.5.0&quot;&gt;
    &lt;wb-module deploy-name=&quot;myAppl&quot;&gt;
        &lt;wb-resource deploy-path=&quot;/&quot; source-path=&quot;/src/main/webapp&quot;/&gt;
        &lt;wb-resource deploy-path=&quot;/WEB-INF/classes&quot; source-path=&quot;/src/main/java&quot;/&gt;
        &lt;wb-resource deploy-path=&quot;/WEB-INF/classes&quot; source-path=&quot;/src/main/resources&quot;/&gt;
        &lt;property name=&quot;context-root&quot; value=&quot;myApp&quot;/&gt;
        &lt;property name=&quot;java-output-path&quot; value=&quot;target/classes&quot;/&gt;
    &lt;/wb-module&gt;
&lt;/project-modules&gt;
</pre>
<p>V souboru <code>.classpath</code> budete mít svoje specifické nastavení, nicméně neměla by tam chybět násludující část.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;classpathentry kind=&quot;con&quot; path=&quot;org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER&quot;&gt;
	&lt;attributes&gt;
		&lt;attribute name=&quot;org.eclipse.jst.component.dependency&quot; value=&quot;/WEB-INF/lib&quot;/&gt;
	&lt;/attributes&gt;
&lt;/classpathentry&gt;
&lt;classpathentry kind=&quot;con&quot; path=&quot;org.eclipse.jst.j2ee.internal.web.container&quot;/&gt;
&lt;classpathentry kind=&quot;con&quot; path=&quot;org.eclipse.jst.j2ee.internal.module.container&quot;/&gt;
</pre>
<p>Nyní můžete aplikaci spouštět na tc Serveru z STS a využívat možností profileru Spring Insight (o tom v některém z dalších příspěvků).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.aspectworks.com/2012/02/od-sysdeo-v-eclipse-k-tc-serveru-v-sts/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<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 Čečrdle</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 Čečrdle</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>
	</channel>
</rss>

