GlassF 3.1.2上的JSF Reload资源包

时间:2013-08-04 18:52:06

标签: jsf caching glassfish resourcebundle

我想在数据更新后重新加载/刷新我的资源包。

我的ResourceBundle实现基于db,这里是代码:

public class DatabaseResourceBundle extends ResourceBundle {

  private static EntityManagerFactory factory = Persistence.createEntityManagerFactory("ADAEcommerceEjbPU");
  private EntityManager _entityManager = factory.createEntityManager();
  private Map<String, String> _values = new HashMap<>();
  protected final static String BUNDLE_NAME = "com.infomaxgroup.adaecommerce.bundles";
  private final static Logger LOGGER = Logger.getLogger(DatabaseResourceBundle.class.getName());
  private Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
  protected Control DB_CONTROL = new DBControl();

  /**
   * Public constructor setting the parent bundle
   */
  public DatabaseResourceBundle() {
    LOGGER.log(Level.FINE, "DatabaseResourceBundle()");
    setParent(ResourceBundle.getBundle(BUNDLE_NAME,
            FacesContext.getCurrentInstance().getViewRoot().getLocale(), DB_CONTROL));
  }

  public DatabaseResourceBundle(Locale locale) {
    LOGGER.log(Level.FINE, "DatabaseResourceBundle(Locale locale)");
    setParent(ResourceBundle.getBundle(BUNDLE_NAME, locale, DB_CONTROL));
  }

  @Override
  protected Object handleGetObject(String key) {
    LOGGER.log(Level.FINE, "handleGetObject() Locale {0} Key: {1} ", new Object[]{locale.toString(), key});
    return _values != null ? _values.get(key) : parent.getObject(key);
  }

  @Override
  public Enumeration<String> getKeys() {
    LOGGER.log(Level.FINE, "getKeys() Parent Locale {0} ", parent.getLocale());
    return parent.getKeys();
  }

  /**
   * The Control Callback.
   *
   * @see
   * http://docs.oracle.com/javase/6/docs/api/java/util/ResourceBundle.Control.html
   */
  protected class DBControl extends Control {

    @Override
    public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
            throws IllegalAccessException, InstantiationException, IOException {
      LOGGER.log(Level.INFO, "reload {0} ", reload);
      return new MyResources(locale);
    }

    /**
     * A simple ListResourceBundle
     */
    protected class MyResources extends ListResourceBundle {

      private Locale locale;

      /**
       * ResourceBundle constructor with locale
       *
       * @param locale
       */
      public MyResources(Locale locale) {
        this.locale = locale;
      }

      @Override
      protected Object[][] getContents() {
        if (locale == null) {
          locale = Locale.ITALY;
        }

        TypedQuery<ResourceEntity> query = _entityManager.createNamedQuery("ResourceEntity.findForLocale", ResourceEntity.class);
        query.setParameter("locale", locale.getLanguage());

        List<ResourceEntity> resources = query.getResultList();

        Object[][] all = new Object[resources.size()][2];
        int i = 0;
        for (Iterator<ResourceEntity> it = resources.iterator(); it.hasNext();) {
          ResourceEntity resource = it.next();
          all[i] = new Object[]{resource.getKey(), resource.getValue()};
          _values.put(resource.getKey(), resource.getValue());
          i++;
        }
        return all;
      }
    }
  }
}

当我更新数据并调用DatabaseResourceBundle.clearCache()时,我看到下一个请求调用该方法:

MyResources.getContents()

如果我调试返回的数据

Object[][] all

这里我看到了更新的数据,但在JSF页面上我仍然看到旧数据,看起来JSF使用缓存数据。

如何在JSF页面中看到更新的数据?

非常感谢...

1 个答案:

答案 0 :(得分:0)

问题已通过以下步骤解决:

1)修改(插入,更新,删除)任何ResourceEntity后我调用

DatabaseResourceBundle.clearCache();

2)如果我想刷新JSF资源标签,我会调用此代码(建议的代码来自:How to reload resource bundle in web application?):

  ApplicationResourceBundle applicationBundle = ApplicationAssociate.getCurrentInstance().getResourceBundles().get("msg");
  Field field = null;
  try {
    field = applicationBundle.getClass().getDeclaredField("resources");
  } catch (NoSuchFieldException | SecurityException ex) {
    Logger.getLogger(UserRegistrationController.class.getName()).log(Level.SEVERE, null, ex);
  }
  if (field != null) {
    field.setAccessible(true);
    Map<Locale, ResourceBundle> resources = null;
    try {
      resources = (Map<Locale, ResourceBundle>) field.get(applicationBundle);
    } catch (IllegalArgumentException | IllegalAccessException ex) {
      Logger.getLogger(UserRegistrationController.class.getName()).log(Level.SEVERE, null, ex);
    }
    if (resources != null) {
      resources.clear();
    }
  }

希望这会有所帮助......