在OSGi包中加载ResourceBundle

Lan*_*nce 5 java osgi resourcebundle

我有一个使用java.util.ResourceBundle来处理显示字符串的应用程序.我使用ListResourceBundle作为基类型,因为我希望能够返回一些属性键的字符串数组(大多数是标准名称/值配对).

当我尝试在OSGi环境中加载ResourceBundle时,我得到一个MissingResourceException.我无法弄清楚为什么会这样.在尝试获取包之前,我可以解析类名并在两个语句中创建类的新实例,因此我知道类在包中.我正在使用区域设置(en_AU)但没有为该区域设置提供特定的类,回退规则应该选择我的默认实现.即使我为语言环境添加了一个类,它也没有解析.

我获取数据的过程是:

服务

public interface NameManager {
   public String getCategoryName(String identifier, Locale locale);
}
Run Code Online (Sandbox Code Playgroud)

这个的实现

public class OsgiNameManager implements NameManager {
   public String getCategoryName(@Nonnull Identifier category, Locale locale)
   {
      try {
        Collection<ServiceReference> references = (Collection)osgiContext.getServiceReferences(
                 DisplayNameProvider.class, "(namespace=" + category + ")");
        Iterator<ServiceReference> it = references.iterator();
        while ( it.hasNext() ) {
           ServiceReference reference = (ServiceReference)it.next();
           DisplayNameProvider namer = (DisplayNameProvider)osgiContext.getService(reference);
           String name = namer.getCategoryName(category, locale);
           osgiContext.ungetService(reference);

           if (name != null)
              return name;
        }
     }
     catch (InvalidSyntaxException badFormat) {
        LOG.warn("No registered provider for category [" + category + "]" , badFormat);
     }

      return null;
   }
}
Run Code Online (Sandbox Code Playgroud)

这使用自定义服务接口DisplayNameProvider.希望注册名称的模块将其作为服务添加到其激活器中.默认实现采用完全限定资源包名称的类.

public class DefaultDisplayNameProvider implements DisplayNameProvider {
    private Class<?> categoryResolver;
    public String getCategoryName(@Nonnull String category, Locale locale)
    {
       ResourceBundle res = ResourceBundle.getBundle(categoryResolver.toString(), locale);
       try {
          return res.getString(CATEGORY_NAME_KEY);
       }
       catch (MissingResourceException noCols) {
          return null;
       }
    }
 }
Run Code Online (Sandbox Code Playgroud)

(注意,我遗漏了一些字段和静态引用,但这是所做的事情的要点).

我进入DefaultDisplayNameProvider,所以我知道正在找到资源.我知道类在bundle中(它存储在内部bundle类中,但对本地类加载器是可见的).

我的问题是我需要在OSGi中加载我的ResourceBundle?我宁愿继续使用这种方法,而不是开始使用资源片段或硬编码字符串名称.

以下两个有关ClassLoader帮助的建议都很有用,但事实证明我的问题要简单得多.不要使用toString()来获取类名(我应该知道但当天一定是懒惰的).要使用的正确方法是Class.getName().

通过注意到如果我使用属性文件它正确加载,就可以发现这一点.然后,如果我输入的类名也在工作.只有当我试图通过使用现有的类引用来获取正确的名称来减少文本输入错误时.

我会坚持使用String版本的资源名称.这意味着JVM不必在实际请求之前加载类(并不是说此时要做很多事情).

Fra*_*Lee 5

在我的脑海中:您可能想尝试该ResourceBundle.getBundle(name,locale,classloader)方法,因为ResourceBundle不知道要搜索哪个类加载器.你可以得到DefaultDisplayNameProviderwith 的类加载器getClass().getClassLoader().

问候,弗兰克