Posts mit dem Label Maven werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Maven werden angezeigt. Alle Posts anzeigen

Samstag, 30. August 2014

Tangram CoMA erwacht

Da ich nach einem langen Sommeurlaub nun wieder schwerpunktmäßig mit dem CoreMedia CMS zutun habe, habe ich mir auch im Tangram nach sehr langer Ruhe mal wieder die entsprechende Anbindung angesehen.

Ein altes Beispiele

Seit geraumer Zeit gibt es eine Beispielanwendung zum CoreMedia Adapter CoMA im Tangram Framework. Diese litt aber daran, daß das Aufsetzen der Umgebung dazu nicht ganz trivial war. Alleine schon deshalb konnte ich nicht soviel Energie in die Weiterentwicklung stecken.
Für diese Anwendung stehen Möglichkeiten von Tangram, Content einzugeben, nicht zur Verfügung, da der CoMA nur lesend arbeitet. Um dennoch Inhalte und ein paar Templates zum Zeigen zu bekommen, nutze ich die uralte Beispielanwendung MenuSite von CoreMedia selbst.
Man benötigt also zum Nutzen der Anwendung eine Datenbank, wie sie ein CoreMedia Content Server für die MenuSite angelegt und mit Daten befüllt hätte.
Bisher waren die Schritte, die nötig waren, um diese Datenbank aufzusetzen nur zur Ausführung beschrieben. Alle andere Beispiele kann man einfach bauen und starten.

Neue Server

Meine Experimente mit Gradle zum Zusammenbau von CoreMedia Softwarekomponenten ohne das bei mir nicht sehr beliebte Maven haben allerdings nun einen Stand erreicht, in dem man Skripte und kleine Workspaces präsentieren kann, mit denen man die benötigte Datenbank erstellen kann.
Die Content Management Server Webanwendung unter
https://github.com/mgoellnitz/cm-cms-webapp
und die Content Management Server Tools unter
https://github.com/mgoellnitz/cm-cms-tools
Die harte Nuß dabei war weniger der Server als das Tools Paket. Aber ohne die Tools konnte ich die Daten natürlich nicht in den Server importieren. Außerdem hat das von mir gewählte Tomcat Plugin für Gradle sich nicht von der freundlichen Seite gezeigt. Mittlerweile weiß ich, daß auch andere Anwendungen als der CoreMedia Content Server unter dem falsch zusammengestellten Classpath leiden.

Und alles ohne Maven

Die genaus Beschreibung findet sich im Beispiel Repository zu Tangram.

Montag, 23. Juni 2014

CoreMedia CMS und Gradle - just for the LOLs

Um das tangram-coma Modul wieder mehr in meinen Fokus zu bringen, brauche ich zum Testen immer einen CoreMedia CMS Content Server als backend.

Bisher war dieser Server entsprechend einer Anleitung und mit der Lieferung des Produktes als ZIP-Datei von Hand herzustellen. Das paßt natürlich nicht so richtig in die Tangram Beispiele, die in sich abgeschlossen sein sollten, und die bisher genutzte Version CMS 2008 (5.2) läuft nun unwidderruflich auch aus.

Mit den aktuellen Versionen wird das Produkt handlich in Form von Artefakten in einem Maven-Repository geliefert und es stehen Maven-Module zur Verfügung, daraus komplette Server zu erstellen, zu customizen und zu bestücken.

Leider ist dieser Bereich eben noch mit Maven formuliert und außerdem müßte ich mich dann - und dafür ist es ein wenig früh - vom Minimalbeispiel MenuSite verabschieden.

Also habe ich mich gefragt, ob ich fit genug bin, die Baupläne von CoreMedia mal im ganz kleinen nach gradle zu übersetzen und mir so den Content Management Server mit Build-Script in die Tangram Beispiele zu integrieren. Dabei habe ich natürlich wieder einen Dienst menr aus der Cloud als Entwicklungsunterstützung hinzugezogen, wie es zum Entwicklungsmodell von Tangram am besten paßt: Gut funktionierende Dienste und Komponenten nutzen. Da ich mit CoreMedia in der aktuellen Version hsqldb nicht mehr nutzen kann und nicht mehr wie im bisherigen Beispiel postgresql lokal installieren und nutzen wollte, habe ich mir mal schnell eine Testdatenbank bei DB4Free besorgt, da das "default" Datenbanksystem im CoreMedia CMS derzeit MySQL ist.

Um's kurz zu machen: Das Zusammenstellen eines Content Management Servers geht ganz wunderbar einfach und auch die Maven-Vorlagen sind - für Maven's Verhältnisse - relativ kompakt (d.h. unlesbar, häßlich, langatmig aber nicht lang). Den Prototyp für einen komplett Maven-freien und nicht Tangram-bezogenen Content Management Server gibt's ab heute unter

https://github.com/mgoellnitz/cm-cms-webapp

Und mit diesem Werkzeug gehe ich nun bei Tangram in die nächste Runde. Außerdem sieht man, daß man langsam den Weg weg von Maven (unter Beibehaltung der großartigen Dependency und Repository-Bereitstellung) beschreiten kann hin zu Gradle. Das ist kein harter Schnitt, das ist ein Weg, sodaß ich nun auch im CoreMedia Kontext keinen Neubau mit Maven-Syntax beginnen werde. Gradle verspricht, uns dabei zu unterstützen, da sie die installierte Maven-Basis im Blick haben.

Mittwoch, 13. November 2013

mavenLocal() - remote and clean

Working in the cloud even for development tasks oftentimes needs what used to be the local maven artifact repository – referred to as mavenLocal() – available somewhere remote, accessible by your cloud continuous integration server.

The usual Suspect

A very easy way is to use an e.g. WebDAV accessible folder somewhere for every days snapshots.
For gradle users this has two drawbacks and for all others still at least one:
You will get a bunch of snapshots over time and the housekeeping there is as time consuming as with your local maven artifact repository, which – from time to time – needs some cleaning to avoid unreproducable build on your machine.

Cloudbees humming to a Gradle Blues

This is where my latest suggestion comes in: The cloudbees forge.
This is still a more or less normal WebDAV accessible storage but it has one important feature: Just with a check box in the administration panels you can ask for snapshot clean up to be done for you.
The one additional problem for Gradle users is the fact, that the latest maven-publish plugin from the distribution cannot publish to WebDAV resources until http://issues.gradle.org/browse/GRADLE-2919 is resolved.

Cloudbees Forge cleans my local Repository

As a workaround I'm publishing to a local folder and using a synchronisation software (https://github.com/mgoellnitz/JFileSync3 or AllwaySync) to bringt the stuff online. This in turn has the advantage that the clean up of cloudbees hums over to my local drive. Thus I'm not really sure if I'm waiting for a solution to the Gradle WebDAV publish problem...

Tangram Snapshot Artifact Repository

As a result I now – without any additional effords on my side – present public snapshots of the tangram system.

Tangram Snapshot Maven Artifact Repository now to be found at:
https://repository-tangram.forge.cloudbees.com/snapshot

And I myself am using these on any cloud platform I'm trying some remote build on, still having the latest changes for these plattforms available. All this avoiding the need to release to my old Ad-hoc Maven Artifact Repository at

http://my-amor.appspot.com/repository/

which still holds the releases.
I expect to be using the cloudbees solution for my releases some day soon as well. It's way easier to handle.

Donnerstag, 3. Oktober 2013

Wolkig aber sonnig

Bereits im Sommer konnte ich hier verkünden, daß ein Tangram Deployment in der Wolke bei den Bienen von CloudBees ohne weiteres - und ohne weitere Änderungen möglich - und sehr einfach ist.
Dabei sind die 5MB, die dort bei MySQL Instanzen kostefrei zur Verfügung gestellt werden jedoch auch für einen Playground, z.B. auf Basis des RDBMS Beispiels, sehr eingeschränkt. Beim Versuch, diese Grenze zu erweitern, stieß ich in den Services bei CloudBees auf die MongoDB, die man mir ja schon lange an's Herz gelegt hat - z.B. im CoreMedia Kontext. Schade nur, daß Tangram ja keine MongoDB unterstützt... Außerdem war die Beschreibung, die damals gegeben wurde zwar vollständig, aber für eine vollen Integration der Möglichkeiten der CloudBees Plattform sehr knapp.

MongoDB für Tangram

Das Fehlen der MongoDB-Unterstützung ließ sich mit wenigen Handgriffen beseitigen, sodaß es nun ein entsprechendes Modul gibt. Lerneffekt dabei: Die separaten RDBMS und MongoDB Layer oberhalb von JDO sind eventuell nicht nötig, und man könnte die Entscheidung der konkrekten Anbindung auf die Konfiguration auslagern. Ich lege mich damit nur auf die datanucleus dataaccess Plattform fest und verschiebe alle weiteren Fragen auf diese Ebene. Bevor ich aber soweit gehen will, sollte ich evtl. noch ein paar kleinere Ecken bei der Behandlung von strukturierten Texten und Blobs angehen.

Keine Beispielanwendung

Die Minimalversion aus dem Sommer sollte nun anhand etwas realistischerer Szenarien erweitert werden. Im Moment haben wir statt einer weiteren Beispielanwendung erst einmal unsere eigene (sehr kleine) Website, die in diesem Fall sogar eine Webseite ist - und das mit Absicht - auf CloudBees, MongoDB und Tangram umgezogen.
Dabei wird außer CloudBees nichts weiter als die lokale Entwicklungsumgebung genutzt und gegebenenfalls ein separater GIT-Client.
Nur die eingegebauten, privaten Maven-Repositories blieben bisher außen vor, und wir haben das Release 0.8 beschleunigt und gleich auf Tangrams amor abgelegt.
Die Tatsache, daß man bei CloudBees registriert sein muß, kann man hier voraussetzen und die unterschiedliche Optionen dabei ignorieren wir hier. Man muß allerdings damit rechnen, ab und zu drollige Support-Mails zu bekommen, die einen dazu animieren sollen, sich mehr mit der Plattform zu beschäftigen oder die Hilfe anbieten, wenn das CRM-System das Gefühl bekommt, das wäre notwendig.

Schritt für Schritt

Alle weiteren Schritte, bis die Site mit der neuen Technik aktiv war, finden sich nun hier in Bild und Text. Der grobe Ablauf ist:
1. Anwendung erstellen
2. Datenbank erstellen
3. GIT-Repository erstellen
4. Anwendung lokal erstellen
5. Jenkins Build erstellen
6. Anwendung einchecken
7. Konfiguration abstimmen
Für die Einrichtung einer Anwendung beschäftigt man sich zunächst mit dem run@cloud Bereich.

Bereich Applications

Von der Home-Page aus wählen wir Apps aus und erstellen eine Anwendung für Java/JVM.

Dialog Create abApplication 
 
Für den Moment muß in der Anwendung nichts weiter konfiguriert werden. Viele Texte beschreiben hier auch nur die Optionen, die man nun für die Entwicklung hat. Später kann man hier seine Domain (unten) aufschalten. Dafür muß man natürlich nicht nur hier den Domain-Namen angeben, sondern auch entsprechend seinen DNS mit einem weiteren CNAME konfigurieren.

Seite Manage Application

Für die Datenbanken hat man mehrere Optionen. Zum einen findet sich unter DBs MySQL. Dort kann man eine MySQL Datenbank anlegen und verwalten.

 Dialog Create MySQL Database

Seite Manage Database

Eine MySQL Datenbank sollte man mit dem Kommandozeilenwerkzeug bees mit der Anwendung verbinden. Alternativ kann man natürlich immer den Datenbankzugang direkt in der Anwendung einstellen, wie es auch Tangram-RDBMS erlaubt. Durch die Verbindung löst man die konkreten Einstellungen zur Datenbank von der Anwendung und verlagert sie in die Systembetreuung - keine schlechte Idee.

bees app:bind -db <DBNAME> -a <APPID> -as tangramdb

Zum anderen gibt es MongoDB, die man als Service im entsprechenden Bereich findet und sich gegebenenfalls erst abonnieren muß. Unter dem MongoDB Service legt man sich eine neue Datenbank an.

Bereich Services

Für die weiteren Schritte hier haben wir MongoDB gewählt. Jetzt wird es Zeit, die Anwendung vorzubereiten. Dazu legt man sich ein GIT Repository an und davon einen lokalen Clone auf dem Entwicklungsrechner.

 Bereich Repositories

Hier hinein kopiert man sich das MongoDB Beispiel (oder das RDBMS-Beispiel). 
Unter CloudBees ist eine Sache anders als in allen anderen bisher probierten Plattformen: Es gibt ein Problem mit den Bibliotheken, die als „provided“ angesehen werden. Also fügen wir sie explizit über die build.gradle hinzu.

configurations {
  libs
  webapp
  // add this:
  reallyNeeded
}
...
dependencies {
  webapp "tangram:tangram-mongo:$tangram_version:war@war"
 
  compile "tangram:tangram-mongo:$tangram_version"
 
  providedCompile "javax.servlet:servlet-api:$servlet_spec"
  providedCompile "javax.servlet:jsp-api:$jsp_spec"
 
  // add this:
  reallyNeeded "org.ow2.asm:asm:4.0"
 
  testCompile "junit:junit:$junit_version"

  providedCompile "org.apache.ant:ant:1.8.4"
  providedCompile "org.datanucleus:datanucleus-enhancer:$datanucleus_enhancer_version"
}
...
war {
  // change this:
  classpath = jar.outputs.files
  + configurations.runtime
  - configurations.providedRuntime
  + configurations.reallyNeeded
  excludes = [ "classes/**" ]
}

Für MongoDB kann man nicht den eleganten Weg über eine Verbindung der Datenbank in der Konfiguration gehen und trägt den konkreten Zugang im Code in src/main/resources/jdoconfig.xml ein. Aus der Konfiguration der MongoDB Datenbank extrahiert man die notwendigen Informationen für Benutzernnamen, Kennwort und Zugangs-URL. 

 Seite Manage MongoDB

Unter Show Config findet man eine Zeichenkette der Form 

mongodb://<username>:<password>@<host>:<port>/<database> 

Diesen Text muß man entsprechend zerlegen, um die Teile für den Zugang für die Datei src/main/resources/jdoconfig.xml passend einfügen zu können.

<?xml version="1.0" encoding="utf-8"?>
<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">

<persistence-manager-factory name="transactions-optional">
  <property name="javax.jdo.PersistenceManagerFactoryClass"    
            value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"/>

  <!-- jndi datasource for mongodb -->
  <property name="datanucleus.ConnectionURL" value="mongodb:host:port/database" />
  <property name="datanucleus.ConnectionUserName" value="username" />
  <property name="datanucleus.ConnectionPassword" value="password" />

  <property name="datanucleus.autoCreateSchema" value="true" />
  <property name="datanucleus.validateTables" value="true" />
  <property name="datanucleus.manageRelationships" value="true" />
  <property name="datanucleus.validateConstraints" value="true" />
</persistence-manager-factory>

</jdoconfig>
 
Für den ersten Schritt ist ein erweitertes Logging in src/main/webapp/WEB-INF/log4j.properties hilfreich.

# Daily rolling file appender
log4j.appender.file=org.apache.log4j.ConsoleAppender
# log4j.appender.file.File=build/tangram.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout

Bevor wir das Ergebnis nur in das GIT-Repository pushen, legen wir uns lieber gleich vorher einen Job im Jenkins Continous-Integration Server an, der auf unseren Push mit dem ersten Deployment-Versuch reagieren kann.


Bereich Builds

Wir legen also eine Freestyle Job in Jenkins an.

 Seite Neuen Job Anlegen

Diesen neuen Job konfigurieren wir dann. Zunächst wählt man unter Source-Code Management git aus und fügt die ssh-basierte Zugangs-URL ein.

 Seite Job konfigurieren

Im Buildverfahren sind zwei Schritte nötig, die über Build-Schritt hinzufügen... eingefügt werden können: Invoke Gradle Script und Deploy applications. In beiden Schritte kann die weitgehend leere Basiskonfiguration beibehalten werden.

Seite Job konfigurieren - Buildverfahren

Alle weiteren Anpassungen und Entwicklungen sind jetzt nur noch dem konkreten Bedarf und nicht mehr der Technik geschuldet.
Nun wird jedesmal, wenn man das GIT-Repository pusht ein Build im Jenkins angestoßen und die aktuelle Version versucht zu bauen und zu deployen.
Im Erfolgsfall kann man dann sein Logging tunen und eine eigene Domain aufschalten.

Sicherheitsfragen

Sicherheitsbedenken? In diesem Fall ist ein ohnehin veröffentlichtes Framework mit nichts weiter als der Beispielanwendung - ebenfalls öffentlich zugänglich - und ein paar eigenen Templates für ohnehin öffentlich zugänglichen Inhalt zu sehen. Dies ist nicht die Stelle, an der uns die Cloud Sorgen machen kann, aber die Cloudbees Plattform nimmt uns die Betreuung aller Komponenten von der Entwicklung bis zum produktiven System ab. Physische eigene zu wartende Rechner finden sich nur noch im Form der Entwicklermaschinen. Alles andere kann abgegeben werden. Die eingesetzte Technik erlaubt es uns aber, jeden Schritt auch anders umzusetzen.

Danke Gradle!

Evtl. bin ich nach über 25 Jahren professioneller Softwareentwicklung und Projektgeschäft etwas abgebrüht, desillusioniert und blind gegen die Schönheit des Neues geworden, aber ich finde Maven nicht besser als ANT und ANT nicht grundlegend mächtiger als make. Bisher habe ich noch mit jedem Build-Werkzeug meine Ziele erreichen können und mich dabei immer in dem Sinne verrenken müssen, daß ich nie aufscheiben konnte, was ich eigentlich meine.

"Das war schon immer so", "Da kann ja jeder kommen" und andere Leitsätze

Egal, ob es make, ant oder maven waren: Meist bestimmte das Werkzeug den Build und nicht die Entwickler oder die Art der Software, die es zusammenzubauen galt. Im wesentlichen nutze ich die Werkzeuge daher immer nur deshalb, weil sie Verfügbar im jeweiligen Kontext sind, oder weil es einfach eine breite Masse von Nutzern gibt, sodaß man nicht so alleine ist.
Im Moment nutze ich in jeden professionellen Projekt Maven und weiß daher, welche Kosten es entfesselt, um seinen Nutzen zu bringen. Den Nutzen der vernünftigen Abhängigkeitsumsetzung will ich nicht missen, aber der Rest ist weder gut lesbar noch gut im Ablauf verständlich. Ich finde die Schreibeweisen nach wie vor unleserlich und das Werkzeug unverständlich in seiner Sprache und Komplexität.

Peak Maven?

Nachdem ich also nun viele Jahre lang leidenschaftslos beim Buildwerkzeug war, sehe ich jetzt auf die umfassenden Lösungenmit Maven in großen Projekten (wie dem CoreMedia 7 Blueprint) wie auf die letzten Werke des Maven-Barock. Großartige umfassende Lösungen, die mir netto sehr helfen (weil ich sie nicht selbst schreiben mußte), Maven und das Projekt im Griff zu halten, und die so vieles bedacht haben, das ich nicht einmal bemerke.

Kleine Danksagung zum 1.8er Release

Den Grund, warum sich meine Sicht auf Buildwerkzeuge nun geändert hat, möchte ich anhand einer kleinen Begebenheit illustrieren: Immer wenn ich kleinere Softwareprojekte anderen Menschen bereitstellen will, reicht es nicht, daß ich reprodzierbar aus meiner IDE getestet eine Software purzeln lassen kann. Bevor ich also beschreibe, was ich getan habe und was eventuell bei anderen dann gerade einmal nicht genauso aussieht, schreibe ich lieber gleich die notwendigen Build-Skripte, um den Vorgang zu dokumentieren und dabei gleich zu automatisieren.
Bei tangram habe ich mich noch lange mit der Auswahl des Werkzeugs gequält, weil ich mich nicht auch noch in meiner Freitzeit mit Maven herumschlagen wollte und kein anderes Tool mir spontan unter "das machen alle so" oder "das war einfach da" vorlag. Letztlich hat Gradle über Maven gewonnen und ich habe mich ahnungslos in die Umsetzung gestürzt. Heute verstehen wir uns recht gut.
Als ich vor kurzem wieder ein paar Zeilen Code herausgeben wollte, stand ich mit einem kompletten Fremdprojekt und einem alten ANT-Script da. JFileSync sollte - weit vor der NSA-Affäre, die mir keine neuen Erkenntnisse brachte - um für mich notwendige Features erweitert werden. Das Ergebnis wollte ich wieder gerne reprodzierbar als nutzbares Programm erzeugen können. Und das ging mit Gradle so erschreckend gut und einfach - und mit wenigen Worten, daß ich mich gleich wieder in Goodies für ein schöneres Ergebnis stürzen konnte.

Gradle-Deutsch / Deutsch-Gradle

Wir haben also ein Java-Programm

apply plugin: 'java'

Und wir hätten den Code gerne sauber in aktueller Java-Version, mit UTF-8 und ohne alten Kram.

sourceCompatibility = 1.7
targetCompatibility = 1.7
compileJava.options.encoding = 'UTF-8'
compileJava.options.deprecation = true

Der Source-Code und die Ressourcen finden sich zusammen im Verzeichnis src.

sourceSets {
  main {
    java {
      srcDir 'src'
    }
    resources {
      srcDir 'src'
    }
  }
}

Damit man das ganze kompilieren kann, muß man aus diesen Quellen

repositories {
  maven { url "http://repo1.maven.org/maven2" }
  maven { url "http://sardine.googlecode.com/svn/maven/" }
  maven { url "http://repo2.maven.org/maven2/org/bouncycastle" }
}

diese Dinge besorgen

dependencies {
  compile 'org.slf4j:slf4j-api:1.5.8'
  compile 'org.slf4j:slf4j-log4j12:1.5.8'
  compile 'org.apache.httpcomponents:httpclient:4.2.5'
  compile 'commons-lang:commons-lang:2.6'
  compile 'org.apache.commons:commons-compress:1.3'
  compile 'org.bouncycastle:bcprov-jdk16:1.46'
  compile 'javax.servlet:servlet-api:2.5'
}

Ach, und ich würde gerne weiterhin Eclipse nutzen

apply plugin: 'eclipse'

Könnt Ihr Euch bitte auf ein Vereichnis für den Output einigen?

eclipse.classpath.conventionMapping.defaultOutputDir = { 
  new File(project.projectDir, 'build/classes/main')
}
Du solltest aber sauberer Arbeiten als meine IDE!

defaultTasks 'clean', 'build'

Das ganze soll am Ende ein benutzbares Programm werden.

apply plugin: 'application'

Den Einstieg findest Du dabei in dieser Java-Klasse:

mainClassName = 'jfs.JFileSync'

Wow! Du hast ja automatisch Start-Scripts für Unix und Windows erzeugt! Danke! Ich hätte da noch ein paar Verbesserungsvorschläge...

startScripts {
  doLast {
    // Add some more reasonable memory settings to JFileSync3
    unixScript.text = 

      unixScript.text.replace('DEFAULT_JVM_OPTS=""', 
                                     'DEFAULT_JVM_OPTS="-ms1280m -mx1536m -Xms1280m -Xmx1536m"')
    windowsScript.text = 

      windowsScript.text.replace('DEFAULT_JVM_OPTS=', 
                                        'DEFAULT_JVM_OPTS=-ms1280m -mx1536m -Xms1280m -Xmx1536m')
    windowsScript.text = windowsScript.text.replace('java.exe', '%JAVA_CMD%')
    windowsScript.text = 

      windowsScript.text.replace('@rem Find %JAVA_CMD%', 
                                 'set JAVA_PREFIX=start ... java.exe')
    windowsScript.text = 

      windowsScript.text.replace('"%JAVA_EXE%" %DEFAULT_JVM_OPTS%', 
                                 '%JAVA_PREFIX% "%JAVA_EXE%" %DEFAULT_JVM_OPTS%')
  }
}
Und ich habe da gerade diesen netten Launcher für Java-Anwendungen unter Windows gefunden

buildscript {
  repositories {
    maven { url "http://repo.smokejumperit.com" }
    ivy {artifactPattern 'http://gradle-launch4j.googlecode.com/files/[module]-[revision].[ext]'}
  }
  dependencies {
    classpath 'com.smokejumperit:gradle-plugins:0.8.2'
    classpath 'edu.sc.seis:gradle-launch4j:1.0.5'
  }
}

den will ich haben!

apply plugin: 'launch4j'

Schreib doch bitte einfach rein, wer das gemacht hat, danke.

launch4j {
    mainClassName = project.mainClassName
    version = '3.0.0'
    copyright = '(C) 2002-2013, J. Heidrich, M. Goellnitz'
    downloadUrl = 'https://www.dropbox.com/s/3n4snlbw9tyjgec/JFileSync3.zip'
    supportUrl = 'https://github.com/mgoellnitz/JFileSync3'
    icon = "$project.projectDir/win/JFileSync.ico"
    dontWrapJar = true
    xmlFileName = 'JFileSync3-launcher.xml'
    initialHeapSize = 1024
    maxHeapSize = 1536
}
Ach, und wo Du gerade da bist: Pack das doch noch mal etwas anders ein, als sonst

distZip {
  into(project.name) {
    from "$buildDir/launch4j"
    include '*.exe'
    include '*.xml'
  }
  into(project.name) {
    from '.'
    include 'legal/*.*'
    include 'profiles/*.*'
    include 'README.md'
  }
}

Oh, äh. Testen. Machst Du das noch schnell? Ich habe da vier Beispiele abgelegt.

apply plugin:com.smokejumperit.gradle.ExecPlugin

task(encryptionTest) << {
  // Extract distribution
  println "Extracting distribution"
  ant.unzip(src: "$buildDir/distributions/${project.name}.zip", dest: "$buildDir")
  // Extract test data
  println "Extracting test data"
  ant.unzip(src: "test/test-folders.zip", dest: "$buildDir/${project.name}")

  println "Encrypting"

  String cmd = "";
  cmd = "cmd /c bin${File.separator}${project.name} -config 1encrypt.xml -nogui -nohistory -quiet"
  project.exec(cmd, "$buildDir/${project.name}")

  println "Decrypting taking every folders metadata into account"
  cmd = "cmd /c bin${File.separator}${project.name} -config 2decrypt1.xml -nogui -nohistory -quiet"
  project.exec(cmd, "$buildDir/${project.name}")

  println "Decrypting ignoring every folders metadata"
  cmd = "cmd /c bin${File.separator}${project.name} -config 3decrypt2.xml -nogui -nohistory -quiet"
  project.exec(cmd, "$buildDir/${project.name}")

  println "And now please compare by hand"
  cmd = "cmd /c bin${File.separator}${project.name} -config 4compare.xml -nohistory"
  project.exec(cmd, "$buildDir/${project.name}")
}


Macht das bitte nicht nur in der Kürze sondern auch in so kurzer Zeit und so, daß man es immer wieder lesen kann, mit anderen Werkzeugen. Für mich ist Gradle nun weiterhin die erste Wahl in allen Projekten, in denen ich die Wahl habe.

Freitag, 21. Dezember 2012

Artefakte mit viel Liebe

Es liegt ganz sicherlich an mir, daß ich zwar nun für fast alles, was man so zu Entwicklung und Betrieb braucht, dienste in der "Cloud" gefunden habe, aber das Bereitstellen von Bibliotheken via Maven Repository noch nicht hingebekommen habe.
Aber im Grunde - so von der lesenden Seite - sind das ja nur Verzeichnisstrukturen mit einigen festgtelegten Dateien darin, die man per HTTP zugreifen kann. - Und das solle ist: Alle Daten dazu habe ich ja schon lokal auf der Platte, wenn ich meinen Build - bei mir ja immer mit Gradle - abgeschlossen habe.
Bis ich also verstanden habe, wie ich meine Projekte in den Prozeß in die Zentralen Maven Repositories einkippe, habe ich eher mal eben heute für die Zeit bis dahin ein Ad-hoc Maven Object Repository mit dem Tangram - in Version für die Google App Engine - geschrieben und es deshalb amor genannt.
Was mußte man dafür tun? Es gibt nur ein Datenmodell: Das Artefakt, wie es im Repository zugänglich gemacht werden soll. Der Rest ist URL-Format und eine kleine Listing-Seite - und damit sind das nur noch Dinge, die man dynamisch im Tangram mal schnell hinzufügen kann. Der Code findet sich auf github - mit Datenbank Abzug diesmal.
Die Beispiel-Site ist nun das Repository auf dem ich das aktuelle Tangram 0.7 zur Verfügung stelle: http://my-amor.appspot.com/

Montag, 26. September 2011

Raus aus dem Deadlock

Eigentlich wollte ich ja schon vor Monaten Code veröffentlicht haben, aber es gibt leider drei wesentliche Probleme, von denen wenigstens eines gelöst werden sollte, bevor man daran geht.
Um überhaupt etwas herausgeben zu können braucht man ein Build-System, das ich mit Gradle umsetzen wollte.Dabei mußte ich feststellen, daß dann alle meine Google App Engine Codes im JDO Bereich nicht mehr funktionierten, wenn man sie mit Gradle baut.
Also wollte ich mich der Lösung mit relationalen Datenbanksystemen zuwenden. Das funktioniert im Unterschied zur Google App Engine auch ganz wunderbar, nur muß ich natürlich ein Bepiel bereitstellen, damit jeder am Ende auch die Funktionsweise nachvollziehen kann. Da wiederum trat als nächstes Problem die Schwierigkeit auf, daß ich bisher keine Lösung gefunden habe, unabhängig vom darunterliegenden System einen JDO-Datastore mit Datenzu befüllen, die ich aus einem andere gewonnen habe. Klingt nach einer einfachen Fingerübung mit XML oder JSON als Übertragungsformat, aber bisher habe ich da nicht nichts gefunden, das nicht in erheblicher Eigenarbeit oder viele Exceptions mündet. Ideen und Anregungen sind willkommen!
Das dritte Problem? Naja, ich müßte das Beispiel schreiben. :-)
Die völlig unverständlichen Probleme beim Bauen mit Gradle habe ich nun aber endlich umschiffen können. Damit kann ich für die Google App Engine nun auch ein Beispiel bereitstellen, indem ich einfahc das Austauschformat dort verwende. Ein Teil des Problems war "recht schnell" gefunden: Binnen einiger weniger Tage findet man heraus, daß die Dateien im JAR verpackt wurden, bevor der JDO-Enhancer sie in die Finger bekam. Der andere Trick ist hartnäckiger gewesen und ich bin ihm er jetzt auf die Schliche gekommen: Die Google Datentypen für Text und Blob wurden nicht als persistent angesehen, wie es bei der indirekten Benutzung mit dem Google App Engine Plugin für Eclipse der Fall ist. Was auch immer da genau los ist: Man muß einfach nur @Persistent an ein paar mehr Stellen schreiben. Ich will hier die Problematik von Datanucleus und App Engine gar nicht auswalzen, aber ich bin da technisch wohl ein wenig zwischen die Fronten geraten. Resultat ist jedenfalls ein ArrayIndexOutOfBounds irgendwo ganz tief im nur binär vorliegenden, enhancten Code. Eine kleine Reverse Engineering Runde durhc den Enhancer brachte nun endlich Klarheit.
Nun kann es also endlich weitergehen!
Wer doch lieger mit (a) RDBMS oder (b) CoreMedia als Speicher arbeiten möchte: Dort brauche ich also noch die (a) Datenübertragungsmöglichkeit (s.o.) und (b) Code, der mir den Richtext aus der Datenbank fischt. Anyone?

Sonntag, 22. Mai 2011

Muß es denn Maven sein?

Im Moment ist mein Code hier für mich total gut zu benutzen, aber es ist eben ein Workspace für genau einen Benutzer, der eine Reihe von Websites (z.B. www.themen-geburtstag.de und www.dragon-map.de) bastelt.
Dabei fehlt natürlich auch mir ein gutes Dependency-Management für die eingesetzte Libraries (ja ich habe síe total unzivilisiert einfach in meine jeweiligen lib/-Verzeichnisse gelegt). Im Moment pushen die einzelnen Module ihre Ergebnisse in die jeweils nächsten Schichten.
Klingt gruselig? Ist aber einfach sehr schnell und effizient zu benutzen, und das will ich auf keinen Fall verlieren!
Gewohnheitsmäßig benutzen zur Zeit viele Projekte Maven. Dabei mußten wir alle lernen, daß man nicht Maven an seine Bedürfnissen anpassen kann, sondern sich an Mavens Bedürfnisse anpassen muß. Emotionaler ausgedrückt meinte ein Kollege, daß Maven ihn nicht möge. Aber wir stellten fest, daß es noch viel schlimmer war: Maven ignoriert ihn!
Wenn ich Maven einsetze verliere ich die schöne, einfache Deploybarkeit meiner Projekte nach Google App Engine aus der IDE heraus (denke ich) und ich verliere die enorm kurzen Round-Trips beim Entwickeln, die es ermöglichen das Framework weiterzuentwickeln und die notwendigen Änderungen an den benutzenden Appliaktionen sofort zu sehen. - Sofort, nicht 4min später! Dafür bekomme ich ein sauberes Dependecy-Management und ein etwas unverständliches Build- und Packaging System. Das klingt also genauso gruselig wie der Status quo.
Also habe ich mal nach Möglichkeiten gegooglet. Dabei entdeckt man natürlich sofort JAppStart als Startpunkt für die Entwicklung einer Java-Anwendung für die App Engine. Leider bin ich über den Punkt schon seit Monaten hinaus. - Danke Jungs - zu spät. Außerdem habe ich ja einen modularen Ansatz und nicht einfach nur ein Webprojekt. Dann gibt's da die angeblichen Alternativen zu Maven (z.B. http://www.streamhead.com/maven-alternatives/). Davon habe ich mir mal Gradle genauer angesehen, weil die anderen nicht erstrebenswert schienen. Die Beschreibungsdateien für den Build-Prozeß mit Gradle sind einfacher als bei Maven, obwohl ich hier ja bei der Lernkurve bei Null anfange (bei Maven bin ich doch schon kanpp über Null nach ein paar Jahren), andererseits muß ich mir nun doch auf einmal ein komplettes Build-System aufbauen und nicht einfach etwas funktionierendes zusammenstöpseln. Das gefällt mir noch nicht. Verstanden hat der Autor aber anscheinend, daß XML nicht als Sprache zum Schreiben für Menschen gedacht ist. Gradle schreibt sich als DSL zielorientierter als das Maven XML. Das Dependency-Management kann auf Maven Repositories zurückgreifen (die sind ja in jedem Fall genau das was ich brauche) und sogar mein lokales Repository findet Berücksichtigung. Ich traue mich nun nach dem Posting gestern nicht "Maven done right" zu Gradle zu sagen, aber es fühlt sich gut an. Einziger Wehrmutstropfen: Es werden als Default Ivy-Repositories genutzt und angelegt. Ivy ist bei mir nicht positiv besetzt. Liegt das an mir?
Aber mit Gradle wie mit Maven müßte ich nun wieder alles selbst erstellen. Dazu habe ich eigentlich keine Lust. Möchte jemand übernehmen oder Tips geben?

Samstag, 21. Mai 2011

Bekehrung zu GIT

Hat schon jemand von dem Zeug, über das ich hier schreibe, den Source Code gesehen? Nein? Ok, einer hat es, aber der liest hier wohl gerade nicht.
Das hat zwei einfache Gründe: Der Code ist noch nicht in einem Zustand zusammengestellt, den ich herausgeben mag, und ich habe mich noch nicht für das "richtige" Source-Code-Verwaltungssystem und entsprechende, konkrete Repository entscheiden können.
Zum ersten Punkt gibt es entschuldigend nur zu sagen, daß die Module alle brav sauber geschrieben und zugeschnitten sind, aber das Buildsystem einfach nicht existiert. Ich fürchte mich einfach vor dem Verlust an Produktivität den mir Maven bringen würde. Gibt es Alternativen?
Für die Source-Code-Verwaltung dachte ich bisher, daß man im Open Source Bereich nun einfach mal so GIT (http://git-scm.com/) nimmt. Das lag hier so als Entscheidung herum und ich wartete nur auf den Zustand des Codes ihm bereitzustellen. Nun habe ich aber endlich Verstanden, was GIT für mich leisten kann und frage mich, worauf ich die ganze Zeit gewartet habe. Ich bin absolut bekehrt! Der Vortrag von Linus Torvalds bei Google dazu ist zwar erschreckend überheblich und er scheint auch zu wenig Erfahrung mit den anderen Arbeitsweisen im kommerziellen Umfeld zu haben (http://www.youtube.com/watch?v=4XpnKHJAok8), aber wahr bleibt wohl, daß ich mit dem Werkzeug alle Abläufe, die ich in verschiedenen Projekten brauche, damit abdecken kann. Egal, was Ihr mit Source Code macht, legt Euch einfach ein GIT-Repository an! (http://code.google.com/p/tortoisegit/) Man kann nichts falsch machen. Ich jedenfalls werde mich nun bemühen, das Backup des Tangram Workspaces (er enthält leider auch noch das halbe Dutzend Sites, die damit umgesetzt sind) durch ein GIT-Repository zu ersetzen. Das muß ich natürlich wieder sichern, aber das war es schon. Der einzige Kampf, der dann einer Herausgabe noch entgegensteht ist die Frage, ob ich ein "Superproject" in GIT brauche...