Veröffentlichung einer Fremdbibliothek als OSGI Plugin

Eingetragen bei: Eclipse, Java, RCP | 0

Wer mit OSGI arbeitet kennt das. Man findet eine Library die genau das tut, was man benötigt, es liegt nur keine OSGI-Plugin-Variante zum Download bereit.

Eine Möglichkeit ist nun das Jar-Archive zu downloaden und in Eclipse ein neues Projekt Plug-in from Existing JAR Archive zu erstellen. Im nächsten Schritt können nun External JAR Archives hinzugefügt werden. Benötigt man verschiedene Libraries, bzw. hat die gewünschte Library weitere Dependencies, können diese hier direkt hinzugefügt werden. Selbst wenn die verschiedenen Archive eine gleiche package-Struktur aufweisen, ergibt dies keine Probleme, die class-Dateien werden in die entsprechenden Packages gemergt.

Theoretisch ist man nun fertig und man kann die gewünschte Library verwenden. Allerdings werden sich dann die Kollegen bedanken, da sie nun ein weiteres Projekt auschecken müssen. Also exportiert man das soeben erstellte Projekt noch als Deployable plug-ins and fragments, legt das erstellte OSGI-Plugin in die Target-Plattform und kann nun das Projekt wieder schließen.

Sofern die Library nicht in einem Maven-Kontext benötigt wird, ist man nun tatsächlich fertig, andernfalls muss man sie noch manuell in ein Maven-Repository legen.

Eine zweite Möglichkeit, um aus einer Fremdbibliothek ein OSGI-Plugin zu erstellen, ist die Verwendung des Maven Plugins Felix von Apache. Hier wird eine pom.xml der folgenden Art benötigt:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>de.example</groupId>
<artifactId>de.example.project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>de.example.project</name>
<packaging>bundle</packaging>

<dependencies>
<dependency>
<groupId>de.example</groupId>
<artifactId>de.example.dependency</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/xxx.jar</systemPath>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>*</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

Wichtig ist hierbei, dass packaging den Wert bundle erhält, wofür allerdings das Plugin org.apache.felix korrekt eingebunden seien muss. Zu beachten ist hier der Wert true für Extensions.

Als dependency wird im obigen Beispiel die Library de.example.dependency benötigt, die sich in dem aktuellen Maven-Projekt in dem Jar-Archive xxx.jar befindet. Der Ort des Jar-Archives wird im systemPath definiert.

Die class-Dateien der auf diese Weise angegebenen Dependencies werden beim Bauen des Maven-Projektes mittels package mit ins target gelegt. Weiterhin erstellt bei obiger Definition das Plugin Felix ein Manifest in dem alle packages der eingebundenen Libriries exportiert werden. Möchte man diese Einschränken, so können die zu exportierenden packages explizit in der pom-Datei unter Export-Package definiert werden.

Als Fazit lässt sich sagen, dass beide Varianten Arbeit bedeuten und man stehts hoffen sollte, dass die benötigten Libraries bereits als OSGI-Plugin zur Verfügung stehen. So lohnt sich immer zuerst ein Blick auf das SpringSource Enterprise Bundle Repository, da hier bereits viele Libraries als OSGI-Bundle vorliegen: http://ebr.springsource.com/repository/app/

Internationalisierung in Java

Eingetragen bei: Java | 0

Anders als vielleicht vermutet, geht es in diesem Beitrag nicht um die obligatorischen länderspezifischen Property-Dateien, sondern um die Verwendung von Ländern, Landesvorwahlen, Währungen und  landestypischen Formattern in Java-Anwendungen.

Benötigt man innerhalb eines Java  Programmes eine vollständige Liste von Ländern, stößt man schnell auf die Klasse java.util.Locale. Die hier definierten Länder-Konstanten sind zwar recht begrenzt, es gibt hier aber die statische Methode:

Locale.getAvailableLocales()

mit der man sich – denkt man – eine vollständige Liste von allen Locales liefern lassen kann. Tatsächlich werden hier aber nur 152 Locales zurückgegeben. Verwendet man stattdessen folgenden Aufruf:

for (String country : Locale.getISOCountries()) {
Locale lc = new Locale(„“, country);
}

kommt man auf insgesamt 247 Locales. Interessant hierbei ist, dass man sich sowohl den kompletten Namen des Landes, als auch den ISO 3166-2 bzw. ISO 3166-3 Code über die Locale liefern lassen kann.

locale.getDisplayCountry() //Ländername
locale.getCountry() // ISO 3166-2 Code
locale.getISO3Country() // ISO 3166-3 Code

Außer der Klasse Locale ist auch noch die Google Library libphonenumber.jar interessant, die zur Zeit in der Version 3.8 vorliegt. Hier gibt es die PhoneNumerUtil, die über den ISO 3166-2 Ländercode die Landesvorwahl liefert:

int countryCode = PhoneNumberUtil.getInstance().getCountryCodeForRegion(locale.getCountry());

Diese Library kann über maven verwendet werden:

<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>libphonenumber</artifactId>
<version>3.8</version>
</dependency>

Möchte man Zahlen landestypisch darstellen, kann die Klasse java.text.DecimalFormat verwenden werden, in dem man die entsprechende Locale übergibt. Als Beispiel wird hier die deutschsprachige Schweiz verwendet, da hier der Separator der 1000er Stelle abweichend zur deutschen Schreibweise ist:

DecimalFormat.getInstance(new Locale(„de“, „CH“).format(1234.123); //liefert: 1’234.123

Genauso einfach ist es, sich die passend formatierte Währung inklusive Währungssymbol an der korrekten Stelle ausgeben zu lassen:

NumberFormat.getCurrencyInstance(new Locale(„de“, „CH“).format(1234.123); // SFr. 1’234.12

In der deutschen Variante befindet sich das Euro-Symbol am Ende und die 1000er Stelle wird wie erwartet mit einem Punkt separiert:

NumberFormat.getCurrencyInstance(new Locale(„de“, „DE“).format(1234.123); // 1.234,12 €

Möchte man statt der lokalen die internationale Schreibweise verwenden, läßt man bei der Erstellung der Locale den Parameter für die Sprache weg. So ergibt sich für obige Beispiele folgende Ausgabe:

DecimalFormat.getInstance(new Locale(„“, „CH“).format(1234.123); //liefert: 1,234.123
NumberFormat.getCurrencyInstance(new Locale(„“, „CH“).format(1234.123); // CHF 1,234.12

Die in diesem Beitrag erwähnten Klassen bieten noch weitere Möglichkeiten für landesspezifische Darstellungen. Bevor man sich die Arbeit macht und hier eigene Komponenten entwickelt, lohnt sich ein Blick auf gegebenen Java Funktionalitäten.

Leider gibt es aber auch hier Grenzen. So treten grade für die Schweiz Probleme auf, da auf Schweizer Portalen eine Mischung aus Internationaler und Lokaler Darstellung gewählt wird. Aufgrund der Unterscheidung zwischen französischer, italienischer und deutscher Schweiz wird hier das internationale Währungssymbol CHF mit dem Hochkomma als Separator der 1000er Stellen kombiniert. Hierfür konnte ich leider keine fertige Java-Lösung finden.