Česky   |  Deutsch   |  English   |  Español   |  Français   |  Indonesia   |  日本語   |  한글   |  Polski   |  Português (BR)   |  Türkçe   |  中文   |  正體中文   |  Your Language  
PlanetNetbeans
Planet NetBeans ist eine Sammlung aller NetBeans-relevanten Gedanken aus der ganzen Blogosphäre.
Java Getriebe » NetBeans - June 29, 2012 08:50 AM
Die NetBeans Laufzeitkonfiguration auf einen Blick

Geertjan hatte vor ein paar Tagen schon einen Artikel “Viewing the NetBeans Central Registry” in seinem Blog eingestellt in dem er mit einen mehr oder weniger Einzeiler das aktuelle “SystemFileSystem” anzeigen kann. Diese “Zentralen Einstellungen” (bzw “XML Layer File System”) ist DER Mechanismus der NetBeans Platform um die Modularität der RCP Anwendungen sicher zu stellen. [...]

Java Getriebe » NetBeans - June 18, 2012 03:17 PM
Projektbezogene Context-Action

In NetBeans RCP Anwendungen in denen mit Projekten gearbeitet wird, ist die “Project API” und “Project UI API” unverzichtbar. Sie bieten die komplette Funktionalität, die man von Projekten in der NetBeans IDE kennt. Erweiterbare Nodes, Konfigurationsverwaltung, Abhängigkeiten und vieles mehr. Eine Fähigkeit dieser großartigen API durfte ich heute neu entdecken. NetBeans kennt so genannte ContextActions. [...]

Java Getriebe » NetBeans - June 14, 2012 08:57 AM
Release Files in der Projektansicht

Bei der RCP Entwicklung mit der NetBeans Platform tauchen unweigerlich auch so genannte “Library Wrapper Modules” auf. Also solche Module, die einfach nur eine .jar-Datei eines Drittanbieters in ein NetBeans Modul verpackt. Die NetBeans IDE kopiert die externen Dateien in das Unterverzeichnis “release” des entsprechenden Moduls. Aber genau dieses Verzeichnis “release” wird nur in der [...]

JNBB - Joschs NetBeans Blog - May 23, 2012 01:00 PM
Lookup und Swing-Tricks: Wie ich Events zu Lookup-Changes bekomme

Ich melde mich mal mit einer Kleinigkeit zurück.

Der Kunde wünscht sich bei der Auswahl von Nodes auch die Modifier der Tastatur zu ermitteln. Üblicherweise ist das gar nicht möglich, wenn man nur mit Lookup-Listener auf Results arbeitet (was ja die Regel sein sollte).

Da Swing ja singlethreaded ist und die meisten Lookup-Benachrichtigungen sich auch daran halten (außer man erzwingt Mutlithreading – was böse ist), kann man einfach über das AWT das aktuelle Event ermitteln:

AWTEvent currentEvent = EventQueue.getCurrentEvent();

Da AWTEvent recht schmalbrüstig ist, müssen wir es noch casten. Beispiel:

if ( currentEvent instanceof InputEvent ) {
  mods = ((InputEvent)currentEvent).getModifiers();
}

Ist kein aktuelles Event vorhanden, wird null zurückgegeben, was mit instanceof ohne NPE abgefangen wird. Dann erhalten wir aber auch keine Modifier.

flattr this!

Java Getriebe » NetBeans - April 12, 2012 07:29 AM
Zu welchem Projekt gehört die Datei?

Wer mit der Project API von NetBeans arbeitet kommt früher oder später zu dem Punkt an dem man eine Datei (oder besser ein FileObject) hat und wissen will “zu welchem Projekt gehört diese Datei denn nun?” Anfangs habe ich das über den ProjectManager geregelt. Dort sind Methoden, die heißen findProject oder auch isProject. Eigentlich naheliegend. [...]

JNBB - Joschs NetBeans Blog - March 02, 2012 09:36 AM
JavaFX 2 Multiplatform in einer NetBeans Platform App

Da auch JavaFX 2 mit einem eigenen Native-Loader kommt, haben wir in einer NetBeans Platform wieder das Problem, die DLL/SO/… Bibliotheken an die richtige Stelle zu bekommen.

Man kann natürlich den Anwender JavaFX installieren und bin-Pfade einrichten lassen. Aber bequemer ist es natürlich, wenn sich die Platform Application darum kümmert.

Hier eine extrem simple (und nicht für alle Plattformen gültige) Lösung.

Es wird davon ausgegangen, dass sich die javafx-2.0.jar in dem Ordner cluster/modules/ext/somename befindet. Cluster ist der suite-Name. Der Pfad modules/ext ist Standard für externe Bibliotheken und somename ist (ggf.) ein Codename-Base-Name der externen Bibliothek oder “lib” (das ist JavaFX aber egal). Ich habe z.B. com.oracle verwendet (die aus der Gruppen-ID meiner Maven-Artifakte kommt).

Will ich nun (nur) Windows in 32bit und 64bit unterstützen, lege ich in dem ext-Order noch bin und darunter amd63 und x86 an. Also: cluster/modules/ext/bin/amd64 und cluster/modules/ext/bin/x86. Der Native Loader von JavaFX sucht immer (von der javafx-2.0.jar) in ../bin. Ich muss also nun die DLL’s kopieren.

Hier ein Beispiel meiner Dateistrukturen:

Da JavaFX fast mit Java7 verheiratet ist, werde ich auch nur mit Java7-nio den Weg beschreiten:

public class Installer extends ModuleInstall {

  @Override
  public void restored() {
    Class c = Installer.class;
    URL u = c.getProtectionDomain().getCodeSource().getLocation();
    String path = u.getPath();
    if ( path.startsWith("file:/") && path.endsWith(".jar!/")) {
      path = path.substring(6);
      path = path.substring(0, path.length()-2);
      int pos = path.lastIndexOf("/");
      if ( pos >= 0 ) {
        path = path.substring(0, pos);
        FileSystem fs = FileSystems.getDefault();
        Path dest = fs.getPath(path, "ext", "bin");
        Path source = fs.getPath(path, "ext", "bin", System.getProperty("os.arch"));
        try {
          for (Path toCopy : Files.newDirectoryStream(source)) {
            Path destFile = fs.getPath(dest.toString(), toCopy.getFileName().toString());
            Files.copy(toCopy, destFile, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
          }
        } catch (IOException ex) {
          Exceptions.printStackTrace(ex);
        }
      }
    }
  }
}

Am aufwendigsten ist die Ermittlung des Modulpfades per URL u = c.getProtectionDomain().getCodeSource().getLocation(); mit dem Extrahieren des eigentlichen Pfades (man sieht, WebStart wird nicht unterstützt). Den Path “source” ermittle ich ausschließlich über os.arch. Das ist natürlich nicht wirklich nützlich für Plattformen wie Linux. Wer weitere Plattformen unterstützen will, sollte noch zusätzliche Systemparameter ermitteln und weitere Unterordner anlegen. Ich würde aber explizit die Methoden aus org.openide.util.Utilities (isMac, isUnix, isWindows) verwenden. Die System Properties sind da zu geschwätzig.

Nehmen wir an, es würde alles fehl schlagen (weil wir Bibliotheken nicht mitliefern), dann sollte man noch eine eigene Hilfsklasse basteln, die den erfolgreichen (oder nicht erfolgreichen) Kopiervorgang an andere Module liefern kann (z.B. JavaFXHelper.isJavaFXAvailable()). Wenn man das nämlich nicht abprüft und doch JavaFX verwendet, sind die Abstürze so hart, dass häufig nicht mal das Hauptfenster angezeigt wird. Im Log findet ihr dann Fehler wie: java.lang.UnsatisfiedLinkError: Can’t load library: …

Was allerdings schön ist: mehr ist nicht zu machen. Man muss nicht (wie in einem alten Artikel von mir beschrieben) eine Startup-Klasse der Platform unterschieben, um JavaFX zu nutzen.

Einen Mini-WebBrowser fügt man so in eine TopComponent ein:

    final JFXPanel fxPanel = new JFXPanel();

    add(fxPanel);
   
    Platform.runLater(new Runnable() {

      @Override
      public void run() {
        Group group = new Group();
        Scene scene = new Scene(group);
        fxPanel.setScene(scene);
       
        view = new WebView();
        view.setMinSize(1024, 768);
        view.setPrefSize(1024, 768);
        group.getChildren().add (view);
      }
    });

view ist eine Feldvariable der TopComponent. Mit der Methode:

  public void browseTo (final String url) {
    Platform.runLater(new Runnable() {
      @Override
      public void run() {
        view.getEngine().load(url);
      }
    });
  }

kann man eine Webseite öffnen (http:// muss aber am Anfang der URL stehen).

Viel Spaß mit JavaFX in der NetBeans Platform.

flattr this!

JNBB - Joschs NetBeans Blog - March 01, 2012 10:00 AM
NetBeans Release 7.1.1 ist da

Seit kurzer Zeit ist ein neues Release von NetBeans fertig und kann hier heruntergeladen werden.

Die Version 7.1.1 bring kleinere Neuerungen:

  • Java ME SDK 3.0.5 Unterstützung
  • Bundle GlassFish 3.1.2 Update
  • JavaFX 2.0.3 SDK Unterstützung
  • Maven 3.0.4 Upgrade

Dazu wurden 123 Fehler berichtigt, die noch in 7.1 waren oder bis 7.1.1 entdeckt wurden. Hier eine Liste der P1 Fehler:

All [71cat] ArrayIndexOutOfBoundsException: -72
All Closing editor clone not handled correctly;
editor TC out of sync with disk file
All [regression] Use of FindUsages modifies all
documents with references
Wind Applications not using OSGi don’t start on NbP 7.1
Linu Can’t deploy to remote GlassFish 3.1.1 server
Wind Mercurial gives getaddrinfo failed
Wind Insufficient CSS parser error recovery
All [71cat] Scanning projects never ends
All Add friend dependency for Java ME
Wind Find Occurences (Alt+F7) tries wrongly to modify the file
Mac Evaluate org.openide.awt
.ActionsTest.testTooltipsContainAccelerator
failure on Mac
All ScriptingCreateFromTemplateTest
.testCreateFromTemplateEncodingProperty failure
Wind ME 3.0.5 emulator never starts on Win 7 64bit
All Failing test org.netbeans.modules.apisupport.project.
NbModuleProviderImplTest.testGetDependencyVersion
Wind Failing tests in release71_fixes branch
Wind REST sample cannot be deployed to GlassFish 3.1.2.

flattr this!

JNBB - Joschs NetBeans Blog - February 27, 2012 02:16 PM
Die wichtigsten Tastatur-Tricks in der NetBeans IDE

Es gibt ein paar kleine Tricks, um mit der IDE etwas schneller arbeiten zu können. Die folgende Liste ist bei weitem nicht vollständig, sondern beschreibt nur die Shortcuts, die ich gerne nutze (auch die Verwendung von einigen Assistenten).

Zwischenablage / Clipboard

Mehr durch Zufall bekommt man mit, dass Strg+C / Ctrl-C die komplette Zeile in die Zwischenablage kopiert, wenn man kein Zeichen selektiert. Das ist sehr praktisch, weil man sich die Tastenkürzel für das Markieren einer kompletten Zeile ersparen kann.

Strg-V / Ctrl-V fügt die Zwischenablage ein. Aber mit der Umschalt/Shift Taste wird der importierte Quelltext noch zugleich formatiert. Umschalt+Strg+V ist damit meine häufigst verwendete Tastaturkombination.

Löschen

Strg+E löscht eine komplette Zeile, ohne sie markieren zu müssen.

Auskommentieren

Schnell muss mal eine Zeile raus aus den Programmablauf, löschen will man sie aber nicht. Toggle Comment [Strg+Umschalt+C] hilft hier, um selektierte Zeilen schnell auszukommentieren oder die Kommentare wieder zu entfernen.

Zeilen bewegen / duplizieren

Mit den Pfeil/Cursor Tasten und Alt+Umschalt / Alt-Shift, kann man die aktuelle Zeile oder die markierten Zeilen nach oben oder unten verschieben, bzw. ein- oder ausrücken.

Sehr praktisch ist auch das Kopieren der aktuellen Zeile (oder der markierten Zeilen). Pfeil / Cursor auf und ab mit Strg+Umschalt / Ctrl+Shift erzeugt eine Kopie über oder unter dem Original. Dabei wird die Zwischenablage / Clipboard nicht verändert.

So kann man z.B. relativ schnell Felder in Klassen duplizieren, um dann nur den Namen zu ändern.

Actions für “Java-Zeile beenden”

Das sind Shortcut-Actions, die auf deutschen Tastaturen nicht funktionieren. Bevor man diese Funktionen nutzen kann, muss man diese in den Options neu zuweisen. Dazu geht man in die Optionen (Tools -> Options), dort auf die Keymap. Im Suchfeld gibt man “Complete Line” ein. Man bekommt zwei Editor Actions die auf Ctrl+SEMICOLON und Ctrl+Shift+SEMICOLON hören. Die eine Action (Complete Line) wird auf ALT+COMMA geändert, die andere (Complete Line and Create New Line) auf Ctrl-Alt-COMMA.

Complete Line in NetBeansJetzt kann man mitten im Bearbeiten der Zeile die Shortcuts eingeben. Die IDE fügt dann ein ; an das Ende der Zeile an und fügt (auf Wunsch) eine neue Zeile ein.

Rechteckige Selektion im Editor

Die Texteditoren haben neuerdings zu der klassischen Zeichen/Zeilen-Selektion nun eine rechteckige Selektion. Die kann man mit Strg+Umschalt+R aktivieren und deaktivieren. Man kann dann mit der Maus oder Umschalt+Pfeiltaste einen rechteckigen Bereich markieren. Das Besondere ist nicht das Kopieren des Bereiches, sondern die Eingabe von neuen Daten in den Bereich. Jede Zeile aus dem rechteckigen bereich erhält die neue Eingabe. Somit kann man z.B. sehr schnell einen Bereich von public Feldern in private ändern.

public int a;
public String b;
public double c;

Rectangular Selection ManipulationNun mit Strg+Umschalt+R den Selektionsmodus auf Rechteckig ändern und alle drei public’s selektieren. Dann einfach private eingeben. Alle drei Felddeklarationen haben nun private als Modifier. Es ist zu empfehlen die Selektion nach solchen Operationen wieder zurückzusetzen.

Alles hybsch machen

Mit Strg+Umschalt+F wird der selektierte Bereich (oder alles, wenn keine Markierung existiert) neu durchformatiert.

Quelltextvervollständigung / Codecompletion

Import Statements aufräumen und ergänzen

Die Tastenkombination Strg+Umschalt+I wirft ungenutzte Imports raus, löst *-Imports auf und fügt fehlende Imports hinzu. Wenn Klassennamen doppelt existieren, dann muss man die passenden Klassen in einem Dialog bestätigen. Man braucht die Kombination seltener, seit dem Strg+V und Strg+Umschalt+V automatisch die Imports mit übertragen. Aber manchmal braucht man es doch noch.

Methoden überschreiben

Man kann den Alt-Einf / Alt-Insert Assistenten verwenden, oder direkt den Namen der zu überschreibenden Methode eingeben und dann Strg+Leertaste / Ctrl-SPACE drücken (natürlich im Body der Klasse). Es wird dann vorgeschlagen, eine Methode aus der Liste zum Überschreiben auszuwählen. Mit Enter bestätigen, erzeugt die Methode mit dem super-Aufruf der überschriebenen Methode.

Variablenzuweisungen von der IDE

Ma sollte möglichst nicht mit einer VAriablenzuweisung beginnen, sondern erst den Methodenaufruf  schreibe. Beispiel:

getDimension();

Man bleibt mit dem Eingabecursor hinter den Semikolon. Die IDE wird schon jetzt eine gelbe Lanpe (Hint) bei der Zeilennummer einblenden. Nicht mit der Maus anklicken (dauert zu lange), einfach Alt+Enter. Es erscheint idR. nur ein Hinweis: Einen Rückgabewert einer neuen Variable zuordnen. Einfach mit Enter bestätigen und die IDE erzeugt:

Dimension dimension = getDimension();

Dazu den passenden Import. Außerdem ist der Variablenname dimension markiert, so dass man ihn ggf. überschreiben kann.

POJOs erzeugen

Ein sehr einfacher Weg, um Plain Old Java Objects zu erzeugen, ist wieder per Assistent. Erstmal eine Klasse anlegen. Im Body der Klasse nur Alt+Einfügen / Alt+Insert tippen.

In der Auswahlbox “Add Property” auswählen. Der Assistent erlaubt nun neben den Namen und Typ auch weitere nützliche Optionen zu aktivieren. Insbesondere “Bound” erleichtert viel Arbeit, weil damit das PropertyChangeSupport für die set’er Methoden erzeugt wird.

Nie wieder muss man diesen Boilerplate Code schreiben:

/**
 * Set the value of name
 *
 * @param name new value of name
 */
public void setName(String name) {
   String oldName = this.name;
   this.name = name;
   propertyChangeSupport.firePropertyChange(PROP_NAME, oldName, name);
}

Nun kann man mit den Klassen erstmal arbeiten. Wenn man später die Architektur etwas aufmöbeln will, kann man aus der Klasse ein Interface extrahieren (Im Kontextmenü: Refactor -> Extract Interface).

Navigation

Hyperlinks für Klassen, Methoden und Felder

Hyperlink Navigation in NetBeansStrg-Taste / CTRL  halten und mit dem Mauszeiger über einen Namen (Methode, Feld, Klassenname) gehen. Es erscheint ein Hyperlink. Ein Klick darauf und man springt zur Deklaration (öffnet dabei ggf. einen neuen Editor).

Aktuelle Editor-Datei im Projektfenster markieren

Wenn man keine sofortige Synchronisation aktiviert hat (View -> Synchronize Editor with Views), dann stimmt die markierte Datei im Projektfenster nicht mit der aktuell bearbeiteten Datei im Editor überein. Strg+Umschalt+1 markiert die Datei im Projektfenster (und öffnet ggf. das zugehörige Projekt). Das ist dann besonders nützlich, wenn man in eine Klasse per Strg+Mausklick (wie ein Browser-Hyperlink) über Methodennamen gesprungen ist oder der Debugger die Quelltexte geöffnet hatte.

Klasse suchen

Strg+O (Goto Type) ist ein Suchdialog für Klassennamen. In dem Dialog den Suchbegriff eingeben, Doppelklick auf eines der Ergebnisse öffnet die Datei. Strg-Umschalt-1 zeigt die Datei dann in der Projekts-Struktur.

Zu Zeilennummer springen

Strg+G (Goto Linenumber) öffnet einen Dialog, um eine Zeilennummer einzugeben. Dorthin springt dann der Eingabecursor. Wer Exceptions per Mail zugeschickt bekommt, wird das Feature lieben.

Alle Implementationen eines Interfaces

Vor der Deklarationszeile eines Interfaces, abstrakter Klassen und überschriebener Klassen erscheint in der Zeilennummer ein kleines (i). Klickt man darauf, wird eine Liste aller bekannten Implementationen angezeigt. Per Klick kann man in die einzelnen Implementationen springen. Das ist nützlich, wenn man Interface erweitert (neue Methoden-Signaturen) und damit die Kassen angepasst werden müssen.

Editor maximieren

Eigentlich ist der Editor immer zu klein, zumindest geht es mir so. Der Doppelklick auf die Registerzunge zum Maximieren des Editors ist nett aber umständlich. Das Tastenkürzel Maximize Windows [Strg+ESC] ist da schneller. Entgegen des Namens setzt [Strg+ESC] die vergrößerte Registerzunge auch wieder zurück.

Generelle Probleme mit Tastenkürzel

Wer Ubuntu verwendet, wird mit allen Tastenkürzeln unglücklich werden, die mit Alt+Umschalt / Alt+Shift eingeleitet werden. Das klappt unter Ubuntu nicht, da Alt+Umschalt schon vom System belegt ist. Man muss diese Kürzel unter Tools -> Options -> Keymap ändern.

Nutzer deutscher Tastenlayouts kämpfen mit den Shortcuts, deren Keycodes sowieso per Umschalt / Shift zu erreichen sind (Komma, Semikolon, Stern) oder per AltGr (geschweifte und Eckige Klammern). Da muss man meistens die Zugriffs-Kürzel der Actions ebenfalls unter Tools -> Options -> Keymap anpassen.

flattr this!

Java Getriebe » NetBeans - December 22, 2011 02:06 PM
Eigene Einstellungen für die eigene RCP Anwendung

Erstellt man eine eigene Anwendung auf Basis der NetBeans Platform erstellt kommt man irgendwann unweigerlich an den Punkt das Resultat auch an die Endanwender verteilen zu wollen. Im Kontextmenü des Suiteprojekt liefert der Eintrag “Package as” alles was man dafür benötigt. Ein Problem gibt es nur, wenn man während der Entwicklung der eigenen Anwendung individuelle [...]

Java Getriebe » NetBeans - December 12, 2011 08:12 AM
“Organize Imports” in NetBeans 7.1

Die neue Version von NetBeans steht kurz vor der Veröffentlichung. Die passende Wiki-Seite mit den Neuerungen ist nun auch online. Am meisten freut mich, dass nun endlich eine “Organize Imports” Funktion direkt in NetBeans integriert sein wird. Mir gefällt das ziemlich gut und deswegen werde ich die Arbeiten an meiner eigenen Version wohl einstellen. Danke [...]

Java Getriebe » NetBeans - December 01, 2011 01:48 PM
Wie debugge ich einen Processor in NetBeans

Es ist schon nicht einfach einen eigenen Processor für Annotations zu schreiben, wenn man etwas Fehlerbehandlung einbauen möchte. Aber noch “schwieriger” ist es diesen Processor im Debugger betrachten zu können. Das Problem ist, dass sich die IDE im Grunde genommen selber debuggen muss. Zur IDE hat man in den seltensten Fällen ein Projekt, zu dem [...]

Java Getriebe » NetBeans - November 22, 2011 01:20 PM
@ServiceProvider in einem JavaSE Projekt

Ich bin im Moment auf einem Annotation-Trip. Die Dinger sind cool. Vor allem in Zusammenhang mit ihren Processor Implementierungen. NetBeans macht es in seinen neusten Versionen selbst vor. So cool die XML Layer Strukturen zur Laufzeit auch sind, so uncool sind sie in dem Quellen zu pflegen. Dank des LayerGeneratingProcessors ist es aber verdammt einfach [...]

Java Getriebe » NetBeans - November 10, 2011 10:14 AM
Ein Wrappermodul für ein JavaSE Projekt

Für eine NetBeans Rich Client Platform Anwendung ist es ein leichtes eine bestehende .jar-Datei in ein Modul zu kapseln. Das so genannte “Library Wrapper Module” steht im “New Project Wizard” zu Verfügung und man muss nur noch eine (oder mehrere) Java Archive auswählen, fertig. Den Rest erledigt die NetBeans IDE für uns. Das klappt prima, [...]

Java Getriebe » NetBeans - November 10, 2011 09:06 AM
Annotation Processor for Main Popup Menus (Geertjan’s Blog)

Ich hatte den Entwurf für einen eigenen Artikel schon begonnen. Aber Geertjan war diesmal schneller: Annotation Processor for Main Popup Menus (Geertjan’s Blog).

Java Getriebe » NetBeans - October 19, 2011 01:14 PM
NetBeans Suite als OmegaT Projekt exportieren

Meine Version der Übersetzungshilfe geht in die nächste Runde. Ich habe meinen “NetBeans Suite Translator” aktualisiert und im NetBeans Plugin Center hoch geladen. Die wichtigste Neuerung dabei ist ein Export aller Bundle Properties als OmegaT Projekt. Der Export ist eine erste Version die stark auf meine eigenen Bedürfnisse zugeschnitten ist und hat dementsprechend im Moment [...]

OlliN's » netbeans - August 09, 2011 12:19 PM
netbeans 7 update and the license agreement dialog

I’ve just updated NetBeans. The following dialog appeared:

License Agreement Dialog

How many people read those 85 263 lines of text carefully?

Java Getriebe » NetBeans - August 05, 2011 07:56 PM
Der Eclipse Code Formatter in NetBeans

Der Code Formatter in NetBeans ist ja ganz nett und stellt auch einen rudimentären Support dar um den Sourcecode nicht komplett “versauen” zu lassen. Aber so richtig viel kann der nicht. Andere Open Source Projekte wie Jalopy, jindent oder Jacobe sind entweder veraltet, nicht vollständig frei oder komplett auf kommerziell umgestellt. Ich vermisse in NetBeans [...]

Java Getriebe » NetBeans - July 26, 2011 02:04 PM
Ant-basierte Suite Projekte mit Jenkins erstellen

Auf dem letzten NetBeans Training wurde ich von Geertjan gefragt wie wir bei uns den Continuous Integration Server Jenkins dazu nutzen um unsere WZL Gear Toolbox automatisch generieren zu lassen. Das großen Problem ist, dass Jenkins zwar sehr einfach Maven Builds einbinden kann und zusammen mit Maven auch Suiteprojekte sehr einfach einzufügen ist aber für [...]

JNBB - Joschs NetBeans Blog - April 04, 2011 09:59 AM
BeanDev: New DZone Refcard for NetBeans 7.0 Platform

Hi!

The new updated Refcard #80 by Heiko Böck, Anton Epple, Miloš Šilhánek, Andreas Stefik, Geertjan Wielenga, and Tom Wheeler for the brand new NetBeans 7 Platform is published.

You can find many informations about the NetBeans Platform, a getting started intro, main features, NetBeans Platform modules,  NetBeans Platform APIs, reusable GUI components and  more.

In this Refcard, you are introduced to the key concerns of the NetBeans Platform so that you can save years of work when developing robust and extensible applications.

Six pages packed with many informations, download this Refcard #80 now!

JNBB - Joschs NetBeans Blog - April 01, 2011 09:04 AM
IDEDev: Bundle-Key Hyperlinks im Editor Quelltext

Moin!

Bin gerade mit 1001 Sachen beschäftigt und habe mein Blog etwas vernachlässigt. Aber einen kleinen Tipp habe ich gerade zur Hand. In einem älteren Blogeintrag erwähnte ich die Fähigkeit, dass NetBeans in den 7′er Dev-Builds Bundle Einträge in ein Code-Fold bringen kann. Es wird dann der Wert des Standard-Bundle angezeigt.

Es gibt aber noch ein nettes Feature. Man kann mit der Strg-Taste + Mausklick nun auch direkt zur Bundle-Datei zum Schlüssel springen. Es funktioniert genau so, wie man auch zu Klassen, Methoden und Variablen-Deklarationen springen kann.

Mit dem Klick wird die Bundle-Datei geöffnet und der Cursor auf den Schlüssel gesetzt. Wenn man nun die Tastenkombination Strg+1 drückt, wird diese Bundle Datei auch im Project Explorer selektiert (soweit man nicht sowieso eine automatische Selektion aktiviert hat).

Beste Grüße!

JNBB - Joschs NetBeans Blog - March 09, 2011 04:15 PM
JavaFXDev: Screen capture tool with 200 lines and 500ms startup time

Hi!

Here is my next test with the JavaFX 2.0 ea release. I’ve created a 200-liner to capture parts from the desktop. The “Snipper” detects mouse dragging and two different key strokes (Escape and the letter ‘A’). The captured picture is automatically stored in the user.home/snapshot path.

Before I start to explain the code, I show a small picture about the different scene graph nodes:

At the bottom is the Desktop (I use only the primary screen, but it’s possible to detect all additional screens). The stage is created by the JavaFX Launcher class. I modify the stage to a transparent style and fullscreen mode. The scene (embedded in the stage) captures the mouse events (button pressed, released and dragging). The scene itself has a transparent fill color and contains one group with three different nodes. In the KeyPane-Node I capture the key events. The node is focusable and transparent to mouse events (any mouse event sinks down to the scene). GlassPane is a node with a Shape created by the screen bounds with a rectangular hole. This hole is calculated by the mouse gestures from the user. At last I’ve a visual representation for the user interaction: a red rectangular lasso node.

Disclaimer: The solution here is based on the early access release through the JavaFX partner program. This “best practice” may change significantly between now and the final version. However, I’ll show only a concept, not compilable code.

Here the start up:

  @Override
  public void start(final Stage stage) {
    primaryStage = stage;
    Group group = new Group();
    Scene scene = new Scene(group);
    scene.setFill(Color.TRANSPARENT); // default is white
    scene.setCursor(Cursor.CROSSHAIR);

    stage.setStyle(StageStyle.TRANSPARENT);
    stage.setFullScreen(true);
    stage.setScene(scene);
    stage.setVisible(true);

    screenBounds = new Rectangle (
      Screen.getPrimary().getBounds().getWidth(),
      Screen.getPrimary().getBounds().getHeight()
    );

Nothing special. Only few notes: The Scene-fill must be transparent and the Screen class provides more than the primary screen. But this small example captures only from the primary screen.

I have a special helper class named Rebounder. This class creates and manipulates the lasso rectangle and calculates the shape with the hole for the GlassPane. The KeyPane needs the Rebounder for a fullscreen capture. The scene mouse handlers are call the rebounder with the current mouse points.

  class Rebounder {
    Rectangle lasso;
    double px;
    double py;
    Rebounder() {
      lasso = new Rectangle(0, 0);
      lasso.setFill(null);
      lasso.setSmooth(false);
      lasso.setStroke(Color.RED);
      lasso.setStrokeWidth(1);
      lasso.setStrokeType(StrokeType.OUTSIDE);
      lasso.setMouseTransparent(true);
      lasso.setVisible(false);
    }

    Rectangle start(double x, double y) {
      lasso.setX(x);
      lasso.setY(y);
      lasso.setWidth(0);
      lasso.setHeight(0);
      px = x;
      py = y;
      lasso.setVisible(true);
      return lasso;
    }

    Rectangle rebound(double x, double y) {
      lasso.setWidth(Math.abs(x - px));
      lasso.setHeight(Math.abs(y - py));
      lasso.setX(Math.min(x, px));
      lasso.setY(Math.min(y, py));
      return lasso;
    }

    Rectangle stop(double x, double y) {
      rebound(x, y);
      lasso.setVisible(false);
      return lasso;
    }

    boolean isStopped() { return !lasso.isVisible(); }

    Node getLasso() { return lasso; }

    Shape shapeBuilder(Rectangle r) {
      return r != null
        ? Path.subtract(screenBounds, r)
        : new Rectangle(screenBounds.getWidth(), screenBounds.getHeight());
    }
  }

In the constructor I create the lasso node. The three methods start(x,y), rebound(x,y) and stop (x,y) are called by mousePressed, mouseDragged and mouseReleased. The shapeBuilder-method returns a shape for the GlassPane.

Here are my mouse handlers:

    scene.setOnMousePressed(new EventHandler() {
      @Override public void handle(MouseEvent me) {
        glassPane.setShape(
          rebounder.shapeBuilder(rebounder.start(me.getX(), me.getY())), false);
      }
    });

    scene.setOnMouseDragged(new EventHandler() {
      @Override public void handle(MouseEvent me) {
        glassPane.setShape(
          rebounder.shapeBuilder(rebounder.rebound(me.getX()+1, me.getY()+1)), false);
      }
    });

    scene.setOnMouseReleased(new EventHandler() {
      @Override public void handle(MouseEvent me) {
        if ( !rebounder.isStopped() ) {
          capture(rebounder.stop(me.getX()+1, me.getY()+1));
        }
      }
    });

A very straight forward implementation.

Ok we miss the KeyPane and the GlassPane. The KeyPane is complete transparent, contains only a screen wide rectangle which is focusable and captures key events:

  class KeyPane extends Group {
    public KeyPane(final Stage stage, final Rebounder rebounder) {
      final Rectangle keyEventPane =
        new Rectangle(screenBounds.getWidth(), screenBounds.getHeight());
      keyEventPane.setFill(Color.TRANSPARENT);
      keyEventPane.setStroke(null);
      keyEventPane.setMouseTransparent(true);
      keyEventPane.setFocusTraversable(true); // for keyPressed events
      keyEventPane.setOnKeyPressed(new EventHandler() {
        @Override public void handle(KeyEvent key) {
          if (key.getCode() == KeyCode.VK_ESCAPE) {
            stage.setVisible(false); // == Close
          } else if (key.getCode() == KeyCode.VK_A) {
            capture(new Rectangle(screenBounds.getWidth()+1, screenBounds.getHeight()+1));
          }
        }
      });
      getChildren().add (keyEventPane);
    }
  }

In my GlassPane I’ve only the calculated shape and a small help text:

  class GlassPane extends Group {
    void setShape(Shape shape, boolean showInfo) {
      while (!getChildren().isEmpty()) {
        getChildren().remove(0);
      }
      if ( shape != null ) {
        double BLUE = 0.95;
        Stop[] stops = new Stop[] {
          new Stop(0.00, Color.color(BLUE, BLUE, 1, 0.3)),
          new Stop(0.2, Color.color(BLUE, BLUE, 1, 0.7)),
          new Stop(0.25, Color.color(BLUE, BLUE, 1, 0.5)),
          new Stop(0.4, Color.color(BLUE, BLUE, 1, 0.3)),
          new Stop(0.70, Color.color(BLUE, BLUE, 1, 0.7)),
          new Stop(1.0, Color.color(BLUE, BLUE, 1, 0.3)),
        };
        LinearGradient lg = new LinearGradient(0, 0, 1, 1, true, CycleMethod.NO_CYCLE, stops);
        shape.setFill(lg);
        shape.setMouseTransparent(true);
        shape.setStroke(null);
        getChildren().add(shape);

        if ( showInfo ) {
          Text info = new Text("'ESC' to leave the Snipper\n"
                        + "'A' to capture the whole screen\n"
                        + "Drag the mouse to capture a rectangle");
          info.setFill(Color.WHITE);
          info.setTranslateX(200);
          info.setTranslateY(60);
          info.setScaleX(2);
          info.setScaleY(2);
          info.setEffect(new DropShadow());
          info.setMouseTransparent(true);
          getChildren().add (info);
        }
      }
    }
  }

I fill the shape with a LinearGradient paint.

In the start method I stick all panes together:

    KeyPane keyPane = new KeyPane(stage, rebounder = new Rebounder());
    glassPane = new GlassPane();
    glassPane.setShape(rebounder.shapeBuilder(null), true);

    group.getChildren().addAll(new Node[] {keyPane, glassPane, rebounder.getLasso()});

Ok where is the heart of my Snipper application? The capture method?

The capture method is currently developed with the java.awt.Robot class. So we need to leave the JavaFX thread and dive into the EventQueue. But first we must hide the whole stage window to get an good image from the desktop. But don’t use stage.setVisible (false) (it closes the application). I resize the stage to a zero dimension. Here my capture method:

  public void capture(final Rectangle finished) {
    primaryStage.setWidth(0);
    primaryStage.setHeight(0);
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        if ( (((finished.getWidth()-1) * (finished.getHeight()-1) ) > 0.0d ) ) {
          try {
            Robot robot = new Robot();
            BufferedImage img = robot.createScreenCapture(
              new java.awt.Rectangle(
                (int)finished.getX(), (int)finished.getY(),
                (int)finished.getWidth()-1, (int)finished.getHeight()-1));
            File folder = new File (System.getProperty("user.home"), "snapshots");
            folder.mkdirs();
            File file = File.createTempFile("jfx2_screen_capture", ".jpg", folder);
            ImageIO.write(img, "jpg", file);
          } catch (Exception ex) {
            Logger.getLogger(Snipper.class.getName()).log(Level.SEVERE, null, ex);
          }
        }
        Platform.runLater(new Runnable() {
          @Override public void run() {
            glassPane.setShape(rebounder.shapeBuilder(null), true);
            primaryStage.setWidth(screenBounds.getWidth());
            primaryStage.setHeight(screenBounds.getHeight());
          }
        });
      }
    });
  }

With this few 200 lines I’ve created a very useful screen capture application. The start up time is incredible: Between the main method and the complete visible stage the JavaFX framework needs only 500ms on my one year old double-core notebook. The complete startup (double-click the jar) is under a second (hard to stop the time). I need only one AWT dependency to the Robot class. I hope this could be changed to increase the startup time (e.g. with the internal FXRobot class).

best regards,
Josh.

JNBB - Joschs NetBeans Blog - March 04, 2011 06:48 PM
JavaFXDev: NetBeans Platform with JavaFX 2.0ea

Hi!

Alan O’Leary shows in his blog a WebView integration in Swing. It is a not good documented feature, how to integrate JavaFX 2.0 controls into a swing application. But an integration is a main goal for the JavaFX 2.0 release.

As an enthusiastic NetBeans Platform/RCP developer and JavaFX partner, I work since two days to marriage JavaFX 2.0 and a NetBeans Platform Application. And yes, it works :-)

I’ve created a maven based platform application with a special starter Main.class. I need to launch the JavaFX toolkit system before any other module bootstrapping. The solution here is based on the early access release through the JavaFX partner program. This “best practice” may change significantly between now and the final version. However, I’ll show only a concept, not compilable code.

The solution behind the bootstrapping a NetBeans Platform is based on a FAQ by Tom Wheeler. My Main.class is a JavaFX Application class – I need this Application instance to get rid of from invoke exceptions. The created Stage object by the Launcher can be ignored.

public class Main extends Application{

  private static final String NB_MAIN_CLASS = "org.netbeans.core.startup.Main";

  public static void main(String[] args) throws Exception {
    // do whatever you need here (e.g. show a custom login form)
    System.out.println("Launch Java FX");
    long ms = System.currentTimeMillis();

    Launcher.launch(Main.class, args); // This is the main start up for JavaFX 2.0

    System.out.println("Launched Java FX in " + (System.currentTimeMillis() - ms) + "ms");

    // once you're done with that, hand control back to NetBeans
    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    Class mainClass = Class.forName(NB_MAIN_CLASS, true, classloader);

    Object mainObject = mainClass.newInstance();
    Method mainMethod = mainClass.getDeclaredMethod("main", new Class[]{String[].class});
    mainMethod.invoke(mainObject, (Object) args);
  }

  @Override
  public void start(Stage stage) {
    // Nothing to do, forget the stage....
  }
}

The Main class is in a standard Java archive. This JAR file and all the JavaFX files must be in the platform/core folder.

At runtime all the core-Libs are available to the whole NetBeans Platform modules (and plugins). For the compiler I need a special dependency to the runtime:

<dependency>
 <groupId>sun.javafx</groupId>
 <artifactId>tools</artifactId>
 <version>2.0.0</version>
 <scope>system</scope>
 <systemPath>${basedir}/../../corelauncher/mainlauncher/src/main/lib/jfxrt.jar</systemPath>
</dependency>

The system path depends on your project structure.

Now I can access all the JavaFX classes in a NetBeans module.

Please note, any scene construction needs to be build up in the JavaFX event queue thread. This is not the EventDispatcher-Thread from Swing!

My favorite call to jump in the JavaFX event thread is: Toolkit.getDefault().defer (Runnable) javafx.application.Platform.runLater (Runnable). But the Toolkit class is in a com.* package. IMHO in the future we get an official way to do this.

The creation of a WebView component is pretty similar to the sample from Alan. But I don’t need a stage object:

    Platform.runLater(new Runnable() {

      @Override
      public void run() {
        group = new Group();
        Scene scene = new Scene(group);

        browser = new WebView(new WebEngine());
        browser.getEngine().addChangeListener(PropertyReference.WILDCARD, new ChangeListener() {

          @Override
          public void handle(Bean paramBean, PropertyReference paramPropertyReference) {
            if ("title".equals(paramPropertyReference.getName())) {
              EventQueue.invokeLater(new Runnable() {
                // Jump to Swing EventDispatcher...
                @Override
                public void run() {
                  BrowserTopComponent.this.setDisplayName(browser.getEngine().getTitle());
                }
              });
            }
            if ("url".equals(paramPropertyReference.getName())) {
              EventQueue.invokeLater(new Runnable() {
                // Jump to Swing EventDispatcher...
                @Override
                public void run() {
                  String url = browser.getEngine().getUrl();
                  tfUrl.setText(url);
                  addHistory(url);
                }
              });
            }
          }
        });

        group.getChildren().add(browser);
        group.setScaleX(0.8d);
        group.setScaleY(0.8d);
        Reflection r = new Reflection();
        r.setTopOffset(8);
        group.setEffect(r);

        scene.setFill(javafx.scene.paint.Color.BLACK);
        browser.setWidth(panel.getWidth());
        browser.setHeight(panel.getHeight());

        panel.setScene(scene);
      }
    });

    panel.addComponentListener(new ComponentAdapter() {
      @Override
      public void componentResized(ComponentEvent e) {
        Platform.runLater (new Runnable() {
          // Jump from Swing-EventDispatcher to the JavaFX Thread:
          @Override
          public void run() {
            browser.setWidth(panel.getWidth());
            browser.setHeight(panel.getHeight());
          }
        });
      }
    });

I’ve added some useful listeners. Please aware the switches between different threads (Swing and JavaFX).

The result is a beautiful NetBeans Platform application with an embedded JavaFX 2.0 WebView:

PS.: I like the Twitter message from Dean Riverson: “Ok, I call a moratorium on rotating and reflecting WebView…” (origin).  -

I have to write 100 times:

I’ll never rotate and reflect WebView again, I’ll never rotate and reflect WebView again,I’ll never rotate and reflect WebView again,I’ll never rotate and reflect WebView again,I’ll never rotate and reflect WebView again,I’ll never rotate and reflect WebView again,I’ll never rotate and reflect WebView again,I’ll never rotate and reflect WebView again,I’ll never rotate and reflect WebView again,I’ll never rotate and reflect WebView again, …

JNBB - Joschs NetBeans Blog - February 28, 2011 08:33 AM
Training: Lingen/Ems – FH Osnabrück – NetBeans Platform Certified Training

Moin!

Letzten Donnerstag und Freitag war es mal wieder soweit, ein sehr intensives und hoffentlich für die Teilnehmer spannendes Training ist zu Ende gegangen.

In zwei Tagen haben wir (Geertjan und ich) mehr als 20 Teilnehmern, an der Fachhochschule Osnabrück Lingen/Ems, die NetBeans Plattform in einem Trainings-Kurs nahe gebracht. Es hat uns besonders gefreut, dass alle Anwesenden bis 18:00 am Freitag durchgehalten haben. Und nein, die Tür war nicht abgeschlossen ;)

Die Inhalte waren, wie immer, nicht ohne. Windows System API, Lookups, System File System, Nodes, Explorer und Visual Library waren die Kernthemen. Durch all diese Themen zog sich natürlich: “Modulare Softwareentwicklung”. So wurde den Studenten schnell klar, dass es ohne Theorie nicht geht. Es schien auch einige überrascht zu haben, dass es hier nicht nur darum ging, in der NetBeans Plattform ein paar Swing-Programme zu entwickeln. Wir vermitteln immer dazu – völlig vom Produkt losgelöst – wichtige Paradigmen der modularen Entwicklung von Software. Darunter fallen Punkte wie Separation of Concern, Single Responsible Principle, Komponentenorientierung, Kohäsion und Entkopplung.

Mit vielen eingeschobenen Workshops haben wir dieses Thema von der trockenen Grundlage auf das praktische Feld verschoben.

Für einen besonders guten Einstieg in die NetBeans Platform API haben alle Teilnehmer des Kurses eine DZone NetBeans Platform Refcard erhalten. Ich hoffe, dass sich diese 2-seitige DIN-A3 Karte nun immer neben dem Bildschirm befindet.

Ich war begeistert, dass einige Studenten sich am Freitag Abend zu kleinen Entwicklergruppen zusammengeschlossen haben, um erste Projekte in der NetBeans RCP Welt zu realisieren. Ich freue mich auf die Ergebnisse!

Ganz großen Dank an die Organisation des Events und kulinarische Betreuung. Es gab immer genug Kaffee und andere Getränke und vor allem ein fantastisches Buffet. Da kommen wir doch gerne wieder!

Auf unseren edu-Seiten gibt es unsere Präsentationen zum nachlesen und nacharbeiten: Trainings-Präsentationen. Ein sehr wichtiger Anlaufpunkt ist auf jeden Fall die Platform-Seite: platform.netbeans.org.

Fragen im Nachgang werden über die NetBeans Platform Certified Students Mailingliste abgehandelt. Natürlich stehen auch die englisch- und deutschsprachigen NetBeans Foren zur Verfügung.

Beste Grüße!

––

JNBB - Joschs NetBeans Blog - February 18, 2011 11:28 AM
IDEDev: NetBeans 7 Beta2 und spezielles zu Git und JUnit

Moin!

Gestern kündigte ich ja die Beta2 zur NetBeans 7.0 IDE an. Zwei Dinge hatte ich da unterschlagen, die hier noch einer besonderen Erwähnung bedürfen.

Git

In der Beta2 kann man nun (ohne Plugin) git als Versionierungssystem nutzen. Der Git Plan im Wiki gibt schon einen recht guten Überblick, was funktioniert und worauf man noch warten muss.

Folgende Features sollten funktionieren:

Bis zum Finale ist noch einiges zu tun, gerade für das Distributing steht noch was aus (Repository Clone, Pull, Push, Fetch), die Vervollständigung der Branching und Merging Tools (Merge from Branch, Export uncommited changes (Local changes), Apply Patch) sowie Search history of files und eine Blame Integration.

JUnit

Trotz der verwirrenden und unterschiedlichen, teils negativen, Meldungen wird JUnit natürlich weiter von NetBeans unterstützt. Allerdings muss JUnit in Zukunft extra aus dem Plugin-Center geladen werden. Fest integriert ist nur ein Bridge-Modul zu JUnit. Unabhängig zu rechtlichen Vorgaben hat das in Zukunft vielleicht sogar Vorteile, wenn es um die Integration von anderen Unit-Tools geht (z.B durch eine einheitliche API).

Ich hoffe, dass heute der Download nicht so überlastet ist wie gestern. Viel Spaß mit NetBeans 7.

Beste Grüße,
Josch.

JNBB - Joschs NetBeans Blog - February 17, 2011 04:26 PM
IDEDev: NetBeans 7 Beta2 is out

Moin!

Ab heute ist NetBeans 7.0 Beta 2 verfügbar zum Download.

Die Highlights sind:

  • JDK 7 Unterstützung
  • Integration des WebLogic Servers
  • Verbesserungen, um eine Oracle Datenbank einzubinden
  • Glassfish 3.1 Unterstützung
  • Maven 3 Support
  • Remote URL-JavaDoc Support (JavaDoc muss nicht mehr lokal installiert sein)
  • Neuer GridBagLayout Customizer
  • Für JavaEE CDI, REST Dienste und Java Persistence Verbesserungen, zudem Bean Validation
  • JSF Component Bibliothekenunterstützung,  PrimeFaces ist mit an Board
  • Verbesserte EL-Unterstützung in JSF
  • HTML5
  • JSON
  • PHPDoc-Generierung
  • PHP Rename Refactoring und Safe delete Refactoring
  • PHP 5.3 Alias-Unterstützung
  • C/C++ kann nun besser Binär-Libs importieren
  • C/C++ Projekt-Typ mit Quelltexten auf Remote-Servern
  • Endlich für PHP User: Word-Wrap im Editor
  • Der Profiler wurde aufgebohrt
  • Verbesserte Überprüfung von externen Änderungen an Quelltexten außerhalb der IDE

Auch die NetBeans Platform bekommt Erweiterungen:

Ich hoffe nur die Maven Artifacts werden für Beta2 zeitnah freigegeben, am SNAPSHOT teste ich ungern.

Die aktuellen Release-Notes (en) stehen natürlich auch zur Verfügung. Sehr umfangreich ist, wie immer, die NewAndNoteworthy Seite.

Beste Grüße,
Josch.

JNBB - Joschs NetBeans Blog - February 03, 2011 02:14 PM
BeanDev: native2ascii Datei Konverter. NetBeans Plugin Idee

Moin!

Ich habe mal wieder was für meine Ideensammlung: Plugins, die ich schon immer mal programmieren wollte, aber nie die Zeit dazu fand.

Heute der native2ascii Konverter für Dateien, die man im Project-Explorer markiert hat. Kontextmenü mit folgenden Befehlen:

  • To ASCII…
  • Reverse to native…
  • Native to native…

To ASCII wandelt von einem vorgegebenen Encoding in die \u-Notation. Reverse to native fragt nach eine Encoding, in der die Datei konvertiert werden soll und Native to native fast beide Transformationen zusammen.

Vielleicht kann man das dem existierenden kenai.com Projekt NATIVE2ASCII hinzufügen? Ich muss mal Hlavki fragen und mit einem hg-clone einen Prototypen schreiben… wenn ich mal wieder Zeit habe.

Beste Grüße,
Josch.

JNBB - Joschs NetBeans Blog - February 01, 2011 05:00 PM
JavaDev: Java auf dem Desktop – Come on Oracle!

Moin!

Eines der massiv unterschätzten Themen ist Java auf dem Desktop. Immer wieder höre ich von Entwicklern, dass Web-Oberflächen, Java EE, Server und Backend-Development die Domäne für Java sei.

Ich denke mal, man muss da ein wenig über den Tellerrand hinaus schauen. Sicherlich ist Java nicht die 1a Desktop Sprache, weil für die vielen netten Gimmiks einfach die nativen OS spezifischen Schnittstellen fehlen. Aber mal ehrlich, warum sollte eine so robuste Programmiersprache auf dem Desktop nichts taugen? Seit 15 Jahren entwickele ich Java-Desktop-Applikationen zunächst für eine kurze Zeit mit AWT, dann seit Swing 1.1 raus war, Swing-Applikationen.Ich plagte mich davor mit der Microsoft Welt und auch mit 4GL Sprachen rum. Aber kein Framework hat mir so viele Freiheiten und so eine stabile Grundlage gegeben, wie es Java mit Swing und den ganzen zusätzlichen Bibliotheken konnte.

Zwar spricht man heute bei Java vom Cobol des einundzwanzigsten Jahrhunderts, aber auch das ist völlig unterschätzt. Denn neben der Masse an Programmen, die Java (wie ehemals Cobol) trägt, gibt es doch eine Weiterentwicklung die ganz sicher keine Stagnation erfährt.

Geertjan hat in seinem Blog selbst mal wieder eine Lanze für den Desktop Einsatz von Java gebrochen und da ein Zitat von James Gosling ausgegraben, das ich hier gerne wiederhole:

If I had to say I’m jaded it’s sort of about the fact that people’s attention is so focused on the web. And it feels to me like that’s 10% of the computing landscape. If you look at what goes on in, say, biology. Huge, huge computational problems in biology. The people who do protein folding up in San Francisco, which is kind of everybody there, that stuff is really really cool. It sure doesn’t show up on anybody’s “cool” radar but, you know, all modern medicine research, it’s computers. Right, it’s computing. And none of that has any magic pixie dust coolness on it and modern materials. It’s, again, all computer simulation and all the rest of that and the computing behind that and the rest of that, most people don’t even think of it as computing because it’s something that a scientist does. Talk to most people in physics, they spend most of their time writing code, not doing physics experiments. And it’s just a cool world filled with thousands and thousands of different things and it feels like the web is only a corner of it.

Hinter dem ganzen Internet mit all seinen Online-Applikationen, Webservices, Shops, Social Media, Blogs, Twitter-Diensten, Online-Spielen usw. verbirgt sich eine Welt in der Computer auch für etwas anderes gebraucht werden. Eine Welt im Business-Bereich, eine Welt in der Forschung und Wissenschaft, eine Welt in der Produktentwicklung, eine Welt von Künstlern, Designern, Entwicklern und Autoren. Welten, wo Programme auf browserbasierten Oberflächen nur die zweite Wahl sind.

Wenn man sich das mal klar macht, kann man Goslings Aussage verstehen, wenn er vom Internet nur als eine 10% Ecke der Computerwelt spricht. Gefühlt wird jeder immer sagen, das ist mehr: Das Internet füllt mein Leben als Computer-Nerd sicher zu 90% aus. Aber die produktive Entwicklungsarbeit geschieht immer noch auf dem Desktop. Sicher, Server- und Webgestützt, aber Desktopprogramme schlagen Browser-Ajax-Anwendungen immer noch in ihrer Bedienbarkeit, Reaktion und Funktionalität.

Auch die NetBeans-Plattform als klassisches RCP Framework zeigt mit seinen ganzen existierenden Derivaten, dass der Desktop eben nicht eine verarmte Softwarelandschaft ist. Im Gegenteil, da wo massive Robustheit, gute Wartbarkeit und flexible Schnittstellen zu anderen tausenden Frameworks benötigt werden, ist Java auf dem Desktop, nach meinem Dafürhalten, die zentrale Plattform.

Was tatsächlich allein schon auf der NetBeans Plattform existiert, zeigt eindrucksvoll die Liste auf netbeans.org. Hier ein paar Screenshots:

und Hundert mehr. Diese Applikationen sind ausschließlich auf der NetBeans Plattform entstanden und stellen keine vollständige Liste dar. Dazu gibt es wieder unzählige reine Swing-Applikationen und Anwendungen, die auf dem Eclipse RCP Framework basieren.

Alles Anwendungen die stabil und robust in den Firmen dieser Welt werkeln. Vielleicht unbeachtet und nicht immer sichtbar in dem omnipräsenten Internet, aber wichtig für Entwicklung und Wirtschaft.

Aber die Entwickler stöhnen, sie vermissen den Anschluss zu den ganzen schönen Gimmicks, die Silverlight, Adobe Air und andere Frameworks bieten, um Desktop-Anwender das 110%-Feeling zu geben. Unabhängig davon, ob man das wirklich braucht, vielleicht gibt es mit JavaFX for Swing eine Lösung, die Desktop-Apps auch für den privaten Desktop wieder attraktiver macht. Vielleicht schaffen wir es SwingX und Labs-Komponenten verstärkt in das JDK aufzunehmen. Vielleicht wird es endlich eine HTML-Browser-Komponente in den Standard-Runtimes geben. Eventuell sieht man die Notwendigkeit, dass Java einfacher mit nativen Schnittstellen arbeiten kann, sei es zum OS, sei es zu Hardware-Schnittstellen.

Ich denke schon, dass es da eine Zukunft gibt. Die geballte Wucht der vorhandenen Applikationen kann sowieso nur eine Richtung vorgeben. Ich hoffe nur, dass die Macht des Faktischen auch bei Oracle erhört wird.

Beste Grüße,
Josch.

JNBB - Joschs NetBeans Blog - January 31, 2011 08:53 PM
BeanDev: BetterIconView in NetBeans Plattform aufgenommen

You can find an English version on NetBeans Zone.

Moin!

Bei den NetBeans Certified Trainings übernehme ich regelmäßig den Teil Nodes & Explorer Views (pdf). Dabei stelle ich regelmäßig die unterschiedlichen Views vor. Dafür habe ich ein kleines Demo-Programm geschrieben. Das Programm zeigt allerdings nicht nur die Vorzüge der Views, sondern auch die Probleme mit deren Darstellungen. Gerade das IconView glänzt nicht gerade mit schöner Optik. Ich hatte aus der Not eine Tugend gemacht und gerade für das Training eine eigene Implementation vorbereitet. Damit kann man den Teilnehmern sehr leicht zeigen, wie man eigene Views für die Nodes-API erstellen kann.

Dieses BetterIconView hat es Toni Epple angetan und er zeigte es im Dezember letzten Jahres Jaroslav Tulach. Er hatte gestern Zeit gehabt, meine paar Codezeilen zu nehmen, um damit das alte IconView zu ersetzen.

Wie man an dem Beispiel des alten IconView erkennen kann, funktioniert so einiges nicht. Fokusrahmen fehlt, Größenberechnung in der Höhe ist zu groß und die Nodes überlappen sich bei langen Texten.

Meine neue Implementation ist zwar recht einfach und nicht im jeden Detail perfekt, aber sicherlich um einiges besser, als die alte Version in der NetBeans Plattform.

Hier ein Screenshot mit drei selektierten Nodes und dem korrekten Fokusrahmen-Verhalten:

Den Quelltext kann man hier einsehen. Es ist wirklich sehr einfach ein ListView zu erweitern, um ein neues IconView zu erzeugen, deswegen werden da keine großen Überraschungen auftauchen.

Man sollte nur berücksichtigen, dass man in Views nicht mit dem Nodes aus dem Modell des Entwicklers arbeitet, sondern mit optimierten Wrappern. In einem Renderer (hier ListCellRenderer) konvertiert man das übergebene Value-Objekt in ein Node mit der Hilfsklasse Visualizer:

Node node = Visualizer.findNode(value);

Hat man diese Hürde geschafft, kann man alles realisieren, was Swing zu bieten hat. Der Kreativität sind also keine Grenzen gesetzt. Ich möchte da zum Beispiel auch auf Geertjans Blog verweisen, wo er die Visual Library als Explorer-View nutzt.

Beste Grüße,
Josch.

JNBB - Joschs NetBeans Blog - January 27, 2011 12:50 PM
IDEDev: NetBeans IDE 7 ohne Ruby On Rails Unterstützung

Moin!

Leider erreichte mich heute über die Mailingliste eine nicht sehr schöne Nachricht. Die Ruby On Rails Entwicklung wird nicht mehr vom NetBeans Core Team unterstützt.

Tinuola Awopetu von Oracle beschreibt es so:

After thorough consideration, we have taken the difficult step to discontinue support for Ruby on Rails in the NetBeans IDE.

Dabei werden zwei Hauptgründe genannt. Erstens:

Java SE 7 and Java Development Kit 7 (JDK 7) are the next major releases of the Java SE platform, which Oracle is committed to deliver in 2011. A key objective of the NetBeans IDE has always been to offer superior support for the Java platform. To maintain that objective and capitalize on the JDK 7 release themes–multi-language support, developer productivity and performance–it is necessary that our engineering resources are committed to a timely and quality release of NetBeans IDE 7.0.

Das Entwicklerteam will sich auf den Fokus JDK 7 konzentrieren, damit NetBeans 7 eine 100% Unterstützung mit dem Release bieten kann. Damit setzt Oracle (wie auch schon in der Vergangenheit angekündigt wurde), verstärkt auf die Java-Entwicklung. Ruby on Rails kann da nicht in der gewünschten Qualität einfließen.

Oracle sieht aber nicht nur einen stärkeren Fokus bei Java, sondern sieht Ruby on rails überhaupt im Abwind. Das ist der zweite Grund:

Second: Although our Ruby support has historically been well received, based on existing low usage trends we are unable to justify the continued allocation of resources to support the feature.

Ab dem 27. Januar 2011 wird Ruby on rails aus den Dev-Builds verschwinden. Entwickler aus der Community, die Ruby on Rails weiter unterstützen wollen, werden auf die NetBeans Ruby Support Seite verwiesen.

Feedback zu dieser Entscheidung wird ebenfalls gewünscht. Oracle verweist dazu auf die Mailinglisten/Foren, Twitter oder den direkten Kontakt zum NetBeans IDE Team.

Beste Grüße,
Josch.

JNBB - Joschs NetBeans Blog - January 26, 2011 03:50 PM
JavaDev: Transparente Swing-Buttons

Moin!

Nur ein kleines Appetithäppchen. Wenn man transparente JButtons benötigt, weil die dahinter liegenden JPanels Grafiken oder Farbverläufe haben, benötigt man besonders beim Windows-System Look&Feel einen Trick.

Zunächst reicht es nicht, nur setOpaque (false) zu verwenden. Es wird trotzdem ein Hintergrund als Füller gemalt. Die ui-Klasse ist so leider programmiert. Man kann aber eine transparente Hintergrundfarbe setzen:

public class TransparentButton extends JButton {
  public TransparentButton () {
    super();
    setBackground (new Color (255, 255, 255, 0));
    setOpaque (false);
  }
}

Wenn man bei (halb-) transparenten Hintergrundfarben das setOpaque (false) vergisst, hat man übrigens sehr unschöne Back-Buffer Effekte. D.h. die Optimierungen im Swing-Framework verursachen dann unschöne zerhackte Grafikeffekte. In Kombination funktioniert es aber super.

Beste Grüße,
Josch.

JNBB - Joschs NetBeans Blog - January 17, 2011 08:21 AM
JavaDev: Installer und Launcher für Java Programme

Moin!

Die Frage kommt immer wieder mal, deswegen wollte ich hier eine kleine Liste an Programmen erfassen, die Java-Programme in native Betriebssysteme integrieren, Installer erzeugen oder das Starten vereinfachen.

Ich habe dafür drei Gruppen. Die Launcher sind Executables, die Java-Programme wie native Programme starten lassen. Das ist üblicherweise nur unter Windows notwendig. Linux und Mac behandeln Java-Programme wie alle anderen Executables. Die nächste Gruppe wäre Installer. Diese Werkzeuge erzeugen aus Java-Projekten Installationspakete, die es dem Anwender ermöglichen per Kommandozeile oder Assistenten Java-Programme zu installieren oder später zu deinstallieren. Die letzte Gruppe behandelt Packer. Darin fasse ich Tools zusammen, die 3rd-Party-Libs in ein JAR zusammenfassen, JARs komprimieren oder Klassen so umbenennen, so dass eine Quelltextwiederherstellung sehr schwer gemacht wird (Obfuscator).

Ich würde mich freuen, wenn ein paar Anregungen und Erfahrungsberichte rein kommen würden. Für die NetBeans Platform gibt es schon integrierte Installer für Windows, Linux, MacOS und Solaris sowie eine WebStart Variante. Außerdem einen Pack200 Tool für den Installer. Da braucht man für die meisten Fälle keine externen Tools.

Hier also eine Liste, die ich schon so gesammelt habe:

Launcher

  • WinRun4J
    • Lizenz: CPL
    • OS: Windows
    • Integration: Kommandozeile, Eclipse Plugin
    • Ein Executable mit native Bindings, Windows DDE-Zugriff, konfigurierbarem Icon, INI-Datei für Startparameter, Dienste-Wrapper, Systemlog-Unterstützung und Konsolenmodus.
    • Es unterstützt auch das Packaging von 3rd-Party Bibliotheken.
    • Soweit ich das sehen kann, hat man mindestens immer ein JAR und eine Java-Umgebung muss installiert sein.
  • Launch4j
    • Lizenz: BSD und MIT
    • OS: Alle Java-Plattformen (Ziel bleibt aber Windows)
    • Integration: Kommandozeile, Ant, Maven, GUI (Wizard)
    • Launch4j erzeugt eine Windows Executable-Datei, die alle JARs, native Bibliotheken und sogar ein Embedded JRE enthalten kann.
    • Es unterstützt eigene Icons für die Exe, JAR’s werden nicht beim Start extrahiert, unterstützt auch Konsolenanwendungen,

Installer

  • Open Installer (Crossplatform Installer)
    • Lizenz: CDDL 1.0
    • OS: Alle Java-Plattformen
    • Integration: Kommandozeile, NetBeans Platform Installer
    • Ich erwähne den Open Installer hier, weil dieser in der NetBeans Platform integriert ist und als Installer für den Glassfish verwendet wird. Ansonsten würde ich als Entwickler die Finger davon lassen, weil das Projekt extrem schlecht dokumentiert ist. Am besten den Quelltext anschauen, wenn man eine hohes Maß an Interesse und Leidensfähigkeit hat.
  • Antigen (Ant Installer Generator)
    • Lizenz: k/a
    • OS: Alle Java-Plattformen
    • Integration: Ant, Kommandozeile, (evtl. Maven)
    • Erzeugt aus Ant-Scripts einen grafischen Installer
    • Alle Programmbestandteile werden in einem JAR-Installer gepackt. Eine Java Runtime muss auf dem Zielrechner existieren.
  • InstallJammer
    • Lizenz: GPL mit “Special Exception“, darf kommerziell genutzt werden
    • OS: Multiplattform (tck/tcl), Windows 98, ME, 2000, XP, 2003, Vista, 2008, Linux, FreeBSD, Solaris, HP-UX, AIX
    • Integration: Kommandozeile, GUI
    • InstallJammer ist eine mächtige OpenSource Lösung die einen nativen Installer mit umfangreicher Buildumgebung anbietet. Der Installer ist nicht auf Java-Programme beschränkt. JRE wird vom Installer nur gesucht, aber nicht bei Bedarf installiert. Man kann aber das JRE wohl über Actions mitinstallieren.
    • Mehrsprachigkeit, Multiplattform, Nativer Installer im OS-Look, Benutzerdefinierte Aktionen, Installer-Profile (Kommandozeile, GUI, Silent, usw), GUI-Bearbeitung der Assistenten-Panels, Themen, Deinstallationsroutinen.
    • Umfangreiche Dokumentation
  • Install4j
    • Lizenz: Kommerziell (Windows Single ab 600€, Multiplatform Single ab 1700€, nach oben offen…)
    • OS: Win32, Win64, Linux RPM, MacOS, Unix
    • Integration: Ant, Kommandozeile, GUI
    • Dieser kommerzielle Installer bietet einen GUI oder Kommandozeileninstaller (auch Silent), JRE-Pacakging oder Detection, GUI und Scriptsprache, Mehrsprachigkeit, Dienste-Unterstützung, eigenes Icon und sehr vieles mehr.
  • Advanced Installer for Java Freeware Edition
    • Lizenz: Kommerziell, Freeware Edition
    • OS: Windows
    • Integration: Kommandozeile, GUI
    • Die Freeware Edition bietet einen MSI Installer Generator für Java Programme mit UAC Unterstützung, Registry-Zugriff, 32bit und 64bit, Scripting über XML-Konfiguration.
    • JRE Bundling ist nicht in der Free Edition, Custom Icon ist nicht möglich.
    • Feature Matrix

Packer

  • one-jar
    • Lizenz: Proprietär, OpenSource, BSD?
    • OS: Alle Java-Plattformen
    • Integration: Ant, Maven
    • Erzeugt aus mehreren JAR-Bibliotheken eine einzelne ausführbare JAR-Datei
    • Unterstützt auch native Bibliotheken, die während des Starts in das Dateisystem entpackt werden.
  • ProGuard (Obfuscator)
    • Lizenz: GPL
    • OS: Alle Java-Plattformen
    • Integration: Kommandozeile, Ant
    • Verändert sprechende Bezeichner (z.B. Paket und Klassennamen) in kompilierten JARs in verkürzte oder randomisierte Namen, um die Wiederherstellung von bearbeitbaren Quelltext zu erschweren.
    • Unterstützt viele Plattformen (Java 1.1 bis 6, ME, Android)
  • pack200 JAR Packager
    • Lizenz: Oracle License
    • OS: Alle Java-Plattformen
    • Integration: Kommandozeile
    • Ein Tool des Java SE SDKs von Oracle, dass seit Java 5 JAR Dateien besonders effizient packen kann.
    • Der Einsatz sind üblicherweise webbasierte Java-Anwendungen, damit diese im Download möglichst wenig Bandbreite verwenden
  • Ant Script für die NetBeans IDE
    • Lizenz: k/a
    • OS: Alle Java-Plattformen
    • Integration: Ant, NetBeans IDE
    • Es handelt sich dabei nicht um ein Programm, sondern ein Ant-Target-Script zum Erstellen von Single-JARs. Der verlinkte Blogeintrag beschreibt, wie man in NetBeans dieses Script integrieren kann.

flattr this!

JNBB - Joschs NetBeans Blog - January 12, 2011 06:16 AM
IDEDev: Hudson Continious Integration (CI) wird Jenkins

Moin!

Kohsuke Kawaguchi hat es gestern veröffentlicht. Der Name Hudson CI ist gestorben. Der Continious Integration Server soll in Jenkins (CI?) umbenannt werden.

Wie Kohsuke in einer Nachricht schreibt, konnte Oracle, trotz einer ein Monat langen Kommunikation, nicht davon überzeugt werden, dass der Name Hudson CI in einer “neutralen Organisation” gut aufgehoben wäre.

The central issue was that we couldn’t convince Oracle to put the trademark under a neutral party’s custody (such as Software Freedom Conservancy), to level the playing field.

Er führt aber auch aus, dass Oracle Pläne mit Hudson verfolgen will, die der aktuellen Entwicklung des CI-Servers nicht entspricht. Dazu gehöre auch eine erheblich formalisiertere Projektstruktur, Änderungen in der Architektur und das verstärkte Einbinden von 3rd-Party Abhängigkeiten.

Aside from this, Oracle wanted a broader change to the way the Hudson project operates, including a far more formal change review process, architectures, 3rd party dependencies and their licenses, and so on.

[...]

All of those still might not have been a show-stopper if we felt that there is a genuine trust between us, but in this case, we just failed to build such a relationship, even after a month long conversation.

Als Konsequenz soll das Projekt in Jenkins umbenannt werden. Dieser Name ist erneut ein “Buttler”-Name aus dem englischen Sprachraum und soll aktuell von keinem anderen Software-Projekt beansprucht sein.

So in the end, we’d like to propose the community that we regrettably abandon the name “Hudson” and rename to “Jenkins” — it’s another English-sounding butler name that doesn’t collide with any software project as far as I can tell.

Das Proposal für die Namensänderung wurde im Hudson Lab veröffentlicht:

The Proposal

First, we rename the project – the choice for a new name is Jenkins, which we think evokes the same sort of English butler feel as Hudson. We’ve already registered domains, Twitter users, etc for the new name, and have done our best to verify that there are no existing trademarks which would conflict with it. Kohsuke will be registering the trademark for Jenkins in his name, with the intent of transferring ownership of the trademark to the umbrella of the Software Freedom Conservancy once the Jenkins project has been admitted to it (which, I should add, is very much our plan, hopefully in their next round of new projects in a few months – we’ve already had preliminary contacts with SFC). We still invite Oracle to remain involved with the project, on equal terms with all other contributors, and hope they’ll take us up on this invitation.

[...]

Das Proposal umfasst aber mehr als nur eine Namensänderung. Außerdem soll die Infrastruktur des Projektes komplett von Oracle weg verschoben und ein Governance Board eingerichtet werden.

Ich würde mich freuen, wenn der CI Server auch in Zukunft in der NetBeans IDE unterstützt wird. Hudson nutze ich schon seit einiger Zeit, um zentralisierte Maven- und Ant-Builds durchzuführen.

Noch besser wäre es, Oracle würde mit seinem verbleibenden Hudson Projekt sich nicht zu weit von Jenkins entfernen. Konkurrenz belebt zwar das Geschäft, aber in diesem Fall wäre der Nutzen für die Anwender fraglich.

Beste Grüße,
Josch.

JNBB - Joschs NetBeans Blog - January 10, 2011 05:35 PM
BeanDev: Plugins schneller testen

Moin!

Wenn man kleine schnelle Testumgebungen für NetBeans IDE-Plugins haben möchte, sollte man sich diese FAQ anschauen.

DevFaqNetBeansFullHack

Can I test changes to the IDE without going through the license check and so on?

Ja, tatsächlich geht das. Mit einem kleinen Parameter netbeans.full.hack auf true gesetzt, werden einiges an Dialogen, Test und Remotezugriffen (Auto Update Center, Maven Index) deaktiviert:

  • Auto Update background check (to see if updates are available); you can still use AU via Tools > Plugin Manager
  • prompting about still-running tasks when shutting down
  • license dialog
  • import of old user directory
  • IDE registration dialog
  • dialog suggesting that you submit usage statistics
  • welcome screen displayed by default and RSS feed refreshed
  • blocking dialog when some modules could not be loaded
  • use of ~/NetBeansProjects/ for newly created projects (java.io.tmpdir will be used instead)
  • resizing gesture submit dialog (SubmitStatus.resize)
  • weekly Maven repository indexing (can be configured in Options dialog)
  • long package name for default group ID in new Maven project (test used instead)

So können Plugin-Tests und automatisierte Tasks mit Aufruf der NetBeans IDE ohne störende Dialoge durchgeführt werden.

Beste Grüße,
Josch.

JNBB - Joschs NetBeans Blog - January 06, 2011 05:29 PM
IDEDev: SevenBeans NetBeans IDE Plugin für Windows7 Feeling

Moin!

Das Plugin SevenBeans bringt für die NetBeans IDE das 100% Native-Feeling auf Windows 7 Betriebssystemen.

Mit diesem Plugin erhält man zu dem NetBeans-Taskbar Icon eine

  • Jumplist (spezielles Kontextmenü per rechter Maustaste),
  • Iconoverlays (d.h. ein Build wird in der Taskbar als Badged Icon dargestellt),
  • Den hellgrünen Fortschrittsbalken im Taskbar-Icon,
  • Minivorschau der geöffneten Tabs, wenn man mit der Maus über das Taskbar-Icon fährt
  • und einen Konfigurationsdialog in den Options, um alle neuen Features ein- oder auszuschalten.

SevenBeans basiert auf der Technologie von J7Goodies, ein Framework um Swing-Anwendungen mit solchen Features auszustatten.

Eine Jumplist wird so zum Kinderspiel:

DestinationList albums;
albums.addFile("C:\\Users\\Alex\\My Pictures\\Bachelor Party.alb");
albums.addFile("C:\\Users\\Alex\\My Pictures\\Family.alb");
albums.addFile("C:\\Users\\Alex\\My Pictures\\Flowers.alb");

DestinationList tasks;
tasks.addTask("/camera", "Import from camera", cameraIconPath);
tasks.addTask("/scan", "Scan a photo", scannerIconPath);

JumpList jumpList;
jumpList.appendRecentCategory();
jumpList.appendCustomCategory("Albums", albums);
jumpList.appendTasks(tasks);
jumpList.save();

Viele weitere Beispiele finden sich auf der J7Goodies Homepage.

Schön ist es, dass das Plugin für NetBeans schon fertig ist. Die aktuelle Version kann hier heruntergeladen werden.

Beste Grüße,
Josch.

JNBB - Joschs NetBeans Blog - January 04, 2011 10:37 PM
IDE: Wichtigstes Ereignis 2010?

Moin!

JAXenter hat wieder eine (der sehr häufigen) Quickvote-Umfragen. Aktuell geht es um das wichtigste Java-Ereignis 2010.

Klar, dass die Sun-Übernahme durch Oracle inzwischen über 60% bekommen hat, aber es wird auch gefragt, ob nicht vielleicht NetBeans 6.9 das wichtigste Ereignis gewesen ist? Hmm :-)

Zumindest 2% erreicht NetBeans 6.9 zur Zeit, Eclipse e4-Linie nur 1%.

Ich persönlich finde neben 6.9 und Snoracle noch das Maven 3 Release als sehr wichtiges Ereignis an.

[UPDATE]

Das Ergebnis steht fest, 274 Teilnehmer (nicht sehr repräsentativ).

Nur ein kurzer Kommentar: Die NetBeans 6.9 Version bekam (ggü. den anderen wichtigen Ereignissen) gute 5%. Klar, Sun-Übernahme durch Oracle bekommt 56%. Eclipse e4 allerdings nur 0%. Die JDK7/8 Roadmap bekam 5% und ist m.E. abgestraft. Auch Oracle hat es bis jetzt nicht geschafft mehr Schwung in die Entwicklung zu bringen. Altlast durch Sun? Man könnte noch die Sprachenvielfalt für Java mit 6% dazu addieren, um das Ergebnis zu beschönigen. Aber na ja…

Beste Grüße,
Josch.

OlliN's » netbeans - August 11, 2009 08:35 PM
Netbeans, Ivy und Spring 3.0.0M4

Ich programmiere gerade eine kleine Web-Applikation und möchte dazu die neuen REST-Features vom Spring-Framework benutzen. Bis gestern habe ich mir dazu in Netbeans ein Webprojekt gebaut und dann ganz artig alle notwendigen Bibos von Hand dem Projekt hinzugefügt. Gestern wurde nun der Milestone 4 von Spring 3.0.0 veröffentlicht und ich wollte mir nicht noch einmal die Arbeit machen.

Also musste ein Tool her, welches mir alle notwendigen Jar’s auflösen kann und in mein Projekt einhängt. Da ich nicht so ein rechter Fan von Maven bin, habe ich wieder einmal die Gelegenheit genutzt und Ivy ausprobiert. Als IDE verwende ich Netbeans – also muss ein Plugin für Netbeans her, welches mir die Arbeit mit Ivy innerhalb der IDE vereinfacht. Also schnell mal bei ivybeans vorbeigeschaut. Version 1.1 unterstützt jetzt auch Webprojekte – Schick! Also schnell das Plugin installiert und ein Repository gesucht in welchem die 3.0.0M4 Version von Spring liegt. Nach ein wenig Suchen habe ich dann herausgefunden, dass es ein Spring-eigenes Repository in Amazon S3 gibt (S3Browse ist übrigens ein guter Browser für S3).

Dann habe ich mir noch die folgenden zwei Dateien für die Konfiguration von Ivy im Projektverzeichnis meines Webprojektes angelegt:

Ablageort der Konfigurationsdateien von Ivy

Hier der Inhalt der Dateien:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation=
                   "http://ant.apache.org/ivy/schemas/ivy.xsd">
    <info module="WebApplication2" organisation="WebApplication2" revision="1.0"/>
    <configurations>
        <conf name="compile"/>
        <conf name="runtime"/>
        <conf name="compile-test"/>
        <conf name="runtime-test"/>
    </configurations>
    <dependencies>
        <dependency org="org.springframework" name="spring-webmvc" rev="3.0.0.M4" conf="" />
    </dependencies>
</ivy-module>
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<ivysettings>
    <settings defaultResolver="chained"/>
    <resolvers>
        <chain name="chained">
            <ibiblio name="maven2" m2compatible="true"/>
            <ibiblio name="s3.maven.springframework.org" m2compatible="true" root="http://s3.amazonaws.com/maven.springframework.org/milestone/"/>
        </chain>
    </resolvers>
</ivysettings>

Dann im Projekt Ivy aktivieren. Dazu mit der rechten Maustaste auf das Projekt und in den Ivy-Einstellungen das Häkchen machen und die zwei Dateien auswählen:

Ivy in Netbeans aktivieren

Dann noch das Projekt zwingen sich die Jars zu holen:

Force Resolve

Und siehe da… alle Jar’s und Sourcen (wenn im Repository) sind da:

Mit Ivy geholte Abhängigkeiten (Jar's und Sourcen)

Mit der rechten Maustaste kann man nun ganz einfach die Abhängigkeiten entfernen, die man nicht braucht.

Bernhard's Weblog - June 12, 2009 10:14 PM
Webtest wrapped as maven project

I have wrapped the canoo webtest project as a maven project. By default canoo webtest is shipped with ant script, only. My intention is to avoid downloading the webtest jars manually, but using the maven dependency, and downloading mechanism for downloading the webtest jars. The webtest jars are expressed as maven dependencies.

Directory Layout

The webtest maven project has following directory layout

etc/webtest
webtest resources except jars
lib
maven-ant-task jar
src/assembly
maven assembly for building a bin distribution of this project
src/dist
ant, and groovy scripts packed into the bin distribution
src/test/resource
webtestLog4j.properties log4j configuration
src/test/webtest
webtest scripts as ant, and groovy scripts
build.xml
ant script for running webtests using webtest dependencies defined in pom.xml
pom.xml
maven pom, goals for running webtest, and building bin distribution
build-maven-antrun.xml
ant script invoked from maven antrung plugin

Running Webtest

There are two ways to run webtest:

Launch mvn test, or run ant; both uses the webtest dependency expressed in the maven pom.xml.

"mvn test" uses internally maven antrun, and build-maven-antrun.xml to run the tests.

"ant" uses build.xml, and maven-ant-task jar for running the webtests.

Both ways store the webtest results in target/webtests-result.

Bin distribution

Running "mvn assebly:assembly" a zip file is created in the target directory. This zipfile stores all webtest jars in the directory lib. After unzipping the file, you can run the webtests by launching "ant".

Have fun!

APIDesign - Blogs - May 18, 2009 05:43 PM
API Podcast #2: Reentrancy

Listen to podcast #2: to learn about our take on Swing and its poor reentrancy. Find out what it may mean for your own API design and especially Runtime_Aspects_of_APIs that you create. Learn to fight with that problem by maximizing the declarative nature of your API. --JaroslavTulach 17:43, 18 May 2009 (UTC)

APIDesign - Blogs - May 12, 2009 07:50 PM
API PodCast #1

Listen to this: ! It is almost a year since we (me and Geertjan) started our regular API Design Tips podcasts. They used to be part of larger NetBeans podcasts, however recently I needed some promotion material for TheAPIBook and I decided to extract the API Tip parts. I am glad I can offer these sketches to you. Enjoy podcast #1. --JaroslavTulach 19:50, 12 May 2009 (UTC)

Bernhard's Weblog - April 20, 2009 06:34 PM
First Experience With Grape

This blog summarizes my first experiences with groovy's Grab annotation.

As I have downloaded groovy 1.6.1, I have become aware of the Grab annotation.

Using Grab

I defined a simple groovy script which shall use apache's commons-lang abbreviate method from org.apache.commons.lang.StringUtils#abbreviate.

Thus I defined a script, like:


import org.apache.commons.lang.StringUtils

@Grab(group='commons-lang', module='commons-lang', version='2.4')

def strings = ['Hello', 'Groovy', 'AVeryLongWord!', 'A simple sentence']
strings.each { String aString ->
    println "$aString: ${StringUtils.abbreviate(aString)}"
}
        
Sadly this script, did not work, I experienced following exception stack trace:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed,
...\groovy\Grab1_1.groovy: 1: unable to resolve class org.apache.commons.lang.StringUtils
 @ line 1, column 1.
   import org.apache.commons.lang.StringUtils
   ^

1 error
        

Probably I have not read the doumentation close enough, put defining a method after the @Grab annotation, the problem, disappeared.

Thus the script becomes now:


import org.apache.commons.lang.StringUtils

@Grab(group='commons-lang', module='commons-lang', version='2.4')

def abbreviate(String s) {
    StringUtils.abbreviate( s, 10 )
}

def strings = ['Hello', 'Groovy', 'AVeryLongWord!', 'A simple sentence']
strings.each { String aString ->
    println "$aString: ${abbreviate(aString)}"
}
        

Running this script the commons-lang jar is downloaded, and the script prints:


Hello: Hello
Groovy: Groovy
AVeryLongWord!: AVeryLo...
A simple sentence: A simpl...
        

Reusing Maven Repository

I really like the @Grab feature, as it saves me from downloading additional jars manually. As I was using maven already, maven has downloaded some jars already into my local repository at the ~/.m2/repository directory. So I wonder if it is possible to tell grapes to reuse these jars.

The solution I use today, is reusing the maven jars from my local repository, grapes copies these jars over to the local grapes repository at ~/groovy/grapes. Thus this solution just saves me some bandwith and time, as accessing my local maven repository is surly faster than reaching out to the offical maven repositories at ibiblio.

The grapes documentation states that you can define the ivy settings by specifying ~/.groovy/grapeConfig.xml. So I created this file, which is by the way the default setting used by grapes:


<ivysettings>
  <settings defaultResolver="downloadGrapes"/>
  <resolvers>
    <chain name="downloadGrapes">
      <filesystem name="cachedGrapes">
        <ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy-[revision].xml"/>
        <artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
      </filesystem>
      <!-- todo add 'endorsed groovy extensions' resolver here -->

      <ibiblio name="codehaus" root="http://repository.codehaus.org/" m2compatible="true"/>
      <ibiblio name="ibiblio" m2compatible="true"/>
      <ibiblio name="java.net2" root="http://download.java.net/maven/2/" m2compatible="true"/>
    </chain>
  </resolvers>
</ivysettings>
        

Now I wonder how to add my local maven repository, I defined an addtion ibiblio entry, defining as root my local maven repository, so the grapeConfig.xml became:


<ivysettings>
  <settings defaultResolver="downloadGrapes"/>
  <resolvers>
    <chain name="downloadGrapes">
      <filesystem name="cachedGrapes">
        <ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy-[revision].xml"/>
        <artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
      </filesystem>
      <!-- todo add 'endorsed groovy extensions' resolver here -->

      <ibiblio name="local" root="file:${user.home}/.m2/repository/" m2compatible="true"/>

      <ibiblio name="codehaus" root="http://repository.codehaus.org/" m2compatible="true"/>
      <ibiblio name="ibiblio" m2compatible="true"/>
      <ibiblio name="java.net2" root="http://download.java.net/maven/2/" m2compatible="true"/>
    </chain>
  </resolvers>
</ivysettings>
        

By adding my local maven repository I'm able to reuse my local maven repository. You can add your local maven proxy, too by adding an additional ibiblio entry in the ~/.groovy/grapeConfig.xml file.

Have fun!

Bernhard's Weblog - February 24, 2009 11:13 PM
First experiences with jasperreports, ireport, and barcode

This blog summarizes my first experienced with iReport-nb-3.1.2.

As a first example I have created a report for the XML result of webtest.

ireport-webtest screenshot

Next I have created a report for the Junit XML.

ireport-junit screenshot

As I become familiar with jasperreport, and iReport, I want to evaluate, if it is possible to print a barcode with jasper-report. As I have downloaded jasperreports-3.1.4, too, there are two barcode samples in the demo folder. I run them standalone, and I wanted to view them in the iReport tool.

Especially the barcode folder shows a nice sample. I open the BarcodeReport.jrxml in the iReport application, but there are some classloader problems, as there are some sample specific classes needed for this sample.

As iReport allows to defined extra jars in the Options|iReport dialog, I add two jars there.

The first jar is the barbecue-1.5-beta1.jar from the barcode/lib directory. The second jar - I have created from the barcode/build/component classes.

Next I restart iReport, and after the restart the additional jars are active, and I'm now able to view the barcodes as defined by the BarcodeReport.jrxml.

ireport-barcode screenshot

Have fun!

Bernhard's Weblog - January 27, 2009 11:08 PM
Using unit-testing code using Netbeans' Repository class

This blog is about unit-testing using netbeans Repository. I'm using the solution described below on Netbeans 6.5.

In my netbeans plugin-project I have code like


        Repository r = Repository.getDefault();
        FileSystem fs = r.getDefaultFileSystem();
        FileObject root = fs.getRoot();
        FileObject baseFolder = FileUtil.createFolder(root, "nb-xpath/data");
        final String foName = "history.xml";
        FileObject historyFileObject = baseFolder.getFileObject(foName);
...
        File file = FileUtil.toFile(historyFileObject);

When you try to unit-test this code, the file instance is null.

Thus I read UsingFileSystemsMasterfs, and I installed the masterfs in the UnitTestLibary. By selecting "UnitTestLibraries|Add UnitTest Dependency", selecting "Show Non-API Modules, and searching for "masterfs", and selecting the Module "Master Filesystem".

The nbproject/project.xml results :


...
            </module-dependencies>
            <test-dependencies>
                <test-type>
                    <name>unit</name>
                    <test-dependency>
                        <code-name-base>org.netbeans.modules.masterfs</code-name-base>
                        <compile-dependency/>
                    </test-dependency>
                </test-type>
            </test-dependencies>
            <public-packages/>
...

But this does not help! The file instance is still null!

After examing the Repsitory sources, I came to the conclusion that if there is no Repository registered in META-INF/services, the MemoryFileSystem is used. Thus I need a way to register some repository class.

Thanks to InitializationOfDefaultLookup, MockServices can help.

I wrote a simple Repository implementation, and register it as Repository implementation to use:

The Repository implemenation for my test-case:


    public static final class MyRepositoryIOTempDir extends Repository {

        private static final long serialVersionUID = 20090127L;

        public MyRepositoryIOTempDir() {
            this(new LocalFileSystem());
        }

        private MyRepositoryIOTempDir(LocalFileSystem lfs) {
            super(lfs);
            // make the java.io.tmpdir the root of this lfs
            final String tmpDir = System.getProperty("java.io.tmpdir");
            assertNotNull(tmpDir);
            File rootFile = new File(tmpDir);
            assertTrue(rootFile != null);
            assertTrue(rootFile.canRead());
            assertTrue(rootFile.canWrite());
            assertTrue(rootFile.isDirectory());
            try {
                lfs.setRootDirectory(rootFile);
            } catch (Exception ex) {
                AssertionError ae = new AssertionError("Cannot set root directory");
                ae.initCause(ex);
                throw ae;
            }
        }
    }

My test-case setUp registers this class like:


    @Before
    public void setUp() {
        MockServices.setServices(MyRepositoryIOTempDir.class);
        // assert that for lookup(Repository.class) MyRepositoryIOTempDir is returned
        final Repository repositoryInstance = Lookup.getDefault().lookup(Repository.class);
        assertTrue(repositoryInstance instanceof MyRepositoryIOTempDir);
    }

Now my tests can run the above code, and the file instance is not null!

Now, that I removed the Master Filesystem dependency from the Unit Test Libraries, my test-cases still work, so it seems to me that when you use File instances retrieved via Repository, you don't need the masterfs test dependency, so far.

Have fun!

Seapegasus Blog - January 21, 2009 04:42 AM
Kostenloses Java-EBook (Neue Auflage)

Die achte Auflage des Java-Kurses "Java ist auch eine Insel" ist draußen: Ein praxisorientiertes Buch nicht nur für diejenigen, die beim Brennball in der Schule immer als letztes gewählt wurden! (He... woher weiss der das?)

Das Buch erwähnt (empfiehlt) auch IDEs (z.B. auch den NetBeans GUI Builder), bleibt aber insgesamt Tool-neutral. Das hat den Vorteil, dass man das Gelernte überall einsetzen kann -- und welchem IDE-Menüpunkt das Beschriebene eventuell entspricht, findet man recht schnell raus. Anscheinend ist geplant, die achte Auflage nach und nach für JDK 7 zu aktualisieren.

Für 50 Euro bekommt man das komplette Buch auf toten Bäumen ausgedruckt -- plus eine DVD mit JDK 6, NetBeans, Eclipse, Beispielprogramme, Aufgaben und Lösungen, und sogar (hä?) ;) ein paar C/C++ Openbooks.
Das Javainsel-Ebook ist kostenlos online, und es gibt's es auch als 14MB Download zum Mitnehmen.

APIDesign - Blogs - December 12, 2008 09:06 AM
2009: The Year of Annotations

As I noted recently, I see the year 2009 as the year of annotations. The NetBeans project is about to rely on them more heavily. Finally! We've been waiting for that for ages, but finally we can compile with JDK 1.6 JavaC and we can use compile time annotation processors. As a result we can replace our layer based registrations with annotations and benefit from compile type checking, code completion, from having the registrations in the same place as the code that is being registered, etc. Also we can offer our API users simple looking annotations and let associated annotation processors do more advanced and more effective processing. As a result the developers have simple API to deal with, while actual registration hidden behind can be as effective as possible, even at the cost of complexity, but without compromises to reliability (as the complexity is kept in the processing infrastructure, not exposed to API users).

The other project related to annotations that we are likely to incorporate during 2009 is our extended use of Annotations for Software Defect Detection. This is heavily based on the JSR 305, yet until it is stable we do not want to expose such unstable API to users of our stable APIs (more on that in Chapter 10, in section Beware of Using Other APIs). As such we are going to create our own annotations (still recognizable by FindBugs and co.). The hope is that our annotation will stay compatible even if the underlaying JSR 305 slightly changes. Please find our current patch and comment here or in the issue 137437.

Last project that deals with annotations is developed by our editor hints guru Jan Lahoda - its aim is to bring complex refactoring to masses! How? Why? We have observed that using @Deprecated annotation is good hint to help your API users recognize that some part of your API is obsolete and shall no longer be used, however that in no way helps users of your API with converting their code to new, non-deprecated style. We have a solution: Use Code Transformation Annotations! Dear [API] writers, let's adopt these annotations and use them in your API! They are completely standalone (read more), lightweight and we are ready to incorporate feedback of everyone interested in the project. Indeed, my plan is to bring these easy to use and flexible refactorings to NetBeans soon, hopefully for version 7.0.

So these are my three annotation related projects. I find them quite exciting and I cannot wait to see them being used. Annotations are here to simplify life of API users and developers. As soon as we have them, we will have full right to call the year 2009 the year of annotations!

Listen to our podcast or download it.

Name (required):

Website:

Comment:

--JaroslavTulach 09:06, 12 December 2008 (UTC)

Seapegasus Blog - November 19, 2008 09:42 AM
NetBeans6.5_de

Wie Ihr sicher schon gesehen habt, ist NetBeans IDE 6.5 (Download) draußen. :) Aber wo ist die deutsche Community-Lokalisierung? Im Sprachen-Menü sind nur die 100%-fertigen aufgelistet (Chinesisch etc). Um die Community-Lokalisierungen wie Deutsch, Franzöisch, Spanisch, Italienisch, Polnisch, u.a. runterzuladen, klickt Ihr "More Languages..."

Der Direktlink ist: NetBeans Multilingual Download

Welche Module sind übersetzt? Auf der Statusseite seht Ihr, dass die gesamte Basis-IDE (Platform, Profiler, Versionsverwaltung), und auch Java SE, C/C++, PHP, Profiler, und Ruby, fertig sind. Das sind stolze 52%! Wir arbeiten noch an Java EE/Web App, Java ME, Groovy, SOA/XML.

Dank dafür an das ganze Team vor allem an Christian P. und Peter H.! Sobald die Lieferung bei mir ankommt, schick ich Euch das neue TranslatedFiles-T-Shirt. :)

Wie kann ich Übersetzungsfehler melden?

Bernhard's Weblog - October 28, 2008 11:15 PM
Xhtmlrenderer plus Groovy's SwingBuilder

Today I integrated groovy's SwingBuilder into xhtmlrenderer.

Xhtmlrenderer is a pure-Java library for rendering arbitrary well-formed XML (or XHTML) using CSS 2.1 for layout and formatting, output to Swing panels, PDF, and images.

I downloaded the release flyingsaucer-R7final, and integrated Groovy's SwingBuilder as object tag element. I used the ElementFactory, as outlined in the svg-demo delivered as xhtmlrenderer demo; now I can write groovy SwingBuilder scripts inside the XHTML page, like:


...
            </p>
            <h2>header.one.
            <div style="border: 1px solid red; margin: 15px; text-align: left;">
                <object type="text/groovy"><![CDATA[
import net.miginfocom.swing.MigLayout
import net.miginfocom.layout.LC
import net.miginfocom.layout.AC
import net.miginfocom.layout.CC

/**
 * A script expected to run in SwingBuilder#build
 *
 * It demonstrates defining the layout using LC, AC objects.
 */
final LC layC = new LC().fill().wrap();
final AC colC = new AC().align("right", 0).fill(1, 3).grow(100, 1, 3).align("right", 2).gap("15", 1);
final AC rowC = new AC().index(6).gap("15!").align("top").grow(100, 8);

final def migLayout = new MigLayout( layC, colC, rowC )
panel(layout: migLayout) {
    label("Last Name")
...

The resulting panel looks, like:

Well, that's just the first step, I still face some problems with layout the groovy panel, according its parent panel. You will notice the problem in the screenshot, as the grey area is smaller then the div's red border.
But maybe I'll find some time to solve this, too.


Have fun!

Seapegasus Blog - October 20, 2008 07:19 AM
Handelsreisende mit NetBeans im Gepäck

Geertjan hat ein interessantes Interview mit "unserem" Aljoscha Rittner über dessen neue Kundendatenverwaltung gemacht. Die Anwendung stellt die Kundenstandorte auf einer annotierten Landkarte dar (inklusive z.B. Radarfallen), und ein Handelsvertreter oder Geschäftsmensch lässt sich damit die optimale Route anzeigen, um auf seiner Fahrt so viele Kunden wie möglich abzuklappern. Sehr schön mit den NetBeans-Platform-APIs implementiert, inklusive Hilfesystem und Assistenten, davon kann man viel lernen.

Auf Englisch ist das Interview als Porting a Sales System to the NetBeans Platform auf der NetBeans Zone erhältlich. Alle Antworten auf Deutsch gibt es zusätzlich als PDF. Lest auch Joschs neuste Platform-Erkenntnisse in seinem Blog.

PS: Herzlichen Glückwunsch zum 10. Geburtstag, NetBeans!

Bernhard's Weblog - October 05, 2008 03:00 AM
Webapplications using shared classloader

<p> The last week I was trying share a classloader among different web applications. </p> <p> So, first a short description of the problem described in this blog. <br> </p> <p><br> </p> <p>In the near future I will have to deal with a bunch of similar web-applications. The web-application may be grails applications, they may be appfuse-light web applications. So I assume that about ten web-applications shall be get deployed, on an application server, like oc4j (10.1.3), and jboss 4.2.2. <br> </p> <p><br> </p> <p> One simple option is to deploy each web application with the full range for needed jars. <br> </p> <p>For a very simple grails application that's about 17 MB. The same application without all the jars shrinks down to 254 KB. <br> </p> <p>For a simple appfuse-light web application the numbers are 15 MB, and 241 KB without the WEB-INF/lib jars. </p> <p><br> </p> <p>Thus I was trying to find a way to deploy the reduced-size web applications, instead of the full-blown web applications. <br> </p> <p>Beside deploying smaller-sized web applications, shall be faster, I'm hoping that the class-loader memory-consumption of each application is smaller. </p> <p><br> </p> <p>For OC4J I successfully defined a shared-classloader, and when deploying the shrinked web application, I defined that this application shall use already defined shared library. <br> </p> <p>The shared classloader definition in conf<span style="font-family: Courier New;">/server.</span>xml<span style="font-family: Courier New;"> </span>for grails-1.0.3 looks like this: </p> <pre><code> &lt;shared-library name="grails" version="1.0.3"&gt;<br> &lt;code-source path="ant-launcher.jar"/&gt;<br> &lt;code-source path="ant.jar"/&gt;<br> &lt;code-source path="antlr-2.7.6.jar"/&gt;<br> &lt;code-source path="cglib-nodep-2.1_3.jar"/&gt;<br> &lt;code-source path="commons-beanutils-1.7.0.jar"/&gt;<br> &lt;code-source path="commons-cli-1.0.jar"/&gt;<br> &lt;code-source path="commons-collections-3.2.jar"/&gt;<br> &lt;code-source path="commons-dbcp-1.2.1.jar"/&gt;<br> &lt;code-source path="commons-fileupload-1.1.1.jar"/&gt;<br> &lt;code-source path="commons-io-1.4.jar"/&gt;<br> &lt;code-source path="commons-lang-2.1.jar"/&gt;<br> &lt;code-source path="commons-logging-1.1.jar"/&gt;<br> &lt;code-source path="commons-pool-1.2.jar"/&gt;<br> &lt;code-source path="commons-validator-1.3.0.jar"/&gt;<br> &lt;code-source path="dom4j-1.6.1.jar"/&gt;<br> &lt;code-source path="ehcache-1.3.0.jar"/&gt;<br> &lt;code-source path="ejb3-persistence.jar"/&gt;<br> &lt;code-source path="grails-cli-1.0.3.jar"/&gt;<br> &lt;code-source path="grails-core-1.0.3.jar"/&gt;<br> &lt;code-source path="grails-crud-1.0.3.jar"/&gt;<br> &lt;code-source path="grails-gorm-1.0.3.jar"/&gt;<br> &lt;code-source path="grails-spring-1.0.3.jar"/&gt;<br> &lt;code-source path="grails-test-1.0.3.jar"/&gt;<br> &lt;code-source path="grails-web-1.0.3.jar"/&gt;<br> &lt;code-source path="grails-webflow-1.0.3.jar"/&gt;<br> &lt;code-source path="groovy-all-1.5.6.jar"/&gt;<br> &lt;code-source path="hibernate-annotations.jar"/&gt;<br> &lt;code-source path="hibernate-commons-annotations.jar"/&gt;<br> &lt;code-source path="hibernate3.jar"/&gt;<br> &lt;code-source path="hsqldb-1.8.0.5.jar"/&gt;<br> &lt;code-source path="jaxen-1.1-beta-11.jar"/&gt;<br> &lt;code-source path="jdbc2_0-stdext.jar"/&gt;<br> &lt;code-source path="jstl-2.4.jar"/&gt;<br> &lt;code-source path="jta.jar"/&gt;<br> &lt;code-source path="junit-3.8.2.jar"/&gt;<br> &lt;code-source path="log4j-1.2.15.jar"/&gt;<br> &lt;code-source path="ognl-2.6.9.jar"/&gt;<br> &lt;code-source path="oro-2.0.8.jar"/&gt;<br> &lt;code-source path="oscache-2.4.1.jar"/&gt;<br> &lt;code-source path="sitemesh-2.3.jar"/&gt;<br> &lt;code-source path="spring-2.5.4.jar"/&gt;<br> &lt;code-source path="spring-binding-2.0-m1.jar"/&gt;<br> &lt;code-source path="spring-test.jar"/&gt;<br> &lt;code-source path="spring-webflow-2.0-m1.jar"/&gt;<br> &lt;code-source path="spring-webmvc.jar"/&gt;<br> &lt;code-source path="standard-2.4.jar"/&gt;<br> &lt;code-source path="xercesImpl.jar"/&gt;<br> &lt;code-source path="xpp3_min-1.1.3.4.O.jar"/&gt;<br> &lt;code-source path="xstream-1.2.1.jar"/&gt;<br> &lt;/shared-library&gt;<br></code></pre> <p>For JBoss I deployed the grails applications inside a sar application. First I defined in the deployment directory a directory grails-1.0.3.sar. Inside this directory I created the file META-INF/jboss-service.xml, like:</p> <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br>&lt;!--<br> JBoss Grails 1.0.3<br> <br> $Id: jboss-service.xml 63100 2007-05-16 18:02:32Z bdecoste $<br>--&gt;<br>&lt;server&gt;<br> &lt;loader-repository&gt;<br> org.grails:archive=grails-1.0.3.sar<br> &lt;loader-repository-config&gt;java2ParentDelegation=false&lt;/loader-repository-config&gt;<br> &lt;/loader-repository&gt;<br>&lt;/server&gt;<br><br></code></pre> <p> Next I copied all the grails jars into the directory grails-1.0.3.sar. Moreover I created a directory named more-apps. I deployed the grails applications without the grail-1.0.3 distributed jars in the directory more-apps. </p> <p>Summing up the JBoss directory structure is </p><pre><code> ----grails-1.0.3.sar | ... more grails-1.0.3 jars | ejb3-persistence.jar | grails-cli-1.0.3.jar | grails-core-1.0.3.jar | grails-crud-1.0.3.jar | ... more grails-1.0.3 jars +---META-INF | jboss-service.xml \---more-apps grails-app-1.war ... more grails web applications </code></pre> <p> Both shared jar solutions for oc4j, and jboss worked for the grails-applications so far. <br></p><p><br></p><p>I'm not quite sure, if removing the jars from the the web applications, and creating some shared class loader does really improve either the memory-consumption, or the redeployment speed of the web applications. Do you have any similar ideas, or experiences, hosting a high number of web applications using the same jars? </p> <p><br></p><p>Have fun!</p>

Bernhard's Weblog - October 04, 2008 09:52 PM
Grails Deployment Issues

I experienced an interesting problem with a grails-application.

The operating team noticed me that the grails-web application, is not deployed, after a restart of the tomcat application server, and the db-server.
After inquiring the details about the restart sequence I came to the conclusion that following scenario happened:

  1. The machine hosting tomcat, and the db was rebooted
  2. The tomcat application server was restarted
  3. The grails-application tried to restart, but failed as the db was not up and running, yet
  4. The db was restarted

As the db was started after tomcat the grails was not started successfully inside of tomcat.

The operating team launched the tomcat-manager, and restarted the grails-application manually, and voila the grails-application started successfully.

Now I tried to find a solution that the operating team does not have to restart the grails-application manually.

This leads me to the question what db-accesses are performed by a grails-application, when the grails-application is started.

I come to the following two db-accesses:
  1. If now hibernate-dialect is specified explicitly, grails looks up the jdbc meta-data to find the database, to set the hibernate dialect
  2. Regardless of the hibernate dialect, grails accesses the jdbc meta-data again to set the lob-handler

Now if the grail-application shall succeed even if no db is available, you have to avoid these two db-access, as they surely fails if no db is available, yet.

You can avoid the first db-access by specifying the hibernate dialect, explicitly in the grails-app/conf/DataSource.groovy, like:
dataSource {
    pooled = true
    driverClassName = "org.hsqldb.jdbcDriver"
    username = "sa"
    password = ""

   dialect = 'org.hibernate.dialect.HSQLDialect'
}

The second db-access is hard-coded into grails org.codehaus.groovy.grails.orm.hibernate.support.SpringLobHandlerDetectorFactoryBean. To avoid this db-access you have to replace this class by your own class, and configure it as spring-bean in grails-app/conf/resource.xml, or grails-app/conf/resource.groovy.

I wrote a simple preconfigurable MySpringLobHandlerDetectorFactoryBean :

package org.mycompany.orm.hibernate.support;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.jdbc.support.lob.OracleLobHandler;

/**
 * A simple LobHandler detector which does not access the dataSource for
 * detecting the appropriate LobHandler.
 * <p>
 * You must set the dbname explicitly, this has the advantage that no
 * db-access is needed at startup time. Hence the application starts even if
 * the database is not available at startup-time.
 * <p>
 * You this class by configuring a spring bean instance having the
 * id <code>lobHandlerDetector</code> in the grails spring configuration
 * <code>conf/spring/resources.xml</code>, like:
 * <code><pre>
 * <bean id="lobHandlerDetector" class="org.mycompany.orm.hibernate.support;.orm.hibernate.support.MySpringLobHandlerDetectorFactoryBean">
 * <property name="databaseProductName" value="Oracle"/>
 * </bean>
 * </pre></code>
 * @author HuberB1
 */
public class MySpringLobHandlerDetectorFactoryBean implements FactoryBean, InitializingBean {

    private final static Log log = LogFactory.getLog(MySpringLobHandlerDetectorFactoryBean.class);
    private static final String ORACLE_DB_NAME = "Oracle";
    private LobHandler lobHandler;
    private String databaseProductName;

    public void setDatabaseProductName(String databaseProductName) {
        this.databaseProductName = databaseProductName;
    }

    public Object getObject() throws Exception {
        return this.lobHandler;
    }

    public Class getObjectType() {
        return LobHandler.class;
    }

    public boolean isSingleton() {
        return true;
    }

    public void afterPropertiesSet() throws Exception {
        if (this.databaseProductName == null) {
            throw new IllegalStateException("DatabaseProductName is not set!");
        }

        final String dbName = this.databaseProductName;
        log.info("Using dbName " + dbName);

        if (ORACLE_DB_NAME.equals(dbName)) {
            this.lobHandler = new OracleLobHandler();
        } else {
            this.lobHandler = new DefaultLobHandler();
        }

    }
}

I added a bean configuration for an Oracle DB in conf/spring/resourcex.xml:

<bean id="lobHandlerDetector" class="org.mycompany.orm.hibernate.support;.orm.hibernate.support.MySpringLobHandlerDetectorFactoryBean">
<!--property name="databaseProductName" value="Other"/-->
<property name="databaseProductName" value="Oracle"/>
</bean>

Now with this simple MySpringLobHandlerDetectorFactoryBean, and specifying the hibernate dialect explicitly. The grails-application starts successfully even if no db is available. Of course the user will not be able to view any db-content, as long as the db is not available.

But the operating team does not have to fiddle around with any restart-sequence, and they don't have to restart the grails-application manually, neither.

Have fun!

Bernhard's Weblog - October 04, 2008 07:33 PM
EJB3-SpringBeanAutowiringInterceptor

<p> This blog is about using <code>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</code>. The spring 2.5.4 documentation states that this interceptor can be used for injecting spring-beans into ejb3 instances. </p> <p> My environment setup is: </p> <ul> <li>JVM 1.5 </li> <li>JBoss 4.2.2.GA </li> <li>Springframework 2.5.4 </li> </ul> <p> My first attempt was not very successful as I experienced some wired ClassLoader exceptions. I analysed the problem and came to the conclusion that the problem is that spring uses the thread context class loader by default. </p> <p> I must admit that I was not trying to inject the spring-beans into a simple stateless ejb, but into an mdb, triggered by the quartz resource adapter. The stacktrace goes like this: </p> <pre><code> 2008-05-20 17:40:20,423 ERROR [DefaultQuartzScheduler_Worker-6] org.quartz.core.JobRunShell : Job default.job.0.1211297867763 threw an unhandled Exception: java.lang.RuntimeException: org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [null], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0 at org.jboss.ejb3.interceptor.LifecycleInterceptorHandler.postConstruct(LifecycleInterceptorHandler.java:113) at org.jboss.ejb3.EJBContainer.invokePostConstruct(EJBContainer.java:619) at org.jboss.ejb3.AbstractPool.create(AbstractPool.java:131) at org.jboss.ejb3.StrictMaxPool.get(StrictMaxPool.java:141) at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:54) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.mdb.MessagingContainer.localInvoke(MessagingContainer.java:249) at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.delivery(MessageInflowLocalProxy.java:268) at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.invoke(MessageInflowLocalProxy.java:138) at $Proxy84.execute(Unknown Source) at org.jboss.resource.adapter.quartz.inflow.QuartzJob.execute(QuartzJob.java:57) at org.quartz.core.JobRunShell.run(JobRunShell.java:203) at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520) Caused by: org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [null], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0 at org.springframework.beans.factory.access.SingletonBeanFactoryLocator.useBeanFactory(SingletonBeanFactoryLocator.java:410) at org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.getBeanFactoryReference(SpringBeanAutowiringInterceptor.java:139) at org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.getBeanFactory(SpringBeanAutowiringInterceptor.java:120) at org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.autowireBean(SpringBeanAutowiringInterceptor.java:100) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.jboss.ejb3.interceptor.LifecycleInvocationContextImpl.proceed(LifecycleInvocationContextImpl.java:131) at org.jboss.ejb3.interceptor.LifecycleInterceptorHandler.postConstruct(LifecycleInterceptorHandler.java:109) ... 12 more Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0 at org.springframework.beans.factory.BeanFactoryUtils.beanOfType(BeanFactoryUtils.java:379) at org.springframework.beans.factory.access.SingletonBeanFactoryLocator.useBeanFactory(SingletonBeanFactoryLocator.java:400) ... 21 more 2008-05-20 17:40:20,543 ERROR [DefaultQuartzScheduler_Worker-6] org.quartz.core.ErrorLogger : Job (default.job.0.1211297867763 threw an exception. org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.RuntimeException: org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [null], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0] at org.quartz.core.JobRunShell.run(JobRunShell.java:214) at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520) * Nested Exception (Underlying Cause) --------------- java.lang.RuntimeException: org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [null], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0 at org.jboss.ejb3.interceptor.LifecycleInterceptorHandler.postConstruct(LifecycleInterceptorHandler.java:113) at org.jboss.ejb3.EJBContainer.invokePostConstruct(EJBContainer.java:619) at org.jboss.ejb3.AbstractPool.create(AbstractPool.java:131) at org.jboss.ejb3.StrictMaxPool.get(StrictMaxPool.java:141) at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:54) at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) at org.jboss.ejb3.mdb.MessagingContainer.localInvoke(MessagingContainer.java:249) at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.delivery(MessageInflowLocalProxy.java:268) at org.jboss.ejb3.mdb.inflow.MessageInflowLocalProxy.invoke(MessageInflowLocalProxy.java:138) at $Proxy84.execute(Unknown Source) at org.jboss.resource.adapter.quartz.inflow.QuartzJob.execute(QuartzJob.java:57) at org.quartz.core.JobRunShell.run(JobRunShell.java:203) at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520) Caused by: org.springframework.beans.factory.access.BootstrapException: Unable to return specified BeanFactory instance: factory key [null], from group with resource name [classpath*:beanRefContext.xml]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0 at org.springframework.beans.factory.access.SingletonBeanFactoryLocator.useBeanFactory(SingletonBeanFactoryLocator.java:410) at org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.getBeanFactoryReference(SpringBeanAutowiringInterceptor.java:139) at org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.getBeanFactory(SpringBeanAutowiringInterceptor.java:120) at org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.autowireBean(SpringBeanAutowiringInterceptor.java:100) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.jboss.ejb3.interceptor.LifecycleInvocationContextImpl.proceed(LifecycleInvocationContextImpl.java:131) at org.jboss.ejb3.interceptor.LifecycleInterceptorHandler.postConstruct(LifecycleInterceptorHandler.java:109) ... 12 more Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.beans.factory.BeanFactory] is defined: expected single bean but found 0 at org.springframework.beans.factory.BeanFactoryUtils.beanOfType(BeanFactoryUtils.java:379) at org.springframework.beans.factory.access.SingletonBeanFactoryLocator.useBeanFactory(SingletonBeanFactoryLocator.java:400) ... 21 more </code></pre> The quartz mdb is simply: <pre><code> ... @Interceptors(SpringBeanAutowiringInterceptor.class) public class MyQuartzJobMdb implements Job { protected static final long serialVersionUID = 20080515L; private static final Log log = LogFactory.getLog(Mc2GatherQuartzJobMdb.class); // @Autowired private transient GatherServiceIfc gatherService; ... </code></pre> <p> Note the <code>GatherServiceIfc gatherService</code>, that's the spring-bean which shall be injected. </p> <p> Strangely the SpringBeanAutowiringInterceptor works fine for a stateless EJB. In other words autowiring <code>GatherServiceIfc gatherService</code> in a stateless EJB works fine. </p> <p> If you examine the stack trace carefully, you will notice that the current thread is <code>[DefaultQuartzScheduler_Worker-6]</code>. As spring is using the current thread context loader, and the quartz thread does not know anything about the springframework classes, I thought about extending the <code>SpringBeanAutowiringInterceptor</code> the application classloader. Thus I extended the <code>SpringBeanAutowiringInterceptor</code> to </p> <pre><code> ... public class MySpringBeanAutowiringInterceptor extends SpringBeanAutowiringInterceptor { /** * Determine the BeanFactoryLocator to obtain the BeanFactoryReference from. * </code><p>The default implementation exposes Spring's default<br> * {@link ContextSingletonBeanFactoryLocator}.<br> * @param target the target bean to autowire<br> * @return the BeanFactoryLocator to use (never <code>null</code>)<br> * @see org.springframework.context.access.ContextSingletonBeanFactoryLocator#getInstance()<br> */<br> @Override<br> protected BeanFactoryLocator getBeanFactoryLocator(Object target) {<br> return MyContextSingletonBeanFactoryLocator.getInstance();<br> }<br>}<br></p></pre> Moreover I defined the <code>MyContextSingletonBeanFactoryLocator</code> as copy-paste from <code>ContextSingletonBeanFactoryLocator</code>, but defining: <pre><code> public class MyContextSingletonBeanFactoryLocator extends SingletonBeanFactoryLocator { ... /** * Overrides the default method to create definition object as an ApplicationContext * instead of the default BeanFactory. This does not affect what can actually * be loaded by that definition. * </code><p>The default implementation simply builds a<br> * {@link org.springframework.context.support.ClassPathXmlApplicationContext}.<br> */<br> @Override<br> protected BeanFactory createDefinition(String resourceLocation, String factoryKey) {<br> //return new ClassPathXmlApplicationContext(new String[]{resourceLocation}, false);<br> final ClassPathXmlApplicationContext cpxac = new ClassPathXmlApplicationContext(new String[]{resourceLocation}, false);<br> final ClassLoader classLoader = this.getClass().getClassLoader();<br> cpxac.setClassLoader(classLoader);<br> return cpxac;<br> }<br>...<br></p></pre> <p> And finally using <code>MySpringBeanAutowiringInterceptor</code> like: </p> <pre><code> ... @Interceptors(MySpringBeanAutowiringInterceptor.class) public class MyQuartzJobMdb implements Job { </code></pre> <p> Using <code>MySpringBeanAutowiringInterceptor</code> in the quartz-mdb works, the spring-bean is injected successfully, maybe you reuse this approach on different application servers, too. </p> <p>Have fun!</p> <br>

Seapegasus Blog - August 27, 2008 08:23 AM
Continuous Integration Im Kampf Gegen Den Golem

Es ist vielleicht eine vergessene Tatsache, aber wenn bei NetBeans ein Engineer es schafft, trotz aller Tests und Checks die Build zu vermurksen, dann wird derjenige zur Strafe von dem furchterregenden Prager Golem heimgesucht! (Nein, ich weiss nicht wer ihn gerade zu Besuch hat, wir harmlosen Tech Writer machen ja nie nie nie was an der Build kaputt... :-D)

Hat Eure Firma auch so nette Traditionen? Falls Ihr Euch für Eure wachsenden Team-Projekte gerade nach Werkzeugen für automatisierte Builds und automatisierte Tests umseht, dann lege ich Euch diesen Vortrag zum Stichwort Permanente Integration ans Herz:

In München findet am 19. September das erste Continuous Integration Camp statt. Veranstalter ist die NetBeans User Gruppe der JUG München. Mit dem Meeting wollen wir die Möglichkeit zum Erfahrungsaustausch und zu Diskussionen darüber bieten, was möglich und was sinnvoll ist. Weitere Informationen findet Ihr im WIKI der JUGM.

Es gibt einen Vortrag von Toni Epple und eine konkrete Fallstudie. Einfach per Email anmelden und dann am 19.9. (Freitag Nachmittag) ab nach Heimstetten. Gebt dem Golem keine Chance! ;-)

Seapegasus Blog - August 22, 2008 06:54 AM
GlassFish-Vortrag in Berlin

Wie Arun schon auf Englisch angekündigt hat, gibt es im September einen Vortrag über den GlassFish Application Server zusammen mit der Berlin-Brandenburg JUG.

Mittwoch, 3. September
17:30 - ca. 19:30
Zimmer FR5516, Technische Universität Berlin
Franklinstrasse 28/29 (Stadtplan)
10587 Berlin

Bitte meldet Euch vorher via XING an! Dort findet Ihr auch die Beschreibung. Arun hält den Vortrag auf Englisch.

OlliN's » netbeans - July 27, 2008 07:48 PM
Apropos Profiler

Gestern habe ich kurz den Netbeans-Profiler gezeigt. Der ist übrigens einfach so bei der Installation von Netbeans mit dabei und funktioniert tadellos. Vor einer Zeit habe ich mal versucht den Profiler von Eclipse (TPTP) zum Laufen zu bringen. Ich habe es nach einiger Zeit geschafft auf meiner Gentoo-Linux-Büchse eine Applikation nach Memory-Leaks zu untersuchen. Aber es ist schon ein Unterschied zwischen “funktioniert einfach” bei Netbeans und “Lese mal Installationsanleitung und probiere eine Weile bis es läuft” bei Eclipse.

Auch den Subversion-Client von Eclipse wird standardmäßig nicht installiert. Und auf der Website von Eclipse ist derzeit (Version 0.7.1) aus Lizenzgründen nicht mal ein vollständiger Client vorhanden. Man muss noch auf eine andere Seite um sich von dort noch Teile des Clients zu holen. Ist zwar alles dokumentiert, doch auch hier ist es bei Netbeans via Pluginmanager ganz einfach den Client zu installieren.

Gerade für Neueinsteiger ist also Netbeans besser geeignet. Aber auch die “alten” Eclipse-Hasen sollten mal über den Tellerrand in Richtung Netbeans schauen… da läuft Einiges (siehe Scripting) und zum Teil besser (siehe GUI-Builder).

Ach, wenn Netbeans doch nur so viele schöne Einstellungen für die Codeformatierungen hätte wie Eclipse… dann wäre ich überglücklich. Wenn man nämlich wie ich in einem Projekt arbeitet, welches die automatische Formatierung beim Speichern einer Datei vorschreibt und auch noch viele spezifische Formatierungsoptionen von Eclipse benutzt, dann ärgert man sich ab und zu wenn man mit Netbeans die eine oder andere Formatierung noch per Hand machen muss.

Seapegasus Blog - July 23, 2008 09:43 AM
EJB-Artikel im JavaSpektrum

Auf ans Kiosk: NetBeans-Dream-Team-Mitglied Adam Bien hat einen weiteren berühmt-berüchtigten EJB 3-Artikel geschrieben, diesmal bekommt Ihr ihn im JavaSpektrum-Magazin zu Gesicht.

Eine Zusammenfassung findet Ihr hier online; für den vollen Inhalt (inklusive NetBeans-Bildschirmphotos) kauft Ihr das Magazin — oder Ihr ladet für zwoenhalb Euro das PDF runter.

<WÄÄBUNG>Unterstützt einen Entwickler, kauft ein PDF!</WÄÄBUNG> :-D (Adam, kriegst Du da was von?)

Dass ich so lange nicht geblogt habe, lag übrigens daran dass ich "kurz" in Island war. :) Und danach hat sich der D&D-Floh in mein Ohr gesetzt. Also, d.h. konkret, ich habe mich überreden lassen, es demnächst zumindest mal zu probieren. Ich hatte bisher erst einmal eine Uraltversion vom Schwarzen Auge gespielt (mein armer Typie befindet sich immer noch im Limbo in irgendeinem aventurischen Wald, umzingelt von Orks), und hab mir noch keine endgültige Meinung über modernere Editionen gebildet. Mal sehen! Jetzt erst mal eine suuupi-Hintergrundstory erfinden. Es muss etwas besseres geben als "ich bin Vollwaise, alle hassen mich, und ein Ork hat meine Hausaufgaben gefressen"...! ;-)

OlliN's » netbeans - June 25, 2008 10:08 AM
Netbeans Fonts

Rohan Ranade (alias gridbag) hat in seinem letzten Blogeintrag nach Kombinationen der Schriften in Netbeans unter Linux gefragt. Ich benutze ProFont von Tobias Jung unter Gentoo Linux. Die Schrift ist wirklich gut zum Programmieren.

Hier also meine Einstellungen:

my netbeans fonts

netbeans fonts config

OlliN's » netbeans - April 29, 2008 07:32 AM
package org.jdesktop.beansbinding does not exist

Wer in einer Netbeans Platform Application das Beans Binding benutzen will, stösst auf folgenden Fehler wenn man in Matisse binden möchte:

...package org.jdesktop.beansbinding does not exist

Das entsprechende JAR wird nicht gefunden. Und da es derzeit kein Modul für das Beans Binding gibt, muss man das JAR-File in einem Library Wrapper Module selber dem Projekt hinzufügen. Die entsprechende Datei ist unter <netbeanshome>/java2/modules/ext/beansbinding-1.2.1.jar zu finden. Also legt man in seiner Suite ein neues Library Wrapper Module an und nimmt diese Datei als Jar. Alle Module die das Binding benutzen wollen können nun unter den Properties–>Libraries–>Add Dependency diese Library anziehen und schon ist der Fehler weg.

OlliN's » netbeans - April 28, 2008 02:55 PM
Netbeans 6.1 ist da

Zwar ist Netbeans 6.1 noch nicht auf der Frontpage, downloaden kann man es aber schon:

Und installiert:

about_netbeans_61

Bernhard's Weblog - April 22, 2008 09:36 PM
Extending groovy's SwingBuilder2

In my previous blog i have sketched some ideas for extending SwingBuilder. Today I'd like to introduce a small extension.

SwingBuilder offers already an items attribute for the combobox. Sadly this attribute is missing for the list node.

But it is not too complicate to extend SwingBuilder to make the items attribute available for the list node, too.

Fist create a new factory using the already existing groovy.swing.factory.ComboBoxFactory as starting template:


package org.huberb.groovy.swing.factory

import javax.swing.JList

/**
 * Create a JList, and handle the optional items attribute.
 * 
 * @author HuberB1
 */
public class ListFactory extends AbstractFactory {
    
    public Object newInstance(FactoryBuilderSupport builder, Object name, Object value, Map attributes) throws InstantiationException, IllegalAccessException {
        FactoryBuilderSupport.checkValueIsNull(value, name);
        //TODO expand to allow the value arg to be items
        Object items = attributes.remove('items');
        if (items instanceof Vector) {
            return new JList((Vector) items);
        } else if (items instanceof List) {
            List list = (List) items;
            return new JList(list.toArray());
        } else if (items instanceof Object[]) {
            return new JList((Object[]) items);
        } else {
            return new JList();
        }
    }
}

Next you have to register this factory, In fact you are overriding the original list registration.


import groovy.swing.SwingBuilder
def swing = new SwingBuilder()
swing.registerFactory( "list", new ListFactory() )

Now you can use swing for building lists like:


def panel = swing.panel() {
  scrollPane() {
    list( items: ['A', 'B','C'] )
  }
}

Have fun!

Bernhard's Weblog - April 13, 2008 09:19 PM
Extending groovy's SwingBuilder

Groovy's SwingBuilder builds swing user interfaces. It is simple, and has some nice extension points.

SwingBuilder provides all the swing's components, like JButton, JTextField, JSpinner, etc. So what's missing?

By the time I'm using SwingBuilder I have missed following features:

  • Easy integration of internationalized text
  • Easy linking JLabel using the labelFor method, and mnemonics

In the following sections I will describe each feature and sketch the implementation.

Internationalized Text

Using internationalized text in SwingBuilder you have to provide the internationalized text like:


            ResourceBundle rb = ResourceBundle.getBundle( "foo.bar.Bundle" )
            swingBuilder.panel() {
              button( text: rb.getString('someKey') )
              label( text: rb.getString('someLabelKey' )
              ...
        

Beside typing rb.getString over, and over again, it fails with a MissingResourceException if the specified key is not found.

The solution I have implemented so far, defines the attributes i15dText, and i15dTitle for specifying the message key, and a new closure-name i15dMessageSource for defining the resource bundle

Thus the above snippet changes to:


            ResourceBundle rb = ResourceBundle.getBundle( "foo.bar.Bundle" )
            swingBuilder.panel() {
              i15dMessageSource( resourceBundle: 'foo.bar.Bundle' )
              button( i15dText: 'someKey' )
              label( i15dText: 'someLabelKey' )
              ...
        

I think this is quite an improvment, regarding readability. Moreover the i15d* attribute implementations return the key as-is if the key is not defined in the resource bundle.

The implementation of the i15dMessageSource is quite simple to store the specified resource bundle as builder variable named i15dMessageSource.

The i15d* attribute implementation peeks the resource bundle from the builder variable, and retrieves the message. In case of i15dText, the message is set as new text attribute; in case of i15dTitle, the message is stored as new title attribute.

Linking JLabel, and mnemonics

Swing's JLabel has a method setLabelFor(JComponent). The javadoc explains:

Set the component this is labelling. Can be null if this does not label a Component. If the displayedMnemonic property is set and the labelFor property is also set, the label will call the requestFocus method of the component specified by the labelFor property when the mnemonic is activated.

SwingBuilder makes it not that easy to use this feature

The snippet below defines the label first, and gives it an id, next id defines the textfield. Finally it links the label with the textfield, by using the defined ids.


            label( id: 'myLabel', text: 'XXX', displayedMnemonic: 'X' )
            textField( id: 'myTextField', columns: 15)
            myLabel.labelFor = myTextField
        

I think it would be easier to use a snippet like:


            labelForGroup {
                label( id: 'l0', i15dText: 'View1.firstName')
                textField( id: 'tf0' )
            }            
        

Alternativly if you use a layout manager like MigLayout you can even skip the explicit label definition at all:


            textField( i15dLabel: 'View.firstName' )
        

The labelForGroup creates a node-list as dummy node. All children nodes are added to this list. More the childern nodes are passed to the parent node of the labelForGroup node. The node-completion processing of the labelForGroup implementation links the first JLabel of the node-list with first non-JLabel of the node-list.

The implementation of the attributes i15dLabel, and label is registered via addAttributeDelegate. When the node is completed, the implementation creates a JLabel, setting the text, and it as label for the current node.

Finally the implementation of mnemonic processing is registered as addPostNodeCompletionDelegate. The implementation just strips off the '&' from the text of the created JLabel, or AbstractButton. Moreover it sets the mnemonic to the character following the stripped '&' character.

Summary

Reading the sources of groovy.swing.SwingBuilder, and groovy.util.FactoryBuilderSupport, have helped me to implement the above described features.

Extending groovy's SwingBuilder allows you to add new features, easily. My next exploring steps are creating a BeansBinding builder, and some simple templates generation for creating the view, and a binding from a given bean class.

Have fun!

Bernhard's Weblog - April 01, 2008 08:50 PM
NetBeans 6.1 Beta

Introduction

Netbeans 6.1 Beta is out, I have downloaded it, and I have given it a try. Especially the slow startup of the official Netbeans 6.0 disturbs me, so I was hoping this newer version starts more quickly.

Faaast

The startup time is now really faster. I really like that. Since I have installed Netbeans 6.1 Beta, I have never touched Netbeans 6.0 again. Now I'm really pleased.

Debugging Local Variables

Beside the startup speed I enjoyed another improvement. When I debug a program, now I can change variables of any wrapper classes, like Integer, Double, etc. In previous versions only the equivalent built-in types were modifiable, but not their wrapper-classes.

Thus now you are able to modify in the "Local Variable" window the vars like i1, d1, and l1.

Debug Window

In the version Netbeans 6.0 you have seen a dialog box, notifying "Can't assign primitive value to object".

You can check the Issue 125267. As you might notice I reported the issue, and it was fixed. Kudos to responsivness of the nb team member mentlicher!

I was very surprised that the netbeans team fixed this issue:

  • very fast
  • very uncomplicated

So if you have an issue, contact the mailing-lists, or enter an issue. It's really worth!

Groovy And Grails

I' m using grails in two projects successfully. So I'm very pleased about the new groovy and grails plugin. Although there are still some rough edges, I enjoy the syntax highlightning for the groovy, and gsp files.

You might want to give it a try, see the Groovy and Grails support in NetBeans and GlassFish, and News from Grailsland.

Fade Out

A cool feature is the fading-out of the status text in bottom left corner. I have rechecked that it is already available in the NetBeans 6.0, but I'd like to mention it here, too. Surley it's not very functional, but just cool!

Have fun!