Skip to content


Sails - die Scala Version von Rails/Grails

Ich habe mir das Scala Webframework Lift angesehen und finde, es ist zu kompliziert. Aber ich habe mir heute morgen auch wieder ein paar Möglichkeiten angesehen, die Scala so bietet und frage mich, ob man nicht (mit etwas Hilfe) ein Stack erstellen könnte, der Scala als Basissprache benutzt und sonst sich aber eher von Rails/Grails inspirieren lassen könnte. Für das UI käme natürlich Wicket in Frage.

Ich glaube, das wäre reizvoll, spannend und wichtig: sehr produktiv.

p.s.: wenn es sowas schon gibt, bitte gerne einen Hinweis.

Tags:

Veröffentlicht in scala, Technologie, Wicket, .

Grails Ajax Update zu kompliziert...

Man lernt ja jeden Tag etwas neues. Gestern habe ich gelernt, dass Grails von Haus aus nur ein Element per Ajax austauschen kann. Man klickt auf einen Link und kann dann z.B. den Inhalt eines DIV-Tags ersetzten, ergänzen oder was auch immer. Das ist alles ganz nett und einfach. Ändert sich aber durch eine Interaktion mehr als ein Element auf der Seite, fängt es an kompliziert zu werden. Wobei kompliziert eigentlich nicht das richtige Wort ist, denn man muss diese fehlende Funktionalität selbst ergänzen.

Es ist unzweifelhaft möglich, so das gewünschte Ziel zu erreichen. Aber ich finde es spannend, dass es eine IMHO derart triviale Anforderung nicht in den "Grails-Standard" geschafft hat. In Wicket füge ich die Komponenten, die aktualisiert werden müssen, einfach zu einer Liste hinzu. Ich muss mich nicht darum kümmern, was dann genau passiert.

Festzuhalten bleiben für mich die Punkte, die für mich eher gegen einen Einsatz von Grails sprechen:

  • Ajax Update nur für ein Element möglich.
  • Spring Security ist pfadbasiert - das ist IMHO ein extrem limitierter Ansatz.
  • Taglibs sind kein Ersatz für Komponenten.

Grails hat Stärken.. aber ich bezweifle zunehmend, dass in Projekten, die mit Grails angefangen wurden, Grails diese positiven Effekte aus dem Projektstart auch auf lange Sicht ausspielen kann.

Update:

Immerhin habe ich gerade wieder gelernt, dass man Spring Security auch mit Annotationen am Controller benutzen kann, so dass man die Pfade nicht von Hand aktualisieren muss, wenn man etwas umbaut.

Das ich hier vielleicht Wicket und Grails vergleiche, obwohl die beiden Technologien nicht so einfach vergleichbar sind, bezieht sich in dieser Kritik nur auf den View-Layer. Es gibt sehr viele Dinge, die ich recht cool finde, an Grails. Aber um View-Layer bin ich einfach besseres gewohnt.

Tags:

Veröffentlicht in Technologie, Wicket, .

Scala kommt

Ich habe letztes Jahr in der Java User Group HamburgJan Kriesten kennen gelernt, als er einen Vortrag zu Wicket gehalten hat. Dabei erwähnte er, dass er seine Projekte mit Scala umsetzt. Wenn man sein Haus umbauen möchte, ist es keine Gute Idee, alle Wände gleichzeitig einzureißen, als konzentrierte ich mich auf Wicket.

Heute habe ich gedacht, ich könnte diesen Kontakt ja mal aufleben lassen. Ich bekam prompt Antwort. Die Überraschung folgt auf den Fuss: Jan hat ebenfalls ein Buch geschrieben (es wird vermutlich zur selben Zeit erscheinen). Das Buch hat er auch noch beim selben Verlag geschrieben. Und offensichtlich hatten wir die selbe Intention, denn sein Buch ist ebenfalls auf die praktische Anwendung von (in diesem Fall) Scala ausgerichtet.

Ich habe das Buch natürlich nicht gelesen, aber ich habe ein gutes Gefühl. Es gibt hier jetzt keine Kaufempfehlung, außer an mich selbst.

Jan's Blog und das Buch:Praxisbuch Scala: Programmieren in Scala für Ein- und Umsteiger

Tags:

Veröffentlicht in scala, Wicket, .

Wicket und Scala - der Rückweg ist anstrengend

Ich habe mal ein wenig mit Scala rumgespielt und mit den Sprachmöglichkeiten, die Scala bietet, versucht aus einem Java-lastigen Wicket-Beispiel etwas zu machen, was sich wie Scala anfühlt. Zuerst der Java-Code:

package de.flapdoodle.incubator.scalawicket.web.pages;

import org.apache.wicket.Component;
import org.apache.wicket.IClusterable;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;

public class StartJava extends WebPage
{
  public StartJava()
  {
    IModel messageModel=Model.of("Huiii");
    final Label label=new Label("message",messageModel);
    label.setOutputMarkupId(true);
    
    add(label);
  
    final Bean bean=new Bean();
    bean.setName("Klaus");
    bean.setAlter(12);
   
    final Component labelName = new Label("name",new PropertyModel(bean,"name")).setOutputMarkupId(true);
    final Component labelAlter = new Label("alter",new PropertyModel(bean,"name")).setOutputMarkupId(true);
    add(labelName);
    add(labelAlter);
    
    final Form form=new Form("form", new CompoundPropertyModel(bean));
    form.add(new TextField("name")).add(new TextField("alter"));
    form.setOutputMarkupId(true);
    add(form);
    
    add(new AjaxFallbackLink("link",messageModel)
    {
      public void onClick(AjaxRequestTarget target) 
      {
        getModel().setObject("Klick");
        bean.setName("Peter");
        target.addComponent(form);
        target.addComponent(label);
        target.addComponent(labelName);
        target.addComponent(labelAlter);
      }
    });
  
    add(new AjaxLink("link2",messageModel)
    {
      @Override
      public void onClick(AjaxRequestTarget target)
      {
        getModel().setObject("Klack");
        bean.setAlter(24);
        target.addComponent(form);
        target.addComponent(label);
        target.addComponent(labelName);
        target.addComponent(labelAlter);
      }
    });
  }
  
  class Bean implements IClusterable
  {
    String _name;
    int _alter;
    public String getName()
    {
      return _name;
    }
    public void setName(String name)
    {
      _name = name;
    }
    public int getAlter()
    {
      return _alter;
    }
    public void setAlter(int alter)
    {
      _alter = alter;
    }
  }
}

.. und nun das ganze in Scala

package de.flapdoodle.incubator.scalawicket.web.pages;

import org.apache.wicket.Component;
import org.apache.wicket.IClusterable;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import de.flapdoodle.incubator.scalawicket.web.wicket.WicketHelper._
import scala.reflect.BeanProperty;

class Start extends WebPage 
{
  val messageModel=Model.of("Huiii")
  val label=new Label("message",messageModel)
  label.enableAjax
  
  this+=label;

  val bean=new Bean
  bean.name="Klaus";
  bean.alter=12;

  val labelName = new Label("name",bean model {_.name}).enableAjax
  val labelAlter = new Label("alter",bean model {_.alter}).enableAjax
  this+=labelName
  this+=labelAlter
  
  val form=new Form[Bean]("form", new CompoundPropertyModel[Bean](bean));
  form+=(new TextField("name"),new TextField("alter"))
  form.enableAjax
  this+=form
  
  this+=new AjaxFallbackLink[String]("link",messageModel)
  {
    override def onClick(target: AjaxRequestTarget) = 
    {
      this.model set "Klick"
      bean.name="Peter"
      target.refresh(form,label,labelName,labelAlter)
    }
  };

  this+=new AjaxLink("link2",messageModel)
  {
    override def onClick(target: AjaxRequestTarget) =
    {
      this.model set "Klack"
      bean.alter=24
      target.refresh(form,label,labelName,labelAlter)
    }
  };

  class Bean extends IClusterable
  {
    @BeanProperty
    var name: String = _;
    @BeanProperty
    var alter: Integer = _;
  }
}

Zuerst zu den offensichtlichen Dingen:

  • Java: Zeilen=91, Wörter=155, Zeichen=2.567
  • Scala: Zeilen=69(75%), Wörter=126(81%), Zeichen=1.921(75%)

In diesem Beispiel kann Scala seine Vorteile vielleicht noch nicht richtig ausspielen. Wobei 25% weniger Schreibarbeit (wenn man vernachlässigt, dass ich einmalig etwas Scala-Code schreiben musste, was mir das ermöglicht) für dieses Beispiel vielleicht auch schon eine bemerkenswerte Menge ist.

Spannender ist folgender Umstand: Ich habe den Java-Code aus dem Scala-Code abgeleitet. Wenn ich das Beispiel direkt in Java geschrieben hätte, sähe der Code fast genauso aus. Als ich aber den Scala-Code rückübersetzte, fiel es mir sehr schwer, die ganzen Typ-Definitionen zu schreiben, die abschließende Semikolons zu setzen und Parameter in geschweifte Klammern einzubetten. Auch wenn die Unterstützung für Scala in Eclipse noch einiges Potential hat, kann man a) damit bereits erstaunlich gut arbeiten (wenn man bedenkt, welche interessanten Sprachmöglichkeiten (und damit Schwierigkeiten für eine IDE) Scala bietet).

Meine schönste Zeile Code ist in diesem Beispiel das Erzeugen eines AbstractReadOnlyModel durch den Aufruf von "bean model { _.alter }" , der in diesem Fall das selbe leistet wie ein PropertyModel, nur dass das Attribut nicht erst per Reflection ermittelt wird.

Ich warte eigentlich darauf, dass jemand Wicket nach Scala portiert, denn das Lift-Framework gefällt mir nicht so gut (da wird wieder Code in die Templates verlagert). Jetzt geht es erst einmal weiter mit Java, auch wenn der Rückweg jetzt schon ein beschwerlicher war.

Tags:

Veröffentlicht in Allgemein, Refactoring, scala, Wicket, .

Wicket ohne Template

Ich spiele seit einiger Zeit mit dem Gedanken, ob man basierend auf Wicket Komponenten entwickelt, die alle das entsprechende eigene Template mitbringen. Auf diese Weise könnte man dann Webanwendungen entwickeln, ohne eine Zeile Html-Code schreiben zu müssen. Verrückte Idee?

Normalerweise reduziert sich die Arbeit mit dem Html-Templates auf das Anordnen der Komponenten. Das was übrig bleibt (eine paar div-Tags), sollte man durch den Einsatz von Layout-Komponenten ersetzen können. Dann programmiert man wie für eine Desktopanwendung und das Ergebnis sieht gleich entsprechend gut aus, wenn man zu die passende CSS-Datei mitliefert.

Bis jetzt fehlt mir noch der geeignete Ansatz und die Entscheidung für ein CSS-Framework. Für Empfehlungen und Tipps bin ich in dieser Phase sehr empfänglich. :)

Tags:

Veröffentlicht in Refactoring, Technologie, Wicket, .