I created an UML diagram for the JVLC Java Multimedia Library version 0.9.
Die Physik-Engine Phys2D
Phys2D ist eine 2D Physik-Engine, welches Massen, Trägheiten, Reibung simuliert. Die Bibliothek ist in Java 1.4 programmiert und unterstützt
- Boxes
- Circles
- Static Lines
- Restituion and Friction
- Fixed, Elastic and Loose Joints
- Angluar Velocity/Momentum
- Simple API
- Quad Tree Collision
- Gideon Smeding’s Polygon
Ein Demo gibt es via via webstart.
Shell-Script-Editor (ShellEd) und Eclipse Target Management Project/Remote System Explorer
ShellEd (Bild) ist ein Shell-Script-Editor für Unix-Skripte (also ash, bsh, bash, csh, ksh, sh, zsh). Mit Manual und Vervollständigung. Interessant dazu ist das relativ unbekannte Target Management Project, wo man remote, etwa über SSH oder FTP auf einem Server arbeiten und zum Beispiel Dokumente editieren kann. Siehe dazu den Screenshot zum Remote System Explorer (RSE).
Mehr Eclipse-Plugins gibt’s unter http://www.tutego.com/java/eclipse/plugin/eclipse-plugins.html.
Java EE 6 — das Spiel geht weiter
Es war klar, dass es nach der Java EE 5 ein Java EE 6 geben wird. Nun wurde die neue JSR 313: JavaTM Platform, Enterprise Edition 6 (Java EE 6) Specification ausgerufen. Teil der Java EE 6 wird sein:
- JSR-196 Java Authentication SPI for Containers
- JSR-236 Timer for Application Servers
- JSR-237 Work Manager for Application Servers
- JSR-299 Web Beans
- JSR-311 JAX-RS: Java API for RESTful Web Services
Auf Web-Beans bin ich gespannt, denn da gehen die Ideen von JBoss Seam ein, also EJB 3 und JSF zu verheiraten.
Aktualisiert werden laut Standard:
- Enterprise JavaBeans
- Java Persistence API
- Servlets
- JavaServer Faces
- JAX-WS
Und Verschoben sind:
- JSR-168 Portlet Specification
- JSR-170 Content Repository for Java technology API
- JSR-207 Process Definition for Java
- JSR-208 Java Business Integration (JBI)
- JSR-225 XQuery API for Java (XQJ)
- JSR-235 Service Data Objects
- JSR-286 Portlet Specification 2.0
- JSR-289 SIP Servlet v1.1
- JSR-301 Portlet Bridge Specification for JavaServer Faces
Das Release ist für das 3 Q 2008 angedacht. Viel Zeit also noch.
Eclipse auf das Basis von Swing
Gerade habe ich ein interessantes Projekt gefunden: http://eos.sourceforge.net/. Zwar gab es seit einiger Zeit kein Update, dennoch sehen die Screenshots schon sehr gut aus: http://eos.sourceforge.net/gallery/Eos%20-%204th%20Release%20(Beta%20Status)/index.html.
PHP in purem Java mit Quercus
Quercus (http://quercus.caucho.com/) implementiert eine PHP 5 Engine in purem Java. Die Software ist unter LGPL und stammt von Caucho, die auch den performanten Resin-Server implementieren. Laut Herstellerangaben laufen bisher
- DokuWiki, Dragonfly CMS, Drupal, Gallery2, Joomla, Mambo, Mantis, MediaWiki, Phorum, phpBB, phpMyAdmin, PHP-Nuke, WordPress, XOOPS (http://quercus.caucho.com/quercus-3.1/doc/quercus-list-of-applications.xtp)
Von den PHP-Funktionen fehlen bisher:
- call_user_method, call_user_method_array, get_declared_interfaces, interface_exists, property_exists
- date_default_timezone_get, date_default_timezone_set, date_sunrise, date_sunset, idate, localtime, strptime
- debug_print_backtrace, restore_exception_handler, set_exception_handler
- exif_read_data, exif_thumbnail, exif_tagname
- disk_free_space (stub), disk_total_space (stub), readlink (stub), umask (stub)
- register_tick_function, unregister_tick_function
- bind_textdomain_codeset (stub)
- headers_list, setrawcookie
- ob_iconv_handler
- imagecolorclosesthwb, imagecolorset, imagecolorstotal, imageftbbox, imagefttext, imagegammacorrect, imageinterlace, imagelayereffect, imageloadfont, imagepalettecopy, imagepsbbox, imagepscopyfont, imagepsencodefont, imagepsextendfont, imagepsfreefont, imagepsloadfont, imagepsslantfont, imagepstext, imagerotate, iptcembed, image2wbmp, jpeg2wbmp, png2wbmp, imagecreatefromgd2, imagecreatefromgd2part, imagecreatefromgd, imagegd2, imagegd
- ezmlm_hash
- mhash_keygen_s2k
- connection_aborted, connection_status, connection_timeout, __halt_compiler, highlight_file, highlight_string, ignore_user_abort, php_check_syntax, php_strip_whitespace, show_source, sys_getloadavg, time_nanosleep, time_sleep_until
- mysqli_debug, mysqli_disable_reads_from_master, mysqli_disable_rpl_parse, mysqli_info, mysqli_kill, mysqli_master_query, mysqli_report, mysqli_rpl_parse_enabled, mysqli_rpl_probe, mysqli_rpl_query_type, mysqli_send_long_data, mysqli_send_query, mysqli_server_end, mysqli_server_init, mysqli_ssl_set, mysqli_stmt_send_long_data, mysqli_thread_id, mysqli_thread_safe
- dns_get_record, inet_ntop, inet_pton, long2ip, pfsockopen, socket_get_status, socket_get_blocking, socket_get_timeout
- assert_options, dl (stub), get_current_user (stub), get_included_files, get_magic_quotes_gpc, get_magic_quotes_runtime, get_required_files, getopt, getrusage, ini_restore, memory_get_usage, php_ini_scanned_files, php_logo_gid, phpcredits, putenv, restore_include_path, set_magic_quotes_runtime, zend_logo_gid, zend_version
- proc_close, proc_get_status, proc_nice, proc_open, proc_terminate
- stream_bucket_append, stream_bucket_make_writeable, stream_bucket_new, stream_bucket_prepend, stream_filter_append, stream_filter_prepend, stream_filter_register, stream_filter_remove, stream_get_filters, stream_get_meta_data, stream_select, stream_set_blocking, stream_set_timeout (stub), stream_set_write_buffer (stub), stream_socket_accept, stream_socket_server, stream_socket_client, stream_socket_enable_crypto, stream_socket_get_name, stream_socket_pair, stream_socket_recvform, stream_socket_sendto, stream_socket_server
- xml_error_string, xml_get_current_byte_index, xml_get_current_column_number, xml_get_current_line_number, xml_get_error_code, xml_set_external_entity_ref_handler
- und noch ein paar
Aus PHP heraus lassen sich Java-Objekte bauen und auf die gesamte API zugreifen:
<?php
$a = new java(„java.util.Date“, 1234567);
echo $a->day();
?>
Neu eingeführt in PHP wurde auch das import Schlüsselwort.
Beiträge, die sich mit Quercus beschäftigen und zeigen, wie das MediaWiki und Forums-Software läuft, sind:
- http://blogs.sun.com/alexismp/entry/php_in_glassfish_first_steps, Video: http://blogs.sun.com/alexismp/resource/phpbbingf.html
- 100% Java Quercus PHP engine running in GlassFish Java EE 5 Application Server… http://weblogs.java.net/blog/ludo/archive/2007/03/100_java_quercu.html
- Java and PHP Intermingling? http://www.javalobby.org/java/forums/t91427.html
JAX-WS 2.1 with Spring under Java 6
First you need some jars in your classpath of an web application
- commons-logging.jar
- jaxw-api.jar
- jaxws-rt.jar
- jaxws-spring-1.1.jar
- saaj-api.jar
- saaj-impl.jar
- spring.jar
- stax-ex.jar
- streambuffer.jar
- xbean-spring-2.8.jar
The Jars are from Spring itself, http://geronimo.apache.org/xbean/, https://jax-ws.dev.java.net/ (jax-ws 2.1, JAXWS2.1_nightly.zip) and https://jax-ws-commons.dev.java.net/spring/ (jaxws-spring-1.1.jar). It is although important to place
- jaxb-api.jar
- jaxb-impl.jar
under C:\Programme\Apache Software Foundation\Tomcat 5.5\common\endorsed.
This was the necessary and boring preparation.
Next the Web Service itself
package com.tutego.service;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class GreeterService
{
@WebMethod
public String greet( String name )
{
return "Hello " + name + "!"
}
}
And web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>SpringWeb</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>jaxws-servlet</servlet-name>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSSpringServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jaxws-servlet</servlet-name>
<url-pattern>/greet</url-pattern>
</servlet-mapping>
</web-app>
The applicationContext.xml follows the suggestions with the namespace.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ws="http://jax-ws.dev.java.net/spring/core"
xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core.xsd
http://jax-ws.dev.java.net/spring/servlet http://jax-ws.dev.java.net/spring/servlet.xsd">
<ws:service id="greeterService"
impl="com.tutego.service.GreeterService" />
<wss:bindings id="jax-ws.http">
<wss:bindings>
<wss:binding url="/greet" service="#greeterService" />
</wss:bindings>
</wss:bindings>
</beans>
Now you can consume your WS. If your Web-Context is SpringWeb use http://localhost:8080/SpringWeb/greet?wsdl. Enjoy it!
Spring in einer Web-Applikationen nutzen – so einfach ist das
Mit dem WTP ist es eine Sache von Minuten.
Lege ein Dynamic-Web-Projekt an. Nenne es etwa spring.
Aus dem Spring-all-in-one-glücklich.zip kopiere spring.jar und common-loggings.jar in das WEB-INF/lib.
Lege in WEB-INF eine Datei applicationContext.xml.
Setze in die Datei:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans><bean id="date" class="java.util.Date" />
</beans>
Setzte in WEB-INF/web.xml die Zeilen:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param><listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
Schreibe eine index.jsp
<%@page import="org.springframework.web.context.support.WebApplicationContextUtils"%>
<%@page import="org.springframework.context.ApplicationContext"%>
<%
ApplicationContext appContext = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
%><%= appContext.getBean("date") %>
Das war’s. Unter http://localhost:8080/spring/ gibt’s dann das Datum.
Swing Application Framework und Swing Databinding — eine Aufzeichnung
Axis2/XFire Zoff. Der Gewinner: JAXWS 2.1?
Im Moment tobt der Kampf zwischen Axis2 und XFire um die Performance-Krone. Einige Benchmarks zeigen Axis2 vorne, doch das wohl nur, weil eigentlich XML-Bindings-Frameworks (JAXB bei XFire, ADB (Axis2 Data Binding) bei Asix2), also vergleichen werden, und nicht der Serialisierer selbst. Andere wiederum erfreuen sich über die Rechtschreibfehler in der Axis2-Doku bis zur Frustration:
- isOneHanlder
boolean isOneHanlder
this is want if the phaseFirst and phaseLst same hanlder that is for this phase there is only one phase - This send the SOAP Message to other SOAP nodes and this alone write the SOAP Message to the wire. Out flow must be end with one of this kind.
- cloneOMElement
public OMElement cloneOMElement()
Clones this element. Since both elements are build compleletely, you will lose the differed building capability.
Returns:
Returns OMElement.
Im Moment sieht gar nicht so schlecht für die Referenzimplementierung aus, insbesondere seit der neuen Version JAXWS 2.1 FCS. Die Performance-Ergebnisse sind ausgezeichnet und Spring-Support gibt’s auch. Was will man mehr?
Einiges mehr zur Debatte:
SwingX Demos
Unter http://swinglabs.org/demos.jsp gibt’s ein Demo (JNLP) aller zentraler SwingX-Komponenten. Im Incubator ist auch einiges interssantes dabei — eine JXSplitButton Demo habe ich immer schon vermisst.
JNLP-Demos:
XFire + JSR 181 Annotations + Jetty = Simple Web-Service
package xfire;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService( serviceName = "GreeterService" )
public class GreeterService
{
@WebMethod
public String greet( Person p )
{
return "Hello " + p.getName() + "!";
}
}
package xfire;
public class Person
{
private String name;
public Person()
{
}
public Person( String name )
{
this.name = name;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
}
package xfire;
import org.codehaus.xfire.XFire;
import org.codehaus.xfire.XFireFactory;
import org.codehaus.xfire.annotations.AnnotationServiceFactory;
import org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations;
import org.codehaus.xfire.server.http.XFireHttpServer;
import org.codehaus.xfire.service.Service;
public class ServiceServer
{
public static void main( String[] args ) throws Exception
{
XFire xfire = XFireFactory.newInstance().getXFire();
AnnotationServiceFactory factory = new AnnotationServiceFactory(
new Jsr181WebAnnotations(),
xfire.getTransportManager() );
Service service = factory.create( GreeterService.class );
xfire.getServiceRegistry().register( service );
new XFireHttpServer().start();
// http://localhost:8081/GreeterService?wsdl
}
}
package xfire;
import java.net.MalformedURLException;
import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.service.binding.ObjectServiceFactory;
public class ServiceClient
{
public static void main( String[] args ) throws MalformedURLException
{
ObjectServiceFactory serviceFactory = new ObjectServiceFactory();
Service serviceModel = serviceFactory.create( GreeterService.class );
GreeterService service = (GreeterService)
new XFireProxyFactory().create( serviceModel,
"http://localhost:8081/GreeterService" );
String s = service.greet( new Person( "Ulli" ) );
System.out.println( s );
}
}
@Service-EJBs bei JBoss — EJB 3.1 ruft
Bei JBoss ist eine Service-Bean eine besondere EJB, wovon es serverseitig nur ein Exemplar gibt.
Unterschiedliche Clients werden immer mit dem gleichen Exemplar arbeiten.
Es ist ein Singleton, ein nicht gepooltes Objekt.
Eine Service-Bean wird mit @org.jboss.annotation.ejb.Service annotiert.
@Service
public class VitalityCheckBean implements…
Über @Remote und/oder @Local wäre sich auch ganz normal von außen zugänglich.
Interessant sind Service-Bean, weil sie an einem MBean-Server angemeldet werden können und so über JMX zugänglich sind.
Dazu muss die EJB
mit @Service annotiert werden,
ein Management-Interface für die JMX-Operationen implementieren und
mit der Annotation @org.jboss.annotation.ejb.Management das Management-Interface benennen.
Das Management-Interface ist eine ganz normale Java-Schnittstelle und muss keiner Namenskonvention folgen.
Alle dort genannten Methoden sind über eine JMX-Konsole sichtbar.
interface MyManagementInterface
{
void doIt();
String getValue();
void setValue( String string );
}
import org.jboss.annotation.ejb.*;
@Service
@Management( MyManagementInterface.class )
public class SimpleServiceBean implements MyManagementInterface
{
private String string = „(default)“
public void doIt() {
System.out.println( „Ausgabe“ );
}
public void setValue( String string ) {
this.string = string;
}
public String getValue() {
return string;
}
}
In der JMX-Konsole unter http://localhost:8080/jmx-console/ suchen nach SimpleServiceBean mit ManagementInterface.
Der JMX-ObjectName lässt sich über das Attribut objectName der Annotation @Service ändern:
@Service(objectName=“javatutor:service=SimpleServiceBean“)
@Management(MyManagementInterface.class)
public class SimpleServiceBean implements …
Weiteres, auch zum Lebenszkylus unter
Eclipse-Plugin JSEclipse für JavaScript
JSEclipse: Ein JavaScript Editor aus den Adobe-Labors. Der bietet farbliche Hervorhebung, Templates, Tastaturvervollständigung, Fehler- und Hinweismeldungen, Outline und mehr. Das Plugin lässt sich manuell, oder über den Update-Manger mit der Adresse http://download.macromedia.com/pub/labs/jseclipse/autoinstall installieren. In einem Forum finden Probleme und Lösungen zusammen. Die Doku wird im Eclipse Hilfe-Manager eingebunden. (Bild 1, Bild 2)
Java 2D unter 3D JOGL
Das Programm mit zu starten ist ein MUSS!
Mehr zur Vorgehensweise, wie Java 2D mit JOGL auf Open GL kommt, gibt es unter http://weblogs.java.net/blog/campbell/archive/2007/01/java_2d_and_jog.html.
Jettison – JSON-Dokumente nach dem StAX-Modell schreiben
Viele JSON-Implementierungen nehmen ein direktes Mapping der Java-Objekte nach JSON vor. http://jettison.codehaus.org/ geht da einen anderen Weg. Mit den aus StAX bekannten Methoden zum Schreiben/Lesen von Elementen wird nicht in ein XML-Format „gemarshalled“, sondern in das JSON-Format. Ein Testfall für MappedXMLStreamWriterTest macht deutlich, was hier vor sich geht:
StringWriter strWriter = new StringWriter(); MappedNamespaceConvention con = new MappedNamespaceConvention(); AbstractXMLStreamWriter w = new MappedXMLStreamWriter(con, strWriter); w.writeStartDocument();w.writeStartElement("root"); w.writeStartElement("child1");w.writeStartElement("subchild1");w.writeCharacters("test");w.writeEndElement(); w.writeStartElement("subchild2");w.writeCharacters("test");w.writeEndElement(); w.writeEndElement(); w.writeStartElement("child2");w.writeStartElement("subchild");w.writeCharacters("test");w.writeEndElement();w.writeEndElement(); w.writeEndElement();w.writeEndDocument(); w.close();strWriter.close(); System.out.println(strWriter.toString()); assertEquals("{\"root\":{" +"\"child1\":{\"subchild1\":\"test\",\"subchild2\":\"test\"}," +"\"child2\":{\"subchild\":\"test\"}}}", strWriter.toString());
Ein Servlet/JSP würde statt in den StringWriter in den response Strom schreiben.
SimpleJdbcTemplate aus Spring 2.0
Das org.springframework.jdbc.core.JdbcTemplate compiliert unter Java 1.4 und nutzt keine Eigenschaften von Java 5 wie Generics, Autoboxing und Varags.
Seit Spring 2.0 gibt es mit org.springframework.jdbc.core.simple.SimpleJdbcTemplate eine neue Klasse mit eine überschaubaren Anzahl Methoden für Java 5.
– Es ist eine Java 5-Fassade vor dem JdbcTemplate.
Der Konstruktor von SimpleJdbcTemplate nimmt wie JdbcTemplate eine DataSource an.
Methoden vom SimpleJdbcTemplate
int queryForInt(String sql, Object… args)
long queryForLong(String sql, Object… args)
Erfragt ein int/long über einen SQL-String und Argumenten.
List<Map<String,Object>> queryForList(String sql, Object… args)
Map<String,Object> queryForMap(String sql, Object… args)
Führt die SQL-Anfrage mit optionalen Argumenten aus.
<T> T queryForObject(String sql, ParameterizedRowMapper<T> rm, Object… args)
Die SQL-Anfrage liefert ein Ergebnis, das der Mapper auf ein Objekt überträgt.
<T> T queryForObject(String sql, Class<T> requiredType, Object… args)
Führt eine SQL-Anfrage aus und überträgt die Eigenschaften auf ein Objekt.
<T> List<T> query(String sql, ParameterizedRowMapper<T> rm, Object… args)
Der ParameterizedRowMapper überträgt Ergebnisse auf Objekte.
int update(String sql, Object… args)
Führt ein SQL-Update mit optionalen Argumenten durch.
SimpleJdbcDaoSupport
Die DAO-Klassen von Spring erlauben Zugriff auf die Template-Objekte.
Während JdbcDaoSupport ein JdbcTemplate liefert, gibt SimpleJdbcDaoSupport ein SimpleJdbcTemplate.
SimpleJdbcDaoSupport ist eine Unterklasse von JdbcDaoSupport:
org.springframework.jdbc.core.support.JdbcDaoSupport
extended by org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport
Buchkritik "Java 6 Plattform Revealed"
Ein frühes Buch (Juni 2006) zu Java 6, aber es zeigt alle wesentlichen Eigenschaften der neuen Version. Sehr gut gefallen hat mit die Beschreibung von CookieHandler, CookieManager & Co. KG, etwas, was ich noch nie ordentlich erklärt gefunden habe. Der einzige Fehler, der mir aufgefallen ist, befindet sich auf Seite 111, wo eine Variable statt rs (für ResultSet) fälschlicherweise st heißt. Eine präzisere Beschreibung für Web Services und JAXB liefert das Buch leider nicht — nur ein paar Standard-Beispiele und eine schlaffe Aufzählung der Annotationen — aber dafür gibt es ja andere Bücher aus der Ecke der Java EE Literatur. Auch StAX ist nicht sonderlich präzise und späteren Neuerungen, wie Java DB oder GroupLayout finden keine Erwähnung. Das gleiche gilt für neue Funktionen copySign(), getExponent(), nextAfter(), nextUp(), scalb() aus Math/StrictMath. Eigentlich wäre jetzt Zeit für ein Buch-Update.
John Zukowski. APress. ISBN 1590596609. 220 Seiten
Prefuse: Immer wieder schöne Graphen
Das „prefuse visualization toolkit“ ist eine feine API zur Informationsvisualisierung. In der visualization gallery gibt es etwa folgendes zu sehen und auszuprobieren:
Small-World Networks by Stephen Frowe Ingram
Vizster by Jeffrey Heer and danah boyd
Flow Map Layout by Doantam Phan
NameVoyager by Martin Wattenberg, rebuilt by Jeffrey Heer
zipdecode by Ben Fry, rebuilt by Jeffrey Heer
RadialGraphView Demo by Jeffrey Heer
GraphView Demo by Jeffrey Heer
FisheyeMenu Demo by Jeffrey Heer
Closures – Muss das wirklich sein?
Nach dem vierten Proposal (http://www.javac.info/closures-v04.html) für Closures von Gilad Bracha, Neal Gafter (der mit dem Java-Puzzlers), James Gosling und Peter von der Ahé (nach seiner Whishlist unter http://blogs.sun.com/ahe/entry/java_se_7_wish_list werden weitere abgefahrene Sachen möglich sein) wird in der Community heftig diskutiert, ob Closures nötig sind. Ich finde sie toll! Zwar sehe ich schon meine Teilnehmer über den Ausdrücken brüten und zweifeln an der Aussage „Java ist eine einfache objektorientierte Programmiersprache“ zweifeln, doch denke ich, dass es unausweichlich ist, Java mehr sprachliche Möglichkeiten zu bieten.
Java: A simple, object-oriented, network-savvy, interpreted, robust, secure, architecture neutral, portable, high-performance, multithreaded, dynamic language […] Java omits many rarely used, poorly understood, confusing features of C++ that in our experience bring more grief than benefit. [http://java.sun.com/docs/overviews/java/java-overview-1.html]
Dass Java im Moment so viele Veränderungen erfährt ist vielleicht auch eine Frage der Wahrnehmung. Sun war mit Grammatikänderungen bisher sehr konservativ und seit mehr als 10 Jahren haben wir bis auf den Wechsel von Java 1.0 auf Java 1.1 und Java 1.4 auf Java 5.0 kaum Änderungen gesehen; strictfp/Sprachänderungen wäre man so ein Außenseiter. Nun gibt es stärkere Veränderungen, wie wir sie bei anderen Sprachen auch erleben. C# hat sich in den letzten Jahren unglaublich verändert — was als Java-Klon begann, ist heute eigenständig und als Sprache hoch innovativ. Mitunter starke strukturelle Änderungen lassen sich auch bei Skriptsprachen ausmachen, etwa Python (trinärer Operator, try/except/finally), PHP (die ganzen OOP-Eigenschaften), Perl (für Perl 2.6 ebenfalls Änderungen der OOP-Schreibweise/perl6-language-objects und funktionale Programmierelemente geplant) aber auch C++ und SQL. Als Java-Entwickler hat uns Sun nur in den letzten Jahren so „erzogen“ dass es kaum große Änderungen gab, was sich nun ändert. Hier muss Sun uns also wieder „umerziehen“.
Dass Java keine einfache Programmiersprache ist, müsste jedem eigentlich bewusst geworden sein, der didaktisch versucht, Konzepte wie Generics zu vermitteln. Unternehmen müssen auch mit nicht-Cracks Software entwickeln können und können nicht darauf bauen, dass alle Mitarbeiter Spezifikationen lesen und Best-Practices befolgen. (IMHO kann man mit OOP-Spezialisten in jeder Programmiersprache exzellente Ergebnisse erziehlen.) Eine Sprache muss daher auch immer ein bisschen Narrensicher sein. (Ein kleiner Seitenhieb auf Perl, der Sprache, der man „Write Once Read Never“ (WORN) nachsagt.) Da sehe ich in Closures auf jeden Fall ein Problem, denn während Generics doch noch einfach zu lesen sind (von der Deklaration sprechen wir nicht!) sieht das bei Closure-Nutzungen etwas anders aus. Hier muss der Java-Entwickler wieder eine neue Syntax lernen.
Bisher ist in der neuen Syntax kein Wort von neuen Schlüsselwörtern. Das macht die Anwendung einfacher als es bei Java 5 mit enum war. Ein weiterer Punkt ist, dass man über allgemeine Closures Dinge schreiben kann, die wie spezielle Lösungen aussehen. Ein häufig zitiertes Beispiel ist der Lock:
withLock( lock ) { System.out.println( "Closures in Java 7" ); }
Das ist eine Kurzform für
withLock( lock, {=> System.out.println( "Closures in Java 7" ); } );
Es ist gerade nicht withLock() ein spezielles Java-Konstrukt, sondern nur die Anwendung eines allgemeinen Closures. Intern wird das Umgesetzt über übliche Schnittstellen. Und mit { => } sieht man schon, wie Closures in Java aussehen können.
In der Summe finde ich Closures toll und freue mich schon. Zwar habe ich schon die ersten Ideen, wie man das didaktisch umsetzen kann, aber mal sehen, was bis dahin geschrieben wird. Was Madbean unter http://madbean.com/2006/closure/ zeigt, finde ich schon nett. Doch bis Java 7 „freigelassen“ wird, dauert es noch. Wer sich schon einmal vorbereiten möchte, der sollte sich zum Beispiel die Präsentation von Neal Gafter unter http://www.bejug.org/confluenceBeJUG/display/PARLEYS/Closures+for+Java anschauen.