Updates from July, 2013 Toggle Comment Threads | Keyboard Shortcuts

  • Andreas Höhmann 0:53 on Tuesday, 16. July 2013 Permalink | Log in to leave a Comment
    Tags: Neo4j,   

    Lets play with neo4j 

    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

     
  • Andreas Höhmann 22:47 on Thursday, 27. June 2013 Permalink | Log in to leave a Comment
    Tags: , memcached, , tinkerpop   

    Quick Maven Workaround 

    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>
    
     
  • Andreas Höhmann 15:21 on Thursday, 26. April 2012 Permalink | Log in to leave a Comment
    Tags: GWT, , ,   

    Use maven profile to recompile vaadin widgetset #2 

    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>
    

    :-)

     
  • Andreas Höhmann 9:43 on Thursday, 15. December 2011 Permalink | Log in to leave a Comment
    Tags: ,   

    Use maven profile to recompile vaadin widgetset 

    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>

    :)

     
  • Andreas Höhmann 20:56 on Saturday, 12. February 2011 Permalink | Log in to leave a Comment  

    Bloxel 0.1.0 make progress 

    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 …

     
  • Andreas Höhmann 21:30 on Wednesday, 22. December 2010 Permalink | Log in to leave a Comment
    Tags: maven3, rector   

    Intermodule Dependencies now better working in Maven 3 

    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!

     
  • Andreas Höhmann 12:55 on Friday, 11. June 2010 Permalink | Log in to leave a Comment
    Tags: , graph, jung, , , ricochet robots   

    Oberwald Rally 

    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

     
  • Andreas Höhmann 12:05 on Tuesday, 1. June 2010 Permalink | Log in to leave a Comment
    Tags: integration-test, , maven2, port already bind, ,   

    Howto define jetty port for integration tests 

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

     
  • Andreas Höhmann 11:31 on Tuesday, 25. May 2010 Permalink | Log in to leave a Comment
    Tags: , ,   

    Export maven war artifact as runnable jetty package 

    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 …

     
    • tplee923 19:54 on Thursday, 16. June 2011 Permalink | Log in to Reply

      When I use your code, and execute the bat file, why I get the error:
      java.lang.ClassNotFoundException: org.mortbay.xml.XmlConfiguration
      at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
      at org.mortbay.start.Main.invokeMain(Main.java:179)
      at org.mortbay.start.Main.start(Main.java:534)
      at org.mortbay.start.Main.start(Main.java:441)
      at org.mortbay.start.Main.main(Main.java:119)

  • Andreas Höhmann 12:21 on Thursday, 11. February 2010 Permalink | Log in to leave a Comment
    Tags: antihype, hype,   

    Yet another Maven discussion 

    I posted a comment to the Code Buzz Blog.

     
c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
Follow

Get every new post delivered to your Inbox.