Vor nicht allzulanger Zeit startete Eclipse mit Strg+F11 das letzte Programm. Dann änderte man dies und Eclipse versuchte automatisch das im Editor aktive Programm zu starten. Ich denke, dass diese Umstellung eher lästig ist und eines der ersten Sachen sein dürfte, die man abschaltet. Das geht so: In den Preferences unter Run/Debug > Launching den Schalter bei Always launch the … einstellen.
1 Stunde Suchen für eine doofe Eclipse-Einstellung
<Sarkasmus>Dankenswerterweise</Sarkasmus> hat Eclipse eine neue Einstellung bekommen, in dem gewissen Daten vom Kopieren in den Output-Folder ausgenommen werden können. Dass sich diese Einstellung unter Java > Compiler > Building befindet, fand ich erst nach langem Suchen hier: http://www.codecommit.com/blog/eclipse/wtps-crazy-and-undocumented-setting-change
Mein Problem: Bei der Entwicklung mit Wicket stehen die HTML-Seiten Seite an Seite mit den Java-Klassen. In den classes-Folder für die Web-Anwendung gingen aber nur die Klassen und nicht die HTML-Dateien. Da gestern auf einer anderen Eclipse-Version alles noch lief, war ich heute lange verzweifelt und kann glücklicherweise nach dieser Einstellung wieder an die Arbeit gehen.
SQL für Objekte: JoSQL (SQL for Java Objects)
JoSQL (SQL for Java Objects) unter http://josql.sourceforge.net/index.html ist eine Open-Source Biblitohek, um SQL-Anfragen an Objektgrafen zu stellen. Die Webseite gibt interessante Beispiele.
String query = "SELECT * FROM java.io.File WHERE name LIKE '%.mp3'";
Query q = new Query();
q.parse( query );
QueryResults results = q.execute( Arrays.asList( new File("C:/Data/Musik/").listFiles() ) );
System.out.println( results.getResults() );
Oder für Ausdrücke:
/*
* Use as a file filter.
*/
String exp = "lastModified BETWEEN toDate('10/May/2007') AND toDate('28/Jun/2007') " +
"AND " +
"length >= 10 * 1024" +
"AND " +
"path LIKE '%/subdir/%'";
ExpressionEvaluator ee = new ExpressionEvaluator (exp, File.class);
if (ee.isTrue (myfile))
{
// Process the file.
}
GMailer API for Java (g4j)
Die GMailer API for Java (g4j) ist eine Java-Bib, um einfach mit GMail zu kommunzieren. Das ist natürlich viel einfacher als über die JavaMail-API an das Postfach zu kommen.
GMConnector gm = new GMConnector( userID,passwd,1 );
gm.connect();
GMContact[] data = gm.getContact(1, „“);
Da das letztes Update ist von 2004 ist, kann jmd. sagen, ob das immer noch reibungslos funktioniert?
VisualVM
VisualVM ist eine Open-Source Software zum Profilen von Java-Applikationen und Verfolgen von Referenzen. Screenshots sagen mehr als 1000 Worte.
Buchkritik: Das Java Codebook
Marcus Wiederstein, Marco Skulschus, Mark Donnermeyer, Dirk Brodersen, Benjamin Rusch. Addison-Wesley. ISBN 3-8273-2059-3. 2003. 858 Seiten
Programmabschnitte, sog. Snippets, gibt es im Internet genug (wir wäre es alternativ mit dem Java-Almanac?) und wer eine Suchmaschine bedienen kann, wird immer, ja immer, die Bibliothek oder den Quellcode-Schnippsel finden, die er sucht. Um so erstaunlicher finde ich es, wenn Verlage Quellcode-Kochbücher veröffentlichen, ob sie nun Codebook oder Cookbook heißen. Ernsthaft: Wer eine Klasse zur Bruchrechnung sucht oder ein Beispielprogramm zum Aufbau eines Swing-Fensters, geht sicherlich nicht zum Regal, sucht im Index nach „Bruch“ und holt sich dann die Klasse von der CD. Daher die Frage – ist ein Buch wie „Das Java Codebook“ notwendig? Das Positive zuerst: Die Kapitel über reguläre Ausdrücke und Applets (Daten im Cookie speichern, Uploads, Applet-Konverter für Tags), die kleinen Beispielprogramme, in denen man etwa über ein BufferedImageOp.filter Bilder heller/dunkler macht, sowie Hinweise zur Transparenz und der Index finde ich prima. Eigentlich sind Bücher mit Quellcode gut, denn Software-Entwickler lesen im Allgemeinen zu wenig. Das Studium von Quellcode hilft jedem Entwickler, neue Idiome zu lernen und seine Fähigkeiten zu verbessern. Je nach Schwerpunkt des Buches lernt man weitere Möglichkeiten der Standardbibliothek kennen oder neue Open-Source-Bibliotheken. Soweit die Möglichkeiten guter Codebooks. Leider hat das Java Codebook dann doch die eine oder andere Schwachstelle, so dass man Software-Entwicklern vielleicht doch besser direkt zur Google-Suche raten sollte. (Immerhin gibt es das Buch als PDF.) Die Probleme im Detail: Die Klasse
public class CalcExample {
static final BigDecimal ZERO = new BigDecimal(0);
static final BigDecimal ONE = new BigDecimal(1);
static final BigDecimal FOUR = new BigDecimal(4);
deklariert drei Variablen (Sichtbarkeit könnte auch anders sein), doch vergisst, dass es ZERO, ONE, TEN schon in BigDecimal gibt. In anderen Beispielen gefällt mir die Schreibweise der Felder nicht. Einiges ist nach der Bauart String []array, also Typ, Leerzeichen, Variablenname aufgebaut. Das habe ich nach 11 Jahren Java hier zum ersten Mal gelesen. Zumal sich die Autoren hier uneins zu sein scheinen, denn sie verwenden auch String[]. Die fünf Autoren des Buchs folgen demnach keiner einheitlichen Coding-Konvention. Ein weiteres Thema betrifft die Methodennamen: Überwiegend werden englische Bezeichner (setNumber, less100, …) gebraucht, doch lassen sich innerhalb eines Beispiels Vermischungen mit deutschen Variablennamen entdecken, wie das Feld ZEHN. Einige Autoren mögen (immer noch) die Klassen Hashtable und Vector, andere nutzen doch besser List und Map – hat denn keiner der Autoren die anderen Kapitel gelesen und kommentiert? Bei den Datenstrukturen frage ich mich wirklich, was denn arrayList.add(new String(new java.util.Date().toString())); für eine Anweisung sein soll. Und warum wird ein Stack noch mal neu implementiert? OK, der Original-Stack erbt von Vector, was vom Design total verpfuscht wurde, aber dann könnte man doch immer noch den neuen Stack so implementieren, das er an den alten Stack delegiert, anstatt alle Operationen komplett mit einer ArrayList neu zu implementieren. (Und dann noch die fragwürdige Methode search() zu übernehmen.) Eine weitere Schwachstelle, die ich in der Insel weitestgehend versuche zu vermieden, sind Windows-spezifische Pfadangaben, wie etwa bei new FileOutputStream(„c:\\buecher.ser“). Bei IO-Beispielen fehlt oft das close() im finally. Vor allem bei HTTP-Servern ist das kritisch. Im JSP-Kapitel findet sich plötzlich ein JDBC-Close im finally; also hat es nicht jeder der Autoren vergessen. Frage: Was gibt dieses Programm bei Argumenten auf der Kommandozeile aus?
package javacodebook.io.stdout;
public class StdOut {
public static void main(String[] args) {
String text = "Hallo Welt";
//Wenn Text angegeben, dann diesen ausgeben
if(args.length < 1)
for(int i = 0; i < args.length; i++)
System.out.println(args[i]);
else
System.out.println(text);
}
}
Dass ist wohl eher eine Zertifizierungsfrage statt eines sinnvollen Codebeispiels, denn ist die Anzahl der Argumente kleiner 1, gibt es keine Argumente und die Schleife ist nutzlos. Genauso falsch ist der Satz „JDBC benutzt dabei die Interfaces Connection, Driver und DriverManager.“ Schade, denn DriverManager ist eine Klasse. Sollte es auch, denn aus dieser Zentrale erhält man durch die statische Methode getConnection() eine Verbindung. Im Anhang finden sich dann noch ein paar Dreher in der Groß-/Kleinschreibung. Z. B. beginnen einige Bezeichner in der Tabelle „Java Native Interface Typen“ mit Großbuchstaben. Besser wären „int“ statt „Int“ sowie „void“ statt „Void“ usw. Ähnliches gilt für JscrollPane, was zu JScrollPane werden sollte. Unter „Relationale Operatoren“ findet sich folgender Satz bei ==-Operator: „a == b ergibt true, wenn a gleich b ist. Handelt es sich bei a und b um Referenztypen, so ist der Rückgabewert dann true, wenn beide auf dasselbe Objekt zeigen.“ Wir sollten den Sonderfall a = b = NaN aber nicht Außeracht lassen, denn gerade dann ist a = b, aber das Ergebnis nicht true. In der Tabelle „Klassenobjekte für den primitiven Datentyp“ sollte Void besser nicht auftauchen, da es sich nicht um einen primitiven Datentyp handelt. Oder Void stehen lassen, aber die Überschrift anpassen. Einige Kritikpunkte betreffen die Auswahl der Klassen. Die Klasse Fraction sollte vielleicht besser einer bekannten Open-Source-Bibliothek entstammen und die Matrizen sowie der umfangreiche Quellcode nicht unbedingt abgebildet werden. Für CSV-Dateien wären populäre Standard-Klassen sinnvoller. Der Tipp 186 für Timer sollte diesen nicht selbst implementieren, sondern die zwei (!) Timer-Klassen der Java-Lib vorstellen. Da ein Codebook grundsätzlich eine unendliche Sache ist, könnten weitere Snippets eingebracht werden. Bei den Zufallszahlen wäre z. B. SecureRandom gut untergebracht. Das Beispiel FindInFile, was händisch nach einem String in einer Datei sucht, lässt sich viel effektiver mit NIO (mit Standard-Beispiel von Sun) lösen. Das NIO-Kapitel kommt mit nur zwei Beispielen daher (Datei kopieren und File-Lock). Das ist eine magere Ausbeute. Später kommt noch ein NIO-Server dazu. Der Verweis auf eine einfache NIO-Bibliothek (wie xSocket) wäre dann wünschenswert. Um ein Fenster mittig zu positionieren, muss man nicht rechnen, hier reicht eine Java-Funktion. Wenn es sich schon um ein Java 1.4 Buch handelt, dann sollte ImageIO Grafiken laden. Die Swing-Beispiele sind relativ unspektakulär. Hier wäre es wohl sinnvoller statt „wie erzeuge ich einen Button“ oder „wie etwas mehr mit den Modellen zu machen“, einen Dateibaum in ein JTree zu setzen. Und stilistisch wertvoll ist der Hinweis mit der JDBC-Verbindung in einem JSP-Tag sicher nicht. Und wo sind die DAOs? Bei JMS stimmt es zwar grundsätzlich, dass in einer Tabelle bei Programmiersprachenunabhängigkeit „Nein“ steht und bei HTTP „Ja“, doch allgemeingültig ist das nicht. Für ActiveMQ gibt es ein standardisiertes Protokollformat (OpenWire) und APIs für diverse andere Programmiersprachen. Das gleiche gilt auch für IBMs WebSphere MQ (früher MQSeries) – sicherlich eines der besten MOMs -, das heterogene Plattformen verbindet. Einen XML-Parser über die Anweisung org.apache.xerces.parsers.DOMParser parser = new org.apache.xerces.parsers.DOMParser(); statt über JAXP zu erfragen ist nicht schön sondern fast grob fahrlässig. Zudem haben auch die JAXP-Parser Features, obwohl die String-Kennungen dann immer ein wenig anders aussehen. Zu Tipp 196: Wann immer man sich mit getGraphics() einen Grafik-Kontext holt, sollte man ihn auch wieder freigeben. Dieser Hinweis fehlt leider in den Beispielen. Farbkonstanten sollten groß geschrieben sein, also Color.WHITE, statt Color.white, zumindest seitdem Sun diese Konvention in Java 1.4 eingeführt hat.
Erst wenn der letzte Programmierer eingesperrt und die letzte Idee patentiert ist, werdet ihr merken, dass Anwälte nicht programmieren können.
Shortest Java Quine with 106 chars
Because of a contest in a German Java forum I tried to formulate the shortest Java Quine:
enum _{_;{String _="enum _{_;{String _=%c%s%1$c;System.out.printf(_,34,_);}}";System.out.printf(_,34,_);}}
To compile and run under Windows (with Unix you need to redirect Exceptions to /dev/null and use diff):
>javac _.java
>java _ 2> NUL > Quine.out
> fc Quine.out _.java
Vergleichen der Dateien Quine.out und _.JAVA
FC: Keine Unterschiede gefunden
>jrunscript -e "print(new java.io.File('_.java').length())"
106
I haven’t found a shorter solution on the net, so I suppose this is the shortest for now.
Inselupdate: JMX mit RMI-Adaptor
Für die Anbildung an den JMX-Server dient nicht nur die JConsole, sondern verschiedene andere Wege sind denkbar, etwa über HTTP oder über einen eigenen Client, der über RMI kommuniziert.
JMXConnectorServer für den Server
Zur Veröffentlichung der MBeans über RMI ist der JMXConnectorServer verantwortlich. Damit die MBeans an die RMI-Registry gebunden werden, wird eine besondere URL verwendet, die den Service genau beschreibt. Die JMXServiceURL hat den allgemeinen Aufbau:
service:jmx:<protocol>://[[[<host>]:<port>]/<path>]
Vor dem Start des Programms muss die RMI-Registry für Anmeldungen bereit sein; da unser Programm auf dem gleichen Rechner arbeitet, starten wir den RMI-Namensdienst selbst.
LocateRegistry.createRegistry( 1099 );
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
String url = „service:jmx:rmi:///jndi/rmi://localhost/maze“
JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(
new JMXServiceURL( url ), null, server );
connectorServer.start();
ObjectName name = new ObjectName( „com.tutego.insel.jmx:type=Maze“ );
MazeMBean maze = new Maze();
server.registerMBean( maze, name );
JOptionPane.showMessageDialog( null, „Ende“ );
System.exit( 0 );
JConsole mit Remote-Connection
Mit der JConsole könnten wir nun Verbindung aufnehmen, in dem unter Remote Connection die URL service:jmx:rmi:///jndi/rmi://localhost/maze Einsatz findet.
JMXConnector für den Client
Auf der Clientseite gibt es mit JMXConnector den Gegenspieler zum JMXConnectorServer. Das Objekt liefert uns mit getMBeanServerConnection() ein MBeanServerConnection-Objekt, was sozusagen die Repräsentation des MBean-Servers MBeanServer auf der anderen Seite entspricht (genauso genommen gilt für die Schnittstellen: MBeanServer extends MBeanServerConnection). Über getAttribute() lassen sich dann zum Beispiel Properties erfragen.
JMXServiceURL u = new JMXServiceURL( „service:jmx:rmi:///jndi/rmi://localhost/maze“ );
JMXConnector c = JMXConnectorFactory.connect( u );
MBeanServerConnection mbsc = c.getMBeanServerConnection();
ObjectName name = new ObjectName( „com.tutego.insel.jmx:type=Maze“ );
System.out.println( mbsc.getAttribute( name, „MaxNumberOfPlayers“ ) );
Schnittstelle und Klasse für die MBean
package com.tutego.insel.jmx;
public interface MazeMBean
{
void setMaxNumberOfPlayers( int numberOfPlayers );
int getMaxNumberOfPlayers();
void dragonAlarm();
}
package com.tutego.insel.jmx;
public class Maze implements MazeMBean
{
private int numberOfPersons;
public void setMaxNumberOfPlayers( int numberOfPersons )
{
this.numberOfPersons = numberOfPersons;
}
public int getMaxNumberOfPlayers()
{
return numberOfPersons;
}
public void dragonAlarm()
{
System.out.println( „Heul. Huhuhuhu.“ );
}
}
JIDE Common Layer – Frische Swing-Komponenten
Form the homepage:“JIDE Common Layer has nearly 100k lines of code and over 30 components and utilities. It has been part of JIDE commercial products since 2002 so the quality and stability are quite high. You can run a webstart demo from the link below to see it in action.“
JIDE is dual-licensed: GPL and free commercial license.
TeX-Formulate in Webseiten mit jsMath
http://www.math.union.edu/~dpvc/jsMath/ ist eine Layout-Engine, die TeX-Formulare in Webseiten rendert. Dabei werden nicht, wie bei anderen Ansätzen, Grafiken generiert, sondern die Ausdrücke mit CSS positioniert. Damit skaliert das Ganze schön. Das Ergebnis ist beeindruckend und die Engine wird auch von einigen Wiki-Systemen verwendet. Einige Beispiele: Examples of jsMath. Im Interactive jsMath lab kann man Formen eingeben und es kommt HTML raus, was man nur noch zusammen mit dem CSS auf die eigene Webseite setzen muss. Aus x_i^2 wird etwa:
<SPAN CLASS=“typeset“><nobr><span class=“scale“><span class=“icmmi10″>x</span><span style=“position: relative; top:0.372em;“><span class=“size2″><span class=“icmmi10″>i</span></span><span class=“spacer“ style=“margin-left:0.05em“></span></span><span style=“position: relative; margin-left:-0.260em; top:-0.362em;“><span class=“size2″><span class=“icmr10″>2</span></span><span class=“spacer“ style=“margin-left:0.05em“></span></span><span class=“blank“ style=“height:1.331em;vertical-align:0.908em“></span></span></nobr></SPAN>
Jetzt fehlen nur noch jsMath.js und, falls etwa Summen-Zeichen oder sonstiges Sonderzeichen verwendet werden, im fonts-Ordner die TeX-Fonts.
Danke für die Nutzung der Insel als Vorlage für Uni-Folien
Hier möchte ich mich bei Ihnen, Herrn Dr. Ralf Kunze, und Team der Universität Osnabrück herzlich bedanken. Es freut mich sehr, dass Sie für ihre Vorlesungsunterlagen http://www-lehre.inf.uos.de/~binf/2007/index.html „Objekt-orientierte Programmierung in Java“ im Sommersemester 2007 so viel Abschnitte der Insel gebrauchen konnten. Immer wieder beglückt es mich, wenn Referenten und Dozenten Abschnitte 1:1 übernehmen und damit die Qualität meines Buches „Java ist auch eine Insel“ auch für den wissenschaftlichen Alltag bestätigen. (Ich wusste auch nicht, dass Rechtschreibfehler im Buch ebenfalls zum Insel-Kult gehören, und sie deshalb auch immer mitkopiert werden müssen.) Dass Sie dabei die Insel erst an dritter Stelle Ihrer Literaturangaben platzieren, ist selbstverständlich zu verzeihen. Besonders gefallen hat mir auf Ihrer Uni-Seite die Aussage „Zum legalen online Lesen, herunterladen oder auch kaufen“. Das finde ich gut, denn „illegales Online-Lesen“ wäre ja quatsch. Natürlich habe weder ich noch mein Verlag Galileo-Computing etwas dagegen einzuwenden, wenn ohne Nachfrage die geglücktesten Abschnitte kopiert und ohne Kennung der Quellen übernommen werden – Seite für Seite als Zitat zu kennzeichnen ist natürlich lästig. Das ist Arbeiten im Sinne von Stanisław Jerzy Lec: „Von der Mehrzahl der Werke bleiben nur die Zitate übrig. Ist es dann nicht besser, von Anfang an nur die Zitate aufzuschreiben?“
Ich war so frei, einige Ihrer Folien auf meinen Blog aufzunehmen. Ich hoffe, Sie sehen von Klagen wegen Urheberrechtsverletzungen ab; immerhin kopiere ich Ihre Texte hier ohne Nachfrage. (Alles Aufzulisten wäre zu viel Arbeit.
Das sind nur einige Beispiele mit direkten Kopien ganzer Absätze
für je eine Folie.)
Insel | Kopie |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Auch für zwei Beispiele durfte die Insel Vorlage sein. (Das ist rechtlich sicher, da die Insel im Vorwort erlaubt, dass alle Beispiele frei verwendet werden können.) Das eine ist JCheckBoxDemo, welches als CheckBoxDemo mit anderen Grafiken und Beschriftungen — aus der Auswahl "Ein Colt für alle Fälle" und "MacGyver" wird "Informatik A und Informatik B" — einer weiteren Zeile im Listener ein neues Leben führt.
Oder
package com.javatutor.insel.thread.group;
public class ShowThreadsInMain
{
public static void main( String[] args )
{
ThreadGroup top = Thread.currentThread().getThreadGroup();
while ( top.getParent() != null )
top = top.getParent();
showGroupInfo( top );
}
public static void showGroupInfo( ThreadGroup group )
{
Thread[] threads = new Thread[ group.activeCount() ];
group.enumerate( threads, false );
System.out.println( group );
for ( Thread t : threads )
if ( t != null )
System.out.printf( "%s -> %s is %sDaemon%n",
group.getName(), t, t.isDaemon() ? "" : "no " );
ThreadGroup[] activeGroup = new ThreadGroup[ group.activeGroupCount() ];
group.enumerate( activeGroup, false );
for ( ThreadGroup g : activeGroup )
showGroupInfo( g );
}
}Und das Beispiel vom Doktor:
package threadgroup1;
/**
* Informationen ueber die laufenden Threads liefern.
*
* @author Ralf Kunze (rkunze@uos.de), Institut fuer Informatik, Universitaet
* Osnabrueck
* @date 06.05.2007
*/
public class ThreadInfo {
public static void main(String[] args) {
ThreadGroup top = Thread.currentThread().getThreadGroup();
while (top.getParent() != null)
top = top.getParent();
showGroupInfo(" ",top);
}
public static void showGroupInfo(String indent, ThreadGroup group) {
Thread[] threads = new Thread[group.activeCount()];
group.enumerate(threads, false);
System.out.println(indent + group);
for (Thread t : threads)
if (t != null)
System.out.printf("%s%s -> %s is %sDaemon%n",
indent ,group.getName(), t, t.isDaemon() ? "" : "no ");
ThreadGroup[] activeGroup = new ThreadGroup[group.activeGroupCount()];
group.enumerate(activeGroup, false);
for (ThreadGroup g : activeGroup)
showGroupInfo(indent+indent, g);
}
}Das @author-Tag gefällt mir besonders. Die indent-Erweiterung ist natürlich anzuerkennen. Das habe ich gleich übernommen. Daher gefällt mir der wissenschaftliche Austausch so sehr. Leider gibt es das JavaDoc-Tag @date nicht (zumindest bis Java 6), aber man kann ja schon für die Zukunft programmieren.
Insgesamt finden sich sehr viele Abschnitte aus dem Kapitel IO, Thread, Reflection und Netzwerk in den Uni-Unterlagen, aber in der Reihenfolge, Satzbau und Formulieren sind auch in anderen Kapiteln deutliche Ähnlichkeiten zu erkennen. Danke für die Hommage.
Das ANTLR Eclipse-Plugin
Für den beliebten Parsergenerator ANTLR gibt es unter http://www.javadude.com/tools/antlr3-eclipse/ ein praktisches Plugin. Der Update-Manger von Eclipse wird auf die URL http://javadude.com/eclipse/update gelegt, installiert und neu gestartet. Anschließend geht man im Projekt auf das Kontextmenü und aktiviert Add/Remove ANTLR 3 Nature.
Als nächstes kann man eine ANTLR-Datei ablegen. Auf der Doku-Seite vom Plugin wird eine Grammatik (Datei Expr.g3) angegeben, die hier — leicht überarbeitet — angegeben werden soll:
grammar Expr;
@header {
package com.tutego.script.fp;
import java.util.HashMap;
}
@lexer::header {
package com.tutego.script.fp;
}
@members {
HashMap<String,Integer> memory = new HashMap<String,Integer>();
}
prog:
stat +
;
stat:
expr NEWLINE
{
System.out.println( $expr.value );
}
| ID '=' expr NEWLINE
{
memory.put( $ID.text, $expr.value );
}
| NEWLINE
;
expr returns [int value]:
e = multExpr { $value = $e.value; }
(
'+' e = multExpr { $value += $e.value; }
| '-' e = multExpr { $value -= $e.value; }
)*
;
multExpr returns [int value]:
e = atom { $value = $e.value; }
(
'*' e = atom { $value *= $e.value; }
)*
;
atom returns [int value]:
INT
{
$value = Integer.parseInt($INT.text);
}
| ID
{
Integer v = memory.get( $ID.text );
if ( v!=null ) $value = v.intValue();
else System.err.println( "Undefined variable " + $ID.text );
}
| '(' expr ')' {$value = $expr.value;}
;
ID:
('a'..'z' | 'A'..'Z') +
;
INT:
'0'..'9' +
;
NEWLINE:
'\r' ? '\n'
;
WS:
(' ' | '\t') +
{
skip();
}
;
Bearbeiten lässt sich die Grammatik in Eclipse nicht ordentlich, doch dafür dient ja die ANTLRWorks: The ANTLR GUI Development Environment.
Das Schöne beim Plugin: Es generiert automatisch im Hintergrund den Parser und Lexer. Das Testprogramm ist schnell geschrieben:
package com.tutego.script.fp;import org.antlr.runtime.*;
public class FpRunner
{
public static void main( String[] args ) throws Exception
{
ExprLexer lex = new ExprLexer( new ANTLRStringStream("age=34\nage*2\n12*111\n") );ExprParser parser = new ExprParser( new CommonTokenStream( lex ) );
try
{
parser.prog();
}
catch ( RecognitionException e )
{
e.printStackTrace();
}
}
}
Die Ausgabe ist dann
68
1332
sun.misc.Unsafe zur Objekterzeugung ohne Standard-Konstruktor
Inselupdate: Die Laufzeitumgebung von Sun liefert noch über 3000 Klassendateien in den Paketen sun und sunw aus. Diese internen Klassen sind nicht offiziell dokumentiert[1], aber zum Teil sehr leistungsfähig und erlauben selbst direkten Speicherzugriff oder können Objekte ohne Standard-Konstruktor erzeugen:
com/tutego/insel/sun/UnsafeInstance.java, Ausschnitt
Field field = sun.misc.Unsafe.class.getDeclaredField( "theUnsafe" );
field.setAccessible( true );
sun.misc.Unsafe unsafe = (sun.misc.Unsafe) field.get( null );
File f = (File) unsafe.allocateInstance( File.class );
System.out.println( f.getPath() ); // null
File hat keinen Standard-Konstruktor, noch nicht einmal einen privaten. Diese Art der Objekterzeugung kann bei der Deserialisierung (siehe dazu Kapitel 13) hilfreich sein.
[1] Das Buch “Java Secrets“ von Elliotte Rusty Harold geht den Klassen nach, ist aber schon älter.
Inselupdate: Erkennungsstring (Action-Command) einer Schalftfläche ändern
Manche Ereignisbehandler sind für Schaltflächen so ähnlich, dass Entwickler nur einen Listener mit mehreren Schaltflächen verbinden möchten. Dann taucht nur das Problem auf, wie der Listener die Schaltflächen unterscheiden kann. Eine Idee wäre, die Beschriftung mit getText() auszulesen – das bringt allerdings das Problem mit sich, dass die Software stark landessprachlich ist, denn bei mehrsprachigen Anwendungen kann sich die Aufschrift ändern. Eine andere Lösung wäre mit getSource() zu arbeiten. Doch dann müsste im Listener die Komponenten für einen Vergleich verfügbar sein, was sie oft nicht ist.
Als Lösung bietet die AbstractButton-Klasse die Methode setActionCommand() an, mit der sich eine Kennung, der sogenannte Action-Command setzen lässt.
abstract class javax.swing.AbstractButton extends JComponent implements ItemSelectable, SwingConstants
- void setActionCommand( String command )
Setzt einen neuen Kommandostring, wenn das Ereignis ausgeführt wird.
Der Listener kann diesen Action-Command mit getActionCommand() aus dem ActionEvent auslesen.
class java.awt.event.ActionEvent extends AWTEvent
- String getActionCommand()
Liefert den String, der mit dieser Aktion verbunden ist.
Ohne explizites Setzen ist der Action-Command standardmäßig mit der Beschriftung der Schaltfläche initialisiert.
Inselupdate: Zugriff auf die gesamte Windows-Registry
Wird Java unter MS Windows ausgeführt, so ergibt sich hin und wieder die Aufgabe, Eigenschaften der Windows-Umgebung zu kontrollieren. Viele Eigenschaften des Windows-Betriebssystems sind in der Registry versteckt, und Java bietet als plattformunabhängige Sprache keine Möglichkeit, diese Eigenschaften in der Registry auszulesen oder zu verändern. (Die Schnittstelle java.rmi.registry.Registry ist eine Zentrale für entfernte Aufrufe und hat mit der Windows-Registry nichts zu tun. Auch das Paket java.util.prefs mit der Klasse Preferences erlaubt nur Modifikationen an einem ausgewählten Teil der Windows-Registry.)
Um von Java auf alle Teile der Windows-Registry zuzugreifen, gibt es mehrere Möglichkeiten, unter anderem:
- Windows Registry API Native Interface (http://tutego.com/go/jnireg), die frei zu benutzen ist und keiner besonderen Lizenz unterliegt.
- http://www.cogentlogic.com/jndi/ einen JNDI Service Provider for Windows Registries für teure 299 kanadische Dollar.
- Preferences unter Windows realisiert: java.util.prefs.WindowsPreferences. Damit ist keine zusätzlich native Implementierung – und damit eine Windows DLL im Klassenpfad – nötig. Die Bibliothek https://sourceforge.net/projects/jregistrykey/ realisiert eine solche Lösung.
- reg zum Setzen und Abfragen von von Schlüsselwerten.
Beispiel Zeigen den Dateinamen für den Desktop-Hintergrund an:
$ reg query „HKEY_CURRENT_USER\Control Panel\Desktop“ /v Wallpaper
! REG.EXE VERSION 3.0
HKEY_CURRENT_USER\Control Panel\Desktop
Wallpaper REG_SZ C:\Dokumente und Einstellungen\tutego\Anwendungsdaten\Hintergrund.bmp
Unterschiedlicher Persistence Context und Speicherprobleme
Ein Persistence Context verwaltet Entities und kontrolliert ihren Lebenszyklus.
Man unterscheidet zwei Arten von Persistence Context:
–Transaction-scoped Persistence Context
–Extended Persistence Context
•Mit EntityManagerFactory.createEntityManager() bekommt man den Extended Persistence Context.
–createEntityManager() liefert den Application-Managed Entity Manager.
•Der Persistence Context beginnt, wenn der Application-Managed Entity Manager erzeugt wird und endet erst dann, wenn der Entity-Manager geschlossen wird.
•Werden Entities geladen, so bleiben sie so lange im Extended Persistence Context, bis der der Kontext geschlossen oder alle Entities ausdrücklich gelöscht werden.
–Entities bleiben also sehr lange „manged“ und nur dann „detached“, wenn der Entity-Manager geschlossen wird.
•Der Transaction Persistence Context ist der übliche Persistence Context eines „Container-Managed Entity Managers“, der also über den Container injiziert wird.
@PersistenceContext EntityManager em;
•Der EntityManager erzeugt pro Transaktionen einen neuen Persistence Context.
–Der Persistence Context endet bei einem Commit oder Rollback der Transaktion.
•Innerhalb der Transaktion werden die zum Beispiel über find() oder Query geladenen Entites zu managed Entities.
•Da nach der Transaktion der Persistence Context endet, werden die dort verwalteten Entities detached.
•Da der Transaction Persistence Context pro Transaktion aufgebaut wird, ist die Anzahl der verwalteten Objekte relativ klein.
•Der Extended Persistence Context ist oft deutlich länger und kann nach einer Zeit sehr viele Objekte aufnehmen.
–Damit kann das zu einem Speicherproblem werden.
•Um beim Extended Persistence Context kein Speicherproblem zu bekommen gibt es unterschiedliche Strategien:
–Von Zeit zu Zeit clear() vom EntityManager aufrufen. Das detached Objetkte.
–Auf das passende Lazy-Load achten.
–Weniger Objekte laden: Bei unachtsamem Design werden oft viel zu viele Objekte geladen.
•Besonders Gib-Mir-Alles-Ausdrücke wie „select o from Entity o“ sind gefährlich, da die Anzahl der Objekte groß sein kann, obwohl nur ein kleiner Teil der Objekte wirklich benötigt wird.
–Eine Paginierung kann hier sinnvoller sein um nur das zu laden, was zum Beispiel sichtbar ist.
•Einzelne Entities lassen sich nicht aus dem Entity-Manger entfernen (detachen).
–Bei Hibernate oder anderen Implementierungen funktioniert das, bei JPA standardmäßig nicht.
•Aber andersherum gibt es eine Lösung.
–Also alles freigeben, bis auf ausgewählte Objekte.
•Gibt es einen Verweis auf eine Entity-Objekt vom Persistence Context aus und von außen, und wird dann clear() den Persistence Context löschen, wird der Garbage-Collector das Objekt natürlich nicht freigeben.
–Das losgelöste Entity-Objekt kann später mit merge() wieder in den Persistence Context gesetzt werden.
Gui-Designer in NetBeans 6 (M10) mit Unterstützung für Beans Binding technology (JSR 295) + Swing Application Framework (JSR 296)
Ein kleines Demo zeigt, was heute mit BeanBeans möglich ist: http://www.netbeans.org/download/flash/netbeans_6_gui_builder/netbeans_6_gui_builder.html. Sehr hübsch. Ich lasse mich mal überraschen, wie verpfuscht dann die Gui-Anwendungen werden, wenn sie ohne Kenntnisse über den Entwurf mehrschichtiger Anwendungen gebaut werden.
Automatische Konvertierung von .NET Enterprise Anwendungen über Cross-Compiler in eine Java EE Anwendung
Das hat Mainsoft geschafft. Über die Portierung spricht sich der Hersteller des Cross-Compilers unter http://www.mainsoft.com/solutions/pdfs/PerformanceStudy.pdf aus. Interessant finde ich die Performace-Ergebnisse: Die Anwendung läuft unter dem WebSphere AppServer genauso schnell wie unter der MS .NET Plattform.
The software vendor successfully ported their .NET based application platform onto Java EE using Mainsoft’s technology and professional services saving $1M in R&D costs. The performance of this application was tested on the same hardware and under the same stress test conditions. The ported version of the application showed equivalent performance in average response time, and equivalent performance in server throughput. Thus, an SLA could be met using the ported version of the application without additional hardware investment. The Java EE version of the application also showed that in multi-CPU environments, the scalability characteristics of Java EE and WebSphere Application Server began to show marked improvements over the original .NET application.
Kostenschätzung von Open-Source Projekten mit ohloh
Die Seite ohloh schätzt die Projektkosten bekannter Open-Source Projekte. Unter der Annahme, ein Entwickler verdient $55,000 im Jahr, ergeben das für einige Projekte folgende Zahlen:
Open-Office: $186,086,458
Eclipse WTP: $46,954,139 (WOW!) Nur das WTP soll teurer als das gesamte NetBeans sein?
NetBeans: $35,872,047
Firefox: $27,993,803
JBoss: $20,908,809
Gimp: $17,219,225
Hibernate: $11,779,390
ghostscript: $11,439,855
Samba: $8,359,750
PostgreSQL: $7,473,356
Derby: $7,210,467
Tomcat: $2,766,102
Lucene: $1,809,755
HSQLDB: $1,686,517
Notepad++: $1,224,341
XFire: $931,946
IBMs tolle Seminarbeschreibung…
„Für einen Administrator ist Administration eines Servers, der in Java geschrieben ist und auf dem eine Software läuft, die wiederum in Java geschrieben ist, ohne grundlegende Kenntnisse der Programmiersprache Java sehr schwierig.“ (Quelle) Danke IBM!