Archive

Archive for the ‘Maven’ Category

Lets play with neo4j

Tuesday, 16. July 2013 Leave a comment

Der “Leipziger Firmenlauf 2013″ ist nun auch langsam Geschichte. Doch als ich heute nochmals durch die Ergebnisse stöberte, kam ich auf die Idee die Daten doch einfach mal in eine “NoSQL” Datenbank, in meinem Fall jetzt mal Neo4j, zu importieren.

Also gesagt getan, das Besorgen der Daten ist ein Kinderspiel. Die Homepage liefert alle gewünschten Datensätze per JSON, im Chrome die “CURL” kopieren, auf Kommandozeile ausführen, in eine Datei umleiten … fertig :)

$ curl 'http://results.davengo.com/query' -H 'Origin: http://results.davengo.com' -H 'Accept-Encoding: gzip,deflate,sdch' -H 'Host: results.davengo.com' -H 'Accept-Language: en,de;q=0.8
,en-US;q=0.6' -H 'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36' -H 'Content-Type: application/json' -H 
'Accept: */*' -H 'Referer: http://results.davengo.com/?event=50d426afb8ed1d2318282f54' -H 'Cookie: __utma=9661994.565730006.1373516179.1373516179.1373909845.2; __utmb=9661994.2.10.1373909845; 
__utmc=9661994; __utmz=9661994.1373909845.2.2.utmcsr=leipzig-firmenlauf.de|utmccn=(referral)|utmcmd=referral|utmcct=/ergebnisse2013.html; 
__utma=268406157.662336661.1373516307.1373516307.1373909929.2; __utmb=268406157.1.10.1373909929; __utmc=268406157; __utmz=268406157.1373516307.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); 
projekktorplayercontrolbar_volume=0.5' -H 'Connection: keep-alive' --data-binary '{"key":"50d426afb8ed1d2318282f54", "offset":0, "limit":100000, "where":{"categoryName":"Einzelwertung"}, "order":
{"firma":"ASC"}, "category":"Einzelwertung"}' --compressed > results_2013.json

Jetzt kommt der “schwierige” Part, JSON parsen und via Spring Data Neo4j in eine Neo4j Datenbank einfügen.

<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/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mymita.tools</groupId>
	<artifactId>firmenlauf2013</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-asl</artifactId>
			<version>1.9.12</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-neo4j</artifactId>
			<version>2.2.1.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>0.11.8</version>
		</dependency>
		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>14.0.1</version>
		</dependency>
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>2.2.2</version>
		</dependency>
		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.1.0.Final</version>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>1.0.13</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Der Importerservice

package com.mymita.firmenlauf2013.service;

import java.io.IOException;
import java.util.Map;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.base.Objects;
import com.google.common.collect.Maps;
import com.mymita.firmenlauf2013.model.Company;
import com.mymita.firmenlauf2013.model.Run;
import com.mymita.firmenlauf2013.model.Runner;
import com.mymita.firmenlauf2013.model.Team;

@Service
public class ImportService {

	@Getter
	@AllArgsConstructor
	@ToString
	public static class JsonRunner {

		public JsonRunner(Object[] data) {
			this((Integer) data[0], (Integer) data[1], (Integer) data[2],
					(Integer) data[3], (String) data[4], (String) data[5],
					(String) data[6], (String) data[7], (String) data[8],
					(String) data[9], (String) data[10]);
		}

		Integer platz;
		Integer platzMaennlich;
		Integer platzWeiblich;
		Integer nummer;
		String vorname;
		String nachname;
		String team;
		String zeit;
		String firma;
		String dummy;
		String key;
	}

	@Getter
	@Setter
	public static class JsonRunners {
		Object[][] items;
	}

	Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private Neo4jTemplate template;

	private final Map<String, Company> companies = Maps.newHashMap();
	private final Map<String, Team> teams = Maps.newHashMap();
	private final Map<Integer, Runner> runners = Maps.newHashMap();
	private final Map<String, Run> runs = Maps.newHashMap();

	@Transactional
	public void importData() {
		try {
			JsonRunners jsonRunners = new ObjectMapper().readValue(
					new ClassPathResource("results.json").getInputStream(),
					JsonRunners.class);
			for (int i = 0; i < jsonRunners.items.length; i++) {
				JsonRunner jsonRunner = new JsonRunner(jsonRunners.items[i]);
				String teamName = jsonRunner.getTeam();
				String companyName = jsonRunner.getFirma();
				String time = jsonRunner.getZeit();
				Company company = companies.get(companyName);
				if (company == null) {
					company = new Company(Objects.firstNonNull(companyName,
							"NONAME"));
					template.save(company);
					companies.put(company.getName(), company);
					logger.debug("Created company '{}'", company);
				}
				Team team = teams.get(teamName);
				if (team == null) {
					team = new Team(teamName).sponsoredBy(company);
					template.save(team);
					teams.put(team.getName(), team);
					logger.debug("Created team '{}'", team);
				}
				Run run = runs.get(time);
				if (run == null) {
					run = new Run(time);
					template.save(run);
					runs.put(run.getTime(), run);
					logger.debug("Created run '{}'", run);
				}
				Runner runner = new Runner(jsonRunner.getNummer(),
						jsonRunner.getVorname(), jsonRunner.getNachname())
						.fightFor(team).finished(run);
				template.save(runner);
				runners.put(runner.getNumber(), runner);
				logger.debug("Created runner '{}'", runner);
			}
			for (Team t : teams.values()) {
				template.save(t);
				logger.debug("Updated team '{}'", t);
			}
			for (Run r : runs.values()) {
				template.save(r);
				logger.debug("Updated run '{}'", r);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Der Spring Context

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
		                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		                http://www.springframework.org/schema/data/neo4j http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd">
	<neo4j:repositories base-package="com.mymita.firmenlauf2013" />
	<neo4j:config graphDatabaseService="graphDatabaseService" />
	<bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase"
		destroy-method="shutdown">
		<constructor-arg value="target/firmenlauf2013.db" />
	</bean>
	<context:annotation-config />
	<context:component-scan base-package="com.mymita.firmenlauf2013" />
	<tx:annotation-driven mode="proxy"
		transaction-manager="transactionManager" />
</beans>

Und ein kleines Hauptprogramm um alles zu starten

package com.mymita.firmenlauf2013.importer;

import java.io.File;
import java.io.IOException;

import org.neo4j.kernel.impl.util.FileUtils;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mymita.firmenlauf2013.service.ImportService;

public class Importer {

	public static void main(String[] args) throws IOException {
		FileUtils.deleteRecursively(new File("target/firmenlauf2013.db"));
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
				"classpath:application-context.xml");
		try {
			new Importer().importData(ctx);
		} finally {
			ctx.close();
		}
	}

	private void importData(ClassPathXmlApplicationContext ctx) {
        ctx.getBean(ImportService.class).importData();
    }

}

Die NodeEntites sehen folgendermassen aus …

package com.mymita.firmenlauf2013.model;

import lombok.ToString;
import org.springframework.data.neo4j.annotation.GraphId;

@ToString
public abstract class AbstractEntity {

	@GraphId
	private Long id;

	public Long getId() {
		return id;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (id == null || obj == null || !getClass().equals(obj.getClass())) {
			return false;
		}
		return id.equals(((AbstractEntity) obj).id);
	}

	@Override
	public int hashCode() {
		return id == null ? 0 : id.hashCode();
	}
}

Die Firma für die ein Team von Läufern startete

package com.mymita.firmenlauf2013.model;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.neo4j.annotation.Indexed;
import org.springframework.data.neo4j.annotation.NodeEntity;

@Getter
@NoArgsConstructor
@ToString(callSuper=true)
@NodeEntity
@TypeAlias("Company")
public class Company extends AbstractEntity {

    @Indexed(unique=true)
    private String name;

    public Company(String name) {
		this.name = name;
	}

}

Das Team von Läufern

package com.mymita.firmenlauf2013.model;
import java.util.Set;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.neo4j.annotation.Indexed;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelatedTo;

import com.google.common.collect.Sets;

@Getter
@NoArgsConstructor
@ToString(callSuper=true, exclude={"runners"})
@NodeEntity
@TypeAlias("Team")
public class Team extends AbstractEntity {

    @Indexed(unique=true)
    private String name;
    @RelatedTo(type="have")
    private Set<Runner> runners = Sets.newHashSet();
    @RelatedTo(type="sponsored_by")
    private Company company;

    public Team(String name) {
		this.name = name;
	}

    public Team sponsoredBy(Company company) {
    	this.company = company;
    	return this;
    }

    public Team have(Runner runner) {
    	runners.add(runner);
    	return this;
    }

}

Ein Läufer

package com.mymita.firmenlauf2013.model;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.neo4j.annotation.Indexed;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelatedTo;

@Getter
@NoArgsConstructor
@ToString(callSuper=true, exclude={"run", "team"})
@NodeEntity
@TypeAlias("Runner")
public class Runner extends AbstractEntity{

    @Indexed(numeric=true,unique=true)
    private Integer number;
    @Indexed
    private String firstName;
    @Indexed
    private String lastName;
    @RelatedTo(type="fight_for")
    private Team team;
    @RelatedTo(type="finished")
    private Run run;

    public Runner(Integer number, String firstName, String lastName) {
		this.number = number;
		this.firstName = firstName;
		this.lastName = lastName;
    }

    public Runner fightFor(Team team) {
    	this.team=team;
    	team.have(this);
    	return this;
    }

    public Runner finished(Run run) {
    	this.run=run;
    	run.finishedBy(this);
    	return this;
    }

}

Und das Ergebnis eines Laufs

package com.mymita.firmenlauf2013.model;
import java.util.Set;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelatedTo;

import com.google.common.collect.Sets;

@Getter
@NoArgsConstructor
@ToString(callSuper=true, exclude={"runners"})
@NodeEntity
@TypeAlias("Run")
public class Run extends AbstractEntity{

	private String time;

	@RelatedTo(type="finished_by")
	private Set<Runner> runners = Sets.newHashSet();

    public Run(String time) {
		this.time = time;
    }

	public Run finishedBy(Runner runner) {
		runners.add(runner);
		return this;
	}
}

Ergebnis der ganze Mühen ist ein Verzeichnis im target Ordner des Mavenprojekts, dessen Inhalt in einen Neo4j-Server (http://www.neo4j.org/download) kopiert wird. Ist der Server hochgefahren, kann man unter http://localhost:7474 das Ergebnis bestaunen :)

Eine kleine Abfrage bringt dann auch alle meine lieben Kollegen vom “Running suckz” Team zum Vorschein

neo4j_firmenlauf2013

Quick Maven Workaround

Thursday, 27. June 2013 Leave a comment

Currently I want run https://github.com/jamesward/hello-java-spring-neo4j

$ mvn -version
Apache Maven 3.1.0-alpha-1 (c726cdd3a9ad5c3a419e1171f8c1925e336ead18; 2013-06-01 15:03:28+0200)
Maven home: C:\Development\apache-maven-3.1.0-alpha-1
Java version: 1.7.0_09, vendor: Oracle Corporation
Java home: C:\Program Files\Java\jdk1.7.0_09\jre
Default locale: de_DE, platform encoding: Cp1252
OS name: “windows 7″, version: “6.1″, arch: “amd64″, family: “windows”

Unfortunately I got some strange error like “access denied” for tinkerpop (I never heard about this maven repository until now) and slowwwww connection to memcache repo at googlecode (svn) … so here is a “workaround” for that …

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
	<mirrors>
		<mirror>
			<id>tinkerpop</id>
			<name>tinkerpop</name>
			<url>http://repo.maven.apache.org/maven2</url>
			<mirrorOf>tinkerpop-repository</mirrorOf>
		</mirror>
		<mirror>
			<id>msm</id>
			<name>msm</name>
			<url>http://repo.maven.apache.org/maven2</url>
			<mirrorOf>msm</mirrorOf>
		</mirror>
	</mirrors>
</settings>
Categories: Maven Tags: , , ,

Use maven profile to recompile vaadin widgetset #2

Thursday, 26. April 2012 Leave a comment

In a older post I describe my solution to handle VAADIN/GWT widgetset compilation with maven.

Today I  will share some changes to use GWT 2.4 with my solution.

The problem: after GWT compilation a new directory gwt-unitCache exists under the VAADIN directory. I don’t need this ;)

I integrate this workaround in my profile:

<profile>
  <!-- Updates Vaadin widgetset definitions based on project dependencies -->
  <id>update-widgetset</id>
  <activation>
    <file>
      <missing>${basedir}/src/main/webapp/VAADIN/widgetsets/</missing>
    </file>
  </activation>
  <build>
    <plugins>
      <plugin>
        <groupId>com.vaadin</groupId>
        <artifactId>vaadin-maven-plugin</artifactId>
        <version>1.0.2</version>
        <executions>
          <execution>
            <phase>generate-resources</phase>
            <goals>
              <goal>update-widgetset</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>gwt-maven-plugin</artifactId>
        <version>2.4.0</version>
        <configuration>
          <webappDirectory>${basedir}/src/main/webapp/VAADIN/widgetsets/</webappDirectory>
          <extraJvmArgs>-Xmx512M -Xss1024k </extraJvmArgs>
          <deploy>${project.build.directory}/gwt-tmp/</deploy>
          <soyc>false</soyc>
          <force>true</force>
          <strict>true</strict>
          <style>OBFUSCATED</style>
          <optimizationLevel>9</optimizationLevel>
        </configuration>
        <executions>
          <execution>
            <phase>generate-resources</phase>
            <goals>
              <goal>resources</goal>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <!-- workaround for 
             http://code.google.com/p/google-web-toolkit/issues/detail?id=6397 -->
        <artifactId>maven-clean-plugin</artifactId>
        <version>2.4.1</version>
        <configuration>
          <filesets>
            <fileset>
              <directory>${basedir}/src/main/webapp/VAADIN/</directory>
              <includes>
                <directory>gwt-unitCache/**</directory>
              </includes>
              <followSymlinks>false</followSymlinks>
            </fileset>
          </filesets>
          <excludeDefaultDirectories>true</excludeDefaultDirectories>
        </configuration>
        <executions>
          <execution>
            <id>default</id>
            <phase>generate-resources</phase>
            <goals>
              <goal>clean</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</profile>

:-)

Categories: GWT, Maven, Vaadin Tags: , , ,

Use maven profile to recompile vaadin widgetset

Thursday, 15. December 2011 1 comment

Today I will show you my maven profile to configure Vaadin widgetset recompilation.

The Vaadin wiki shows the basics … but I want widgetset update only if its necessary … so I moved the gwt/vaadin plugins in a profile and add a activation per file for this profile:

<profile>
   <!--
     Updates Vaadin widgetset definitions based on project dependencies
     Remove widgetset directory to trigger recompile:
       rm -Rf src/main/webapp/VAADIN/widgetsets/
   -->
   <id>update-widgetset</id>
   <activation>
     <file>
       ${basedir}/src/main/webapp/VAADIN/widgetsets/
     </file>
   </activation>
   <build>
     <plugins>
       <plugin>
         <groupId>com.vaadin</groupId>
         <artifactId>vaadin-maven-plugin</artifactId>
         <version>1.0.2</version>
         <configuration>
           <!-- if you don't specify any modules, the plugin will find them -->
         </configuration>
         <executions>
           <execution>
             <phase>generate-resources</phase>
             <goals>
               <goal>update-widgetset</goal>
             </goals>
           </execution>
         </executions>
       </plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>gwt-maven-plugin</artifactId>
         <version>2.3.0-1</version>
         <configuration>
           <!-- if you don't specify any modules, the plugin will find them -->
           ${basedir}/src/main/webapp/VAADIN/widgetsets/
           -Xmx512M -Xss1024k
           ${project.build.directory}/gwt-tmp/
           <soyc>false</soyc>
           <force>true</force>
         </configuration>
         <executions>
           <execution>
             <phase>generate-resources</phase>
             <goals>
               <goal>resources</goal>
               <goal>compile</goal>
             </goals>
           </execution>
         </executions>
       </plugin>
     </plugins>
   </build>
 </profile>

:)

Categories: Maven, Vaadin Tags: ,

Bloxel 0.1.0 make progress

Saturday, 12. February 2011 Leave a comment

Now we have a simple open world algorithm, simple water effect, a spring DI integration (of course *g*), a game menu, a groovy console and some testcases :) And we using maven!

And more screenshots …

Categories: Bloxel, Java, Maven

Intermodule Dependencies now better working in Maven 3

Wednesday, 22. December 2010 Leave a comment

Found at http://www.sonatype.com/people/2010/12/whats-in-maven-3-0-for-users/

One of the other major improvements in Maven 3.0 is the resolution of inter-module dependencies from the current reactor build. In the past, it has been quite frustrating for users to find out that mvn install works but mvn verify sometimes fails to resolve artifacts that have just been built by a previous module, in particular when releasing a new version of their projects. Likewise, it’s hard to understand why an execution of maven-dependency-plugin:copy-dependencies succeeds to resolve artifacts from the reactor while the similar maven-dependency-plugin:copy goals fails.

As part of all the refactoring in Maven 3, a dependency resolution has been reworked to consistently check the reactor output. Apparently, the reactor output depends on the lifecycle phases that a project has completed. So if you invoke mvn compile or mvn test on a multi-module project, the loose class files from target/classes and target/test-classes, respectively, are used to create the required class path. As soon as the actual artifact has been assembled which usually happens during the package phase, dependency resolution will use this file. Last but not least, dependencies using version ranges can now be resolved from the reactor, too.

For this a short recap about reactor builds …

 parent-project (reactor)
   | ----  module-a
      | src/main/java/de/ahoehma/Core.java
      | mvn compile will create target/classes/de/ahoehma/Core.class
   | ----  module-b
      | use classes from module A
      | src/main/java/de/ahoehma/Use.java
      | Use have a dependcy to Core (module-b have a dependency to module-a)
      | mvn compile will create target/classes/de/ahoehma/Use.class

Let’s go into module-b and run mvn compile – a build error occured … can’t resolve dependency modul-a.

That’s clear … maven knows nothing about module-a right now. I can go into module-a and run mvn install to fix this “situation”.

After this I find a jar-file module-a.jar in the local maven-repository. Then the build in module-b will work. But install is not always possible … Think about API Changes, experimental code etc.  I don’t want this stuff in my local repo *g*.

For this I can run a reactor build … I go into parent and run mvn compile … that’s all. Maven will use the compile results from module-a during the build of module-b … magic :D

[INFO] [compiler:compile {execution: default-compile}]
[DEBUG] Using compiler 'javac'.
[DEBUG] Source directories: [F:\ws_sts\parent\module-b\src\main\java]
[DEBUG] Classpath: [F:\ws_sts\parent\module-b\target\classes
 F:\ws_sts\parent\module-a\target\classes]
[DEBUG] Output directory: F:\ws_sts\parent\module-b\target\classes
[DEBUG] Classpath:^
[DEBUG]  F:\ws_sts\parent\module-b\target\classes
[DEBUG]  F:\ws_sts\parent\module-a\target\classes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[DEBUG] Source roots:
[DEBUG]  F:\ws_sts\parent\module-b\src\main\java
[INFO] Compiling 1 source file to F:\ws_sts\parent\module-b\target\classes
[INFO]
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] ------------------------------------------------------------------------
[INFO] Unnamed - de.ahoehma:parent:pom:0.0.1-SNAPSHOT ........ SUCCESS [0.758s]
[INFO] Unnamed - de.ahoehma:module-a:jar:0.0.1-SNAPSHOT ...... SUCCESS [1.590s]
[INFO] Unnamed - de.ahoehma:module-b:jar:0.0.1-SNAPSHOT ...... SUCCESS [0.637s]
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Wed Dec 22 20:27:57 CET 2010
[INFO] Final Memory: 20M/128M
[INFO] ------------------------------------------------------------------------

This works in maven 2 too!

Categories: Maven Tags: ,

Oberwald Rally

Friday, 11. June 2010 2 comments

Ich habe heute ein kleines privates Projekt öffentlich zugänglich gemacht.

Das Projekt entstand im Rahmen unseres jährlichen Männertagstreffens (wir Leipziger HTWK Mappen feiern nicht nur einen Tag sondern gleich vier). Dieses Mal waren wir halt im schönen Oberwald. Der Tag war noch jung, ein paar Bier waren auch schon geleert … also was tun. Na dann einfach Mal etwas programmieren :D Ziel: “Rasende Roboter” programmieren, am besten gleich einen Algorithmus schreiben, der das Problem automatisch löst. Das Projekt beschäftigt sich also mit dem Thema “Ricochet Robots” (im dt. Rasende Roboter). Wie ich hier bereits schon schrieb, ist es eines meiner Lieblingsspiele :-)

Das ganze Ding ist mittlerweile zu einem Eclipse PDE Projekt gereift … hier ein paar Screenshots …

Random Calculator View

Der RandomCalculator schiebt die 4 Roboter nach dem Zufallsprinzip über das Brett. Dabei kommt es ab und zu auch dazu, dass die Aufgabe (Roboter vom grünen Feld auf das rote Feld) gelöst wird :)

Graph Calculator View

Der GraphCalculator ist schon etwas “schlauer”, allerdings kann er nur den kürzesten Weg für einen Roboter berechnen.

Den Code gibts unter https://code.google.com/p/oberwaldrally/.

Feedback erwünscht!

Viel Spass beim Bot schreiben!

:D

Howto define jetty port for integration tests

Tuesday, 1. June 2010 Leave a comment

Today I found a simple hack to define the jetty-port for a web-application integration test via command line.

The problem was the defined “default” jetty port (here 8080) … on the build system this port was already bind … so the integration test always failed :-(.

My first idea was to call maven with external system property “jetty.port” … (this worked already to start the web application on different ports):

mvn clean integration-test -Pintegration-test -Djetty.port=1234

The maven profile is here:

...
  <profile>
      <id>integration-test</id>
      <build>
        <defaultGoal>integration-test</defaultGoal>
        <plugins>
          <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <executions>
              <execution>
                <id>integration-tests</id>
                <phase>integration-test</phase>
                <goals>
                  <goal>test</goal>
                </goals>
                <configuration>
                  <forkMode>once</forkMode>
                  <suiteXmlFiles>
                    <suiteXmlFile>src/test/resources/Integration-Suite.xml</suiteXmlFile>
                  </suiteXmlFiles>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>maven-jetty-plugin</artifactId>
            <version>${jetty.version}</version>
            <executions>
              <execution>
                <id>start-jetty</id>
                <phase>pre-integration-test</phase>
                <goals>
                  <goal>run</goal>
                </goals>
                <configuration>
                  <daemon>true</daemon>
                  <connectors>
                    <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
                      <port>${jetty.port}</port>
                    </connector>
                  </connectors>
                </configuration>
              </execution>
              <execution>
                <id>stop-jetty</id>
                <phase>post-integration-test</phase>
                <goals>
                  <goal>stop</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>

I think with this TestNG test this should work … (the base class ImportantUseCaseTest contains some @Test annotated test methods):

public class IntegrationTest extends ImportantUseCaseTest {
  @Override
  protected String getServerURL() {
    final String jettyPort = System.getProperty("jetty.port", "8080);
    return String.format("http://localhost:%s/webapp", jettyPort);
  }
}

But it doesn’t work :-)

If I call maven with “-Djetty.port=1234″ the jetty starts on 1234 but the integration test runs on 8080.  Hmmm …

The solution was to change the surefire plugin configuration a little bit:

...
  <plugin>
     <artifactId>maven-surefire-plugin</artifactId>
     ...
     <configuration>
         ...
         <argLine>-Xmx512m -Djetty.port.integration=${jetty.port}</argLine>
     </configuration>

and the test class:

public class IntegrationTest extends ImportantUseCaseTest {
  @Override
  protected String getServerURL() {
    final String jettyPort = System.getProperty("jetty.port.integration", "8080);
    return String.format("http://localhost:%s/webapp", jettyPort);
  }
}

I guess that surefire with forkMode=once doesn’t pass the given system properties to the test jvm. Maybe with forkMode=never this problem not exists … but you can try this by yourself ;)

Export maven war artifact as runnable jetty package

Tuesday, 25. May 2010 3 comments

Today I will show you a way to export a <packaging>war</packaging> artifact as a runnable windows application.

The ingredients are:

  • maven war artifact (i.e. our web application)
  • embedded Jetty

A minimal web application’s pom looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<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>de.ahoehma</groupId>
  <artifactId>dummy-webapp</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>war</packaging>
</project>

Now we add some components to the artifact …

1. add the following profile to the pom.xml:

<profiles>
   <profile>
      <id>jetty-offline</id>
      <build>
        <plugins>
          <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2-beta-5</version>
            <configuration>
              <finalName>offline-dummy-webapp-${project.version}</finalName>
              <attach>false</attach>
              <descriptors>
                <descriptor>src/assembly/jetty-offline.xml</descriptor>
              </descriptors>
            </configuration>
            <executions>
              <execution>
                <id>make-assembly</id>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
      <dependencies>
        <!-- logging ... -->
        <dependency>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
          <version>1.1.1</version>
        </dependency>
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.15</version>
          <scope>runtime</scope>
        </dependency>
        <!-- embedded jetty -->
        <dependency>
          <groupId>org.mortbay.jetty</groupId>
          <artifactId>jetty</artifactId>
          <version>${jetty.version}</version>
        </dependency>
        <dependency>
          <groupId>org.mortbay.jetty</groupId>
          <artifactId>start</artifactId>
          <version>${jetty.version}</version>
        </dependency>
        <dependency>
          <groupId>org.mortbay.jetty</groupId>
          <artifactId>jetty-util</artifactId>
          <version>${jetty.version}</version>
        </dependency>
        <dependency>
          <groupId>org.mortbay.jetty</groupId>
          <artifactId>jsp-2.1-jetty</artifactId>
          <version>${jetty.version}</version>
        </dependency>
      </dependencies>
      <properties>
          <jetty.version>6.1.23</jetty.version>
      </properties>
    </profile>
</profiles>

2. the assembly descriptor for src/assembly/jetty-offline is here:

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1 http://maven.apache.org/xsd/assembly-1.1.1.xsd">

  <formats>
    <format>dir</format>
  </formats>
  
  <dependencySets>
    <dependencySet>
      <!-- unpack the webapp as root application -->
      <scope>runtime</scope>
      <unpack>true</unpack>
      <outputDirectory>webapps/root/</outputDirectory>
      <includes>
        <include>de.ahoehma:dummy-webapp:war</include>
      </includes>
    </dependencySet>
    <dependencySet>
      <unpack>false</unpack>
      <outputDirectory>lib</outputDirectory>
      <useTransitiveFiltering>true</useTransitiveFiltering>
      <useStrictFiltering>true</useStrictFiltering>
      <includes>
        <include>org.mortbay.jetty:jetty</include>
        <include>org.mortbay.jetty:jetty-util</include>
        <include>org.mortbay.jetty:start</include>
        <include>org.mortbay.jetty:jsp-2.1-jetty</include>
        <include>commons-logging:commons-logging</include>
        <include>log4j:log4j</include>
      </includes>
    </dependencySet>
  </dependencySets>

  <fileSets>
    <fileSet>
      <directory>src/jetty/bin</directory>
      <outputDirectory>bin/</outputDirectory>
      <filtered>false</filtered>
    </fileSet>
    <fileSet>
      <directory>src/jetty/resources</directory>
      <outputDirectory>etc/</outputDirectory>
      <filtered>false</filtered>
    </fileSet>
  </fileSets>
  
</assembly>

See maven-assembly-plugin for more options …

3. src/jetty/bin contains a windows batch file:

 @echo off
 @set JVM_OPTS=-XX:MaxPermSize=256m -XX:PermSize=128m -Xms128m -Xmx512m
 (cd .. && java %JVM_OPTS% -jar lib/start-6.1.23.jar)

4. and at least the src/jetty/resources contains the file jetty.xml:

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure id="Server" class="org.mortbay.jetty.Server">
    <Set name="ThreadPool">
      <New class="org.mortbay.thread.BoundedThreadPool">
        <Set name="minThreads">10</Set>
        <Set name="maxThreads">250</Set>
        <Set name="lowThreads">25</Set>
      </New>
    </Set>
    <Call name="addConnector">
      <Arg>
          <New class="org.mortbay.jetty.nio.SelectChannelConnector">
            <Set name="host"><SystemProperty name="jetty.host" default="localhost"/></Set>
            <Set name="port"><SystemProperty name="jetty.port" default="1976"/></Set>
            <Set name="maxIdleTime">30000</Set>
            <Set name="Acceptors">2</Set>
            <Set name="statsOn">false</Set>
            <Set name="confidentialPort">8442</Set>
      	    <Set name="lowResourcesConnections">5000</Set>
      	    <Set name="lowResourcesMaxIdleTime">5000</Set>
          </New>
      </Arg>
    </Call>
    <Set name="handler">
      <New id="Handlers" class="org.mortbay.jetty.handler.HandlerCollection">
        <Set name="handlers">
         <Array type="org.mortbay.jetty.Handler">
           <Item>
             <New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/>
           </Item>
           <Item>
             <New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/>
           </Item>
         </Array>
        </Set>
      </New>
    </Set>
    <Call name="addLifeCycle">
      <Arg>
        <New class="org.mortbay.jetty.deployer.ContextDeployer">
          <Set name="contexts"><Ref id="Contexts"/></Set>
          <Set name="configurationDir"><SystemProperty name="jetty.home" default="."/>/contexts</Set>
          <Set name="scanInterval">1</Set>
        </New>
      </Arg>
    </Call>
    <Call name="addLifeCycle">
      <Arg>
        <New class="org.mortbay.jetty.deployer.WebAppDeployer">
          <Set name="contexts"><Ref id="Contexts"/></Set>
          <Set name="webAppDir"><SystemProperty name="jetty.home" default="."/>/webapps</Set>
      	  <Set name="parentLoaderPriority">false</Set>
      	  <Set name="extract">true</Set>
      	  <Set name="allowDuplicates">false</Set>
        </New>
      </Arg>
    </Call>
    <Set name="stopAtShutdown">true</Set>
    <Set name="sendServerVersion">true</Set>
    <Set name="sendDateHeader">true</Set>
    <Set name="gracefulShutdown">1000</Set>
</Configure>

Now we are able to build a “offline version” of our web application:

 mvn package -Pjetty-offline

The result will be a directory target\distribution\offline-dummy-webapp-1.0.0-SNAPSHOT with the structure:

 bin/
    jetty_run.bar
 etc/
    jetty.xml
 lib/
    log4j-1.2.15.jar
    commons-logging-1.1.1.jar    
    servlet-api-2.5-20081211.jar
    start-6.1.23.jar
    jetty-6.1.23.jar
    jetty-util-6.1.23.jar
    ant-1.6.5.jar
    core-3.1.1.jar
    ecj-3.5.1.jar
    jsp-2.1-jetty-6.1.23.jar
    jsp-2.1-glassfish-2.1.v20091210.jar
    jsp-api-2.1-glassfish-2.1.v20091210.jar
 webapps/
    root/
       index.html
       css/
       images/
       META-INF/
       pages/
       WEB-INF/
       ...

To run the web application start the jetty_run.bat (i.e. open the dir with the explorer and double click the bat-file).

That’s it :D

This article was the first part if the tutorial … in the second part I will show you how to build a windows exe package with a runnable web application inside …

Categories: Java, Maven Tags: , ,

Yet another Maven discussion

Thursday, 11. February 2010 Leave a comment

I posted a comment to the Code Buzz Blog.

Categories: Maven Tags: , ,
Follow

Get every new post delivered to your Inbox.