GEDOPLAN
Jakarta EE (Java EE)

ResourceBundle auf Basis mehrerer Properties

Jakarta EE (Java EE)

Das übliche Verfahren, lokalisierte Meldungen zu erzeugen, ist die – meist implizite – Nutzung von PropertyResourceBundle. So bezieht bspw. Bean Validation seine Meldungen aus einem Resource Bundle mit Namen ValidationMessages. Dieses materialisiert sich üblicherweise aus Classpath-Ressourcen namens ValidationMessages.properties, ValidationMessages_de.properties etc.

Problematisch ist bei diesem Verfahren, dass z. B. nur eine Datei namens ValidationMessages.properties verwendet wird, auch wenn es davon mehrere im Classpath gibt. Damit ist leider der Weg verbaut, in einer Utility-Bibliothek bspw. Bean Validation Constraints inkl. der zugehörigen Meldungen auf einfache Weise zu definieren:

– Anwendung definiert Validierungsmeldungen als Classpath-Ressource-Bundle “ValidationMessages” (1),
– von der Anwendung genutzte Bibliothek enthält ebenfalls ein Classpath-Ressource-Bundle “ValidationMessages” (2).
– Validierungsfehler nutzen die Meldungen aus (1), aber nicht (2)!

Abhilfe ist hier leicht zu schaffen: Statt der impliziten Nutzung eines PropertyResourceBundle lässt sich eine Lokalisierung von Texten auch durch explizite Bereitstellung eines Resource-Bundles in Form passend benannter Klassen erreichen, d. h. im Beispielszenario können die Klassen ValidationMessages, ValidationMessages_de etc. zur Verfügung gestellt werden (alle im Default-Paket). Die Klassen müssen von java.util.ResourceBundle abgeleitet sein. In ihrem Konstruktor suchen sie nach allen passenden Classpath-Ressourcen und bauen damit einen interne Lookup-Tabelle auf. Sinnigerweise implementiert man dieses Verhalten in einer entsprechenden Basisklasse:

public class ValidationMessages extends MultiPropertiesResourceBundle
 {
 }

public class ValidationMessages_de extends MultiPropertiesResourceBundle
 {
 }

...

public class MultiPropertiesResourceBundle extends ResourceBundle
 {
      private Map messageMap = new HashMap();
 }

public MultiPropertiesResourceBundle()
  {
      loadProperties(this.getClass().getName().replace('.', '/') + ".properties");
  }

public MultiPropertiesResourceBundle(String bundleName)
  {
      loadProperties(bundleName + ".properties");
  }

private void loadProperties(String resourceName)
  {
     try
      {
      Enumeration found = Thread.currentThread().getContextClassLoader().getResources(resourceName);
          while (found.hasMoreElements())
          {
              URL url = found.nextElement();
              loadMessages(url);
          }
      }
      catch (IOException e)
      {
      // ignore
      }
  }

private void loadMessages(URL url)
  {
      Reader reader = null;
      try
      {
          reader = new InputStreamReader(url.openStream(), "UTF-8");

        Properties prop = new Properties();
          prop.load(reader);

        for (Entry entry : prop.entrySet())
          {
              String key = (String) entry.getKey();
              if (!this.messageMap.containsKey(key))
              {
                  String value = (String) entry.getValue();
                  this.messageMap.put(key, value);
              }
          }
      }
      catch (IOException e)
      {
          // ignore
      }
  finally
  {
      try
      {
          reader.close();
      }
      catch (Exception e)
      {
          // ignore
      }
  }
  }

@Override
  public Enumeration getKeys()
  {
      ResourceBundle parent = this.parent;
      return new ResourceBundleEnumeration(this.messageMap.keySet(), (parent != null) ? parent.getKeys() : null);
  }

@Override
  protected Object handleGetObject(String key)
  {
      return this.messageMap.get(key);
  }
 }

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Bitte füllen Sie dieses Feld aus.
Bitte füllen Sie dieses Feld aus.
Bitte gib eine gültige E-Mail-Adresse ein.
Sie müssen den Bedingungen zustimmen, um fortzufahren.

Autor

Diesen Artikel teilen

LinkedIn
Xing

Gibt es noch Fragen?

Fragen beantworten wir sehr gerne! Schreibe uns einfach per Kontaktformular.

Kurse

weitere Blogbeiträge

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!

Work Life Balance. Jobs bei Gedoplan

We are looking for you!

Lust bei GEDOPLAN mitzuarbeiten? Wir suchen immer Verstärkung – egal ob Entwickler, Dozent, Trainerberater oder für unser IT-Marketing! Schau doch einfach mal auf unsere Jobseiten! Wir freuen uns auf Dich!