Archive

Archive for June, 2009

Das war der 12. ICFP

Tuesday, 30. June 2009 Andreas Höhmann Leave a comment

Der ICFP ist ein jährlich stattfindender Programmierwettbewerb im Rahmen der International Conference on Functional Programming. Dieses Jahr hatten wir uns entschlossen am ICFP teilzunehmen. Die Aufgaben der letzten Jahre waren immer recht anspruchsvoll, wir waren sehr gespannt wie es dieses Jahr sein würde. Gerüchten zufolge sollte die etwas krumme Startzeit mit der Aufgabe zu tun haben … so war es dann auch :-)

Wir (Steffen, Kleiner und ich) trafen uns bei Steffen und warteten auf die Freigabe der Spezifikation.

Pünktlich um 20:00:16 ging es los bzw. ging es erstmal nicht los, denn der Webserver des Ausrichters war nicht mehr erreichbar … normal wenn knapp 300 Teams versuchen die Aufgabestellungen herunterzuladen. Das Problem war nach ein paar Minuten erledigt.

Nun ging es erstmal ans Lesen des 16 Seiten langen PDFs. Eine Kurzfassung:

  • es galt eine VM zu programmieren, mit Grundbefehlen wie Addition, Subtraktion, Wurzel etc.
  • auf dieser sollten herunterladbare Binardatein ladbar und ausführbar sein, ausführbar bedeutet alles geladenen Operationen nacheinander ausführen und Speicher verändern
  • die VM sollte Art Input/Ouput Schnittstelle haben mit deren Hilfe ein Satellit auf seinem Weg um die Erde gesteuert werden sollte
  • es gab insgesamt 5 Szenarien (erst 3, dann 4 und am Ende kam noch eine 5. Bonusaufgabe dazu), die unterschiedliche, jeweils immer “komplexere” Lösungen zum Thema “wie steuere ich einen Satelliten” erforderten

Die VM war detailiert beschrieben, es gab Daten und Befehle, das Binärformat musste geladen werden, die Befehle mussten ausgeführt werden usw.

Wir haben das Ganze mit Java umgesetzt.

Laut Specifikation muss die VM 32bit Operatoren und 64bit Daten halten, diese sind über einen 14bit Pointer adressiert, was eine maximale Anzahl von 16384 Einträgen ergibt. Es wird zwischen D-Operatoren (2 Paramtern) und S-Operatoren (1 Parameter) unterschieden:

Orbit VM Operation Types

Die Daten im “Orbit Executable Format” sind in 96 bit lange Frames aufgeteilt, bei gerade Frames (0, 2, 4, …) kommen erst die Daten (64 bit, double) und dann der Operationen (32 bit, int), bei ungerade Frames umgedreht:

Orbit Executable Format - Frame

Diese Frames werden durch den MemoryLoader in den Memory geladen. Dieser besteht aus zwei Listen (Operationen und Daten), einem Status-Bit, einem Output/Input Bereich:

VM Memory

Für die unterschiedlichen Operationen erzeugen wir während des Ladens konkrete Objekte die das Interfaces Instruction implementieren und entweder von DoubleInstruction oder SingleInstruction ableiten. Dadurch enthält unser Memory nach dem Laden bereits eine Liste von “ausführbaren” Objekten, die selbständig den Memory verändern können (eine Instruction kann aus dem Memory lesen bzw. in den Memory schreiben).

UML

Instruction Hierarchie

Gegen 1:00 konnten wir die Datei  “bin1.obf” laden und ausführen. Als Ergebnis sahen wir allerdings nur “0.0.0″. Hmm 3 mal 0, das konnte nix sinnvolles sein … das Problem war nach einer weiteren halben Stunde gelöst …

Um 1:26 hatten wir das erste Szenario “Hohmann” am laufen.  Mit 50000 Interationen konnten wir dann auch soviel Ausgabedaten erzeugen um in Openoffice mit einem XY-Diagramm eine KREIS zu sehen. WOW!!! Das war ein sinnvolles Ergebnis. Wir waren hell wach. Das war unser um die Erde kreisender Sputnik. Ziel war es nun via Input Steuerbefehle an den Sputnik zu senden um die einzelnen Szenarien zu erledigen.

icfp_firstimage

icfp_firstimageb

Im ersten, dem Hohmann-Szenario, ging es nun darum einen Satelliten von seiner initialen Umlaufbahn auf eine höhere Umlaufbahn zu steuern. Die Mathematik war beschrieben und musste nur noch programmiert werden, Kleiner und Steffen machten sich an die Arbeit. Ich versuchte in der Zeit eine Visualisierung mit SWT zu programmieren. Pro Szenario gab es noch 4 unterschiedliche Konfigurationen die wir bewältigten mussten. Hier ist der Anfang und das Ende von Konfiguration 1002 zu sehen. Der Sputnik bewegt sicht von der inneren zur äusseren Umlaufbahn:







Die notwendigen Steuerbefehle galt es dann in einem weiteren Binärformat abzuspeichern und auf der ICFP-Homepage einzureichen. Die zu erreichende Punktezahl hing u.a. von der verbrauchten Zeit und dem verbrauchten Sprit des Sputniks ab. 6:15 hatten wir das erste Szenario geschafft!

Nun ging es ans zweit dem “Meet and Greet” Szenario. Dort galt es einen zweiten Satelliten anzufliegen. Die Mathematik war hier schon wesentlich schwieriger. Wir versuchten unser bestes. Aber irgendwie wollte es nicht so recht klappen. Wir waren knapp davor die Aufgabe zu lösen aber irgendwie fehlten immer ein paar huntert Meter zum Zielpunkt. Und da wir nun jeder über 24  Stunden nicht geschlafen hatten, beschlossen wir es erstmal sein zu lassen :D Immerhin hatten wir eine VM programmiert und einen Sputnik auf eine höhere Umlaufbauen gebracht. Zufrieden und müde trennten wir uns. Danke nochmal an Steffen für die Bereitstellung einer angenehmen Programmierumgebung ;-)

Kleiner hat dann Sonntag noch rausgefunden, dass wir wirklich soooo knapp vor einer Lösung waren … leider hat uns die visualisierte Ausgabe getäuscht, dort waren alle Winkel umgedreht. Statt 150 Grad in die eine Richtung mussten wir in Wirklichkeit (360 – 150 = 210) in die andere :D Somit konnten wir dieses Jahr mit 8 gelösten Aufgaben  glänzen was uns den 139. Platz einbrachte.

Das 3. Szenario “Eccentric Meet and Greet” war vergleichbar mit dem zweiten, nur hier befand sich der Ziel-Satellite nicht auf einer Kreisbahn sondern auf einer Eclipse um die Erde. Im 4. Szenaria “Operation Clear Skies” galt es 11 (!) Satelliten auf unterschiedlichen Umlaufbahnen anzufliegen. Der Mond war hier auch mit dabei :D Aber diese Szenarien werden wir wohl ausserhalb des Wettbewerbs hacken.

Vielleicht  sind ja nächstes Jahr  noch ein paar mehr dabei ?! :D

Hier noch ein paar Screenshots der anderen Szenarien:




Categories: ICFP, Java

Today starts the 12th ICFP Contest

Friday, 26. June 2009 Andreas Höhmann Leave a comment

http://icfpcontest.org/

Clear JSF Input Components

Monday, 22. June 2009 Andreas Höhmann Leave a comment

Beim Implementieren einer einfachen CRUD Anwendung mit Hilfe von Richfaces Datatable und ModalPanel bin ich über ein “Problem” mit validierten (leeren) Eingabefeldern gestolpert.

Das Problem ist eigentlich kein richtiges Problem, sondern das Standardverhalten von JSF :-) Unschön wird es wenn man einen rich:modalPanel als Edit-Dialog einsetzt und diesen wiederverwendet.

Der grobe Aufbau:

  • eine DataTable zeigt eine Liste von Entities (z.B. mit Hilfe eine DAOs geladen)
  • jedes Entity hat eine eindeutige ID (z.B. PrimaryKey aus JPA)
  • pro Tabellenzeile gibt es einen “Edit”-CommandLink der eine rich:modalPanel für das Editieren eines Entity öffnet
  • vor jedem Edit muss die gewünschte Entity in einen CrudManager (Session-Scoped Bean) gelangen, aus der sich der Edit-Dialog mit Daten versorgen kann und mit dessen Hilfe die eigentliche Edit-Aktion durchgeführt wird

Nun sollen bestimmte Eingabefelder im Edit-Dialog validiert werden (z.B. mit einer @NotEmpty Annotation an den ensprechenden Properties der Entitiy-Klasse). Wenn man nun den Dialog für eine Entity mir der ID ‘1′ öffnet und eine Validierungsfehler auslöst, z.B. durch das Abschicken mit leeren Eingabefeldern, wird dieser Fehler ausgegeben … soweit so gut. Der Dialog kann dann geschlossen werden. Soll nun Entity mit der ID ‘2′ mit dem gleichen Dialog editiert werden, sind die Eingabefelder immer noch leer und nicht wie gewünscht mit den Werten aus Entity-2 gefüllt. Warum?!

Nach einer kurzen Googlesuche landete ich auf der Seite http://wiki.apache.org/myfaces/ClearInputComponents die den Effekt beschreibt. Der Grund für das Verhalten ist die Zwischenspeicherung von “SubmitedValues” in den jeweiligen UIComponents (z.B. h:inputText). Die werden den eigentlichen Modeldaten vorgezogen.

Will man nun einen immer aktuellen Edit-Dialog haben, gibt es verschiedene Möglichkeiten (siehe MyFaces). Ich habe mich für die “radikal einfache” Lösung entschieden … lösche alle Elemente innerhalb des Edit-Dialogs und lasse sie immer neu erzeugen.

Die Entity-Liste besteht aus einer rich:dataTable, pro Zeile ein a4j:commandButton:


<rich:dataTable value="#{tableManager.model}" var="dataItem">

<!-- Edit-Command Column -->
<rich:column sortable="false">
<a4j:commandButton ajaxSingle="true" limitToList="true"
reRender="foobar_editPanel"
oncomplete="Richfaces.showModalPanel('foobar_editPanel')"
 actionListener="#{crudManager.onEdit}">
 <f:attribute name="onEditClearTarget" value="foobar_editPanel"/>
 <f:setPropertyActionListener value="#{dataItem}" target="#{crudManager.currentEntity}" />
</a4j:commandButton>

<!-- more Columns ... -->
</rich:dataTable>

Der tableManager liefert die Entity-Daten, also eine Liste von Entity-Beans, jede Bean hat eine eindeutige ID. Der crudManager enthält stellt die gesamte CRUD Funktionalität zur Verfügung. Für eine Edit muss er mit einer Entity “initialisiert” werden, dies geschieht via f:setPropertyActionListener. Das reRender bewirkt, dass der Edit-Dialog aktuallisiert wird.

Der Edit-Dialog wird mit Hilfe von rich:modalPanel erzeugt (foobar_editPanel) und enthält eine Reihe von h:inputText Elementen. Diese sind wiederum an den crudManager gebunden.

Der Code für das Zurücksetzen der Inputelemente im Edit-Dialog ist ebenfalls im crudManager verborgen und sieht folgendermaßen aus:


public abstract class AbstractCrudManager {

public static final String ONEDIT_ATTRIBUTE_CLEARTARGET = "onEditClearTarget"; //$NON-NLS-1$

/**
 * Event-handler will be triggered on <tt>edit</tt>. This method is used as a
 * {@link ActionListener} and will be called before a <tt>edit-view</tt> is
 * shown. So here we can do some "initializations" for the edit-view, i.e.
 * reset input-fields.
 *
 *
 * This base implementation will call {@link #clearEditTarget(UIComponent)}.
 *
 *
 * @param aEvent
 *          is never <code>null</code>
 */
public void onEdit(final ActionEvent aEvent) {
clearEditTarget(aEvent.getComponent());
 }

/**
 * This method handle a edit-form-clear. Per default the command-button which delegates to the
 * edit-view could have a attribute {@link #ONEDIT_ATTRIBUTE_CLEARTARGET}.
 *
 * @param theSourceComponent
 *          is never <code>null</code>
 */
 protected void clearEditTarget(final UIComponent theSourceComponent) {
 final String onEditTarget = (String) theSourceComponent.getAttributes().get(ONEDIT_ATTRIBUTE_CLEARTARGET);
 if (onEditTarget == null) {
 return;
 }
 final UIComponent editTarget = FacesContext.getCurrentInstance().getViewRoot().findComponent(onEditTarget);
 if (editTarget == null) {
 return;
 }
 editTarget.getChildren().clear();
 }

...

}

Damit ist auch klar was das <f:attribute name=”onEditClearTarget” value=”#{id}_editPanel”/> bewirkt … es definiert die UI-Komponente die vor dem Öffnen des Dialogs zurückgesetzt werden soll.

Damit wird bei jedem Klick auf “Edit” ein Ajax-Request zum Server geschickt, dort wird die aktuelle Entity in den crudManager hinterlegt, es wird onEdit aufgerufen und damit der Inhalt des Edit-Dialogs gelöscht. JSF sorgt dann beim RenderResponse wieder dafür, dass alle UI Componenten korrekt erzeugt werden. Da dann alle Eingabeelement noch vollkommen “neu” sind, zeigen diese auch die Werte aus dem Modell an.

Categories: JSF, Richfaces Tags: , , , ,

Nexus Pro verwaltet Eclipse-Repositories

Monday, 8. June 2009 Andreas Höhmann Leave a comment

Mit Hilfe von Nexus-Pro (Version 1.3.2) ist es möglich Eclipse-Plugin-Repositories zu verwalten.

Damit wird es möglich für ein Entwicklungsteam eine Liste von Plugin-Repositories zentral zu verwalten. Alle Entwickler stellen in ihrem Eclipse Update Manager nur noch dieses eine Repository (Nexus) ein und fertig :)

Vorteile:
- externer Netzwerktraffic wird reduziert
- Thema Sicherheit, Entwickler müssen nicht unbedingt ins Internet (Proxy etc.)
- man sieht zentral welche Plugins, in welchen Versionen verwendet werden

Kurzes Video hier: http://vimeo.com/4102464

Categories: Eclipse, Nexus Tags: , , ,

Hibernate sql logging with values

Wednesday, 3. June 2009 Andreas Höhmann Leave a comment

As you might know already, Hibernate supports logging for sql-statements. Your Spring-configuration (e.g. spring-database.xml) must contain this:


<bean id="entityManagerFactory"
 class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="logging-test" />
<property name="jpaVendorAdapter">
 <bean>
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="${jpa.hibernate.dialect}" />
 </bean>
 </property>
<property name="jpaProperties" value="hibernate.dialect=${jpa.hibernate.dialect}" />
 </bean>

With showSql=true hibernate will show you logmessages like this:

Hibernate:
   delete
   from
      SoftwareCategory_SoftwareCategory
   where
      SoftwareCategory_id=?
Hibernate:
   update
      SoftwareCategory
   set
      concurrentVersion=?,
      CATEGORY_NAME=?,
      PARENT_ID=?
   where
      id=?
      and concurrentVersion=?
Hibernate:
   insert
   into
      SoftwareCategory_SoftwareCategory
      (SoftwareCategory_id, POSITION, children_id)
   values
      (?, ?, ?)

To see the values and not the placeholders (?) you must define the loglevel trace for hibernate-types in the log4j.xml:


<category name="org.hibernate.type">
<priority value="trace" />
 </category>

Then you will see logmessages like this:

Hibernate:
   insert
   into
      SoftwareCategory_SoftwareCategory
      (SoftwareCategory_id, POSITION, children_id)
   values
      (?, ?, ?)
NullableType:151 - binding '68' to parameter: 1
NullableType:151 - binding '0' to parameter: 2
NullableType:151 - binding '69' to parameter: 3

Not bad but there is a better way for this :-)

Yesterday i found the project JDBCLogger.  They have implemented a “JDBC-Proxy” with logging support. Its Maven-ready and comes with a easy Spring-integration. So how can we use this cool stuff … it is so easy:

1. Define the JDBCLogger dependencies in the pom.xml:


<dependencies>
<dependency>
 <groupId>net.sourceforge.jdbclogger</groupId>
 <artifactId>jdbclogger-core</artifactId>
 <version>0.7-SNAPSHOT</version>
 </dependency>
 <dependency>
 <groupId>net.sourceforge.jdbclogger</groupId>
 <artifactId>jdbclogger-spring</artifactId>
 <version>0.7-SNAPSHOT</version>
 </dependency>
 </dependencies>

The informations from the installation-guide on the project-site is a little too old, so the maven-repository http://jdbclogger.sourceforge.net/m2-repo/ doesn’t exists. No problem we can build jdbclogger-core and jdbclogger-spring by ourself (read more). The simplest way to build the two artifacts is:

  • checkout from  svn
  • edit master-pom, comment out all modules, leave only core and spring active
  • run mvn clean install from root-dir

2. Change your Spring-configuration, switch showSql off and add the following bean:


<bean id="jdbcLoggerConfig"
 class="net.sourceforge.jdbclogger.spring.JdbcLoggerBeanPostProcessor">
<property name="enabled" value="true" />
<property name="dataSourceConfigurations">
	<list>
 <bean class="net.sourceforge.jdbclogger.spring.JdbcLoggerDataSourceConfiguration">
<property name="dataSourceBeanName" value="dataSource" />
<property name="driverClassNamePropertyName" value="driverClassName" />
 </bean>
 </list>
 </property>
<property name="targetDriverClassNames">
	<list>
 <value>${jpa.driver}</value>
 </list>
 </property>
 </bean>

3.  Activate logging in the log4j.xml:


<category name="net.sourceforge.jdbclogger">
<priority value="debug" />
 </category>
<category name="net.sourceforge.jdbclogger.spring">
<priority value="error" />
 </category>

Thats it :-) Now you will see logmessages like this:

JdbcLoggerDriver:65 – Wrapper ‘net.sourceforge.jdbclogger.JdbcLoggerDriver’ successfully registed for driver ‘com.mysql.jdbc.Driver’
PreparedStatementWrapper:156 – Prepared Statement : select softwareca0_.id as id0_, softwareca0_.concurrentVersion as concurre2_0_, softwareca0_.CATEGORY_NAME as CATEGORY3_0_, softwareca0_.PARENT_ID as PARENT4_0_ from SoftwareCategory softwareca0_ where softwareca0_.PARENT_ID is null
StatementWrapper:45 – Statement : delete from softwarecategory_softwareobject
PreparedStatementWrapper:156 – Prepared Statement : insert into SoftwareCategory_SoftwareCategory (SoftwareCategory_id, POSITION, children_id) values (‘92′, ‘3′, ‘96′)