Google Android ist der Versuch von Google, ein quelloffenes und freies SDK für mobile Endgeräte zu etablieren. Nach ein paar Monaten gibt es die ersten Stimmen aus dem Netz, die nicht so positiv sind. Insbesondere werden die mangelhafte Dokumentation (damit meine ich nicht die „FAQ“ http://code.google.com/android/kb/general.html), fehlende Beispiele und ein nicht öffentliches Issue/Bug-Tracking-System bemängelt. Interessant ist ebenfalls der Ansatz von Google, eine eigene JVM auszuliefern, um sich damit eventuell um Lizenzrechte rumzuwinden. Die Idee ist, den Java Quellcode zunächst über den Standard-Compiler in Java Bytecode zu übersetzen, aber dann über einen weiterer Präprozessor dx den JVM-Bytecode in das so genannte DEX-Format zu bringen, was die VM Dalvik dann ausführt. Dalvik ist etwas anders gebaut als die Standars-JVMs, denn es ist zum Beispiel eine Register-Maschine und keine Stack-Maschine. Ein weiteres Detail sind die Bibliotheken. Die Java Standard Library kommt vom Apache Harmony Projekt und ist somit Apache-Lizenz, genauso wie vieles von Android auch. (Das Betriebssystem unter der Haube ist Linux und somit GPL.)
Allgemein
Sehr große Anfrage an den JBuilder
In meiner Linksammlung sitzt http://www.borland.com/jbuilder, was mit der Browser nun beantwortet mit:
Server Error in ‚/‘ Application.
|
Entweder geht es dem Produkt wahnsinnig gut und jeder will den JBuilder kaufen/laden/… oder .NET ist so schlecht, dass es mit der Last nicht umgehen kann.
Warum catch ( Exception e ) schlecht ist, und was man dagegen tun kann
Eine ganze Reihe von Java-Methoden lösen eine ganze Reihe von unterschiedlichen Ausnahmen aus:
private void setLaf()
{
try
{
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
}
catch ( ClassNotFoundException e )
{
handle();
}
catch ( InstantiationException e )
{
handle();
}
catch ( IllegalAccessException e )
{
handle();
}
catch ( UnsupportedLookAndFeelException e )
{
handle();
}
}
Oftmals befindet sich dann im Quellecode eine Anweisung wie catch ( Exception e ), die große Kaskaden von catch-Anweisungen verkleinern soll. (So kann man auch den gleichen Handler verwenden.) Das Problem dabei: Man fängt mehr, als man will, insbesondere wertvolle RuntimeExceptions, die man ungern als checked SQL- oder sonstwas-Exeption vernudelt haben möchte. Wenn ich mir moderne Frameworks, wie Spring oder Java EE 5 anschaue, wird dort ausschließlich mit RuntimeException gearbeitet, und die fängt eine catch ( Exception e ) ebenfalls brutal ab. Wenn zum Beispiel das Framework aufgrund einer unchecked Exception eine Transaktion abbricht, wir diesen Fehler aber schon „weggefangen“ haben, ist das ein echtes Problem.
Ich sehe für eine vernünftige Behandlung mehrere Möglichkeiten:
- Warten auf Java 3000, da dort sicherlich so etwas wie catch ( IOException, SQLException e ) definiert wird.
- Eine gemeinsame handle()-Funktion zu definieren, die man dann aus den catch-Handlern ansteuert.
- Ein catch ( Exception e ) und dann ein instanceof Test auf die erwarteten Exceptions mit einer re-thow, wenn der Typ nicht bekannt ist.
Schlechter Quellcode von NeuralBuild (NeuralLimits)
Über den Artikel http://entwickler.com/itr/news/psecom,neu,1,id,39010,nodeid,82.html bin ich auf einen Generator aufmerksam geworden, der automatisch DOAs und Transfer-Objekte erzeugt. Leider ist doch der generierte Quellcode wenig überzeugend. En Besipiel:
public Integer insertCompany(Company criteriaCompany)
throws NeuralBuildJavaSampleDAOInsertException {
Integer keyVal = new Integer(0);
con = connMgr.getConnection("neuralbuildjavasample");
int setindex = 1;
String vSQL = constructInsertPreparedStatement(criteriaCompany);
try {
PreparedStatement ps = con.prepareStatement(vSQL,
PreparedStatement.RETURN_GENERATED_KEYS);
if (criteriaCompany.CompanyID_isSet) {
ps.setInt(setindex, criteriaCompany.getCompanyID().intValue());
setindex++;
}
if (criteriaCompany.CompanyName_isSet) {
ps.setDate(setindex,
(java.sql.Date) criteriaCompany.getCompanyName());
setindex++;
}
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
keyVal = Integer.valueOf(rs.getObject(1).toString());
}
rs.close();
rs = null;
ps.close();
} catch (Exception e) {
connMgr.freeConnection("neuralbuildjavasample", con);
throw new NeuralBuildJavaSampleDAOInsertException("Insert Failed " +
e.getMessage(), e);
}
connMgr.freeConnection("neuralbuildjavasample", con);
return keyVal;
}
- new Integer(0) wird immer gebaut, auch wenn es später überschrieben wird.
- finally fehlt: So ist das close() nicht garantiert. (Nicht sooo schlimm, da bei Freigabe der Connection auch ResultSet und XXXStatement freigegeben werden.)
- Quellcode-Duplizierung bei connMgr.freeConnection(„neuralbuildjavasample“, con);. Das gehört auf jeden Fall in finally{}
- Was soll den rs = null; bewirken? Den GC hilt das bei lokalen Variablen nun wirklich nicht.
- catch (Exception e) muss wirklich sein? Ode doch catch (SQLException e)?
- Wenn die Rückgabe ein Integer-Objekt ist, warum dann „Integer.valueOf(rs.getObject(1).toString());“ schreiben? Das funktioniert zwar, aber wenn getObject() schon in Integer ist, muss man nicht erst in ein String und dann wieder zurück konvertieren.
- Sollte man wirklich einfach nur 0 zurückliefern, wenn man keinen Schlüssel bekam?
Die anderen Methoden habe auch so ihre Macken, so mit der Namensgebung.
- CachedRowSet Rs = null; Groß-/Kleinschreibung!
- Gemische Groß-/Kleinschreibung ist Standard, nicht so bei setindex.
- Unterstriche sind von Sun in der Namenskonvention nur bei Konstanten vorgesehen, aber nicht etwa bei CompanyID_isSet
- Ist die Namensgebung so gut, wenn man liest
ps.setDate(setindex, (java.sql.Date) criteriaCompany.getCompanyName() );
Also setDate() auf ein Company-Name? - Die API-Doku sollte nicht schreiben: „Delete an object from the database.“ sondern laut Suns-JavaDoc-Vorgaben: „Deletes an object from the database.“
"Whitespace cleanup on all sources" Java-Quellen endlich einheitlich
Nach mehr als 10 Jahren sind in Java 7 endlich die Quellen so, dass nicht mehr Tabs und Spaces gemischt sind. Endlich. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6616089.
Die übelste Java-Implementierung für einen Schaltjahrtest…
… gibt es bei Worse than failure im Forum unter http://forums.worsethanfailure.com/forums/thread/31448.aspx.
JAXB2-Annotationen an Beispielen
Schreiben der Felder statt Nutzen der Setter/Getter: Annotiere die Klasse mit
@XmlAccessorType( XmlAccessType.FIELD )
@XmlAttribute
class Person { String name;
@XmlAttribute int id; } |
<person id=“123″> <name>Christian</name> </person> |
@XmlValue
Gibt es nur ein Element kann @XmlValue dies in den Rumpf setzten.
class Person { int id; } |
<person> <id>123</id> </person> |
class Person { @XmlValue int id; } |
<person>123</person> |
@Transient
Nimmt Element aus der XML-Abbildung aus.
class Person { @XmlTransient int id;
String firstname; String lastname; } |
<person> <firstname>Christian</firstname> <lastname>Ullenboom</lastname> </person> |
@XmlList
Schreibt Elemente einer Sammlung nicht in einzelnen Elementen, sondern mit Leerzeichen getrennt.
class Person { List<String> emails; }
|
<person> <emails>muh@kuh.de</emails> <emails>zick@zack.com</emails> </person>
|
class Person { @XmlList List<String> emails; } |
<person> <emails>muh@kuh.de zick@zack.com</emails> </person> |
Elemente einpacken mit @XmlElementWrapper
class Person { List<String> emails; } |
<person> <emails>muh@kuh.de</emails> <emails>zick@zack.com</emails> </person> |
class Person { @XmlElementWrapper(name = „emails“) @XmlElement(name = „email“) List<String> emails; } |
<person> <emails> <email>muh@kuh.de</email> <email>zick@zack.com</email> </emails> </person> |
Reihenfolge ändern
class Person { String lastname, firstname; } |
<person> <lastname>Ullenboom</lastname> <firstname>Christian</firstname> </person> |
@XmlType( propOrder = { „firstname“, „lastname“ } ) class Person { String lastname, firstname; } |
<person> <firstname>Christian</firstname> <lastname>Ullenboom</lastname> </person> |
@XmlJavaTypeAdapter
Anpassen der XML-Abbildung, etwa für Datumswerte.
class Person { Date birthday; } |
<person> <birthday>1973-03-12T00:00:00+01:00</birthday> </person> |
class Person { @XmlJavaTypeAdapter( DateAdapter.class ) Date birthday; }
class DateAdapter extends XmlAdapter<String, Date> { private final static DateFormat formatter = new SimpleDateFormat( „dd/MM/yyyy“ );
public Date unmarshal( String date ) throws ParseException { return formatter.parse( date ); }
public String marshal( Date date ) { return formatter.format( date ); } } |
<person> <birthday>12/03/1973</birthday> </person> |
Der spezielle Datentyp XMLGregorianCalendar
Neben der Möglichkeit, Datumswerte mit einen XmlJavaTypeAdapter zu übersetzen, bietet JAXB den Datentype XMLGregorianCalendar.
Person p = new Person();
GregorianCalendar c = new GregorianCalendar( 1973, Calendar.MARCH, 12 );
p.birthday = DatatypeFactory.newInstance().newXMLGregorianCalendar( c );;
class Person { XMLGregorianCalendar birthday; } |
<person> <birthday>1973-03-12T00:00:00.000+01:00</birthday> </person> |
Die Abbildung enthält alle notwendigen Werte. Sollen Segmente, wie die Zeitzone herausgenommen werden, so markiert man sie aus:
Person p = new Person();
GregorianCalendar c = new GregorianCalendar( 1973, Calendar.MARCH, 12 );
XMLGregorianCalendar gc = DatatypeFactory.newInstance().newXMLGregorianCalendar( c );
gc.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
gc.setTime(DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED);
p.birthday = gc;
class Person { XMLGregorianCalendar birthday; } |
<person> <birthday>1973-03-12</birthday> </person> |
Elemente einbetten mit @XmlElements
Person p = new Person();
EmailContact c1 = new EmailContact();
c1.address = „hoho@weihnachtsmann.de“;
PhoneContact c2 = new PhoneContact();
c2.number = „0011-123456789“;
p.contacts = Arrays.asList( c1, c2 );
@XmlRootElement @XmlAccessorType( XmlAccessType.FIELD ) class Person { @XmlElements( { @XmlElement( name = „email“, type = EmailContact.class ), @XmlElement( name = „phone“, type = PhoneContact.class ) } ) List<Object> contacts = new ArrayList<Object>(); }
@XmlAccessorType( XmlAccessType.FIELD ) class EmailContact { @XmlValue String address; }
@XmlAccessorType( XmlAccessType.FIELD ) class PhoneContact { @XmlValue String number; } |
<person> <email>hoho@weihnachtsmann.de</email> <phone>0011-123456789</phone> </person> |
VisualVM
VisualVM ist eine Open-Source Software zum Profilen von Java-Applikationen und Verfolgen von Referenzen. Screenshots sagen mehr als 1000 Worte.
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.“ );
}
}
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.
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!
Some more information about eBays J2EE application?
The presentation The eBay Architecture – Striking a balance between site stability, feature velocity, performance and cost gave me a first impression of the internal architecture but I would like to know a little bit more about the realization. J2EE is (inglorious) “famous” for EJBs, JMS, JCA, … but these terms are not mentioned in the pdf. I got the impression that eBay is not really using the „hard“ stuff.
- “eBay internally-developed pure Java OR mapping solution.” OK. No CMP. That implies that the container is not responsible for CMT.
- “Keep Application Tier Completely Stateless”. Ok. No Stateful Session Beans.
- “eBay scales on Servlets and a rewritten connection pool.” Hm. So no JDBC 2 connection pool from a vendor. So why is this a Java EE application? Because of Stateless Session Beans? (Then JNDI is in the boat.) The Spring folks will see a opportunity for POJOs on Tomcat/Jetty, … 🙂
Does anyone have some more information about this?