在OSGi捆绑包中加载ResourceBundle [英] Loading a ResourceBundle within an OSGi bundle

查看:110
本文介绍了在OSGi捆绑包中加载ResourceBundle的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an application that uses java.util.ResourceBundle to handle display strings. I use the ListResourceBundle as a base type because I want to be able to return an array of strings for some property keys (most of them are the standard name/value pairing).

当我尝试在OSGi环境中加载ResourceBundle时,出现MissingResourceException.我不知道为什么会发生这种情况.在尝试获取捆绑包之前,我可以在两个语句中解析类名并创建该类的新实例,因此我知道该类在捆绑包中.我使用的是语言环境(en_AU),但未提供该语言环境的特定类,因此后备规则应选择我的默认实现.即使我为语言环境添加了一个类,它也无法解析.

When I'm trying to load the ResourceBundle in the OSGi environment I get a MissingResourceException. I can't figure out why this would occur. I can resolve the class name and make a new instance of the class in the two statements before I try to fetch the bundle, so I know the class is in the bundle. I'm using a locale (en_AU) but not providing a specific class for that locale, the fallback rules should select my default implementation. Even when I added a class for the locale it didn't resolve.

我要获取数据的过程是:

The process I go through to fetch data is:

服务

public interface NameManager {
   public String getCategoryName(String identifier, Locale locale);
}

此的实现

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;
   }
}

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

This uses a custom service interface, DisplayNameProvider. Modules that wish to register names add this as a service in their activator. The default implementation takes a class for the fully qualified resource bundle name.

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;
       }
    }
 }

(注意,我省略了一些字段和静态引用,但这是完成的要旨).

(Note, I've left out some fields and static references, but this is the gist of what is done).

我进入DefaultDisplayNameProvider的内部,所以我知道已找到资源.我知道该类在捆绑软件中(它存储在内部捆绑软件类中,但对本地类加载器可见).

I'm getting inside of the DefaultDisplayNameProvider so I know the resource is being found. I know the class is in the bundle (it is stored in the internal bundle classes but is visible to the local class loader).

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

My question is what do I need to do load my ResourceBundle's up within OSGi? I'd prefer to continue with this approach rather than start using Resource Fragments or hard-coding string names.

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

Both of the advice below to help with the ClassLoader was useful but it turns out my problem was much simpler. Don't use toString() to get the class name (which I should've known but must have been lazy that day). The correct method to use is Class.getName().

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

This was found by noticing that if I used a properties file it loaded correctly. Then if I typed the class name in also worked. It was only when I was trying to reduce text entry error by using the existing class reference to get the correct name.

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

I'll stick with the String versions of the resource names. This means the JVM doesn't have to load the class till actually requested (not that there is a lot for it to do at this time).

推荐答案

最麻烦的是:您可能想尝试ResourceBundle.getBundle(name,locale,classloader)方法,因为ResourceBundle不知道要搜索哪个类加载器.您可以使用getClass().getClassLoader()获取DefaultDisplayNameProvider的类加载器.

Off the top of my head: You might want to try the ResourceBundle.getBundle(name,locale,classloader) method, as ResourceBundle wouldn't know which classloader to search. You can get the classloader of the DefaultDisplayNameProvider with getClass().getClassLoader().

致谢,弗兰克

这篇关于在OSGi捆绑包中加载ResourceBundle的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆