<?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>Cygni&#187; Stacktrace</title>
	<atom:link href="http://cygni.se/kategori/stacktrace/feed/" rel="self" type="application/rss+xml" />
	<link>http://cygni.se</link>
	<description>expertis inom agil systemutveckling på moderna plattformar</description>
	<lastBuildDate>Tue, 07 Feb 2012 21:53:25 +0000</lastBuildDate>
	<language>sv</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Synkronisering av multipla Google Calendars med iPhone</title>
		<link>http://cygni.se/2012/01/24/synkronisering-av-multipla-google-calendars-med-iphone/</link>
		<comments>http://cygni.se/2012/01/24/synkronisering-av-multipla-google-calendars-med-iphone/#comments</comments>
		<pubDate>Tue, 24 Jan 2012 07:19:05 +0000</pubDate>
		<dc:creator>Nathalie Sandström</dc:creator>
				<category><![CDATA[Stacktrace]]></category>
		<category><![CDATA[cygni]]></category>
		<category><![CDATA[e-post]]></category>
		<category><![CDATA[exchange]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[microsoft]]></category>

		<guid isPermaLink="false">http://cygni.se/?p=3598</guid>
		<description><![CDATA[På Cygni använder vi Google Apps för en stor del av all kommunikation: e-post, kalendrar, wiki, kontakter o.s.v. vilket fungerar grymt. Kalenderbiten är en viktig del och personligen har jag ett tiotal olika kalendrar &#8211; egna som andras, privata som arbetsrelaterade &#8211; kopplade till mitt konto. I kombination med detta kör jag iPhone, både privat ...]]></description>
			<content:encoded><![CDATA[<p>På Cygni använder vi Google Apps för en stor del av all kommunikation: e-post, kalendrar, wiki, kontakter o.s.v. vilket fungerar grymt. Kalenderbiten är en viktig del och personligen har jag ett tiotal olika kalendrar &#8211; egna som andras, privata som arbetsrelaterade &#8211; kopplade till mitt konto. I kombination med detta kör jag iPhone, både privat och på jobbet, och ser det som en nödvändighet att kunna nå och editera mina kalendrar från den enheten.</p>
<p>Det finns redan mängder med tutorials över hur man sätter upp Google-konton på sin iPhone men jag har upplevt det aningen problematiskt att synka multipla Google-kalendrar och tänker mig att detta inlägg får fungera som en steg för steg-guide över hur jag fick till synkningen. Jag har en iPhone 3GS med iOS 5 och använder mig av <a href="http://www.google.se/mobile/sync/">Google Sync</a> för synkronisering.</p>
<p>Har du inte redan satt upp ett Google-konto på din iPhone följer du dessa steg:</p>
<ol>
<li>Under inställningsmenyn på din iPhone väljer du<strong> E-post, kontakter, kalendrar</strong></li>
<li><strong>Lägg till konto</strong></li>
<li>Välj att skapa ett <strong>Microsoft Exchange</strong>-konto (vilket är det protokoll Google Sync använder vid synkronisering till iPhone)</li>
</ol>
<p><a href="http://cygni.se/2012/01/24/synkronisering-av-multipla-google-calendars-med-iphone/gallery1-5/" rel="attachment wp-att-3636"><img src="http://cygni.se/wp-uploads/2011/10/gallery14.png" alt="Add Microsoft Exchange account" width="550" height="255" class="alignnone size-full wp-image-3636" /></a></p>
<ol start="4">
<li>Under <strong>E-post</strong> fyller du i din fullständiga e-postadress</li>
<li>Lämna <strong>domän</strong>fältet tomt</li>
<li>Fyll i din fullständiga e-postadress under <strong>Användarnamn</strong></li>
<li>Skriv in <strong>lösenordet</strong> för ditt Google-konto</li>
<li>Klicka på <strong>Nästa</strong></li>
<li>När fältet <strong>Server</strong> poppar upp fyller du i <em>m.google.com</em></li>
<li>Klicka på <strong>Nästa</strong></li>
<li>Välj vad du vill synka (denna guide kräver att du åtminstone väljer att synka kalendrar)</li>
</ol>
<p><a href="http://cygni.se/2012/01/24/synkronisering-av-multipla-google-calendars-med-iphone/gallery2/" rel="attachment wp-att-3637"><img src="http://cygni.se/wp-uploads/2011/10/gallery2.png" alt="Account information" width="550" height="255" class="alignnone size-full wp-image-3637" /></a></p>
<p>Setup av synkroniseringen är nu klar och beroende på vad du i steg 11 valde att synka kommer det nu att pushas ut information till din iPhone.</p>
<p>Med Google Sync kan du synka upp till 25 kalendrar på din iPhone vilket man enkelt ska kunna sätta upp genom att surfa in på <a href="http://m.google.com/sync">http://m.google.com/sync</a> och logga in på sitt konto. Här stötte jag dock på problem. Sidan talade om för mig att Google Sync tyvärr inte kunde stödja min enhet eftersom jag var tvungen att ha iOS 3 eller senare &#8211; något som jag uppenbarligen hade då jag precis uppdaterat till iOS 5.</p>
<p><a href="http://cygni.se/2012/01/24/synkronisering-av-multipla-google-calendars-med-iphone/error/" rel="attachment wp-att-3638"><img src="http://cygni.se/wp-uploads/2011/10/error.png" alt="" width="260" height="400" class="alignnone size-full wp-image-3638" /></a></p>
<p>Efter en tids undersökning kunde jag konstatera att detta var en bugg fler användare upplevt och en konsekvens av att Google Sync befinner sig i ett beta-stadie. Sajten kräver att sidan presenteras på engelska och det du behöver göra för att komma runt problemet är att byta språk från svenska till just engelska enligt nedan steg:</p>
<ol start="12">
<li>Med din iPhone, surfa in på <a href="http://m.google.com/sync">http://m.google.com/sync</a></li>
<li>För att ändra språk klickar du på länken <strong>Byt språk</strong> (jag valde English (UK))</li>
<li>Sidan laddas om och du har nu möjlighet att logga in. Gör detta genom att klicka på <strong>Sign in with your Google Account</strong></li>
<li>Du möts nu av de enheter du har satt upp ditt Google-konto på och genom att klicka dig in på de olika enheterna kan du välja exakt vilka kalendrar du vill synka</li>
</ol>
<p><a href="http://cygni.se/2012/01/24/synkronisering-av-multipla-google-calendars-med-iphone/gallery3/" rel="attachment wp-att-3639"><img src="http://cygni.se/wp-uploads/2011/10/gallery3.png" alt="Sync devices" width="550" height="410" class="alignnone size-full wp-image-3639" /></a></p>
<ol start="16">
<li>Efter att ha valt vilka kalendrar du vill synka och klickat på <strong>Save</strong> är du klar</li>
</ol>
<p>När du nu lägger till, editerar eller tar bort händelser i dina kalendrar kommer dessa speglas på alla enheter du synkat enligt ovan steg &#8211; detta gäller självfallet oberoende av om du gör förändringarna i kalendern på din iPhone eller i webbgränssnittet på din dator.</p>
<p><a href="http://cygni.se/2012/01/24/synkronisering-av-multipla-google-calendars-med-iphone/gallery4/" rel="attachment wp-att-3640"><img src="http://cygni.se/wp-uploads/2011/10/gallery4.png" alt="Devices synced" width="550" height="300" class="alignnone size-full wp-image-3640" /></a></p>

	Tags: <a href="http://cygni.se/taggar/cygni/" title="cygni" rel="tag">cygni</a>, <a href="http://cygni.se/taggar/e-post/" title="e-post" rel="tag">e-post</a>, <a href="http://cygni.se/taggar/exchange/" title="exchange" rel="tag">exchange</a>, <a href="http://cygni.se/taggar/iphone/" title="iphone" rel="tag">iphone</a>, <a href="http://cygni.se/taggar/microsoft/" title="microsoft" rel="tag">microsoft</a><br />
]]></content:encoded>
			<wfw:commentRss>http://cygni.se/2012/01/24/synkronisering-av-multipla-google-calendars-med-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mockning &#8211; @InjectMocks med Mockito</title>
		<link>http://cygni.se/2012/01/11/mockning-injectmocks-med-mockito/</link>
		<comments>http://cygni.se/2012/01/11/mockning-injectmocks-med-mockito/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 16:23:55 +0000</pubDate>
		<dc:creator>Leo Wentzel</dc:creator>
				<category><![CDATA[Stacktrace]]></category>
		<category><![CDATA[di]]></category>
		<category><![CDATA[ioc]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[java ee]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[mock objects]]></category>
		<category><![CDATA[mockito]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[tdd]]></category>

		<guid isPermaLink="false">http://cygni.se/?p=3848</guid>
		<description><![CDATA[När ett test skrivs för en klass som har beroenden till en datakälla, en extern service eller bara en annan klass är mockning ofta väldigt användbart. Ibland kan detta leda till att produktionskod anpassas för att det ska gå att skriva dessa tester. Nedan är exempel på ett test som testar en service som använder ...]]></description>
			<content:encoded><![CDATA[<p>När ett test skrivs för en klass som har beroenden till en datakälla, en extern service eller bara en annan klass är mockning ofta väldigt användbart. Ibland kan detta leda till att produktionskod anpassas för att det ska gå att skriva dessa tester. Nedan är exempel på ett test som testar en service som använder en entity manager.</p>
<pre class="brush: java; title: ;">
package se.cygni.blog;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import javax.persistence.EntityManager;

import org.junit.Before;
import org.junit.Test;

public class BlogServiceTest {

    private BlogService service;
    private EntityManager entityManager;

    @Before
    public void setup() {
        entityManager = mock(EntityManager.class);
        service = new BlogService(entityManager);
    }

    @Test
    public void addEntry() {
        Entry entry = new Entry(&quot;title&quot;, &quot;text&quot;);

        service.addEntry(entry);

        verify(entityManager).persist(entry);
    }

}
</pre>
<p>Testet i exemplet är relativt enkelt och verifierar endast att <em>persist</em> anropas i <em>addEntry</em> och ger oss  följande kod för ett Spring-baserat projekt:</p>
<pre class="brush: java; title: ;">
package se.cygni.blog;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class BlogService {

    @PersistenceContext
    private EntityManager entityManager;

    public BlogService() {
    }

    protected BlogService(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Transactional
    public void addEntry(Entry entry) {
        entityManager.persist(entry);
    }

}
</pre>
<p>För att kunna använda en mockad <em>entityManager</em> har vi lagt till en konstruktor som tar en <em>EntityManager</em> som <em>BlogService</em> sedan kan använda. Använder vi dessutom <em>&#8221;field injection&#8221;</em> är vi tvugna att lägga till en no-args-konstruktor. Alternativt hade vi kunnat lägga till en setter istället.</p>
<pre class="brush: java; title: ;">
    protected void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
</pre>
<p>Det är väl antagligen inte så illa att behöva lägga till konstruktorer alternativt setters även om det blir värre när en klass har flera beroenden. Däremot känns det ju lite onödigt när både Spring och Java EE numera stödjer <em>field injection</em>. Det går ju att köra enhetstesterna med till exempel Spring och låta Spring injicera alla beroenden. Detta anses dock inte helt lämpligt för enhetstester utan lämpar sig bättre för integrationstester. Istället kan <a href="http://code.google.com/p/mockito/">Mockito</a> ta hand om injicering, genom att köra testerna med <em>MockitoJUnitRunner</em> och använda annotationerna <em>@Mock</em> och <em><a href="http://docs.mockito.googlecode.com/hg/latest/org/mockito/InjectMocks.html">@InjectMocks</a></em>. Mockito fungerar då i princip som en enkel IOC-container och några extra konstruktorer eller setters behövs inte. </p>
<pre class="brush: java; title: ;">
package se.cygni.blog;

import static org.mockito.Mockito.verify;

import javax.persistence.EntityManager;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class BlogServiceTest {

    @Mock
    private EntityManager entityManager;

    @InjectMocks
    private BlogService service = new BlogService();

    @Test
    public void addEntry() {
        Entry entry = new Entry(&quot;title&quot;, &quot;text&quot;);

        service.addEntry(entry);

        verify(entityManager).persist(entry);
    }
}
</pre>

	Tags: <a href="http://cygni.se/taggar/di/" title="di" rel="tag">di</a>, <a href="http://cygni.se/taggar/ioc/" title="ioc" rel="tag">ioc</a>, <a href="http://cygni.se/taggar/java/" title="java" rel="tag">java</a>, <a href="http://cygni.se/taggar/java-ee/" title="java ee" rel="tag">java ee</a>, <a href="http://cygni.se/taggar/junit/" title="junit" rel="tag">junit</a>, <a href="http://cygni.se/taggar/mock-objects/" title="mock objects" rel="tag">mock objects</a>, <a href="http://cygni.se/taggar/mockito/" title="mockito" rel="tag">mockito</a>, <a href="http://cygni.se/taggar/spring/" title="spring" rel="tag">spring</a>, <a href="http://cygni.se/taggar/tdd/" title="tdd" rel="tag">tdd</a><br />
]]></content:encoded>
			<wfw:commentRss>http://cygni.se/2012/01/11/mockning-injectmocks-med-mockito/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java EE 6 med Spring MVC</title>
		<link>http://cygni.se/2011/12/19/java-ee-6-med-spring-mvc/</link>
		<comments>http://cygni.se/2011/12/19/java-ee-6-med-spring-mvc/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 08:13:19 +0000</pubDate>
		<dc:creator>Leo Wentzel</dc:creator>
				<category><![CDATA[Stacktrace]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[java ee]]></category>
		<category><![CDATA[java ee 6]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[spring mvc]]></category>

		<guid isPermaLink="false">http://cygni.se/?p=3784</guid>
		<description><![CDATA[Nyligen läste jag ett intressant blogginlägg där Spring jämfördes med Java EE 6. Författaren drar slutsatsen att det numera är minst lika enkelt att utveckla en applikation för Java EE-plattformen som för Spring. Då Spring, Spring MVC inkluderat, är väldigt populärt blev jag nyfiken på hur detta kan integreras med Java EE för att lättare ...]]></description>
			<content:encoded><![CDATA[<p>Nyligen läste jag ett intressant <a href="http://www.javacodegeeks.com/2011/11/from-spring-to-java-ee-6.html" title="Bloggartikel om Java EE 6" target="_blank">blogginlägg</a> där <a href="http://www.springsource.org/" title="Spring" target="_blank">Spring</a> jämfördes med Java EE 6. Författaren drar slutsatsen att det numera är minst lika enkelt att utveckla en applikation för Java EE-plattformen som för Spring. Då Spring, Spring MVC inkluderat, är väldigt populärt blev jag nyfiken på hur detta kan integreras med Java EE för att lättare dra nytta av allt som en Java EE-container kan erbjuda. Det visade sig att detta var förbluffande enkelt, till exempel går det utan ytterligare Spring-konfiguration direkt injicera en <em>Session Bean</em> i en Spring-controller.</p>
<pre class="brush: java; title: ;">
@Controller
public class MyController {

    @EJB(mappedName=&quot;java:module/MyService&quot;)
    private MyService myService;

    @RequestMapping(value = &quot;/&quot;, method = RequestMethod.GET)
    public String home(Model model) {
        model.addAttribute(&quot;message&quot;, myService.getMessage());
        return &quot;home&quot;;
    }
}
</pre>
<p>Nyckeln till att injektionen med <em>@EJB</em>-annotation fungerar, i exemplet ovan, är att <em>mappedName</em> används. Spring utför då en JNDI-lookup på det angivna JNDI-namnet. Eftersom JNDI har standardiserats i Java EE 6 är dessutom namnen portabla mellan applikationsservrar. Stödet för Java EE 6 kommer säkerligen förbättras i framtida versioner av Spring så det finns bra defaults för ejb-lookups med JNDI.</p>
<p>En annan spännande detalj med detta exempel är att <em>MyService</em> inte behöver vara ett interface eftersom Java EE 6 inte kräver detta för lokala session beans. Dessutom kan session beans paketeras tillsammans med resten av webbapplikationen i war-arkivet. D.v.s. det behövs ingen ejb-jar och inget EAR-arkiv. </p>
<p>Läs hela artikeln på <a href="http://www.javacodegeeks.com/2011/11/from-spring-to-java-ee-6.html" target="_blank" title="Java Code Geeks">Java Code Geeks</a>.</p>

	Tags: <a href="http://cygni.se/taggar/java/" title="java" rel="tag">java</a>, <a href="http://cygni.se/taggar/java-ee/" title="java ee" rel="tag">java ee</a>, <a href="http://cygni.se/taggar/java-ee-6/" title="java ee 6" rel="tag">java ee 6</a>, <a href="http://cygni.se/taggar/spring/" title="spring" rel="tag">spring</a>, <a href="http://cygni.se/taggar/spring-mvc/" title="spring mvc" rel="tag">spring mvc</a><br />
]]></content:encoded>
			<wfw:commentRss>http://cygni.se/2011/12/19/java-ee-6-med-spring-mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Best of Eclipse &#8211; Godbitar, kortkommandon mm</title>
		<link>http://cygni.se/2011/12/15/best-of-eclipse-godbitar-kortkommandon-mm/</link>
		<comments>http://cygni.se/2011/12/15/best-of-eclipse-godbitar-kortkommandon-mm/#comments</comments>
		<pubDate>Thu, 15 Dec 2011 09:25:07 +0000</pubDate>
		<dc:creator>Tommy Wassgren</dc:creator>
				<category><![CDATA[Stacktrace]]></category>
		<category><![CDATA[artiklar]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[stacktrace]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://cygni.se/?p=3644</guid>
		<description><![CDATA[Det finns mängder av artiklar här på Stacktrace som handlar om Eclipse. Jag tänkte samla ihop några godbitar som fortfarande känns relevanta. Roberts inlägg om kortkommandon och handgrepp är alltid högaktuellt. Inlägget visar bland annat på smarta kommandon för navigering och refactoring. Save Actions är ett ovärderligt verktyg om du vill hålla ordning och reda ...]]></description>
			<content:encoded><![CDATA[<p>Det finns mängder av artiklar här på Stacktrace som handlar om Eclipse. Jag tänkte samla ihop några godbitar som fortfarande känns relevanta.</p>
<ul>
<li>Roberts <a href="http://cygni.se/2007/11/27/eclipse-tips-och-tricks/" title="Eclipse Tips och Tricks">inlägg om kortkommandon och handgrepp</a> är alltid högaktuellt. Inlägget visar bland annat på smarta kommandon för navigering och refactoring.</li>
<li><a href="http://cygni.se/2009/10/07/save-actions-i-eclipse/" title="Eclipse Save Actions">Save Actions</a> är ett ovärderligt verktyg om du vill hålla ordning och reda i koden.</li>
<li><a href="http://cygni.se/2007/12/04/breakpoints-i-eclipse/" title="Conditional Breakpoints">Conditional Breakpoints och Exception Breakpoints</a> kan vara välbehövligt i vissa debugsituationer.</li>
</ul>
<p>Kolla även in en rad tips på olika <a href="http://cygni.se/?s=eclipse" title="Eclipse">smarta plugins, hur man remote-debuggar osv</a>.</p>

	Tags: <a href="http://cygni.se/taggar/artiklar/" title="artiklar" rel="tag">artiklar</a>, <a href="http://cygni.se/taggar/eclipse/" title="eclipse" rel="tag">eclipse</a>, <a href="http://cygni.se/taggar/stacktrace-2/" title="stacktrace" rel="tag">stacktrace</a>, <a href="http://cygni.se/taggar/tips/" title="tips" rel="tag">tips</a><br />
]]></content:encoded>
			<wfw:commentRss>http://cygni.se/2011/12/15/best-of-eclipse-godbitar-kortkommandon-mm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java Bean Validation</title>
		<link>http://cygni.se/2011/11/28/java-bean-validation/</link>
		<comments>http://cygni.se/2011/11/28/java-bean-validation/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 09:01:57 +0000</pubDate>
		<dc:creator>Leo Wentzel</dc:creator>
				<category><![CDATA[Stacktrace]]></category>
		<category><![CDATA[bean validation]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jpa]]></category>
		<category><![CDATA[jsf]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://cygni.se/?p=3449</guid>
		<description><![CDATA[Java Bean Validation (JSR 303) definierar en meta-data-modell och ett API för validering av klasser. Implementationer av denna specifikation gör det möjligt att definiera och utföra validering med hjälp av annotationer eller xml. Exemplet nedan illusterar detta för ett användarnamn: @NotNull @Size(min = 5, max = 20) @Pattern(regexp = &#34;[a-zA-Z0-9\\._-]+&#34;) private String userName; Bean Validation ...]]></description>
			<content:encoded><![CDATA[<p><strong>Java Bean Validation</strong> (<a title="JSR 303" href="http://jcp.org/en/jsr/detail?id=303" target="_blank">JSR 303</a>) definierar en meta-data-modell och ett API för validering av klasser. Implementationer av denna specifikation gör det möjligt att definiera och utföra validering med hjälp av annotationer eller xml. Exemplet nedan illusterar detta för ett användarnamn:</p>
<pre class="brush: java; title: ;">
@NotNull
@Size(min = 5, max = 20)
@Pattern(regexp = &quot;[a-zA-Z0-9\\._-]+&quot;)
private String userName;
</pre>
<p>Bean Validation är inte knutet till något speciellt ramverk eller lager. Det finns däremot bra stöd för Bean Validation i flertalet populära ramverk, såsom Hibernate och JSF 2. Dessutom är det enkelt att utföra validering via API:t:</p>
<pre class="brush: java; title: ;">
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
...
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set&lt;ConstraintViolation&lt;Customer&gt;&gt; constraintViolations = validator.validate(customer);
</pre>
<p>För att komma igång med ett Bean Validation (<a href="http://www.hibernate.org/subprojects/validator.html">Hibernate Validator 4.x</a> är referensimplementationen) i ett Maven-projekt lägg till följande beroenden i din pom:</p>
<pre class="brush: xml; title: ;">
&lt;dependency&gt;
 &lt;groupId&gt;org.hibernate&lt;/groupId&gt;
 &lt;artifactId&gt;hibernate-validator&lt;/artifactId&gt;
 &lt;version&gt;4.2.0.Final&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
 &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
 &lt;artifactId&gt;slf4j-jdk14&lt;/artifactId&gt;
 &lt;version&gt;1.6.1&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>Används Hibernate eller JSF 2 räcker det oftast med att lägga till ovanstående beroenden så länge de finns tillgängliga i applikationens class path. Används JSF 2 går det till exempel att aktivera validering för ett inmatningsfält på följande sätt:</p>
<pre class="brush: xml; title: ;">
&lt;h:inputText value=&quot;#{customer.age}&quot;&gt;
  &lt;f:validateBean/&gt;
&lt;/h:inputText&gt;
</pre>
<p>Bean validation stödjer dessutom validering av grupper som gör det möjligt att validera olika aspekter av ett objekt:</p>
<pre class="brush: java; title: ;">
@Min(value=15, groups=AgeCheck.class)
private int age;
</pre>

	Tags: <a href="http://cygni.se/taggar/bean-validation/" title="bean validation" rel="tag">bean validation</a>, <a href="http://cygni.se/taggar/hibernate/" title="hibernate" rel="tag">hibernate</a>, <a href="http://cygni.se/taggar/java/" title="java" rel="tag">java</a>, <a href="http://cygni.se/taggar/jpa/" title="jpa" rel="tag">jpa</a>, <a href="http://cygni.se/taggar/jsf/" title="jsf" rel="tag">jsf</a>, <a href="http://cygni.se/taggar/spring/" title="spring" rel="tag">spring</a><br />
]]></content:encoded>
			<wfw:commentRss>http://cygni.se/2011/11/28/java-bean-validation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Använda Scala i ett javaprojekt</title>
		<link>http://cygni.se/2011/11/08/anvanda-scala-i-ett-javaprojekt/</link>
		<comments>http://cygni.se/2011/11/08/anvanda-scala-i-ett-javaprojekt/#comments</comments>
		<pubDate>Tue, 08 Nov 2011 13:34:13 +0000</pubDate>
		<dc:creator>Fredrik Tyboni</dc:creator>
				<category><![CDATA[Stacktrace]]></category>
		<category><![CDATA[bdd]]></category>
		<category><![CDATA[borachio]]></category>
		<category><![CDATA[easymock]]></category>
		<category><![CDATA[j2se]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jee]]></category>
		<category><![CDATA[jmock]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[mockito]]></category>
		<category><![CDATA[scala]]></category>
		<category><![CDATA[scalatest]]></category>
		<category><![CDATA[specs]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[testng]]></category>

		<guid isPermaLink="false">http://cygni.se/?p=3562</guid>
		<description><![CDATA[Efter att du har läst Martins artikel om Scala och SBT så kanske du känner dig lite sugen att börja koda i Scala, men inte riktigt vet var du skall börja. Jonas Bonér var hos Cygni och talade för ett tag sedan och nämnde då att det kan vara en bra början att skriva sina ...]]></description>
			<content:encoded><![CDATA[<p>Efter att du har läst <a href="cygni.se/2011/01/20/sbt-maven-for-scala/">Martins artikel om Scala och SBT</a> så kanske du känner dig lite sugen att börja koda i Scala, men inte riktigt vet var du skall börja. <a href="http://jboner.github.com/">Jonas Bonér</a> var hos Cygni och talade för ett tag sedan och nämnde då att det kan vara en bra början att skriva sina testfall i Scala för att komma igång och lära sig språket. Scala erbjuder dessutom väldigt trevliga testramverk, som kan underlätta din vardag. Jag kommer förutsätta att du idag har ett mavenprojekt med javakod och eventuella befintliga tester i java. </p>
<p>Första steget är att lyfta in Scalas API, JUnit 4 (om du inte redan kör det) och ett testramverk. Jag tänkte använda <a href="http://www.scalatest.org/">ScalaTest</a>. För att göra det så lägger vi till följande beroende i pom.xml</p>
<pre class="brush: xml; title: ;">
&lt;dependency&gt;
    &lt;groupId&gt;org.scala-lang&lt;/groupId&gt;
    &lt;artifactId&gt;scala-library&lt;/artifactId&gt;
    &lt;version&gt;2.9.1&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;junit&lt;/groupId&gt;
    &lt;artifactId&gt;junit&lt;/artifactId&gt;
    &lt;version&gt;4.8.1&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.scalatest&lt;/groupId&gt;
    &lt;artifactId&gt;scalatest_2.9.1&lt;/artifactId&gt;
    &lt;version&gt;1.6.1&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
</pre>
<p>Sedan behöver vi säga till Maven att också kompilera och köra testfall som ligger i biblioteket src/test/scala, så då lägger vi till tre plugins. </p>
<p><strong>maven-scala-plugin</strong> ansvarar för att kompilera scalakoden till bytekod.</p>
<pre class="brush: xml; title: ;">
&lt;plugin&gt;
    &lt;groupId&gt;org.scala-tools&lt;/groupId&gt;
    &lt;artifactId&gt;maven-scala-plugin&lt;/artifactId&gt;
    &lt;version&gt;2.15.0&lt;/version&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;goals&gt;
                &lt;goal&gt;testCompile&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;configuration&gt;
                &lt;args&gt;
                    &lt;arg&gt;-make:transitivenocp&lt;/arg&gt;
                    &lt;arg&gt;-dependencyfile&lt;/arg&gt;
                    &lt;arg&gt;${project.build.directory}/.scala_dependencies&lt;/arg&gt;
                &lt;/args&gt;
            &lt;/configuration&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;
</pre>
<p><strong>maven-surefire-plugin</strong> är den som kör testerna &#8211; om du redan har tester i projektet så har du redan lagt till den här pluginen och behöver då bara utöka den att också inkludera filer som heter <strong>**/*Spec.*</strong>.</p>
<pre class="brush: xml; title: ;">
&lt;plugin&gt;
    &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
    &lt;artifactId&gt;maven-surefire-plugin&lt;/artifactId&gt;
    &lt;version&gt;2.6&lt;/version&gt;
    &lt;configuration&gt;
        &lt;useFile&gt;false&lt;/useFile&gt;
        &lt;disableXmlReport&gt;true&lt;/disableXmlReport&gt;
        &lt;includes&gt;
            &lt;include&gt;**/*Spec.*&lt;/include&gt;
            &lt;!-- För att hantera existerande tester --&gt;
            &lt;include&gt;**/*Test.*&lt;/include&gt;
        &lt;/includes&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;
</pre>
<p><strong>build-helper-maven-plugin</strong> lägger till källkodsmappar till kompilering, eftersom Maven från början bara hanterar en källkodsmapp för implementationskod (src/main/java som standard) och en för test (src/test/java som standard).</p>
<pre class="brush: xml; title: ;">
&lt;plugin&gt;
    &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
    &lt;artifactId&gt;build-helper-maven-plugin&lt;/artifactId&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;id&gt;generate-test-sources&lt;/id&gt;
            &lt;phase&gt;generate-test-sources&lt;/phase&gt;
            &lt;goals&gt;
                &lt;goal&gt;add-test-source&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;configuration&gt;
                &lt;sources&gt;
                    &lt;source&gt;src/test/scala&lt;/source&gt;
                &lt;/sources&gt;
            &lt;/configuration&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;
</pre>
<p>Ok, nu behöver vi bara skapa mappen <strong>src/test/scala</strong> och sedan kan du börja koda!</p>
<p>Om du vill kan du stanna här. Nu kan du skriva testklasser i Scala, annotera metoderna med JUnits @Test och köra på som vanligt. Det du vinner är att du får tillgång till Scalas syntax och konstruktioner och att du kan lära dig i en bekant miljö.</p>
<p>Det andra alternativet är att du också börjar titta på vad Scalas testramverk kan erbjuda. I grunden är det inte så stor skillnad, men rent syntatiskt och kanske också tankemässigt så är det lite annorlunda. ScalaTest har stöd för <a href="http://behaviour-driven.org/">BDD &#8211; Behaviour Driven Development</a>. Tanken är att varje test är en beskrivning av en funktion/ett beteende som en roll skall uppfylla. Rollen tar sedan formen av en eller möjligtvis flera klasser. Tack vare att Scalas syntax går att det skriva ganska koncisa specifikationer, nästan som rena texttester för att beskriva beteendet som förväntas.</p>
<p>Vi börjar med att skriva en första specifikation, som vår applikation skall uppfylla.</p>
<pre class="brush: scala; title: ;">
@RunWith(classOf[JUnitRunner])
class MyApplicationSpec extends FlatSpec with MustMatchers {

  &quot;My application&quot; must &quot;convert a string to hex values&quot; in {
  }

}
</pre>
<p>Det här är ett komplett test, även om det inte gör något just nu &#8211; kroppen på specifikationen är tom. Om jag vill kan jag lämna det tomt och fylla på senare, eller så gör jag det lite tydligare att jag inte är klar med testet. Då skriver vi om det såhär</p>
<pre class="brush: scala; title: ;">
@RunWith(classOf[JUnitRunner])
class MyApplicationSpec extends FlatSpec with MustMatchers {

  &quot;My application&quot; must &quot;convert a string to hex values&quot; in (pending)

}
</pre>
<p>Väldigt tydligt och förklarande, eller hur? Ponera att jag skapar en klass som kan konvertera en sträng till hexadecimala värden (wow!). Då kan testkoden se ut som följande</p>
<pre class="brush: scala; title: ;">
@RunWith(classOf[JUnitRunner])
class MyApplicationSpec extends FlatSpec with MustMatchers {

  &quot;My application&quot; must &quot;convert a string to hex values&quot; in {
    val app = new MyApplication()
    app.convert(&quot;The donkey makes a left turn. I observe.&quot;) must equal (&quot;54686520646f6e6b6579206d616b65732061206c656674207475726e2e2049206f6273657276652e&quot;)
  }

}
</pre>
<p>Klassen MyApplication är fortfarande skriven i Java, men jag testar den från Scala. Nyckelordet &#8221;must&#8221; kommer från en <a href="http://www.scala-lang.org/node/126">trait</a> i ScalaTest som heter MustMatchers. Det går också att använda ShouldMatchers, enda skillnaden är terminologin &#8211; must eller should, vilket du tycker om bäst.</p>
<p>Genom att fylla på med test av det här slaget så får du en ganska tydligt dokumentation vad du faktiskt förväntar dig av dina roller/klasser. Då slipper du en massa kommentarer i koden och/eller testmetoder som döpts &#8221;testShouldConvertStringToHexValue&#8221; eller liknande. Enkelt och snyggt!</p>
<p>Vill du använda mockobjekt i din scalakod så kan du antingen köra på någon av de vanliga javabiblioteken (JMock, EasyMock, Mockito), eller så kan du prova <a href="http://borachio.com/">Borachio</a> som är skrivet i Scala.</p>

	Tags: <a href="http://cygni.se/taggar/bdd/" title="bdd" rel="tag">bdd</a>, <a href="http://cygni.se/taggar/borachio/" title="borachio" rel="tag">borachio</a>, <a href="http://cygni.se/taggar/easymock/" title="easymock" rel="tag">easymock</a>, <a href="http://cygni.se/taggar/j2se/" title="j2se" rel="tag">j2se</a>, <a href="http://cygni.se/taggar/java/" title="java" rel="tag">java</a>, <a href="http://cygni.se/taggar/jee/" title="jee" rel="tag">jee</a>, <a href="http://cygni.se/taggar/jmock/" title="jmock" rel="tag">jmock</a>, <a href="http://cygni.se/taggar/junit/" title="junit" rel="tag">junit</a>, <a href="http://cygni.se/taggar/maven/" title="maven" rel="tag">maven</a>, <a href="http://cygni.se/taggar/mockito/" title="mockito" rel="tag">mockito</a>, <a href="http://cygni.se/taggar/scala/" title="scala" rel="tag">scala</a>, <a href="http://cygni.se/taggar/scalatest/" title="scalatest" rel="tag">scalatest</a>, <a href="http://cygni.se/taggar/specs/" title="specs" rel="tag">specs</a>, <a href="http://cygni.se/taggar/tdd/" title="tdd" rel="tag">tdd</a>, <a href="http://cygni.se/taggar/test/" title="test" rel="tag">test</a>, <a href="http://cygni.se/taggar/testng/" title="testng" rel="tag">testng</a><br />
]]></content:encoded>
			<wfw:commentRss>http://cygni.se/2011/11/08/anvanda-scala-i-ett-javaprojekt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Logback 1.0</title>
		<link>http://cygni.se/2011/11/03/logback-1-0/</link>
		<comments>http://cygni.se/2011/11/03/logback-1-0/#comments</comments>
		<pubDate>Thu, 03 Nov 2011 15:07:44 +0000</pubDate>
		<dc:creator>Leo Wentzel</dc:creator>
				<category><![CDATA[Stacktrace]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[log4j]]></category>
		<category><![CDATA[logback]]></category>
		<category><![CDATA[slf4j]]></category>

		<guid isPermaLink="false">http://cygni.se/?p=3714</guid>
		<description><![CDATA[Logback, ett ramverk för loggning på Java-plattformen, släpptes nyligen som version 1.0. Initiativtagare är personen bakom log4j och SLF4J, Ceki Gülcü. Logback bygger på log4j och kan därför ses som en direkt uppföljare. Logback kommer med inbyggt stöd för SLF4J för att underlätta byte av implementation av ramverk. Några av fördelarna över log4j som sägs ...]]></description>
			<content:encoded><![CDATA[<p><a href="http://logback.qos.ch/">Logback</a>, ett ramverk för loggning på Java-plattformen, släpptes nyligen som version 1.0. Initiativtagare är personen bakom <a href="http://logging.apache.org/log4j/">log4j</a> och <a href="http://www.slf4j.org/">SLF4J, </a><a href="http://en.wikipedia.org/wiki/Ceki_G%C3%BClc%C3%BC">Ceki Gülcü</a>. Logback bygger på log4j och kan därför ses som en direkt uppföljare. Logback kommer med inbyggt stöd för SLF4J för att underlätta byte av implementation av ramverk. Några av fördelarna över log4j som sägs vara högre prestanda, utökad testsvit för bättre tillförlitlighet, förbättrad automatisk omladdning av konfigurationsfiler, mer avancerade filter och integration med servlet-containers för loggning av http-access.</p>
<p>För att testa Logback, lägg till följande maven-beroende:</p>
<pre class="brush: xml; title: ;">
&lt;dependency&gt;
  &lt;groupId&gt;ch.qos.logback&lt;/groupId&gt;
  &lt;artifactId&gt;logback-classic&lt;/artifactId&gt;
  &lt;version&gt;1.0.0&lt;/version&gt;
&lt;/dependency&gt;
</pre>
<p>Logback-classic beror på logback-core och SLF4J och därför kommer dessa automatiskt inkluderas i projektet. Därefter är det bara att logga på samma sätt som med SLF4J:</p>
<pre class="brush: java; title: ;">
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
Logger logger = LoggerFactory.getLogger(App.class);
logger.info(&quot;Hello World!&quot;);
</pre>
<p>Konfiguration påminner om log4j men skiljer sig på vissa punkter. Nedan är ett enkelt exempel på en Logback-konfiguration:</p>
<pre class="brush: xml; title: ;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;configuration scan=&quot;true&quot; scanPeriod=&quot;3 seconds&quot;&gt;

    &lt;appender name=&quot;STDOUT&quot; class=&quot;ch.qos.logback.core.ConsoleAppender&quot;&gt;
        &lt;encoder&gt;
            &lt;pattern&gt;%d{HH:mm:ss.SSS} [%thread] %-5level %logger{32} - %msg%n&lt;/pattern&gt;
        &lt;/encoder&gt;
    &lt;/appender&gt;

    &lt;appender name=&quot;FILE&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&gt;
        &lt;file&gt;logFile.log&lt;/file&gt;
        &lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;&gt;
            &lt;fileNamePattern&gt;logFile.%d{yyyy-MM-dd_HH-mm}.log.zip&lt;/fileNamePattern&gt;
            &lt;maxHistory&gt;5&lt;/maxHistory&gt;
        &lt;/rollingPolicy&gt;

        &lt;encoder&gt;
            &lt;pattern&gt;%-26(%d{HH:mm:ss,SSS} [%thread]) %-5level %logger{32} - %msg%n&lt;/pattern&gt;
        &lt;/encoder&gt;
    &lt;/appender&gt;

    &lt;root level=&quot;DEBUG&quot;&gt;
        &lt;appender-ref ref=&quot;STDOUT&quot; /&gt;
        &lt;appender-ref ref=&quot;FILE&quot; /&gt;
    &lt;/root&gt;

&lt;/configuration&gt;
</pre>

	Tags: <a href="http://cygni.se/taggar/java/" title="java" rel="tag">java</a>, <a href="http://cygni.se/taggar/log4j/" title="log4j" rel="tag">log4j</a>, <a href="http://cygni.se/taggar/logback/" title="logback" rel="tag">logback</a>, <a href="http://cygni.se/taggar/slf4j/" title="slf4j" rel="tag">slf4j</a><br />
]]></content:encoded>
			<wfw:commentRss>http://cygni.se/2011/11/03/logback-1-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sätt upp en JEE-applikation mha Codehaus Maven-arketyper och eclipse m2e-plugin</title>
		<link>http://cygni.se/2011/10/31/satt-upp-en-jee-applikation-mha-codehaus-maven-arketyper/</link>
		<comments>http://cygni.se/2011/10/31/satt-upp-en-jee-applikation-mha-codehaus-maven-arketyper/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 16:19:02 +0000</pubDate>
		<dc:creator>Patrik Sjöberg</dc:creator>
				<category><![CDATA[Stacktrace]]></category>
		<category><![CDATA[codehaus]]></category>
		<category><![CDATA[ear]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[ejb]]></category>
		<category><![CDATA[jee]]></category>
		<category><![CDATA[m2e]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[mvn archetype:generate]]></category>
		<category><![CDATA[war]]></category>

		<guid isPermaLink="false">http://cygni.se/?p=3679</guid>
		<description><![CDATA[Här beskriver jag hur man snabbt och enkelt kan sätta upp en jee-applikation (ear, webapp- och ejb-modul) på några få minuter genom att använda sig av Maven-arketyper ifrån org.codehaus.mojo.archetypes och kommandot mvn archetype:generate. Vi tar också användning av eclipse m2e-plugin för att uppdatera beroenden mellan ear och web/ejb-modulerna. För den som vill komma åt det ...]]></description>
			<content:encoded><![CDATA[<p>Här beskriver jag hur man snabbt och enkelt kan sätta upp en jee-applikation (ear, webapp- och ejb-modul) på några få minuter genom att använda sig av Maven-arketyper ifrån <a title="org.codehaus.mojo.archetypes" href="http://mvnrepository.com/artifact/org.codehaus.mojo.archetypes"> <code>org.codehaus.mojo.archetypes</code></a> och kommandot <em>mvn archetype:generate</em>. Vi tar också användning av eclipse m2e-plugin för att uppdatera beroenden mellan ear och web/ejb-modulerna.</p>
<p>För den som vill komma åt det som denna artikel producerar (finns lite mer godis också i form av enklare ejb och servlet-klasser) så finns den tillgänglig på github:<br />
git clone http://github.com/cygni-stacktrace/j2ee-maven-5minutes</p>
<h3>Generera jee-arketyper</h3>
<p>Ställ dig i lämplig katalog för att påbörja skapandet av vårt projekt. Första gången vi kör <em>mvn archetype:generate</em> (ska köras sammanlagt 3 ggr) letar vi upp och anger siffran för codehause-arketypen ear-javaee6. För varje gång vi kör kommandot ser infon ungefär likadan ut.</p>
<p>EAR-input:</p>
<p><em>Define value for property &#8216;groupId&#8217;: : se.cygni.stacktrace.myearproject</em><br />
<em>Define value for property &#8216;artifactId&#8217;: : my-ear</em><br />
<em>Define value for property &#8216;version&#8217;:  1.0-SNAPSHOT: :</em><br />
<em>Define value for property &#8216;package&#8217;:  se.cygni.stacktrace.mywebexample: : ear</em></p>
<p>Andra gången anger vi siffran för arketypen webapp-javaee6. Input:</p>
<p><em>Define value for property &#8216;groupId&#8217;: : se.cygni.stacktrace.mywebexample</em><br />
<em>Define value for property &#8216;artifactId&#8217;: : my-web</em><br />
<em>Define value for property &#8216;version&#8217;:  1.0-SNAPSHOT: :</em><br />
<em>Define value for property &#8216;package&#8217;:  se.cygni.stacktrace.mywebexample: : war</em></p>
<p>Tredje gången anger vi siffran för arketypen ejb-javaee6. Input:</p>
<p><em>Define value for property &#8216;groupId&#8217;: : se.cygni.stacktrace.myejbexample</em><br />
<em>Define value for property &#8216;artifactId&#8217;: : my-ejb</em><br />
<em>Define value for property &#8216;version&#8217;:  1.0-SNAPSHOT: :</em><br />
<em>Define value for property &#8216;package&#8217;:  se.cygni.stacktrace.myejbexample: : ejb</em></p>
<p>När vi är klara med det här kommer det finnas tre kataloger, my-ear, my-web och my-ejb med varsin pom.xml som har en hyfsat bra grunduppsättning av JEE-beroenden uppsatta från början.</p>
<h3>Skapa en parent-pom</h3>
<p>För att bland annat kunna bygga hela vår applikation i ett svep kopplar vi ihop dessa my-ear/my-web och my-ejb pom.xml till en och samma parent pom.xml. Skapa manuellt katalogen my-app på samma nivå som de andra katalogerna och en pom.xml fil med bland annat följande (hela my-app/pom.xml kan hittas  <a href="https://github.com/cygni-stacktrace/j2ee-maven-5minutes/tree/master/my-app/pom.xml">här</a>):</p>
<pre class="brush: plain; title: ;">
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
  xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&gt;
  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
  &lt;groupId&gt;se.cygni.stacktrace&lt;/groupId&gt;
  &lt;artifactId&gt;my-app&lt;/artifactId&gt;
  &lt;packaging&gt;pom&lt;/packaging&gt;
  &lt;version&gt;1.0&lt;/version&gt;
  &lt;name&gt;my-app&lt;/name&gt;

  &lt;modules&gt;
  	&lt;module&gt;../my-ear&lt;/module&gt;
  	&lt;module&gt;../my-web&lt;/module&gt;
  	&lt;module&gt;../my-ejb&lt;/module&gt;
  &lt;/modules&gt;
...
</pre>
<p>I samband med att vi gör det här så tar vi också bort Version-taggen och sätter parent att vara my-app i pom.xml i my-web, my-ejb och my-ear. Hur alla pom.xml ser ut efter detta kan ses: <a href="https://github.com/cygni-stacktrace/j2ee-maven-5minutes">här</a>. </p>
<p>Nu kan vi nerifrån och upp genom ett kommando bygga web, ejb samt ear. Ställ dig bara i my-app och kör mvn package!</p>
<h3>Modifiera ear att innehålla web och ejb-beroenden</h3>
<p>Nu kör vi igång eclipse och tar hjälp av de verktyg som finns där för att sätta våra beroende mellan ear och ejb/web-modulerna. En förutsättning är att du har m2e-pluginen installerad i eclipse. Plocka den härifrån <a href="http://download.eclipse.org/technology/m2e/releases/">http://download.eclipse.org/technology/m2e/releases/</a> och när det är gjort så importerar du pom.xml i my-app-katalogen in i eclipse (File-&gt; Import -&gt; Maven -&gt; Existing Maven Projects). Det kommer skapa 4 olika projekt i eclipse, my-app, my-ear, my-web och my-ejb.</p>
<p>Öppna upp my-ear/pom.xml och modifiera stycket:</p>
<pre class="brush: plain; title: ;">
 &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-ear-plugin&lt;/artifactId&gt;
        &lt;version&gt;2.6&lt;/version&gt;
        &lt;configuration&gt;
            &lt;version&gt;6&lt;/version&gt;
            &lt;defaultLibBundleDir&gt;lib&lt;/defaultLibBundleDir&gt;
        &lt;/configuration&gt;
      &lt;/plugin&gt;
</pre>
<p>till:</p>
<pre class="brush: plain; title: ;">
			&lt;plugin&gt;
				&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
				&lt;artifactId&gt;maven-ear-plugin&lt;/artifactId&gt;
				&lt;version&gt;2.6&lt;/version&gt;
				&lt;configuration&gt;
					&lt;version&gt;6&lt;/version&gt;
					&lt;defaultLibBundleDir&gt;lib&lt;/defaultLibBundleDir&gt;
					&lt;modules&gt;
						&lt;ejbModule&gt;
							&lt;groupId&gt;se.cygni.stacktrace.myejbexample&lt;/groupId&gt;
							&lt;artifactId&gt;my-ejb&lt;/artifactId&gt;
						&lt;/ejbModule&gt;
						&lt;webModule&gt;
							&lt;groupId&gt;se.cygni.stacktrace.mywebexample&lt;/groupId&gt;
							&lt;artifactId&gt;my-web&lt;/artifactId&gt;
						&lt;/webModule&gt;
					&lt;/modules&gt;
				&lt;/configuration&gt;
			&lt;/plugin&gt;
</pre>
<p>Sen högerklickar du på my-ear-projektet i package explorer och väljer Maven -&gt; Add dependency. I sökrutan anger du &#8221;my-ejb&#8221;, då kommer ditt ejb-projekt att dyka upp och du väljer detta och klickar OK. Upprepa proceduren för my-web projektet. Din my-ear/pom.xml bör nu innehålla detta: </p>
<pre class="brush: plain; title: ;">
	&lt;dependencies&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;se.cygni.stacktrace.mywebexample&lt;/groupId&gt;
			&lt;artifactId&gt;my-web&lt;/artifactId&gt;
			&lt;version&gt;1.0&lt;/version&gt;
			&lt;type&gt;war&lt;/type&gt;
		&lt;/dependency&gt;
		&lt;dependency&gt;
			&lt;groupId&gt;se.cygni.stacktrace.myejbexample&lt;/groupId&gt;
			&lt;artifactId&gt;my-ejb&lt;/artifactId&gt;
			&lt;version&gt;1.0&lt;/version&gt;
			&lt;type&gt;ejb&lt;/type&gt;
		&lt;/dependency&gt;
	&lt;/dependencies&gt;
</pre>
<p>Efter det här kan man roa sig med att städa upp ytterligare i sina pom.xml filer genom att t.ex se till att maven-compiler-plugin bara finns i my-app/pom.xml med rätt version etc. Men i princip är din grundstruktur nu klar och du kan ställa dig i my-app och köra mvn package för att få en fin ear-fil som kan deployas på en jee6-kompatibel app-server.</p>

	Tags: <a href="http://cygni.se/taggar/codehaus/" title="codehaus" rel="tag">codehaus</a>, <a href="http://cygni.se/taggar/ear/" title="ear" rel="tag">ear</a>, <a href="http://cygni.se/taggar/eclipse/" title="eclipse" rel="tag">eclipse</a>, <a href="http://cygni.se/taggar/ejb/" title="ejb" rel="tag">ejb</a>, <a href="http://cygni.se/taggar/jee/" title="jee" rel="tag">jee</a>, <a href="http://cygni.se/taggar/m2e/" title="m2e" rel="tag">m2e</a>, <a href="http://cygni.se/taggar/maven/" title="maven" rel="tag">maven</a>, <a href="http://cygni.se/taggar/mvn-archetypegenerate/" title="mvn archetype:generate" rel="tag">mvn archetype:generate</a>, <a href="http://cygni.se/taggar/war/" title="war" rel="tag">war</a><br />
]]></content:encoded>
			<wfw:commentRss>http://cygni.se/2011/10/31/satt-upp-en-jee-applikation-mha-codehaus-maven-arketyper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring Batch 2</title>
		<link>http://cygni.se/2011/10/31/spring-batch-2/</link>
		<comments>http://cygni.se/2011/10/31/spring-batch-2/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 10:43:43 +0000</pubDate>
		<dc:creator>Leo Wentzel</dc:creator>
				<category><![CDATA[Stacktrace]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[batchjobb]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[spring batch]]></category>

		<guid isPermaLink="false">http://cygni.se/?p=3547</guid>
		<description><![CDATA[Denna artikel ingår i serien Spring från början och kommer behandla det springstöd som finns batchjobb. Rapporter, databearbetning eller andra bakgrundsprocesser är förhållandevis vanligt förekommande processer i många system. Dessa processer eller batchjobb kan till exempel vara enkla bash-skript som uppdaterar ett fält i en databas eller applikationer som månatligen skapar komplexa rapporter. Då den ...]]></description>
			<content:encoded><![CDATA[<p>Denna artikel ingår i serien <a href="/2008/05/30/spring-fran-borjan-introduktion/">Spring från början</a> och kommer behandla det springstöd som finns batchjobb.</p>
<p><span id="more-3547"></span></p>
<p>Rapporter, databearbetning eller andra bakgrundsprocesser är förhållandevis vanligt förekommande processer i många system.  Dessa processer eller <em>batchjobb</em> kan till exempel vara enkla bash-skript som uppdaterar ett fält i en databas eller applikationer som månatligen skapar komplexa rapporter. Då den här typen av återkommande jobb ibland kräver en del resurser samtidigt som de inte alltid är beroende av att köras tillsammans med en applikation på en applikationsserver lämpar de sig många gånger väl för att köras som fristående program på separata servrar. </p>
<p><a href="http://static.springsource.org/spring-batch/" target="_blank" title="Spring Batch">Spring Batch</a> är ett ramverk från <a href="http://www.springsource.com/" title="SpringSource" target="_blank">SpringSource</a> skapat för utveckling av batchjobb. Detta ramverk erbjuder en modell, en samling verktyg samt funktionalitet tänkt att förenkla och standardisera utvecklingen av dessa typer av jobb. </p>
<p><img src="http://cygni.se/wp-uploads/2011/10/job-overview.png" alt="" title="job-overview" width="382" height="326" class="center size-full wp-image-3669" /></p>
<p>Ett batchjobb i Spring Batch är uppdelat i ett till flera steg. I varje steg läses data från en källa som sedan skrivs till ett mål. Före det att data skrivs kan denna dessutom bearbetas och transformeras i ett separat delsteg. Själva jobben konfigureras i XML men de bönor som används kan viras som vanliga Springbönor via XML eller annotationer. Exemplet nedan, med <strong>ett</strong> steg, innefattar inläsning från flatfil konfigurerat med den inbyggda <em>läsaren</em> av flatfiler, en enkel <em>processor</em> som konverterar den inlästa textsträngen och en <em>skrivare</em> som loggar den konverterade informationen.</p<</p>
<pre class="brush: xml; title: ;">
&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:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
  xmlns:batch=&quot;http://www.springframework.org/schema/batch&quot;
  xsi:schemaLocation=&quot;http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&quot;&gt;

&lt;batch:job id=&quot;readFileJob&quot;&gt;
  &lt;batch:step id=&quot;step&quot;&gt;
    &lt;batch:tasklet
          transaction-manager=&quot;transactionManager&quot;
          start-limit=&quot;100&quot;&gt;
      &lt;batch:chunk
          reader=&quot;flatFileItemReader&quot;
          processor=&quot;stringLengthProcessor&quot;
          writer=&quot;simpleLogWriter&quot;
          commit-interval=&quot;5&quot; /&gt;
    &lt;/batch:tasklet&gt;
  &lt;/batch:step&gt;
&lt;/batch:job&gt;

&lt;bean id=&quot;flatFileItemReader&quot; scope=&quot;step&quot;
      class=&quot;org.springframework.batch.item.file.FlatFileItemReader&quot;&gt;

  &lt;property name=&quot;resource&quot; value=&quot;${input.file.name}&quot; /&gt;
  &lt;property name=&quot;lineMapper&quot;&gt;
    &lt;bean id=&quot;defaultLineMapper&quot; scope=&quot;step&quot;
        class=&quot;org.springframework.batch.item.file.mapping.PassThroughLineMapper&quot;/&gt;
  &lt;/property&gt;
&lt;/bean&gt;
&lt;/beans&gt;
</pre>
<p>Spring Batch kommer med inbyggt stöd för att läsa och skriva från och till flertalet olika format och källor, till exempel flatfil, XML och SQL-databaser. Det går självklart att utveckla egna readers och writers då dessa inte täcker de behov som kan tänkas finnas. Flatfilsläsaren är i exemplet konfigurerat att läsa in varje rad i en sträng som därefter skickas till en enkel processor som läser av längden på raden som sedan loggas i writern. Värt att nämna är att Spring Batch 2 stödjer generics.</p>
<pre class="brush: java; title: ;">
@Component
public class StringLengthProcessor implements ItemProcessor&lt;String, Integer&gt; {
  @Override
  public Integer process(String s) throws Exception {
    return s == null ? null : s.length();
  }
}
</pre>
<p>Spring Batch 2 använder <a href="http://static.springsource.org/spring-batch/reference/html/configureStep.html" target="_blank" title="Chunk-oriented processing">chunk-oriented processing</a>. Varje <em>chunk</em> konfigureras med ett <code>commit-interval</code> (5 i exemplet ovan) och det är endast dessa 5 <code>items</code> som jobbet läser och bearbetar innan commit sker mot den konfigurerade writern.</p>
<pre class="brush: java; title: ;">
@Component
public class SimpleLogWriter implements ItemWriter&lt;Integer&gt; {
...
  public void write(List&lt;? extends Integer&gt; data) throws Exception {
    for (Integer length : data) {
      logger.info(length);
    }
  }
}
</pre>
<p>Det krävs en så kallad <code>JobLauncher</code> och ett konfigurerat <code>Job</code> för att köra ett batchjobb. Ett jobb kan till exempel startas från kommandoraden eller från en webbapplikation.</p>
<pre class="brush: bash; title: ;">
java CommandLineJobRunner readFileJob.xml readFileJob jobDateParam=2011-10-10</pre>
<p><code>CommandLineJobRunner</code> är inbyggd i Spring Batch och kräver två argument. Det första argumentet är <code>jobPath</code> (sökvägen till jobb-konfigurationen) och det andra är <code>jobName</code> (namnet på det jobb som ska köras). Utöver dessa två argument tillkommer jobbparametrar (format namn=värde). Jobbparametrarna sparas i ett jobbrepository och används för att identifiera unika jobbinstanser. Detta medför bland annat att misslyckade jobb kan återupptas och att slutförda jobb inte kommer köras igen. Vanligen är ett jobbrepository en databas men finns det inget behov att hålla reda på vilka jobb som körts och vilka som är slutförda, eller om det finns speciella prestandakrav, går det att konfigurera ett repository som hålls i minnet istället.</p>
<p>Utförlig dokumentation och instruktioner finns här: <a href="http://static.springsource.org/spring-batch/" target="_blank" title="Spring Batch">Spring Batch</a>.</p>

	Tags: <a href="http://cygni.se/taggar/bash/" title="bash" rel="tag">bash</a>, <a href="http://cygni.se/taggar/batchjobb/" title="batchjobb" rel="tag">batchjobb</a>, <a href="http://cygni.se/taggar/java/" title="java" rel="tag">java</a>, <a href="http://cygni.se/taggar/spring/" title="spring" rel="tag">spring</a>, <a href="http://cygni.se/taggar/spring-batch/" title="spring batch" rel="tag">spring batch</a><br />
]]></content:encoded>
			<wfw:commentRss>http://cygni.se/2011/10/31/spring-batch-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Testning med mockobject</title>
		<link>http://cygni.se/2011/10/25/testning-med-mockobject/</link>
		<comments>http://cygni.se/2011/10/25/testning-med-mockobject/#comments</comments>
		<pubDate>Tue, 25 Oct 2011 07:59:34 +0000</pubDate>
		<dc:creator>Fredrik Tyboni</dc:creator>
				<category><![CDATA[Stacktrace]]></category>
		<category><![CDATA[easymock]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jmock]]></category>
		<category><![CDATA[junit]]></category>
		<category><![CDATA[mock objects]]></category>
		<category><![CDATA[mockito]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[testng]]></category>

		<guid isPermaLink="false">http://cygni.se/?p=3488</guid>
		<description><![CDATA[Idag tillhör det vanligheterna att du som utvecklare skriver automatiska test för din kod. Många projekt använder sig av olika former av dependency injection eller har beroenden mellan klasser som gör det krångligt att testa varje del för sig. Detta leder ibland till att tester omfattar stora delar att systemet (mer åt integrationstestning), vilket i ...]]></description>
			<content:encoded><![CDATA[<p>Idag tillhör det vanligheterna att du som utvecklare skriver automatiska test för din kod. Många projekt använder sig av olika former av <a href="http://en.wikipedia.org/wiki/Dependency_injection" target="_blank">dependency injection</a> eller har beroenden mellan klasser som gör det krångligt att testa varje del för sig. Detta leder ibland till att tester omfattar stora delar att systemet (mer åt integrationstestning), vilket i sin tur leder till att det blir krångligt att underhålla och svårt att felsöka. Vissa framhåller att större tester gör dem robusta &#8211; de går inte &#8221;sönder&#8221; lika lätt om något ändras inne i implementationen &#8211; men jag föredrar en robust implementation framför ett robust test, om ni förstår vad jag menar. Ju mindre del som varje test måste verifiera desto bättre &#8211; själva grunden för <a href="http://en.wikipedia.org/wiki/Unit_testing" target="_blank">enhetstestning</a>.</p>
<p>Hur bryter du isär koden så att det går att testa separat då? Jo, här kommer då <a href="http://en.wikipedia.org/wiki/Mock_object" target="_blank">mockobjekt</a> in i bilden. Med hjälp av dessa syntetiska objekt som representerar dina kodberoenden så kan du isolera den kod som du vill testa, utan att råka ut för NullPointerException. Termen myntades (iallafall för den bredare publiken) av några utvecklare på en extreme-programming-konferens år 2000, där de också presenterade ett första ramverk för detta. </p>
<p>Ponera följande kodexempel (där Courier är ett interface)</p>
<pre class="brush: java; title: ;">
class AwesomeApp {
   Courier courier;
   public Content checkPacket() {
      if ( !courier.hasNewPacket() ) {
         throw new NoNewPacketAsFarAsWeCouldSeeException();
      }
      Packet packet = courier.getNewPacket();
      Content content = packet.open();
      return content;
   }
   public void setCourier(Courier courier) {
      this.courier = courier;
   }
}
</pre>
<p>Om jag skriver följande test, så ramlar jag oundvikligen ned i NullPointerException-gropen eftersom <strong>courier</strong> är null i AwesomeApp.</p>
<pre class="brush: java; title: ;">
class AwesomeAppTest {
   public void testCheckPacket() {
     AwesomeApp app = new AwesomeApp();
     Content content = app.checkPacket();
     // Assert content
   }
}
</pre>
<p>Vad göra? Lösningen är då alltså att använda ett mockobjekt. Antingen kan jag skriva en egen klass som implementerar interfacet Courier, samt hantera alla testvillkor som objekt av den klassen måste uppfylla, eller så använder jag ett färdigt ramverk. Valet känns lätt. Genom att välja ett färdigt ramverk så slipper jag en del underhåll och får samtidigt ett färdigt utvecklingsmönster att följa &#8211; annars kan det lätt bli att varje utvecklare i ett projekt gör på sitt eget sätt.</p>
<p>De vanligaste ramverken som används idag skulle jag säga är EasyMock, JMock samt Mockito. De är alla likvärdiga i funktionalitet och även om konstruktionerna kan skilja sig lite åt så är grunden densamma. Jag har också stött på ett ramverk som heter RMock, men det är gammalt och stöder inte ens Java 5 Generics, så jag tar inte upp det här. Här nedan följer några exempel på hur AwesomeAppTest skulle skrivas med alla tre ramverken, så att läsaren kan jämföra.</p>
<h3>JMock</h3>
<p>JMock har funnits länge och är en vidareutveckling av det ramverk som presenterades på extreme-programming-konferensen jag nämnde ovan. Version 1 var lite knölig att använda, eftersom metodmatchning gjordes med strängar vilket gav problem vid refaktorisering. Detta är dock löst i version 2 som sedan länge är den som gäller.</p>
<pre class="brush: java; title: ;">
class AwesomeAppTest {
   @Test
   public void testCheckPacket() {
      // JMock-specifik klass
      Mockery mockery = new Mockery();
      // Här skapar vi vårt mockobjekt med JMock
      Courier courier = mockery.mock(Courier.class);

      // Förväntat returvärde från testade koden
      Content expectedContent = new Content();
      // Returvärden från mitt mockobjekt
      Packet anyPacket = new Packet(expectedContent); 

      // Definiera våra förväntningar, ett anrop till
      // courier.hasNewPacket() och ett till
      // courier.getNewPacket() samt deras returvärden
      mockery.checking(new Expectations() {{  

         oneOf(courier).hasNewPacket();
         will(returnValue(true));

         oneOf(courier).getNewPacket();
         will(returnValue(anyPacket)); 

      }});

      AwesomeApp app = new AwesomeApp();
      // Här sätter vi vårt mockobjekt som
      // beroende till AwesomeApp
      app.setCourier(courier);
      Content content = app.checkPacket();

      // Kontrollera att resultatet är det förväntade
      assert content == expectedContent;

      // Verifiera att förväntningarna inträffade
      mockery.assertIsSatisfied(); 

   }
}
</pre>
<h3>EasyMock</h3>
<p>EasyMock är också ganska gammal i gemet och var tidig med att ha stöd för refaktorisering. </p>
<pre class="brush: java; title: ;">
class AwesomeAppTest {
   @Test
   public void testCheckPacket() {
      // Här skapar vi vårt mockobjekt med hjälp av EasyMock
      Courier courier = EasyMock.createMock(Courier.class); 

      // Förväntat returvärde från testade koden
      Content expectedContent = new Content();
      // Returvärden från mitt mockobjekt
      Packet anyPacket = new Packet(expectedContent); 

      // Definiera våra förväntningar, ett anrop till
      // courier.hasNewPacket() och ett till
      // courier.getNewPacket()  samt deras returvärden
      EasyMock.expect(courier.hasNewPacket()).andReturn(true);
      EasyMock.expect(courier.getNewPacket()).andReturn(anyPacket);

      // Sätt EasyMock i replay-läge,
      // där förväntningarna skall uppfyllas
      EasyMock.replay(courier); 

      AwesomeApp app = new AwesomeApp();
      // Här sätter vi vårt mockobjekt som
      // beroende till AwesomeApp
      app.setCourier(courier);
      Content content = app.checkPacket();

      // Kontrollera att resultatet är det förväntade
      assert content == expectedContent;

      // Verifiera att förväntningarna inträffade
      EasyMock.verify(courier);
   }
}
</pre>
<h3>Mockito</h3>
<p>Mockito är i praktiken en vidareutveckling av EasyMock, från början en fork som nu har skrivits om helt. Tack vare arvet är dock syntaxen väldigt lik.</p>
<pre class="brush: java; title: ;">
class AwesomeAppTest {
   @Test
   public void testCheckPacket() {
      // Här skapar vi vårt mockobjekt med hjälp av Mockito
      Courier courier = Mockito.mock(Courier.class); 

      // Förväntat returvärde från testade koden
      Content expectedContent = new Content();
      // Returvärden från mitt mockobjekt
      Packet anyPacket = new Packet(expectedContent); 

      // Definiera våra förväntningar, ett anrop till
      // courier.hasNewPacket() och ett till
      // courier.getNewPacket() samt deras returvärden
      Mockito.when(courier.hasNewPacket()).thenReturn(true);
      Mockito.when(courier.getNewPacket()).thenReturn(anyPacket);

      AwesomeApp app = new AwesomeApp();
      // Här sätter vi vårt mockobjekt som
      // beroende till AwesomeApp
      app.setCourier(courier);
      Content content = app.checkPacket();

      // Kontrollera att resultatet är det förväntade
      assert content == expectedContent;

      // Verifiera att förväntningarna inträffade
      Mockito.verify(courier);
   }
}
</pre>
<h3>Summering</h3>
<p>Som ni ser skiljer det inte mycket mellan ramverken, det som kanske framträder mest är att EasyMock har ett steg extra &#8211; där EasyMock sätts i &#8221;replay&#8221;-läge &#8211; mot både JMock och Mockito. Alla tre har stöd för att verifiera att metodanrop sker i rätt ordning, verifiera argument etc. Det går också att sätta mjukare förväntningar, såsom att en metod skall anropas en eller flera gånger, att man inte bryr sig om anrop och returvärde på ett visst objekt osv. </p>
<p>Vilket ramverk du skall välja är mer upp till personlig smak än funktionalitet. I de flesta fall kanske du sitter i ett projekt som redan använder ett mockramverk och då har du förhoppningsvis fått en lite bättre förståelse för vad ramverket gör.</p>
<p>Som avslutning kan jag rekommendera lite läsning från utvecklarna som myntade begreppet mockobjekt. Du hittar det på <a href="http://www.mockobjects.com/">www.mockobjects.com</a>  &#8211; läs gärna deras papper som ligger som länkar i högerkolumnen på den sidan.</p>

	Tags: <a href="http://cygni.se/taggar/easymock/" title="easymock" rel="tag">easymock</a>, <a href="http://cygni.se/taggar/java/" title="java" rel="tag">java</a>, <a href="http://cygni.se/taggar/jmock/" title="jmock" rel="tag">jmock</a>, <a href="http://cygni.se/taggar/junit/" title="junit" rel="tag">junit</a>, <a href="http://cygni.se/taggar/mock-objects/" title="mock objects" rel="tag">mock objects</a>, <a href="http://cygni.se/taggar/mockito/" title="mockito" rel="tag">mockito</a>, <a href="http://cygni.se/taggar/test/" title="test" rel="tag">test</a>, <a href="http://cygni.se/taggar/testng/" title="testng" rel="tag">testng</a><br />
]]></content:encoded>
			<wfw:commentRss>http://cygni.se/2011/10/25/testning-med-mockobject/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

