IDE-Woche: Eclipse 3.5, NetBeans 6.7, IntelliJ 9 M1

So viel IDE gab es noch nie. In einer Woche drei wichtige Neuerungen.

JaQue Version 1.5: MS LINQ Expression Trees für Java

Von der Webseite:

JaQue provides an infrastructure for Microsoft LINQ like capabilities on Java platform. Using ASM, JaQue builds expression trees, which are used to build a query in domain specific technology or language, such as SQL. This way Java developers can focus on writing application logic in the language they know – Java, regardless what the underlying technology or language is in use. JaQue to Objects and JaQue to XML are currently supported and JaQue to JPA is under development.

Ein Beispiel macht das praktisch deutlich:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hibernate");
  EntityManager em = emf.createEntityManager();
  JaqueEntityManager jem = new JaqueEntityManager(em);
  Queryable<Order> orders = jem.from(Order.class);

  System.out.println(count(where(new Predicate<Order>() {
        public Boolean invoke(Order t) throws Throwable {
                return t.getOrderID() > 11000;
        }
  }, orders)));

Wie bei LINQ soll eine eine API für die verschiedenen Datenquellen geben, also XML, Objekte, Datenbanken, … Für JPA schreibt die Seite “Currently it’s able to perform only simple SELECTs, JOINs and AGGREGATEs”. Das ist natürlich nicht viel. Insofern ist diese Lösung WEIT von den LINQ to SQL-Möglichkeiten entfernt.

Der Hinweis der Webseite auf “Interoperability with Java Closures” ist natürlich hinfällig. Dadurch, dass Closures aber wegfallen, wird die ganze API viel aufgeblähter, als wenn man Closures hätte. Die Scala-Variante ist daher auch viel kürzer.

 

PS: Die nächsten 2 Wochen gibt es keine Blog-Einträge, da ich ich Afrika bin.

GWT-bezogene Videos von der Google I/O Konferenz 2009

Im Google Code Blog werden einige Videos vorgestellt, die den aktuellen Zustand von GWT widerspiegeln. Etwa

GWT Can Do What?!?! A Preview of Google Web Toolkit 2.0 (PDF):

 

Und weitere:

Google Wave – Powered by GWT

Google Web Toolkit Architecture: Best Practices for Architecting your GWT App

Measure in Milliseconds: Performance Tips for Google Web Toolkit

Effective GWT: Developing a Complex, High- performance App with Google Web Toolkit

The Story of your Compile: Reading the Tea Leaves of the GWT Compiler for an Optimized Future

Progressively Enhance AJAX Applications with Google Web Toolkit and GQuery

Building Applications with Google APIs

Mit AjaxSwing Swing Anwendungen als Web-Anwendungen laufen lassen

Das macht die Swing – AJAX bridge. Das SwingSet2 Demo ist schon mal ein guter Start. Die Entwickler sagen, dass das Demo ohne Quellcodemodifikationen läuft. Lauf FAQ laufen 95% der Anwendungen vernünfitg nach 30 Minuten Konfiguration. Die Vorraussetzungen für den Web-Server, das das hostet ist minimal: es läuft schon ab Java 1.2. Auch für den Client sind die Anforderungen wirklich gering: Internet Explorer 4+, FireFox 1.2+ bzw. jeder HTML 4.0 Browser. (Vielleich sieht daher das LaF von AjaxSwing standardmäßig so schrottig aus. Lässt sich aber alles anpassen.) Probleme kann es im Einzelfall etwa beim Eventing geben, wenn der Browser nicht alle Events weitergibt. Auch bei Multithreaded-Anwendungen kann es Probleme geben, wenn im AWT-Event-Thread neue Threads aufgemacht werden und die die Gui modifizieren (auch mit SwingUtilities.invokeLater/Now). Da AjaxSwing auch schon bei JComponent mit der Abbildung beginnt, laufen auch Bibliotheken wie SwingX. Mit einen SnapshotRenderer für „harte“ Fälle lässt sich auch serverseitig rendern und dann als JPG in die Seite einfügen.

Thema der Woche: Pull-Parser/StAX

Nicht immer können und müssen Objektgraphen von XML-Dateien – entweder pur als XML-DOM, oder gemappt über etwa JAXB – im Speicher gehalten werden. Muss nur einmal eine XML-Datei abgelaufen werden (natürlich können in diesem einen Durchlauf dann der XML-DOM aufgebaut werden), kann gut ein Pull-Parser eingesetzt werden.

Aufgabe: Implementiere einen XHTML-Prüfer, der meldet, ob im img-Tag das Attribut alt gesetzt ist.

Ext GWT Beispiel mit EditorGrid/GroupingView/GroupingStore

sshot-1

GroupingStore<BaseModel> store = new GroupingStore<BaseModel>();

BaseModel c1 = new BaseModel();
c1.set( „title“, „Java 1“ );
c1.set( „category“, „JAVA“ );
c1.set( „price“, 100 );
store.add( c1 );

BaseModel c2 = new BaseModel();
c2.set( „title“, „Java 2“ );
c2.set( „category“, „JAVA“ );
c2.set( „price“, 200 );
store.add( c2 );

BaseModel c3 = new BaseModel();
c3.set( „title“, „C#“ );
c3.set( „category“, „.NET“ );
c3.set( „price“, 100 );
store.add( c3 );

List<ColumnConfig> config = new ArrayList<ColumnConfig>();
config.add( new ColumnConfig( „category“, „Kategorie“, 200 ) );
config.add( new ColumnConfig( „title“, „Titel“, 100 ) );
config.add( new ColumnConfig( „price“, „Preis“, 100 ) );

store.groupBy( „category“ );

final ColumnModel cm = new ColumnModel( config );

GroupingView view = new GroupingView();
view.setShowGroupedColumn( false );
view.setForceFit( true );
view.setGroupRenderer( new GridGroupRenderer()
{
  public String render( GroupColumnData data )
  {
    String header = cm.getColumnById( data.field ).getHeader();
    String items = data.models.size() == 1 ? „Eintrag“ : „Einträge“;
    return header + “ “ + data.group + “ (“ + data.models.size() + “ “ + items + „)“;
  }
} );

EditorGrid<BaseModel> grid = new EditorGrid<BaseModel>( store, cm );
grid.setView( view );
grid.setBorders( true );
grid.setAutoHeight( true ); 

ContentPanel cp = new ContentPanel();
cp.add( grid );
cp.setHeight( 500 );
RootPanel.get().add( cp );

Will ich eigentlich RIA mit Ext GWT?

Nach dem ich nun eine Woche eine Anwendung mit Ext GWT (GXT) zusammengebaut habe, kommen mir Zweifel, ob Ext GWT überhaupt das richtige für meinen Anwendungsfall ist. Einige Fragen in dem Zusammenhang:

Ist Ext GWT 2.0 M2 gut gewählt?

Ext GWT 2 gibt es noch gar nicht lange (http://extjs.com/blog/2009/05/20/ext-gwt-20-milestone-2-released/), neues M2 Release also vor 2 Wochen, und die Komponenten sind grundsätzlich toll. Auf der Demo Seite http://extjs.com/examples-dev/explorer.html#overview kann man sich das anschauen.

Probleme: Ext GWT 2.0 hat in meinen Augen sehr vielen Änderungen in der API. Quellcode für Ext GWT 1.0 findet man im Netz, doch viele Beispiele lassen sich nicht ohne weiteres auf die 2er Version übertragen. Wer migrieren will/muss wird noch seinen Spaß bekommen. Einige Beispiele laufen in der Demo nicht (http://extjs.com/examples-dev/explorer.html#grouping), bei anderen fehlt der Quellcode im Demo. Da muss man dann die Quellen laden.

Laut Ankündigung müsste GXT schon längst fertig sein.

Was passt mir an Ext GWT nicht?

  • Die Dokumentation. Einfache Beispiele zu finden kostet viel Zeit. Es fehlt so etwas wie ein Java-Almanac für Ext GWT. Aus komplexen Szenarien kann man sich einfache Beispiele ableiten, von dort diese auf seinen Anwendungsfall übertragen. Selbst die Beispiele aus dem ShowCase könnten einfacher sein, denn der ShowCase nutzt interne “Demo-Datengeber-Klassen”. Hier wären in meinen Augen einfachere Beispiele gut gewesen, die wirklich eigenständig sind um schnell die wichtigsten Schnittstellen ablesen zu können.
  • Compiliere ich meine Programme, so lassen sich im Browser plötzlich keine Textfelder mehr selektieren und den Cursor sieht man nicht.
  • Das Layout-Handing. Da die Ext GWT Anwendungen auf eine “Bildschirmseite” kommen, und weniger auf einem beliebig langen HTML-Dokument, gibt es Probleme mit den Höhen. Manches mal sind die Elemente in einem Scroll-Container zu klein, dann zu groß. Ich habe viel Zeit damit verbracht, große Tabellen in den richtigen Größen auf den Container zu setzen.
  • Während das Orginal-GWT viele eher den typischen Web-Charakter hat, basiert Ext GWT auf dem Applikationsgedanken: (Popup-)Menüs in Web-Applikationen? Hm …
  • Anpassungen des Aussehens sind eine Qual. Die CSS-Datei gxt-all.css ist 6478 Zeilen lang, gxt-gray.css noch mal 443! Wer viel Zeit hat, kann einmal versuchen, den Font 2 Pixel größer zu setzen. Dazu müssen natürlich auch die Icons passen. Strg++ geht nicht einfach so.
  • Es “erfindet” GXT eigentlich alles neu: Widgets, Container, Layout-Manager, Grafik-Einbindung, …. Besonders blöd ist das bei den Grafiken, wo Google mit Proxies einen schönen Ansatz fährt.
  • Es gibt keinen Gui-Builder, für GWT aber schon.

War Ext GWT eine gute Wahl, oder hätte es doch SmartGWT sein sollen?

Das weiß ich nicht, denn mit SmartGWT habe ich nur einfache Beispiele programmiert. Ext GWT hat aber den gleichen RIA-Ansatz wie SmartGWT, und unterscheidet sich nicht großartig im Ansatz. Die GXT-Komponenten sehen auf jeden Fall super aus. Daher hat mich GXT ja auch so angezogen. Wer hübscher ist gewinnt 🙂 Die Komponenten sind fancy und meine Lieblinge sind http://extjs.com/examples-dev/explorer.html#advancedcharts (cool), http://extjs.com/examples-dev/explorer.html#gridplugins, http://extjs.com/examples-dev/explorer.html#grouping, http://extjs.com/examples-dev/explorer.html#filtertree, http://extjs.com/examples-dev/explorer.html#gridtogrid.

Ist ein RIA-Framework wie GXT immer gut?

Das ist eigentlich die zentrale Frage.

  • Die Standard-Komponenten von GWT sind etwas “einfach”. Natürlich nutzt GXT das GWT als Infrastruktur, aber hat sich in meinen Augen weit davon entfernt.
  • GXT versucht, alle Desktop-Komponenten in den Browser zu bekommen. Und so bekommen wir immer mehr und mehr tolle Komponenten. Das hat aber seinen Preis! Der generierte JavaScript-Code wird schnell astronomisch. Und die Anwendungen sehen eben nicht mehr so aus wie Webseiten. Das ist mal gewollt, mal nicht gewollt. Ein richtig und falsch gibt es nicht! Wer aber vollständige Applikationen im Web-Schreiben möchte, der bekommt mit GXT ein gutes Framework. Alles ist vorbereitet und das Look-and-Feel konsistent.
  • Änderungen des Aussehens sind aufwändig. Wenn man also HTML/CSS sehen und damit designen möchte, ist mit GXT nicht optimal bedient. (Als nächstes teste ich http://code.google.com/p/google-web-toolkit-incubator/wiki/UiBinder — wenn der denn mal im Trunk ist…) Soll ein (echte) Webdesigner eine GXT-Anwendung skinnen, wird der sicherlich nicht glücklich werden. Es ist eben nicht Design first.

SwingX 1.0

Ich habe ja schon nicht mehr damit gerechnet: SwingX hat es in den 1.0 Status geschafft. Die Fixes/Enhancements sind aber eigentlich minimal und die Freigabe hätte schon früher kommen können …

Und wenn man liest, “From now on, the Java 5 compatibility will no longer be maintained.” heißt das nur, dass die kommenden Versionen mindestens Java 6 erwarten; SwingX 1.0 ist selbstverständlich unter Java 5 lauffähig.

Einen einfachen Baum mit Ext GWT (Tree, TreeItem)

Im Mittelpunkt steht com.extjs.gxt.ui.client.widget.tree.Tree, dem entweder com.extjs.gxt.ui.client.widget.tree.TreeItem-Objekte zugeordnet werden, oder ein komplexeres Modell zugewiesen wird. Mit TreeItem ist schnell ein statischer Baum aufgebaut:

Tree tree = new Tree();

TreeItem rootTreeItem = new TreeItem( „Hauptobjekte“ );
tree.getRootItem().add( rootTreeItem );

rootTreeItem.add( new TreeItem( „Kunden“ ) );
rootTreeItem.add( new TreeItem( „Seminare“ ) );
rootTreeItem.add( new TreeItem( „Referenten“ ) );
rootTreeItem.setExpanded( true );

tree.addListener( Events.OnClick, new Listener<TreeEvent>()
{
  @Override public void handleEvent( TreeEvent be )
  {
    if ( be.getItem().isLeaf() )
      Info.display( „Element: „, be.getItem().getText() );
  }
} );
contentPanel.add( tree );

Wie bei Swing gibt es ein Root-Icon und darunter liegen die Kinder.

Mit einem Listener lässt sich erfragen, ob der Baum ausgefaltet wird oder ob Blätter ausgewählt wurden. Das Beispiel hört nur auf die Auswahl der Kinder und gibt eine Meldung aus.

Quaqua Look And Feel. Das bessere Mac OS X LaF

Quaqua ist ein Swing-LaF, was besonders gut an die Apple Human Interface Guidelines ranreicht.

Quaqua Look And Feel - Metalworks

Das Demo  läuft auch unter Windows.

Java Webstart

Features (von der Webseite):

  • (Nearly) Native User Experience
    Quaqua user interface delegates closely look and behave like their native counterparts. Complex user interface components, such as JFileChooser and JColorChooser, are close enough to make end users feel comfortable with them.
  • Blends into OS X Designs
    Quaqua supports three OS X designs: Tiger, Panther, Jaguar. Quaqua automatically chooses the right design for the current operating system.
  • Alternative Styles
    Quaqua offers alternative styles for many user interface elements. Such as small styles for most of the components, as well as a striped style for tables, lists and trees. Jaguar-design like tabbed panes with stacking tabs are also supported.
  • Additional Components
    Quaqua provides Swing implementations of NSBrowser and NSSheet (named JBrowser and JSheet).
  • Clean Layout
    Laying out Aqua components with Java is quite challenging. Quaqua provides an API for component alignment based on visual criteria (baseline, visual bounds, preferred gaps). JScrollPane’s automatically avoid overlaps with the grow-boxes of windows.
  • Localized in four languages
    Quaqua is localized in the following languages: German, French, Italian and English.

Neben dem LaF für Standardkomponenten gibt es mit JBrowser und JSheet noch zwei “Spezialkomponenten”.

Die Lizenz ist License (LGPL or BSD), und die Doku mit vielen Screenshots. Tolle Arbeit!

Wie viel GWT steckt in Google Square?

In Google Wave steckt eine Zeile, die einen Einsatz
vom GWT nahe legt:

<link rel="stylesheet" href="/squared/styles/squared.css">
<script language="javascript" src="/squared/js/templates.js"></script>
<script language="javascript" src="/squared/api/com.google.quality.views.squared.client.Squared.nocache.js"></script>

Verfolgt man den Link ist das typische obfuscated JavaScript zu sehen. Wer viiiiel Zeit hat, kann das ja mal debuggen und hier berichten. Ein kleiner Test mit FireBug zeigt, dass Squared sich über Service per RPC die Objekte geben lässt

["com.google.quality.views.squared.shared.model.Workspace/4054808271","US presidents",
"com.google.quality.views.squared.shared.model.Suggestions/3280816700",
"java.util.ArrayList/3821976829",
"com.google.quality.views.squared.shared.model.Entry/3459296909" ...

OpenOffice Draw + XForms Export + iText = PDF

Für unseren Seminarbetrieb erstellen wir nach dem Seminarabschluss aus einer XML-Datei die Rechnung und Zertifikate für den Kunden. Die Vorlagen sind in OpenOffice verfasst und können ohne Probleme verändert werden. Ein großer Vorteil ist weiterhin, dass OO einen PDF Exporter mitbringt.

Der Nachteil der Lösung, OpenOffice für die PDF-Erzeugung fernzusteuern ist, dass es sehr schwergewichtig. OO muss installiert und gestartet werden. Das ist auf einem Server, etwa einem einfachen Servlet-Container oder sogar der Google App Engine for Java natürlich nicht denkbar.

Ein anderer Weg ist daher, zwar weiterhin OpenOffice für die Erstellung einer Vorlage zu verwenden, aber beim PDF-Export anders vorzugehen. Die Lösungen können Acrobat Forms (Acroforms) bieten, also eigentlich interaktive Felder, die man später über ein Programm füllen kann. Im ersten Schritt erzeugt man daher mit OpenOffice Draw eine Formular. (Das wird etwa beschrieben unter http://www.devx.com/opensource/Article/38178/.) Dann exportiert man das Dokument in PDF unter Erhaltung der Formulareigenschaften. Dieses PDF lässt sich nun mit iText auslesen, die Formularzellen füllen und wieder als PDF schreiben. Dabei kann die “Formulareigenschaft” wegfallen, dass man später bei dem PDF-Dokument nichts mehr von interaktiven Elementen sieht.

import java.io.FileOutputStream;
import com.lowagie.text.pdf.*;

public class FillInPdfForm
{
  public static void main(String[] args) throws Exception
  {
    PdfReader reader = new PdfReader(„c:/rein.pdf“);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(„c:/raus.pdf“));
    BaseFont font = BaseFont.createFont(„c:\\windows\\fonts\\Calibri.ttf“, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
    AcroFields form = stamper.getAcroFields();
    for( Object o : reader.getAcroForm().getFields() )
      form.setFieldProperty( ((PRAcroForm.FieldInformation) o).getName(), „textfont“, font, null);
    form.setField(„name“, „Christian Ullenboom“);
    form.setField(„content“, „Brav sein\nLieb sein“);
    stamper.setFormFlattening(true);
    stamper.close();
  }
}

Etwas lästig ist, dass beim Ausfüllen der in OO zugewiesen Font flöten geht. Daher muss man diesen neu zuweisen. Sonst ist es Arial/Helvetica.

Wie Google Wave das GWT antreibt

Über Googe Wave wurde in den Medien schon ausreichend gesprochen. (Auf jeden Fall das Video ansehen! Der korrigierende Editor ist super.)

Wirklich interessant ist ist die Tatsache, dass die Clientseite von Google Wave in GWT implementiert ist. Das ist in meinen Augen ein unschlagbares Argument für die Ausgereiftheit von GWT, wenn Google das in einem Projekt einsetzt, was von unglaublichen vielen Menschen verwendert werden wird und definitiv performant laufen muss. Dabei sollte laut einem Blog-Eintrag http://mtwong.ning.com/profiles/blogs/google-io-conference-google-1 Wave auch überhaupt nicht in GWT entwickelt werden, da der Projektleiter Zweifel hatte, GWT würde gescheit laufen. Aber Wave hat wohl auch die Entwicklung von GWT positiv beeinflusst, etwa bei den Tools. Der Blog-Eintrag erwähnt interessante weitere Projekte und GWT-Features:

Update JDK 1.6.0_14 (6u14)

Änderungen listet http://java.sun.com/javase/6/webnotes/6u14.html auf. Interessant sind meines Erachtens: Compressed Object Pointers und Garbage First (G1) Garbage Collector, weil diese Dinge sind, die für Java 7 vorgesehen waren. Aber nun kann man die schon mal “in the wild” testen, was eine gute Sache ist. Dann noch JAX WS 2.1.6 and JAXB 2.1.10 und ein Update von JavaDB (wobei Derby schon deutlich weiter ist, komisch).

Vorschläge für Projekt Coin (Java 7 Sprachänderungen) geht in die nächste Runde

Eine Abstimmung hat ergeben, welche Spracherweiterungen es in Java 7 geben könnte:

In der näheren Auswahl sind desweiteren noch:

Alle andere Vorschläge, die bisher in der Mailingliste http://mail.openjdk.java.net/pipermail/coin-dev/ vorstellt wurden, sind damit raus. (Eine Begründung für die Ablehnung gibt es nicht zwangsläufig.)

Hast du nix zu tun, schreibst du eine neue IDE …

Das ist zumindest das Ziel von https://gravityide.dev.java.net/. Eine “Easy-to-use Java IDE for Java and other JVM languages”. Problem nur: Was einfach mit einem Editor beginnt wird (zwangsläufig) komplexer und komplexer und komplexer. Man kann darüber streiten, was – nach einer gewissen Einarbeitungszeit – nun intuitiver ist, IntelliJ, NetBeans, Eclipse, JDevelper (oder vi?), aber dass es bei einem Editor mit farblicher Hervorhebung nicht getan ist, ist klar. Und wer mit lauten Sprüchen wie “Gravity will be the only IDE you’ll need.” wirbt, und mit dem Satz “A GUI editor so you can make forms in seconds!” schreit, macht sich keine Freunde, wenn gravityide Vaporware bleibt; gravityide bleibt also vorerst das Duke Nukem Forever der Java-IDEs. Toll!

SmartGWT 1.1

Von SmartGWT, der bekannten OpenSource-GWT-Toollibrary gibt es eine neue Version. Der Showcase zeigt neue Komponenten: http://www.smartclient.com/smartgwt/showcase/. Die Release-Notes führen auf:

Unified DataBoundComponent interface which is implemented by DynamicForm, ListGrid, TreeGrid, Menu, ColumnTree, TileGrid, DetailViewer and Calendar.

– Consistent representation of a Record which can be used by any DataBoundComponent

– Support for GWT-RPC DataSource with DataBoundComponents

– Various component and skin performance improvements

Formula and Summary fields:
built-in wizards for end users to define formula fields that can
compute values using other fields, or summary fields that can combine
other fields with intervening / surrounding text. Available in all
DataBoundComponents, easy to persist as preferences

I18n support with resource bundles from 14 locales

– Significant improvements to Javadocs with tons of documentation on various concepts. (over 30MB on disk)

– API’s to save and restore the display and selection state of various components to/from the server

Automatic databound dragging
behaviors: grids and trees will now inspect data relations declared in
DataSources and automatically “do the right thing” for a databound drag

– Numerous enhancements. See the detailed API Changes document

Over 50 additional enhancements and bug fixes that were logged in tracker

– Several new events and extension points on various components to allow advanced usage

– A helloworld-1.6 starter project for SmartGWT with GWT 1.6

– Several new examples in the SmartGWT Showcase (see „New Samples“ side nav item in the Showcase)

Key API’s added

DateUtil

– Ability to globally set the Date input and rendered formats across the application

DataBoundComponent

– ability to select / deselect records, fetch / filter data and carry out various other operations on any DataBoundComponent

DataSource and DataSourceField

– ability to specify custom field value extractor logic for a given DataSourceField

– API’s to control http caching and result batch size

– DataSourceField.setCanSortClientOnly

Window

– listeners for minimize, maximize, restore and close

Calendar

– support for customizing event edit dialog fields

– event remove listener

Forms

– convenience constructors for various FormItems

– support for customizing form field and title tooltips

– TextItem : support for character casing and entry restrictions (regexp based)

– TextItem : support for hints displayed in-field

– ComboBoxItem : fetchDelay setting

– AutoFitTextAreaItem: autofits to contained text as the user types

Column Tree (Miller Columns)

– added node selected listener

ListGrid

– Grouping modes: built-in and custom grouping modes, such as the ability to group a date column by week, day, month or year

– added header click listener

– added record drop listener

– ability to customize grid groupings by record values and also group title

– support for adding custom formula and summary fields on the fly

– ability to register custom handler to control visibility of a ListGridField

– added ListGridField.setCanFreeze, ListGridField.setCanSort

SectionStack (Accordion)

– added section header click event

TreeGrid

– added folder drop listener

– ability to override getIcon() / getNodeTitle() to allow users to have custom node icon / title logic