Posts mit dem Label Tangram CMS werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Tangram CMS 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.

Dienstag, 15. Juli 2014

Google App Annoyance - aka Engine

Together with the missing support for the Servlet 3.0 specification in Google App Engine (and, yes, there are still too many situations were this specification level ist not available) we are reading from Google for their App Engine that classpath scanning is an issue on that platform and that this is one of the reasons that kept them from supporting this version of the servlet specification.
What I didn't read from Google is, that they noticed that the Servlet 3.0 version is (arguably) one of the most important steps since Java came to the web. There is no major framework in the Java world anymore not doing any classpath scanning right now. The mentioned Springframework I'm using is just one example.
After some five years of work with the Google App Engine and Java as the only language in use, I changed my mind and don't consider the App Engine as one of the first choices in cloud platforms for the Java world anymore.
And this is really just because of these two small issues.
Like very many others I'm using the Springframework - with component scan and thus with classpath scanning. Any first request to an instance take ages. But "first requests" are common in the cloud, where instances need to be shut down and brought up depending on load. And the cloud is what Google App Engine is about, isn't it?
I invested quite some effort to learn how to be fast on the first request while still using the Springframework and even developed my own stripped down, minimalistic Dependency Injection environment for the application setup (dinistiq) to only have the features I'm using at hand. But this all didn't help to make the end user experience satisfying. Things feel slow.
So in the end this all gave the push for Tangram to support that many new platforms, use the CI Features and Repositories at cloudbees, enjoy the command line access of OpenShift. This brought options of different frameworks and I learned much about cloud deployment and operation scenarios. So in that respect we should be thankful for the Google App Engine weakness.
But it still is the source of some level of complexity and number of artifacts flying around in what I call my dynamic web application framework Tangram. Also this currently renders Google App Engine the second best cloud platform for Java while still having great web based monitoring tools.

Montag, 14. Juli 2014

Ein weiterer Tangram Nutzer

Die Ponton GmbH aus Hamburg hat nun seit einiger Zeit auch eine Webanwendung mit Tangram im produktiven Betrieb. Dabei habe ich sie natürlich selbst in diese Richtung geschubst, um schnell Ergebnisse vorweisen zu können, aber weder war ich der einzige Entwickler noch hab es ausreichende Gegenwehr.
Auf dieser Basis wird anscheinend das Projekt auch mit neuen Anforderungen weiterentwickelt.
Als eher konservatives Layout wird hier noch das Springframework genutzt und auf JPA als Persistenzschicht gesetzt. URL-Formate als Groovy-Codes in der Datenbank und dort auch jede Menge Busineslogik waren aber gerade der Gewinner bei der laufenden Anpassung von Kleinigkeiten. Nun ist nicht mehr jedesmal ein Deployment erforderlich wie bei der Vorgängerlösung (in PHP).
Aber insbesondere danke, daß ich das laut sagen darf.

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.

Donnerstag, 21. November 2013

Gradle Plugin for JPA, JDO, and EBean Bytecode Transformers

The plugin referenced here is meant for use with the tangram framework but there are a few calls which are helpfull for any user of Gradle and
It simply has easy to use wrappers for the enhancer/wever components for the persistence frameworks above since the solutions presented by those projects each for its own reason needed some cosmetic enhancement to fit into my gradle builds.

Prerequisites

Of course you will have some classes with persistence annotations. I'm assuming that you have a (sub)module containing the model classes for the API to be used (JDO, JPA with OpenJPA, DataNucleus, or EclipseLink, or Ebean with JPA annotations) which get compiled by some task of your project.

Preparation

The plugin can be obtained from the tangram snapshots repository.

// build.gradle
buildscript {
  repositories {
    mavenCentral()
    maven { url "http://repository-tangram.forge.cloudbees.com/snapshot" }
  }
  dependencies {
    classpath "tangram:gradle-plugin:0.9-SNAPSHOT"
  }
}


And of course it must be applied

apply plugin: 'tangram'

When using EclipseLink the bytecode transformer called weaver will already be contained in the compile dependencies of your module. The same applies for OpenJPA except that here the bytecode transformer is called enhancer.
For DataNucleus und Ebean the bytecode transformer is called enhancer again and is a dependency of the plugin itself. There is no generic need to have it in the compile dependencies of your module.
So in short, you will not have to modify your dependencies and the resulting package will not contain any additional classes or jars.

Solution

The plugin does not introduce any new tasks but just some methods that can be placed anywhere in the build process. In a standard gradle task-wiring of the java plugin the methods the following locations make sense:

// JDO with DataNucleus
compileJava.doLast {
  nucleusJdoEnhance()
}


// JPA with DataNucleus
compileJava.doLast {
  nucleusJpaEnhance()
}


// JPA with OpenJPA
jar.doFirst {
  openjpaEnhance()
}


// Ebean
compileJava.doLast { 
  ebeanEnhance()
}


// JPA with EclipseLink
compileJava.doLast {

  eclipselinkWeave()
}


But you may decide to use it at other points within your build process.

Background

For OpenJPA the wrapper presented here is a simple wrapper for the ant tasks provided by this project wired up for the given gradle build setup.
For EclipseLink the weaver the jar is included as a dependency for the plugin itself and the weaver is called called via its Java API. So woven codes can be generated independent of the using projects build setup.
For DataNucleus and Ebean the solution is somewhat more complicated since the enhancers are in separate jars which you most likely don't want to include in your resulting packages.
So those jars are also included as a dependency of the plugin, and again the plugin itself calls the Java APIs of the enhancers directly.

Sonntag, 10. November 2013

Splitter im Frühling

(English summary at the end)
Am Ende dieses Beitrags kommt eine universeller Konfigurations-Helper für das Springframework heraus.
org/tangram/spring/PropertySplittingPlaceholderConfigurer.java
Aber warum man so etwas brauchen könnte, wollte ich kurz an zwei oder vier (je nachdem wie man es zählen möchte) zeigen.
Bisher habe ich das Springframework und die jeweiligen Persistenzschicht immer komplett unabhängig voneinander genutzt: Java Persistence API (JPA) konfiguriert man über eine persistence.xml und Java Data Objects (JDO) über eine jdoconfig.xml. ORM Integrationen habe ich auch im zusammenspiel mit Spring MVC nicht benötigt. - Dachte ich.
Aber insbesondere durch Cloud-Umgebungen habe ich nun lernen müssen, daß der Weg über diese Dateien eigentlich nicht gerade "best practice" ist und eher für einfache Situationen taugt.
Wenn man dann endlich neben der Nutzung der Google App Engine auch mal einen Ausflug nach Cloudbees und OpenShift macht, tritt nämlich ein kleines Problem zutage: Die Werte in den oben genannten Dateien können nicht, wie alles andere, das ich in Spring "zusammenstecke", mit Platzhalter versehen werden, die erst zur Laufzeit des Systems aufgelöst werden.
Durch diese Ersetzung, wie sie z.B. Bei Spring quasi automatisch passiert - paßt sich ein ein grundsätzlich vorkonfiguriertes System dann in seine Laufzeitumgebung ein. - Bis auf die Persistenzschicht in meinem Fall.
Als einfachstes Beispiel nehmen wir mal die Verbindungsdaten zu einer Datenbank unter OpenShift. Diese sollte man am sinnvollsten aus den Umgebungsvariablen lesen, sagt die "best practice" von OpenShift.

JDO auf OpenShift

Also nimmt man beim Einsatz von JDO die Werte

<persistence-manager-factory name="transactions-optional">
  <property name="javax.jdo.PersistenceManagerFactoryClass"

            value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"/>     
  <property name="javax.jdo.option.ConnectionURL"

            value="mongodb://localhost:8111/db"/>
  <property name="javax.jdo.option.ConnectionUserName" value="u"/>
  <property name="javax.jdo.option.ConnectionPassword" value="p"/>
</persistence-manager-factory>


aus der jdoconfig.xml komplett heraus und übergibt sie bei der Instanziierung der PersistenceManagerFactory mit:

factory = 
JDOHelper.getPersistenceManagerFactory(jdoConfigOverrides, 
                                       "transactions-optional");

und diese jdoConfigOverrides bezieht man dann aus der Spring-Configuration, wo sie von den Ersetzungen auf Basis von Umgebungswerten profitieren:

<bean id="jdoConfigOverrides" class="java.util.HashMap">
  <constructor-arg>
    <map>
      <entry key="javax.jdo.option.ConnectionURL"

      value="mongodb://${OPENSHIFT_MONGODB_DB_HOST}:${OPENSHIFT_MONGODB_DB_PORT}/test"/>
      <entry key="javax.jdo.option.ConnectionUserName"

             value="${OPENSHIFT_MONGODB_DB_USERNAME}"/>
      <entry key="javax.jdo.option.ConnectionPassword"

             value="${OPENSHIFT_MONGODB_DB_PASSWORD}"/>
    </map>
  </constructor-arg>
</bean>

JPA auf OpenShift

Entsprechend geht man bei JPA vor und nimmt die Werte

<persistence-unit name="openjpa" transaction-type="RESOURCE_LOCAL">
  <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
  <exclude-unlisted-classes>false</exclude-unlisted-classes>
  <properties>
    <property name="javax.persistence.jdbc.url"

              value="jdbc:postgresql://localhost:5432/postgres"/>
    <property name="javax.persistence.jdbc.user" value="un"/>
    <property name="javax.persistence.jdbc.password" value="pw"/>
  </properties>
</persistence-unit>

auch hier aus der Konfigurationsdatei heraus und fügt sie in die Spring-Konfiguration ein:

<bean id="jpaConfigOverrides" class="java.util.HashMap">
  <constructor-arg>
    <map>
      <entry key="
javax.persistence.jdbc.url"
  value="jdbc:postgres://${OPENSHIFT_POSTGRESQL_DB_HOST}:${OPENSHIFT_POSTGRESQL_DB_PORT}/db"/>
      <entry key="
javax.persistence.jdbc.user"
             value="${OPENSHIFT_POSTGRESQL_DB_USERNAME}"/>
      <entry key="
javax.persistence.jdbc.password"
             value="${OPENSHIFT_POSTGRESQL_DB_PASSWORD}"/>
    </map>
  </constructor-arg>
</bean>

denn auch hier gibt es entsprechende Parameter beim Erzeugen in diesem Fall der EntityManagerFactory:

factory = 
Persistence.createEntityManagerFactory(persistenceUnitName,
                                       jpaConfigOverrides);

Cloudbees

Über die Vorgehensweise hier stolperte ich erst, als ich meine Anwendungen mit Tangram auf OpenShift betreiben wollte, nachdem sie bei cloudbees schon liefen, da es für MySQL auf run@cloudbees eine "managed" Lösung mit einer DataSource gibt

 <!-- jndi datasource example (run@cloudbees) -->
 <property name="datanucleus.ConnectionFactoryName" 

           value="java:comp/env/jdbc/mydb" />

Das Problem besteht also mit der "hauseigenen" MySQL Datenbank dort überhaupt nicht.
Aber auch in dieser Umgebung werden ganz allgemein Werte der Betriebsumgebung an die Anwendungen durchgereicht und sollten von dieser auch benutzt werden.

URL Splitting in der Spring-Konfiguration

Das geht leider nicht ganz genau wie oben beschrieben, da unter Cloudbees z.B. für MongoDB die Verbindungdaten in einer URL übergeben werden (die gibt es auf OpenShift auch, aber man kann dort auch direkt auf die Einzelteile zurückgreifen).
Die Lösung ist hier mit ein wenig Programmieraufwand (s.o.) verbunden, da ich mich entschlossen habe, die Property-Ersetzungen durch Spring an dieser Stelle ein wenig aufzubohren und ganz allgemein URLs in ihren Teilen nutzbar zu machen.
Den

<bean id="propertyConfigurer" 
  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
    <list>
      <value>classpath*:/tangram/*.properties</value>
      <value>/WEB-INF/tangram/*.properties</value>
    </list>
  </property>
</bean>

ersetze ich also durch einen eigenen

<bean id="propertyConfigurer" 
      class="org.tangram.spring.PropertySplittingPlaceholderConfigurer">
  <property name="locations">
    <list>
      <value>classpath*:/tangram/*.properties</value>
      <value>/WEB-INF/tangram/*.properties</value>
    </list>
  </property>
</bean>

Danach steht von jeder URL, wie z.B. ${MONGOHQ_URL_MYBD} für den Service MongoHQ auf Cloudbees mit der verbundenen Datenbank MYDB, die Teile zur Verfügung:

<bean id="jdoConfigOverrides" class="java.util.HashMap">
  <constructor-arg>
    <map>
      <entry key="javax.jdo.option.ConnectionURL"

value="mongodb:${MONGOHQ_URL_TANGRAM.host}:${MONGOHQ_URL_MYBD.port}/${MONGOHQ_URL_MYDB.uri}" />
      <entry key="javax.jdo.option.ConnectionUserName" 

             value="${MONGOHQ_URL_MYDB.username}" />
      <entry key="javax.jdo.option.ConnectionPassword" 

             value="${MONGOHQ_URL_MYBD.password}" />
    </map>
  </constructor-arg>
</bean>

Das macht die Implementierung für alles, was sie für eine URL hält, und damit wird sie zu einem recht universellen Werkzeug bei der Spring-Konfiguration.
Jede URL in einer Property-Datei

# Example
url=mongodb://ruth:guessme@mongo.host:8111/db

wird zerlegt in

url.username=ruth
url.password=guessme
url.host=mongo.host
url.port=8111
url.uri=db 

Diese Platzhalter fügt der PlaceholderConfigurer dann an allen gewünschten Stellen ein. Das sollte für einen ganzen Bereich von Anwendungen erst einmal mit einem Werkzeug ausreichen.

English (sort of) Summary

For easier parameter passing through the springframework down into the JDO or JPA persistence layers of you app - especially on the plattforms of CloudBees and OpenShift - I introduced a PropertySplittingPlaceholderConfigurer, which splits everything it consideres a URL into the parts host, port, username, password, protocol, and uri.
So anything in the form of

# Example
url=mongodb://ruth:guessme@mongo.host:8111/db

gets exploded as if it would read

url.protocol=mongo
url.username=ruth
url.password=guessme
url.host=mongo.host
url.port=8111
url.uri=db

These generated properties can subsequently be used as placeholders in your springframework XML configuration files. So, what started as a little helper to connect to the databases of OpenShift in the best practice way, ended as a small but universal helper class.

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.

Mittwoch, 18. September 2013

NATURINSPIRIERT.org mit Tangram

Die Meldung kommt eigentlich etwas spät, aber es gibt einmal wieder eine neue Site, die mit Tangram realisiert wurde. Das kleine Foto-Blog naturinspiriert.org ist mit dem Tangram Framework auf der Google App Engine realisiert worden.
Das ganze ist insofern technisch dennoch nicht "yet another" und "nur klein", da hier zum ersten Mal live die dynamsichen Content-Zusammenstellungen genutzt werden. Die einzelnen Rubriken der Site befüllen sich mit den passenden Artikeln von selbst. Alle anderen Projekte, die diese Feautures von Tangram 0.8 nutzen sind leider noch nicht online oder können hier nicht öffentlich erwähnt werden.
Was bei der Umsetzung aufstieß sind allerdings die Probleme mit der Google App Engine: Man darf sich nicht mehr blenden lassen von veralteten Hinweisen und Links: Ohne kostenpflichtigen Google Apps Zugang bekommt man keine eigene Domain mehr für Google App Engine Anwendungen geschaltet. Punkt. Die erwähnten Links gibt es nicht mehr. Wir haben sie in keinem Szenario aus Google App Engine Anwendungen und Google Accounts nachstellen können.Wir werden also nun weiter an den alternativen Arbeiten.
Wenn's Geld kosten darf, ist Google Apps sicherlich eine gute Lösung und Google Appengine eine sehr attraktive Plattoform. Wenn man allerdings noch nicht weiß, ob eine Lösung Geld verdient, ist es nach erfolgreichen Jahren seit 2013 nur noch zweite Wahl.

Mittwoch, 9. Januar 2013

JDO 3.0 in der Google App Engine

Es ist nicht gerade ganz neu, aber ich habe es nun einmal bis jetzt aufgeschoben, meine Google App Engine nutzenden Anwendungen auf JDO 3 zu heben, obwohl das ja nun angeblich möglich ist. 
Das wichtigste dabei wären die "unowned relationsships" (was ein Wort-Ungetüm), da sie der Grund sind, daß wir bisher keine referenzielle Integrität auf Datenebene haben und diese merkwürdigen Umwege über die IDs als Strings in in den Datenfeldern nutzen müssen. In Tangram gibt es da einen Haufen Methoden (getIds, getContent(), getContents()), die einem das Leben einfach machen, aber eigentlich sollte das alle ersatzlos gestrichen werden.
Google beschreibt die Umstellung als manuellen Weg, die Anwendung zu modifizieren.
An andere Stelle kursieren immer wieder Anleitetungen, wie man das mit dem Eclipse Plugin für die Google App Engine bewerkstelligen soll. Nur genau dieses Plugin nutze ich natürlich in einem Projekt nicht, das ich auch anderen Menschen zur Verfügung stellen will, da dort mein Anspruch ist, daß man einfach ein Build-Systam hat, das alles genauso zusammenbaut wie ich bei mir.
Mit einer IDE habe ich so etwas noch nie erreicht, also bleibe ich nach make, ant, maven nun bei gradle und will hier einmal für mich und andere Aufzählen, was man zu Umstellung machen muß:
Schritt eins ist, die Abhängigkeit der JDO API zu ändern. In Gradle-Notation wird
javax.jdo:jdo2-api:2.3-eb zu
javax.jdo:jdo2-api:3.0.1
(Die letzten Maven-Nutzer werde das auch lesen können)
Und dann brauch noch die jdoconfig.xml ein paar kleinere Anpassungen:
<property name="javax.jdo.PersistenceManagerFactoryClass"
          value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/>
wird zu
<property name="javax.jdo.PersistenceManagerFactoryClass"
          value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"/>

Außerdem kommen noch zwei kleine Zeile dazu
<property name="datanucleus.appengine.query.inMemoryWhenUnsupported" value="true"/>
<property name="datanucleus.appengine.relationDefault" value="unowned"/>
Die obere Zeile ergibt sich aus den geänderten Paketen für die aktuelle datanucleus Version und die beiden anderen Zeilen versuchen, die performance zu erhöhen und die "unowned relationsships" als default zu setzen, wie es auch bei allen anderen Stores außer der Appengine der Falle ist.
Wenn man das getan hat, funktioniert bis auf die paar Semantik-Änderungen alles wie gehabt und man kann beginnen die Model-Klassen umzuschreiben.
Google beschreibt, daß auch noch die JPA-Anbindung in datanucleus hinzugefügt werden sollte, aber die nutzen ich nicht und so entsteht die Abhängigkeit nicht. Desweitere fehlt noch geronimo-jpa_2.0_spec-1.0, was aber für JDO wieder keine Rolle spielen sollte..
Aus 
package org.tangram.gae.solution;
 
import java.util.List;

import org.tangram.jdo.JdoContent

import javax.jdo.annotations.PersistenceCapable;

@PersistenceCapable
public class Container extends JdoContent {

    private List<String> contentIds;


    public List<Topic> getContents() {
        return getContents(Topic.class, contentIds);
    }


    public void setContents(List<Topic> contents) {
        contentIds = getIds(contents);
    }

} // Container
wird dann das deutlich lesbarere
package org.tangram.rdbms.solution;

import java.util.List;

import javax.jdo.annotations.PersistenceCapable;

@PersistenceCapable
public class Container extends Linkable {

    @Unowned
    private List<Topic> contents;


    public List<Topic> getContents() {
        return contents;
    }


    public void setContents(List<Topic> contents) {
        this.contents = contents;
    }

} // Container

wie wir es schon in der rdbms Variante nutzen. Endlich...
(Daß ich dabei Probleme in der rdbms-Variante entdecken mußte steht auf einem anderen Blatt und damit in einem späteres Posting ;-) )

Dienstag, 14. Februar 2012

Noch mehr funky Groovy - und gradle blues

Rendering war ja nun schon lange nicht mehr mein Problem mit den bequemen Velocity Templates im Repository. Einiges Sites laufes ja schon damit (z.B. themen-geburtstag.de). Die URL-Formate lassen ebenfalls dort definieren, wenn man möchte, was sicherlich ein wenig schwieriger im Coding ist.
Neben dem eigentlichen Datenmodell fehlt nun noch die Action im ganzen, die ich auch gerne in's Repository verlegen würde - zumindest wieder einmal als Option, da das Verhalten doch etwas ist, was man ähnlich oft tunen will, wie das Layout.
Bisher habe ich das mit einem eigenen Satz Controller sauber lösen können, aber eben nicht so agil oder dynamisch wie die Styles und Templates.
Zumindest ist es nicht mehr meine Sicht auf moderne Web-Entwicklung, daß man einen Satz an Funktionalität fest eingebaut hat und nur noch Views darüber legt.
Und da sich am Horizont weitere Projekte abzeichen, die eher Communities als reine Websites werden sollen, bestand wieder einmal Handlungsbedarf.
Also habe ich nun den lange vorhandenen Action-Parameter bei der Link-Generierung einmal zu konsistenterem Leben erweckt (und nicht nur in der simplen Editing-Komponente verwendet) und mit zwei Annotations lassen sich nun in den LinkScheme Instanzen Methoden als Actionen markieren, die direkt über URLs angesprochen werden. Parameter-Übergabe und Resultatseiten Ansteuerung inklusive. Kommentare nach Lektüren der aktuellen Codes bitte gerne an mich.
Leider war eine Entscheidung nicht gerade förderlich (evtl. hatte ich sie deshalb beim letzte Lesen auf gradle.org auch nicht getroffen): Das update auf gradles 1.0 Milestone 7 bremst hier gerade extrem. Gut war es nur, als ich offline im Zug saß :-) Da war diese Version schneller. Ansonsten quält mich diese Version mit ewiglangen Suchaktionen nach den Dependencies. Zum glück kommt gerade Milestone 8 um die Ecke: Downloaden benutzen! Damit fühlt sich gradle wieder so gut an wie vorher :-)

Montag, 5. Dezember 2011

Endlich in's CoMA gefallen

Habe eben gerade einmal die neuen Errungenschaften des Wochenendes nach github geschoben - gepuscht auf neudeutsch. Ein kleines Update auf den neuesten Meilenstein von Gradle habe ich auch gleich noch eingezogen, weil Gradle langsam immer schneller wird und ich damit keinen nennenswerten Migrationsaufwand hatte. - Sehr zu empfehlen!
Letzte Woche hatten einmal wieder ein paar Leute gefragt, ob man nicht auch direkt auf eine CoreMedia Datenbank zugreifen kann. Kann man - aber wer will das schon.
Also habe ich jetzt endlich meinen CoreMedia Adapter (CoMA) in seiner schlichtesten Ausprägung in tangram integriert.
Nein, ich bin nicht zu doof, es ausgefeilter zu machen, aber ich will weder das Copyright von CoreMedia verletzen noch deren System nachbauen. Ich muß auch erst noch am Textkovertierer für den Richtext arbeiten.
Gemäß der neuen Doktrin seit Oktober ist nun ein Beispiel natürlich anbei. Wobei man für die Sache das Original-Beispiel von CoreMedia benötigt. Da meine Teile ohnehin nur als Ergänzung zu verstehen sind, ist das ja aber wohl keine Einschränkung.

Sonntag, 30. Oktober 2011

Beispielhaft

Leider fehlt mir immernoch der Ansatz, wie ich, ohne viel Code zu schreiben, Daten zwischen verschiedenen Datenbanksystemen austauschen kann. Ich hatte da schon auf vorgefertigte Techniken wie den XML-Export gehofft, die mir aber mit den internen IDs der Datenbanken bzw. von JDO Probleme machen.
Also habe ich das erst einmal aufgesteckt und statt dessen einfach die gute alte hsqldb eingesetzt, für die ich die Daten sehr einfach mitliefern kann. Dafür gibt's nun im rdbms Beispiel ein wenig Inhalt mit Velocity Templates und Groovy Code.
Das auf Gradle basierende Buildsystem kommt nun langsam in einen brauchbaren Zustand. Den CoreMedia CMS Adapter halte ich noch zurück, bis ich dort ein Beispiel für den Einsatz liefern kann.
Also: Beispiele und System stehen auf github bereit

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?

Donnerstag, 26. Mai 2011

Vendor Lock In - III

Und nun wieder zurück zu dem Thema, welche Wege man sich verbaut und welche man sich offen halten möchte.
Bisher habe ich nur darüber geschrieben, daß ich mich auf Google App Engine wohlfühle und daß es nun belegt und testweise umgesetzt ist, daß es auch mit dedizierter Datenbank, JSP-Contaienr etc. geht.
Aber da war ja immernoch eine Ausbaustufe vorgesehen, die sich nicht darauf verläßt, daß JDO als ORM Layer benutzt wird. Letztlich läßt sich auf das Kernmodul alles aufsetzen, was irgendwelche Java Objekte erzeugt ,und mit diesen kann man dann objektorientiert Templates für die HTML Ausgabe schreiben.
Mein prominentes Beispiel war die (read only) Nutzung einer Datenbank, wie sie vom CoreMedia CMS beschrieben wurde. Exemplarisch habe ich das umgesetzt, nur mit den Richtext-Elementen habe ich noch so meine Probleme. Und für dieses Szenario gibt's nun tatsächlich ganz praktisch Systeme, für die das nützlich wäre. Mal sehen, ob sich endlich jemand "traut" diesen Weg zu gehen.
Die Lösung dient natürlich nicht dazu, ein CoreMedia CMS abzulösen. Die Kernkomponenten Content Management Server, Master Live Server, Workflow Server und Editoren bleiben notwendig. Wenn man aber unter Aufgabe aller Skalierungsoptionen eine datenausspielende Webanwendung mit dem vorhandenen Content umsetzen will, kann Tangram ein zusätzlicher Baustein sein.
Für diese Zusätzlichen Komponenten könnte der Deal dann so aussehen: Keine Lizenzkosten - Keine Performance.
Die Architektur ist einfach, hat keine zusätzlichen Serverkomponenten, benötigt ggf. die Replikation auf Datenbankebene und skaliert damit nicht ansatzweise so weit wie das "Original". Synergien mit Webanwendungen auf Basis der CAE / Unified API gibt es dann auch nicht mehr. Über Integrationen mit Suchmaschinen etc. habe ich mir nicht einmal große Gedanken gemacht. Was bleibt ist einfach, aber essenziell: Man bekommt seinen Content in's Web.

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

Dienstag, 3. Mai 2011

"Erste" Web Site online

Auch wenn natürlich schon seit Monaten einige Sites mit Tangram laufen und auch schon die Integration über Google Apps und eigene Domainsnamen länger genutzt wird, verkünde ich heute mal offiziell, daß wir eine Site in Betrieb genommen haben (indem wir nur den globalen Login entfernt haben).
http://www.themen-geburtstag.de/
beschäftigt sich mit Konzepten zur Ausgestaltung von Kindergeburtstagen zu verschiedenen Themen - und es werden immer mehr - inklusiver aller Vorbereitungen, eines Leitfadens für den Ablauf. Dazu noch ein allgemeiner Teil. In Zukunft sollen hier noch mehr Themen und Hilfestellungen hinzukommen für alle, die nicht einfach eine Party irgendwo "einkaufen" wollen.