TWAIN-Scannen mit Java

http://www.mms-computing.co.uk/uk/co/mmscomputing/device/twain/ ist eine Java-API für die TWAIN-Schnittstelle, um etwa einen Scanner anzusteuern. Ein Beispiel ist schnell aufgebaut:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;

import org.jdesktop.swingx.JXFrame;
import org.jdesktop.swingx.JXImagePanel;
import org.jdesktop.swingx.JXImagePanel.Style;

import uk.co.mmscomputing.device.scanner.Scanner;
import uk.co.mmscomputing.device.scanner.ScannerIOException;
import uk.co.mmscomputing.device.scanner.ScannerIOMetadata;
import uk.co.mmscomputing.device.scanner.ScannerListener;
public class TwainExample
{
  @SuppressWarnings("serial")
  public static void main( String[] args )
  {
    final JXImagePanel imagePanel = new JXImagePanel();
    imagePanel.setStyle( Style.SCALED_KEEP_ASPECT_RATIO );
    final Scanner scanner = Scanner.getDevice();
    JXFrame f = new JXFrame( "SSP", true );
    Action action = new AbstractAction("Scan") {
      @Override public void actionPerformed( ActionEvent e ) {
        try { scanner.acquire(); } catch ( ScannerIOException ex ) { }
      }
    };
    f.add( new JButton(action), BorderLayout.PAGE_START );
    f.add( imagePanel );
    f.setSize( 1000, 700 );
    f.setVisible( true );
    scanner.addListener( new ScannerListener()
    {
      public void update( ScannerIOMetadata.Type type, ScannerIOMetadata metadata )
      {
        if ( ScannerIOMetadata.ACQUIRED.equals( type ) )
          imagePanel.setImage( metadata.getImage() );
      }
    } );
  }
}

Globale Tastendrücke und Mausoperationen abfangen (Windows)

Globale Mausbewegungen von Java zu überwachen ist mit dem MouseInfo.getPointerInfo().getLocation() kein Problem. Aber mitzubekommen, ob in einer anderen Java-Applikation eine Maustaste oder eine andere Keyboard-Taste gedrückt ist, schon. Wer vor dem Problem steht, dies unter Java und Windows abzufangen, kann SWT zusammen mit den SWT Win32 Extensions (http://www.swtui.cn/index.php) nutzen — auch wenn man selbst nicht mit SWT, sondern mit Swing arbeitet. Soll etwa global die <Pause> Taste abgefangen werden, kann man schreiben:

Hook.KEYBOARD.addListener(new HookEventListener() {
    public void acceptHookData( HookData hookData ) {
      if ( ((KeyboardHookData) hookData).getVirtualKeyCode() == KeyEvent.VK_PAUSE &&
          ! ((KeyboardHookData) hookData).getTransitionState() ) {
         // TU WAS DICH GLÜCKLICH MACHT
      }
} } );
Hook.KEYBOARD.install();

Neben Hook.KEYBOARD gibt es auch Hook.MOUSE.

Möchte man nun beides zusammen haben, also wissen, ob etwa STRG und eine Maustaste gedrückt wurde, meldet man einen HookEventListener für die Maus an und fragt die Taste wie folgt ab:

Extension.GetKeyState(Extension.VK_CONTROL) < 0

Heise schreibt: "Bedarf an Java-Experten legt weiter rasant zu"

http://www.heise.de/newsticker/Bedarf-an-Java-Experten-legt-weiter-rasant-zu–/meldung/116871

Ob man bei der Aussage "Die Ausschreibungen im Bereich Java haben seit Jahresbeginn stark zugenommen und im August erstmals das Niveau der entsprechenden Projektangebote für SAP-Experten erreicht" dies auf Stärke von Java zurückführen kann, oder einfach nur auf die gesunkene Anfrage von SAP sei einmal dahingestellt.

Dass es einen "Aufschwung hat auch die Nachfrage nach Spezialisten für C++" gibt, haben wir bei tutego tatsächlich gemerkt, da vermehrt Anfragen nach C++ und insbesondere der Boost-Bibliothek zu verzeichnen ist.

HOWTO: Change Title, Autor, Subject of a PDF

package com.tutego.traida.util;

import java.io.FileOutputStream;
import java.util.HashMap;

import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;

public class PdfUtils
{
  public static void setMetaData( String sourceFilename, String targetFilename )
  {
    try
    {
      PdfReader pdfReader = new PdfReader( sourceFilename );
      PdfStamper stamp = new PdfStamper( pdfReader, new FileOutputStream( targetFilename ) );

      @SuppressWarnings("unchecked")
      HashMap<String, String> info = pdfReader.getInfo();
      info.put( "Title", "Rechnung für Beratung" );
      info.put( "Author", "tutego" );
      info.put( "Subject", "Rechnung" );
      info.put( "Keywords", "Rechnung, tutego" );
      info.put( "Creator", "http://www.tutego.com/" );
      info.put( "Producer", "tutego Training Software 1.2" );

      stamp.setMoreInfo( info );
      stamp.close();
      pdfReader.close();
    }
    catch ( Exception e )
    {
      e.printStackTrace();
    }
  }

  public static void main( String[] args )
  {
    setMetaData( "c:/a.pdf", "c:/new.pdf" );
  }
}

With iText of course:  http://www.lowagie.com/iText/

Tja, Neal Gafter geht zu Microsoft

Also mich wundert’s nicht… Von Nealls Webseite http://gafter.com/~neal/:

I work for Microsoft on the dotNet platform languages. To balance my life, my hobby is designing and developing the future of the Java programming language. See, for example, my proposal to add closures to the Java Programming Language. I’ve also been discussing it on my blog.

Also von Sun zu Google und dann zu MS. (Eigentlich hatte MS immer damit zu kämpfen, dass die Mitarbeiter zu Google abwandern.)

Alpha-Version vom JAva COm Bridge (JACOB) Plug-In

Das Eclipse-Plugin http://jacob-project.wiki.sourceforge.net/Jacob+Gen+Plugin erlaubt über einen Menüeintrag einfach das Erzeugen von Stub-Code für den Zugriff auf Windows-DLLs.

 

JacobGenScreenShot.PNG

Der Generator geht einen interessanten Weg über Eclipse JET, wie es die Webseite erklärt:

The plug-in uses the old, JacobGen 0.7, c++ program (dll) which reads a Microsoft’s proprietary TLB file and writes out what it finds on stdout. From the information gathered the plug-in produces an ecore model based of what is found inside the TLB. At this point the plug-in has created a model of what’s inside the DLL file. I.E. what classes and enums exist. The plug-in uses Java Emitter Templates (JET) to generate java code based on the above ecore model. It also produces the java method bodies to automatically call JACOB methods with the correct parameters. This will create a strongly typed java proxy, via JACOB, into the windows DLL.
So to wrap up. The plug-in reads the TLB file (using the existing JacobGEN DLL), creates a model based on the TLB / DLL file, and then produces a java proxy. The JET generated classes are really a proxy into the DLL via JACOB. So the end result is a set of java classes hiding all JACOB internal knowledge.

Und überall sitzt die OSGi Service Platform drunter…

Unter http://www.earthtimes.org/articles/show/world-leading-enterprise-application-server-providers,541827.shtml und http://www.osgi.org/blog/2008/09/impressive-press-release.html führen die Autoren auf, wie beliebt mittlerweile OSGi als Basis für Java EE Container ist. Peter Kriens führt folgende Container auf:

  1. IBM Websphere. They started in 2006 and aggresively moved their code on OSGi. Obviously it helped that IBM has committed itself to OSGi since day -1.
  2. Oracle WebLogic. Formerly known as BEA weblogic. BEA was one of the first companies public touting the advantages of OSGi, clearing the road for others.
  3. Paremus Infiniflow. Paremus has pioneered the use of OSGi in highly distributed application servers allowing the system to scale to unprecendented heights.
  4. ProSyst ModuleFusion. ProSyst is the key provider of OSGi technology in the embedded worlds but originated from the development of a J2EE server. They are now back in this market with an offering based completely on OSGi.
  5. Redhat JBoss. JBoss already worked with a microkernel approach but recognized the advantages of a standard two years ago.
  6. SAP Netweaver. Well, they are not yet based on OSGi, but they clearly see their future based on the OSGi specifications and are becoming more and more active in the OSGi Alliance.
  7. SpringSource Application Platform. The company that simplified Enterprise development with their Spring Framework decided to create their own offering in the application server market completely based on the OSGi specifications.
  8. Sun Glassfish. And last, but definitely not least, Sun decided to use OSGi in the JEE reference implementation Glassfish. They clearly take OSGi extremely serious nowadays since they also hired Richard S. Hall. It is so good to see Sun back at the OSGi Alliance.

Interessant sind zwei Feststellungen:

  1. In der Regel geben die Container die OSGi-Implementierung nicht nach oben weiter, abstrahieren also von den Internas. Nur einige Produkte erlauben, auch selbst OSGi-Bundles anzumelden.
  2. Java EE und das SpringFramework sind beides Nutznießer der OSGi-Plattform. Man kann nun fragen, ob man sich überhaupt noch mit OSGi selbst beschäftigen muss, wenn etwa GlassFish oder http://www.springsource.com/products/suite/applicationplatform gute Abstraktionen bieten.

Das erste Android Programm

Im Moment gibt es ein großes Rumgezampel wegen der NDA von Apple bei der Entwicklung von iPhone-Applikationen und das, was es als Applikationen in den Apple App Store darf und was nicht

Google macht das mit Android besser, da hier alles frei sind wird und auch jede Applikation in den Store kommt. Und ein erstes Programm ist schnell aufgebaut:

  1. Gehe auf http://code.google.com/android/download_list.html.
  2. Lade unter Windows zum Beispiel android-sdk-windows-1.0_r1.zip. Entpacke das Zip, etwa nach C:\Program Files\Java\android-sdk-windows-1.0_r1.
  3. Installiere über den Eclipse Update-Manager das Plugin unter der URL http://dl-ssl.google.com/android/eclipse/. Das dauert! Starte Eclipse neu.
  4. Unter Window > Preferences > Android trage das Verzeichnis C:\Program Files\Java\android-sdk-windows-1.0_r1 ein.
  5. Gehe auf http://code.google.com/android/intro/hello-android.html und führe die Schritte für ein neues Android-Projekt durch.
  6. In die generierte onCreate()-Methode setzte rein:
  7. super.onCreate(savedInstanceState);
    TextView tv = new TextView(this);
    tv.setText("Hello, Android");
    setContentView(tv);
  8. Starte die Applikation wie unter http://code.google.com/android/intro/hello-android.html#run beschrieben im Emulator. Das dauert leider sehr lange!

Thema der Woche: Continuous Integration mit Hudson

Lies zunächst http://martinfowler.com/articles/continuousIntegration.html von Martin Fowler über die Motivation von CI in der Softwareentwicklung.

In den letzten Monaten hat sich das Hudson zu einem Publikumslieblig entwickelt. Studiere die folgende Präsentation:

(Hudson stammt vom Kohsuke Kawaguchi, der eine ganze Reihe sehr interessanter Projekte bei Sun macht, etwas JAXB oder auch https://com4j.dev.java.net/. Wer ein Podcast von ihm und Husdon hören möchte: http://blogs.sun.com/glassfishpodcast/entry/episode_007_interview_with_kohsuke)

Blättere ein wenig auf den Seiten unter http://hudson.gotdns.com/wiki/display/HUDSON/Meet+Hudson. Falls ein Projekt mit CSV- oder SVN-Zugriff verfügbar ist teste Hudson.

Java Tipp: Initialisierung einer Map

Der übliche Weg führt über ein put(), wobei man das unterschiedlich schreiben kann:

Map<String, String> map = new HashMap<String, String>();
map.put( "name", "chris" );
map.put( "email", "a@b.c" );

Oder auch mit einem Exemplarinitialisierer (das ist aber schmutzig in meinen Augen!):

Map<String, String> map = new HashMap<String, String>() {{
  put( "name", "chris" );
  put( "email", "a@b.c" );
}};

Alternative: http://commons.apache.org/collections/api-release/org/apache/commons/collections/MapUtils.html#putAll(java.util.Map,%20java.lang.Object[]). Die API nennt ein Beispiel:

Map colorMap = MapUtils.putAll(new HashMap(), new String[][] {
     {"RED", "#FF0000"},
     {"GREEN", "#00FF00"},
     {"BLUE", "#0000FF"}
});

Die Apache Common Collections sind aber erst einmal nicht generisch!

Für http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Maps.html ist so was wohl geplant, aber bisher noch nicht implementiert.

Java Wikipedia API

Wer von Java aus auf die Inhalte von Wikipedia zugreifen, und die Inhalte auch noch Rendern möchte, findet mit der quelloffenen Java Wikipedia API (http://www.matheclipse.org/en/Java_Wikipedia_API) eine passende Unterstützung.

Zum Laden einer Wikipedia-Seite und Renderer in eine Datei ist lediglich nötig:

User user = new User( "", "", "http://de.wikipedia.org/w/api.php" );
List<Page> queryContent = user.queryContent( Arrays.asList( "Java (Programmiersprache)" ) );
String content = queryContent.get( 0 ).getCurrentContent();

WikiModel wikiModel = new WikiModel( "http://de.wikipedia.org/wiki/${image}",
                                     "http://de.wikipedia.org/wiki/${title}" );

String rendererdHtmlContent = wikiModel.render( content );

FileWriter fw = new FileWriter("c:/test.html");
fw.write( rendererdHtmlContent );
fw.close();

Einige Dinge löst der Renderer aber nicht auf. So verbleiben im Text Wiki-Templates wie

  • {{Infobox Programmiersprache}}
  • {{IPA}}
  • {{Wikiversity}}
  • {{Wikibooks}}

oder bei anderen Texten

  • {{Begriffsklärungshinweis}}
  • {{Commonscat}}
  • {{internetquelle}}
  • {Literatur}}

Auch Bilder werden standardmäßig nicht richtig umgesetzt. So wird bei http://de.wikipedia.org/wiki/Linux aus

[[Bild:Linus Torvalds.jpeg|thumb|right|Linus Torvalds 2004]]

kein Bild, sondern ein Link

<a href="http://de.wikipedia.org/wiki/Bild:Linus_Torvalds.jpeg%7Cthumb%7Cright" id="w">Linus Torvalds 2004</a>

Dumm nur, dass %7Cthumb%7Cright falsch ist, sonst wäre wenigstens der Link korrekt. (%7C ist |)

HOWTO Build a REST-Application with Jersey and Jetty

Resource first:

package com.tutego.traida.server;

import javax.ws.rs.*;

@Path( "/" )
public class GreetingResource
{
@GET @ProduceMime("text/plain")

public String get()
{
return "Yea!";
}
}

Bring it to Jetty

package com.tutego.traida.server;

import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.ServletHolder;
import com.sun.jersey.spi.container.servlet.ServletContainer;

public class Application 
{
public static void main( String[] args ) throws Exception
{
ServletHolder sh = new ServletHolder( ServletContainer.class );

sh.setInitParameter( "com.sun.jersey.config.property.resourceConfigClass",
"com.sun.jersey.api.core.PackagesResourceConfig" );
sh.setInitParameter( "com.sun.jersey.config.property.packages", "com.tutego.traida.server" );

Server server = new Server( 9999 );
Context context = new Context( server, "/", Context.SESSIONS );

context.addServlet( sh, "/*" );
server.start();

}
}

To use REST-parameters

@Path( "/edit-customer/{customerid}" )
public class EditCustomerResource
{
@GET @ProduceMime("text/plain")
public String editUser( @PathParam("customerid") String customerId )
{
....
}
}

HOWTO Add a JDBC DataSource/JNDI to GlassFish

Use asadmin with option create-jdbc-connection-pool first:

asadmin create-jdbc-connection-pool --datasourceclassname org.apache.derby.jdbc.EmbeddedDataSource --property databaseName=\$\{com.sun.aas.instanceRoot\}/databases/tutegodb:connectionAttributes=\;create\=true tutegoPool

Use asadmin again to install the actual JNDI name:

asadmin create-jdbc-resource --connectionpoolid=tutegoPool jdbc/tutego

To remove the pool and all attached JNDI names:

asadmin delete-jdbc-connection-pool --cascade tutegoPool

DZone-Interview mit Sacha Labourey über JBoss AS 5

Gibt es unter http://java.dzone.com/videos/tech-chat-sacha-labourey-jboss.

Natürlich galt es im Interview zu klären, warum man auf JBoss 5 so lange warten muss. Fertig ist er aber immer noch nicht!

We are very close to GA.

Warum noch immer nicht soweit? Weil der JBoss einen ganz neuen Microcontainer bekommt und weil unter anderem die Messaging-Lösung (JBoss Messaging) neu entwickelt wurde und JBoss 5 einen neuen Transaktions-Monitor bekommt. Einen Lacher erntet er bei mir aber mit:

Intuitively people usually think that it is an issue with the J2EE spec and how much time it took us to implement this pretty significant update of the J2EE spec.

JBoss war immerhin einer der ersten Container, die EJB 3 unterstützten. Aber Web-Services machen den JBoss 4 immer etwas Probleme, was auch an der Integration von Axis lag.

Ich sehe eher weniger gute Zukunfsaussichten für JBoss. Mit der wachsenden Popularität von GlassFish und Geronimo wird JBoss 5 zu kämpfen haben. GlassFish und Geronimo/IBM WASCE sowie WebLogic Server v10.0, SAP NetWeaver 7.1, Apusic Application Server, TmaxSoft JEUS 6, NEC WebOTX 8.1 sind (zum Teil schon sehr lange) Java EE 5 zertifiziert (http://java.sun.com/javaee/overview/compatibility.jsp) und JBoss 5 hat das auch noch vor sich.

Weiterhin glaube ich in der Java-Community einen Trend in Richtung der Sun-Implementierungen erkennen zu können, was zum Beispiel die RI für JavaServer Faces, aber auch etwa JAX-WS für Web-Services angeht. Interessant ist auch, dass GlassFish die JSP-Servlet-Übersetzung optimiert über JSR 199 regelt, eine Entwicklung, die eben nicht von Tomcat ausgeht. So nutzt auch Jetty das. (Schon 2006 war zu lesen: "patch to allow Jetty to use JSP2.1 from Glassfish instead of Jasper from Tomcat"). Von GlassFish geht im Moment ein sehr starker Zug aus und es bleibt sehr spannend.

MouseScrollableUI für JXLayer

Browser haben mich zum ersten Mal auf ein Gui-Feature aufmerksam gemacht, das folgender Screenshot am Besten erklärt:

demo screenshot

In der Tabelle erkennt man ein Symbol, mit dem sich leicht durch große Views scrollen lässt. Aktiviert wird diese Möglichkeit über die mittlere Maustaste.

Nun ist so etwas auch einfach für Swing über einen Dekorator möglich:

JScrollPane sp = JScrollPane( table );
JXLayer<JScrollPane> lsp = new JXLayer<JScrollPane>( sp, new MouseScrollableUI() );
container.add( lsp );

Thema der Woche: Refactoring

Refactoring von Code ist eine wichtige Aufgabe von Entwicklern neben der Neuentwicklung von Programmcode. Die Pflege und Aufarbeitung darf natürlich nicht zum Selbstzweck werden, aber langlebige Software muss zwingend für immer die Kriterien Wartbarkeit und Erweiterbarkeit bewahren und gut dokumentiert und verständlich sein.

Den größten Einfluss auf das Thema Refactoring hat das Refactoring-Buch von Martin Fowler, der auf seiner Webseite das Prinzip Refactoring, Refactoring-Tools und News auflistet.

Martin Fowler hat mir erlaubt, seinen Refactoring-Katalog auf Deutsch zu übersetzen: http://www.tutego.com/java/refactoring/catalog/. Gehe kurz über alle Refactorings.

Moderne IDEs erlauben von Haus aus das Refactoring von Code. Im Fall von Eclipse finde zu jedem unterstützten Refactoring ein Beispiel und lasse es von Eclipse umbauen:

GWT 1.5 RC2

Bezug unter http://code.google.com/webtoolkit/download.html . Changelog unter http://code.google.com/webtoolkit/releases/release-notes-1.5.1.html#Release_Notes_Current . Grundsätzlich für GWT 1.5:

  • Java 1.5 Support
  • Compiler Enhancements to Improve Application Speed
  • UI Library Additions: Widget Animations, Visual Themes
  • DOM API for simplified DOM Programming
  • Internationalization Improvements: Bi-di, Pluralization
  • Accessibility Support
  • Enhancements to the JRE Emulation Library

Erster Java Closures Prototype im openjdk

Von http://gafter.blogspot.com/2008/08/java-closures-prototype-feature.html:

The complete source code, released under GPLv2, is in the project’s openjdk repository. A binary build, suitable for use with an existing JDK6, is at http://www.javac.info/closures.tar.gz. Other related documents are on the website http://www.javac.info/

Neu sind Method references aus dem  FCM proposal:

{ String => int } parseInt = Integer#parseInt(String);
int x = parseInt.invoke("42");

Damit wird es immer wahrscheinlicher, dass es Closures in Java 7 gibt, obwohl Zeitpunkt und Inhalte immer noch nicht feststehen.