Poster taggade med ‘maven’

Sida 1/3:123

Dropwizard är en körmiljö och ett ramverk för att enkelt utveckla små enheter i form av RESTful webtjänster. En stack bestående av bl.a Jetty, Jersey, Jackson, slf4j, JDBI och en föreslagen projektstruktur gör det väldigt lätt att komma igång!

Begrepp

Dropwizard har idenitifierat följande aktörer och entiteter i sin stack:

Configuration

Konfigurationen är till för att hålla miljöspecifika aspekter av tjänsten. Det kan t.ex vara databaskonfiguration eller nödvändiga sökvägar och url:ar. Konfigurationen skrivs i formatet YAML. Genom JSON-annotationer i din klass läser DropWizard automatiskt upp konfigurationen och populerar din konfigurationsklass.

Representation

Detta är de objekt som ska skickas mellan klient och server och är i sin enklaste form vanliga POJOs. Jackson används för serialisering och deserialisering. DropWizard rekommenderar att dessa objekt är immutable.

Resource

Det är resurserna som exponerar REST API:et. Varje resurs och metod har en URI och klassen annoteras med javax.ws.rs.*-typerna för att definiera sökvägar, innehållstyper och metod. DropWizard använder Jersey-implementationen.

Health check

Hälsokontroller är små kodsnuttar som testar att tjänsten är uppe och att allt är som det ska. Status för hälsokontrollerna kan inspekteras via en speciell admin-url. DropWizard skapar automatiskt några hälsokontroller, bl.a en som kontrollerar att databasanslutningen är korrekt (om man har en i sitt projekt).

Service

Servicen ansvarar för att dra igång tjänsten med en konfiguration och med resurserna initialiserade med eventuella beroenden. Detta sker genom en vanlig main-metod(public static void main(String[] args) { ... } ).

I vårt exempelprojekt ser serviceklassen ut så här:

public class MainService extends Service<MainConfiguration> {
    public static void main(String[] args) throws Exception {
        new MainService().run(args);
    }

    @Override
    public void initialize(Bootstrap<MainConfiguration> mainConfigurationBootstrap) {
        mainConfigurationBootstrap.addBundle(new AssetsBundle("/assets/", "/"));
    }

    @Override
    public void run(MainConfiguration config, Environment environment) throws Exception {

        DBI dbi = initDatabaseConnection(config, environment);

        final EventsRepository eventsRepository = dbi.onDemand(EventsRepository.class);
        final ExpensesRepository expensesRepository = dbi.onDemand(ExpensesRepository.class);

        environment.addResource(new EventsResource(eventsRepository));
        environment.addResource(new ExpensesResource(expensesRepository));
    }

    private DBI initDatabaseConnection(MainConfiguration config, Environment environment) throws ClassNotFoundException {

        final DBIFactory factory = new DBIFactory();
        final DBI jdbi = factory.build(environment, config.getDatabaseConfiguration(), "db");

        createTables(jdbi);

        return jdbi;
    }

    private void createTables(DBI dbi) {

        Handle handle = dbi.open();

        handle.execute(EventsRepository.CREATE_TABLE_STATEMENT);

        handle.execute(ExpensesRepository.CREATE_TABLE_STATEMENT);

        handle.close();
    }
}

För dig som är van vid Spring eller något annat DI-ramverk kan det kännas lite konstigt att själv behöva instansiera t.ex resursklasserna (och skjuta in Repository-implementationerna). Eftersom tanken med en DropWizard tjänst är att ansvara för en relativt liten delmängd av ett system så tycker jag inte att detta är särskilt besvärande.

Resurser, dvs REST-tjänsterna, aktiveras genom att lägga till dem till instansen av Environment. Se rad 19-20 ovan.

Komma igång

Checka ut exempelprojektet och bygg:

git clone git://github.com/cygni-stacktrace/dropwizard-sample.git
cd dropwizard-sample
mvn package

Starta tjänsten med kommandot server och filnamnet för konfigurationen:

java -jar target/expenses-1.0-SNAPSHOT.jar server development.yml

Rest-API:et ligger under kontextet /api, en GET-operation för att lista events finns t.ex här: http://localhost:8080/api/event

Admingränssnittet med länk till Health check finns här: http://localhost:8081

Testning

Testning av resurser är en enkel historia med DropWizard. Genom att låta din testklass uttöka ResourceTest kan du lägga till resursen under test så här:

    @Override
    protected void setUpResources() throws Exception {
        eventsRepository = mock(EventsRepository.class);
        addResource(new EventsResource(eventsRepository));
    }

En testmetod:

    @Test
    public void shouldShowOneEvent() throws IOException {
        //given
        Event event = new Event(1, "An event", null);

        given(eventsRepository.findById(event.getId())).willReturn(event);

        //when
        Event result = client().resource("/event/1").get(Event.class);

        //then
        assertThat("event should be returned", result, is(event));
    }

Dropwizard drar igång Jersey och invokerar anropen i testet via en HTTP-klient så hela request/response kedjan går över JSON och HTTP. Detta är bra för då testas även att Jackson kan serialisera och deserialisera dina POJO:s.

Databasstöd

Dropwizard har moduler med stöd för Hibernate och JDBI. I exempelprojektet används JDBI.

Slutsats

Det är väldigt lätt att komma igång med Dropwizard och jag tycker att de valt en vettig stack med hjälpbibliotek. Den föreslagna projektstrukturen och användandet av Maven gör att det fungerar bra i alla stora IDE:er. Att inkludera Health checks direkt från början känns väldigt bra och det är befriande att ha en app som kan köras helt stand-alone (d.v.s den behöver inte deployas i en webcontainer). Jag tycker också att de tänkt till bra kring testningen.

Om man planerar att börja använda Dropwizard i ett större sammanhang behövs dock en strategi för hur tjänster ska kunna versionshanteras samt upptäckas.

Vidare läsning

http://dropwizard.codahale.com

Maven, som tillämpar en livscykelbaserad ansats, kommer med en tydligt fördefinierad bygg- och distribueringsprocess där användaren endast behöver lära sig ett litet antal kommandon för att bygga sin artefakt. I POM:en talar vi om hur projektet ska se ut och vad det ska innehålla. Här definierar vi upp hur projektet paketeras och vilka beroenden det har. Hur Maven sedan hanterar projektet när det utför sitt jobb bestäms genom mål (goals) knutna till ett gäng bestämda faser (phases) i olika livscykler (lifecycles).

Kort och gott innebär detta att du, när du kör ett Mavenkommando, talar om för Maven att gå igenom ett antal faser och att exekvera de mål som hör till varje fas.

Illustration över Mavens olika nivåer
Illustration över Mavens olika nivåer

Maven har tre inbyggda livscykler:

  • default (även kallad build) som hanterar deployment
  • clean som sköter rensning av projekt
  • site som hanterar projektdokumentering

Var och en av dessa cykler innehåller ett antal faser som representerar ett specifikt steg i cykeln. Exempelvis innehåller defaultcykeln fasen compile som ansvarar för kompilering av källkoden. Trots att varje fas har en specifik uppgift kan sättet den utför sin uppgift på variera då det är de mappade målen som i slutändan bestämmer vad som faktiskt sker. Vilka mål som knyts till vilken fas bestäms dels och framöverallt genom sättet artefakten paketerats men också genom de plugins som sugs in i projektet.

Som bilden ovan visar kan ett mål kan vara knutet till ett, flera eller inga faser precis som en fas kan innehålla noll eller flera mål. Ett fristående mål kan exekveras utanför livscykeln samtidigt som ett mål mappat mot flera faser körs en gång för varje mappning. Faser innehållandes multipla mål exekverar dessa i samma ordning som de deklarerats i POM:en. Däremot kommer en fas utan några mål aldrig att exekveras.

Defaultcyklen – för många användare den mest betydelsefulla cykeln då den fungerar som en generell modell för en applikations byggprocess – innehåller sammanlagt 23 faser. Nedan listar jag de mest framträdande av dessa:

Validate
Bekräftar att projektet är korrekt och att all information som behövs för att slutföra ett bygge finns tillgänligt.

Compilie
Komplilerar källkoden.

Test
Testar den kompilerade koden mot uppsatta tester.

Package
Paketerar den kompilerade koden till ett distribuerbart format (exempelvis .jar).

Integration-test
Om så är nödvändigt läggs den paketerade koden ut i en miljö anpassad för att köra integrationstester i.

Verify
Kör uppsatta kontroller för verifiering av paketets giltighet samt kontrollerar att paketet möter alla kvalitetskriterier.

Install
Installerar paketet i det lokala repot och kan nu användas som ett beroende i andra projekt lokalt.

Deploy
Kopierar det slutgiltiga paketet till ett remote repo för delning med andra projekt och utvecklare.

Utöver dessa faser tillkommer mellanfaser vilka bland annat hanterar förberedelser som att kopiera och flytta resurser till rätt kataloger samt post-process-steg som att städa upp efter körda tester. Här hittar ni den kompletta listan över faser.

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 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.

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 ScalaTest. För att göra det så lägger vi till följande beroende i pom.xml

&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;

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.

maven-scala-plugin ansvarar för att kompilera scalakoden till bytekod.

&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;

maven-surefire-plugin är den som kör testerna – 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 **/*Spec.*.

&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;

build-helper-maven-plugin 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).

&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;

Ok, nu behöver vi bara skapa mappen src/test/scala och sedan kan du börja koda!

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ö.

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 BDD – Behaviour Driven Development. 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.

Vi börjar med att skriva en första specifikation, som vår applikation skall uppfylla.

@RunWith(classOf[JUnitRunner])
class MyApplicationSpec extends FlatSpec with MustMatchers {

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

}

Det här är ett komplett test, även om det inte gör något just nu – 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

@RunWith(classOf[JUnitRunner])
class MyApplicationSpec extends FlatSpec with MustMatchers {

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

}

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

@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;)
  }

}

Klassen MyApplication är fortfarande skriven i Java, men jag testar den från Scala. Nyckelordet ”must” kommer från en trait i ScalaTest som heter MustMatchers. Det går också att använda ShouldMatchers, enda skillnaden är terminologin – must eller should, vilket du tycker om bäst.

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 ”testShouldConvertStringToHexValue” eller liknande. Enkelt och snyggt!

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 Borachio som är skrivet i Scala.

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 som denna artikel producerar (finns lite mer godis också i form av enklare ejb och servlet-klasser) så finns den tillgänglig på github:
git clone http://github.com/cygni-stacktrace/j2ee-maven-5minutes

Generera jee-arketyper

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 mvn archetype:generate (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.

EAR-input:

Define value for property ‘groupId’: : se.cygni.stacktrace.myearproject
Define value for property ‘artifactId’: : my-ear
Define value for property ‘version’:  1.0-SNAPSHOT: :
Define value for property ‘package’:  se.cygni.stacktrace.mywebexample: : ear

Andra gången anger vi siffran för arketypen webapp-javaee6. Input:

Define value for property ‘groupId’: : se.cygni.stacktrace.mywebexample
Define value for property ‘artifactId’: : my-web
Define value for property ‘version’: 1.0-SNAPSHOT: :
Define value for property ‘package’: se.cygni.stacktrace.mywebexample: : war

Tredje gången anger vi siffran för arketypen ejb-javaee6. Input:

Define value for property ‘groupId’: : se.cygni.stacktrace.myejbexample
Define value for property ‘artifactId’: : my-ejb
Define value for property ‘version’:  1.0-SNAPSHOT: :
Define value for property ‘package’:  se.cygni.stacktrace.myejbexample: : ejb

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.

Skapa en parent-pom

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 här):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>se.cygni.stacktrace</groupId>
  <artifactId>my-app</artifactId>
  <packaging>pom</packaging>
  <version>1.0</version>
  <name>my-app</name>

  <modules>
  	<module>../my-ear</module>
  	<module>../my-web</module>
  	<module>../my-ejb</module>
  </modules>
...

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: här.

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!

Modifiera ear att innehålla web och ejb-beroenden

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 http://download.eclipse.org/technology/m2e/releases/ och när det är gjort så importerar du pom.xml i my-app-katalogen in i eclipse (File-> Import -> Maven -> Existing Maven Projects). Det kommer skapa 4 olika projekt i eclipse, my-app, my-ear, my-web och my-ejb.

Öppna upp my-ear/pom.xml och modifiera stycket:

 <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-ear-plugin</artifactId>
        <version>2.6</version>
        <configuration>
            <version>6</version>
            <defaultLibBundleDir>lib</defaultLibBundleDir>
        </configuration>
      </plugin>

till:

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-ear-plugin</artifactId>
				<version>2.6</version>
				<configuration>
					<version>6</version>
					<defaultLibBundleDir>lib</defaultLibBundleDir>
					<modules>
						<ejbModule>
							<groupId>se.cygni.stacktrace.myejbexample</groupId>
							<artifactId>my-ejb</artifactId>
						</ejbModule>
						<webModule>
							<groupId>se.cygni.stacktrace.mywebexample</groupId>
							<artifactId>my-web</artifactId>
						</webModule>
					</modules>
				</configuration>
			</plugin>

Sen högerklickar du på my-ear-projektet i package explorer och väljer Maven -> Add dependency. I sökrutan anger du ”my-ejb”, 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:

	<dependencies>
		<dependency>
			<groupId>se.cygni.stacktrace.mywebexample</groupId>
			<artifactId>my-web</artifactId>
			<version>1.0</version>
			<type>war</type>
		</dependency>
		<dependency>
			<groupId>se.cygni.stacktrace.myejbexample</groupId>
			<artifactId>my-ejb</artifactId>
			<version>1.0</version>
			<type>ejb</type>
		</dependency>
	</dependencies>

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.

I denna artikel mixar vi Jersey med det XML-schema som Tommy Wassgren definierade i Serialisering med JAXB. Jersey är referensimplementationen för JAX-RS som är ett API för att bygga RESTfulla webbtjänster.

I artikeln visar vi hur enkelt det är att dra nytta av Jerseys inbyggda stöd för att skicka bl.a. XML och JSON m.h.a. JAXB. Vi visar också hur du kan enhetstesta REST-applikationen. Koden hittar du på github: https://github.com/cygni-stacktrace/jaxbws.

Läs mer >>

JAXB betyder Java Architecture for XML Binding och används för att konvertera POJOs till XML och vice versa. Metoden för att konvertera en POJO till XML kallas för marshalling eller serialisering. Det motsatta, det vill säga att konvertera från XML till en POJO, kallas för unmarshalling eller deserialisering.

I denna artikel visar jag hur man kan använda JAXB för serialisering/deserialisering på ett enkelt sätt med hjälp av ett enhetstest. Exemplet finns att hämta på GitHub – https://github.com/cygni-stacktrace/jaxb-sample.

Läs mer >>

I Protobuf för serialisering del 1 berättade jag om grunderna i Protobuf som kort kan beskrivas som ett binärt JSON-format. I den här artikeln tänkte jag visa hur man knyter i hop detta med Jersey som är ett snyggt API för RESTfulla webbtjänster. Som grädde på moset gör vi allt i Maven. Koden finns att hämta på https://github.com/cygni-stacktrace/protows.

Läs mer >>

Protobuf är en kodningsteknik för att serialisera datastrukturer till ett binärt format som tar mindre plats än t.ex. XML eller JSON. På så sätt lämpar sig protobuf bättre för transport över kanaler där bandbredd är en avgörande resurs.

Protobuf är utvecklat av Google och används enligt uppgift mycket mellan deras interna tjänster. Ramverket tillhandahålls med stöd för C++, Java och Pyton, men en mängd andra språk stöds också genom tredjepartsprojekt: C, C#, JavaScript etc.

Protobuf använder sig av en s.k. schemabaserad kodning, vilket innebär att ett kodat meddelande inte kan avkodas (i alla fall inte fullständigt) utan en beskrivning (ett schema) av datastrukturen. Datastrukturerna definieras i ett speciellt språk.

Läs mer >>

När man börjar utveckla i Scala dröjer det inte länge innan man behöver ett byggverktyg. Maven kommer med fullt javastöd  men för att kompilera Scala behövs maven-scala-pluginen. Det  gör att man börjar undra om det finns ett byggverktyg med fullt inbyggt stöd för Scala och det gör det, Simple Build Tool, eller SBT. På code.google.com finns SBT att ladda ner och bra engelsk dokumentation för installation och handhavande.

SBT liknar Maven väldigt mycket; samma konvention för hur filerna ska organiseras, de flesta av Mavens kommandon har direkta motsvarigheter i SBT. Så istället för mvn compile skriver man sbt compile.

SBT kan använda Mavens repositories, till och med Mavens pom.xml för beroendehantering. Det gör att det är väldigt enkelt att testa SBT i ett befintligt Maven-projekt.

Så vilka fördelar har SBT framför Maven, förutom att kompilera både scala- och javakod utan plugin-konfiguration?
Läs mer >>

Sida 1/3:123