Gabi und Sascha
Kategorien : Alle | Berlin | Bücher | Fotografie | Java | Linkhalde | Weichware | Verfassung

Für internationalisierte (I10N) Implementierungen verwende ich gerne das CAL10N API. Das API erreicht eine Compiler Assisted Localization durch den Einsatz von Java enums. Der Name des Enumerationsfeldes ist der Schlüssel in einer entsprechenden Properties Datei. Hierdurch wird der Schlüssel innerhalb des Java-Code nicht mehr als String hinterlegt. Durch ein Maven Plugin können die Properties-Dateien überprüft werden. Ich empfehle jedem Java Entwickler sich das API einmal anzuschauen.

Ich habe den Ansatz für den Einsatz in meinen privaten Projekten und bei bei Zimory erweitert. Durch den Einsatz von enums können auch Annotationen zum Einsatz kommen. Zwei Annotationen habe ich definiert. Eine für den enum Typen und eine für die enum Felder. Beide haben als einzigen Wert einen String:


    @Target(TYPE)
    @Retention(RUNTIME)
    public @interface SystemId {
        String value();
    }


    @Target(FIELD)
    @Retention(RUNTIME)
    public @interface MessageId {
        String value();
    }

@SystemId definiert grobgranular das Modul/Subsystem – oder wie auch immer die Systemunterteilung namentlich genannt wird – für die Messages. @MessageId definiert eine spezielle feingranulare ID für z.B. einen Fehlerzustand innerhalb eines Moduls. Der Sourcecode einer Message enum sieht dann in etwa so aus:


    import ch.qos.cal10n.LocaleData;
    import ch.qos.cal10n.Locale;
    import ch.qos.cal10n.BaseName;

    @SystemId("RT")
    @BaseName("messages")
    @LocaleData({@Locale("en")})
    public enum Messages {
        /** Indicates a login failure. */
        @MessageId("001001") LOGIN_VALIDATION_FAILED;
    }

Für die Auswertung haben ich einen eigenen MessageProducer geschrieben. Dieser kapselt eine Implementierung des CAL10Ns IMessageConveyor Interface. Ausserdem analyisert er per Reflection die Annotationen und baut aus den Werten eine ID zusammen. Diese ID wird vor die internationalisierte Nachricht gestellt. Daneben übernimmt die Implementierung noch einige Dinge wie Caching usw. Eine erzeugte Nachricht sieht in etwa wie die Folgende aus:

    RT-001001: Login failed for user "foobar".

Solche IDs sind nicht nur für die Analyse von Fehlermeldungen sinnvoll. Sie bieten auch einen einfachen Ansatz für die Fehlerpropagierung in Systemen, in denen bisher kein durchgängiges Exceptionframework existierte. Damit auch nicht Entwickler die Fehlermeldungen verstehen, haben ich eine Doclet-Implementierung geschrieben. Diese analyisert alle enum Klassen mit @SystemId und generiert aus dem Wert der Annotation, der Javadoc Klassendokumentation, dem Wert von @MessageId und der Javadoc Felddokumentation eine XML Datei mit einer Zusammenfassung der Daten. Durch einfache XSLT Skripte wird das XML Dokument in Docbook und Xdoc umgewandelt und kann somit für die Anwenderdokumentation weiter verarbeitet werden. Da alles aus einer Quelle kommt, werden Fehler durch cut 'n paste reduziert.