[jboss-user] [JBoss Seam] - Re: ResourceBundle in Database

pbrewer_uk do-not-reply at jboss.com
Sun Jul 8 08:33:37 EDT 2007


You can also retrieve the entity manager by calling:

  | EntityManager em = (EntityManager) Component.getInstance("entityManager", true);
  | 

Sorry that this posting is delayed, it sounds like you're pretty much there. But here is a more expanded version of the steps I outlined earlier. Hopefully it'll help you and others...

1. Create the entity beans/ tables. (see my post earlier for table structure)

2. To understand how the new ResourceBundle works in jdk , have a look at these links (in addition those provided by Udo):
http://java.sun.com/developer/JDCTechTips/2005/tt1018.html#2
http://java.sun.com/javase/6/docs/api/java/util/ResourceBundle.html 

Step 3. i) Create DBControl.java

  | import java.util.ResourceBundle.Control ;
  | import java.util.ResourceBundle ;
  | ...
  | 
  | public class DBControl extends Control {
  | 
  |   public static final String FORMAT_DATABASE = "database" ;
  | 
  |   public static final DBControl INSTANCE = new DBControl() ;
  |   
  |   @Override
  |   public List<String> getFormats(String baseName) {
  |     return Collections.singletonList(FORMAT_DATABASE);
  |   }
  | 
  |   @Override
  |   public ResourceBundle newBundle(String baseName, Locale locale, String format,
  |                                   ClassLoader loader, boolean reload) throws IllegalAccessException,
  |           InstantiationException, IOException {
  |     
  |     if ((baseName == null) || (locale == null) || (format == null) ) {
  |       throw new NullPointerException("baseName=" + baseName + ", locale=" + locale + " and format=" + format + " cannot be null.");
  |     }
  |     
  |     ResourceBundle bundle = null;
  |     if (format.equals(FORMAT_DATABASE)) {
  |       try {
  |         bundle = new DBResourceBundle(baseName, locale) ;
  |       } catch (MissingBundleException ex) {
  |         // bundle must return null
  |       }
  |     }
  |     return bundle;
  |   }    
  |   
  |   @Override
  |   public boolean needsReload(String baseName,
  |           Locale locale,
  |           String format,
  |           ClassLoader loader,
  |           ResourceBundle bundle,
  |           long loadTime) {
  |     if (bundle == null) {
  |       return true ;
  |     } else if (format.equals(FORMAT_DATABASE) && bundle instanceof DBResourceBundle) {
  |       try {
  |         EntityManager em = (EntityManager) Component.getInstance("myEntityManager") ;
  |         Long bundleId = ( (DBResourceBundle) bundle).getResourceBundleId() ;
  |         uk.co.iblocks.iflow.data.ResourceBundle rb = em.find(uk.co.iblocks.iflow.data.ResourceBundle.class, bundleId) ;
  | 
  |         return rb.isDirty(new Date(loadTime)) ;
  |         
  |       } catch (Exception ex) {
  |         LOG.warn("Error checking dirty state of resource bundle, requesting reload anyway.", ex) ;
  |         return true ;
  |       }
  |     } else { 
  |       return false ;
  |     }
  |   }  
  |   
  | 
  | }
  | 

Step 3. ii) Create DBResourceBundle.java

  | public class DBResourceBundle extends java.util.ResourceBundle {
  | 
  |   private Map<String, String> messages = new HashMap<String, String>();
  | 
  |   private Long resourceBundleId = -1L;
  | 
  |   public DBResourceBundle (String baseName, Locale locale) throws MissingBundleException, BundleLoadException {
  |     try {
  |       loadBundle(baseName, locale) ;
  |     } catch (RuntimeException ex) {
  |       LOG.error("An error occurred loading the resource bundle, baseName=" + baseName + ", locale=" + locale, ex) ;
  |       BundleLoadException mbe = new BundleLoadException(baseName, locale) ;
  |       mbe.initCause(ex) ;
  |       throw mbe ;
  |     }
  |   }
  |   
  |   
  |   private void loadBundle(String baseName, Locale locale) throws MissingBundleException {
  |     // load from db...
  |     EntityManager em = (EntityManager) Component.getInstance("entityManager") ;
  |     
  |     // query the db and load your messages here - you'll need to handle when variant, country and language aren't defined,
  |     // but a simple example is:
  |     Query bundleQuery = em.createNamedQuery("loadBundleMessages") ;
  |     bundleQuery.setParameter("language", locale.getLanguage());
  |     bundleQuery.setParameter("country", locale.getLanguage());
  |     bundleQuery.setParameter("variant", locale.getLanguage());    
  |     bundleQuery.setParameter("baseName", baseName) ;
  |     
  |     List<ResourceBundle> bundles = bundleQuery.getResultList() ;
  |     if (!bundles.isEmpty()) {
  |       // use the most specific bundle
  |       ResourceBundle resourceBundle = bundles.get(bundles.size()-1) ;
  |       this.resourceBundleId = resourceBundle.getBundleId() ;
  |       for (ResourceMessage msg : resourceBundle.getResourceMessages()) {
  |         messages.put(msg.getKey(), msg.getValue()) ;
  |       }
  |     } else {
  |       throw new MissingBundleException(baseName, locale) ;
  |     }
  | 
  |     em.clear() ;
  |     
  |   }
  |   
  |   @Override
  |   public Enumeration<String> getKeys() {
  | 
  |     Enumeration<String> keys = new Enumeration<String>() {
  | 
  |       private Iterator<String> keyIterator = messages.keySet().iterator() ;
  | 
  |       public boolean hasMoreElements() {
  |         return keyIterator.hasNext() ;
  |       }
  | 
  |       public String nextElement() {
  |         return keyIterator.next() ;
  |       }
  | 
  |     } ;
  |     return keys ;
  |   }
  | 
  |   @Override
  |   protected Object handleGetObject(String key) {
  |     return messages.get(key) ;
  |   }
  | 
  | 
  |   // returns id of the resource bundle stored in the database
  |   public Long getResourceBundleId() {
  |     return this.resourceBundleId;
  |   }
  | 
  |   public void setResourceBundleId(Long resourceBundleId) {
  |     this.resourceBundleId = resourceBundleId;
  |   }
  | 
  | }
  | 

Step 4. Extend the standard seam resource bundle, SeamResourceBundle.java:

  | @Name("org.jboss.seam.core.resourceBundle")
  | public class SeamResourceBundle extends org.jboss.seam.core.ResourceBundle implements Serializable {
  | 
  |   @Logger
  |   private Log LOG ;
  |   
  |   private transient ResourceBundle bundle ;
  |   
  |   @Override
  |   protected ResourceBundle loadBundle(String bundleName) {
  |     try {
  |       ResourceBundle bundle = ResourceBundle.getBundle(bundleName, Locale.instance(), Thread.currentThread().getContextClassLoader(), DBControl.INSTANCE);
  |       return bundle;
  |     } catch (MissingResourceException mre) {
  |       LOG.debug("resource bundle is missing: #0", bundleName);
  |       return null;
  |     }
  |   }
  |   
  |   private void createUberBundle() {
  |     bundle = new java.util.ResourceBundle() {
  |       
  |       @Override
  |       public java.util.Locale getLocale() {
  |         return Locale.instance();
  |       }
  | 
  |       public List<ResourceBundle> getLittleBundles() {
  |         List<java.util.ResourceBundle> littleBundles = new ArrayList<ResourceBundle>();
  |         if (getBundleNames() != null) {
  |           for (String bundleName : getBundleNames()) {
  |             java.util.ResourceBundle littleBundle = SeamResourceBundle.this.loadBundle(bundleName);
  |             if (littleBundle != null)
  |               littleBundles.add(littleBundle);
  |           }
  |         }
  |         
  |         java.util.ResourceBundle validatorBundle = SeamResourceBundle.this.loadBundle("ValidatorMessages");
  |         if (validatorBundle != null) {
  |           littleBundles.add(validatorBundle);
  |         }
  |         java.util.ResourceBundle validatorDefaultBundle = SeamResourceBundle.this.loadBundle("org/hibernate/validator/resources/DefaultValidatorMessages");
  |         if (validatorDefaultBundle != null) {
  |           littleBundles.add(validatorDefaultBundle);
  |         }
  |         return littleBundles ;
  |       }
  |       
  |       
  |       @Override
  |       public Enumeration<String> getKeys() {
  |         List<ResourceBundle> pageBundles = getPageResourceBundles();
  |         Enumeration<String>[] enumerations = new Enumeration[getLittleBundles().size() + pageBundles.size()];
  |         int i = 0;
  |         for (; i < pageBundles.size(); i++) {
  |           enumerations[i++] = pageBundles.get(i).getKeys();
  |         }
  |         for (; i < getLittleBundles().size(); i++) {
  |           enumerations = getLittleBundles().get(i).getKeys();
  |         }
  |         return new EnumerationEnumeration<String>(enumerations);
  |       }
  |       
  |       @Override
  |       protected Object handleGetObject(String key) {
  |         List<ResourceBundle> pageBundles = getPageResourceBundles();
  |         for (ResourceBundle pageBundle : pageBundles) {
  |           try {
  |             return pageBundle.getObject(key);
  |           } catch (MissingResourceException mre) {
  |           }
  |         }
  |         
  |         for (ResourceBundle littleBundle : getLittleBundles()) {
  |           if (littleBundle != null) {
  |             try {
  |               return littleBundle.getObject(key);
  |             } catch (MissingResourceException mre) {
  |             }
  |           }
  |         }
  |         
  |         throw new MissingResourceException("Can't find resource in bundles: " + key, getClass().getName(), key);
  |       }
  |       
  |       private List<java.util.ResourceBundle> getPageResourceBundles() {
  |         FacesContext facesContext = FacesContext.getCurrentInstance();
  |         if (facesContext != null) {
  |           UIViewRoot viewRoot = facesContext.getViewRoot();
  |           if (viewRoot != null) {
  |             return Pages.instance().getResourceBundles(viewRoot.getViewId());
  |           }
  |         }
  |         return Collections.emptyList();
  |       }
  |       
  |     };
  |     
  |   }
  |   
  |   @Override
  |   public java.util.ResourceBundle getBundle() {
  |     if (bundle == null)
  |       createUberBundle();
  |     return bundle;
  |   }
  |   
  | 
  | 
  | }
  | 

Step 5. Override seam messages to avoid caching. SeamMessages.java:

  | @Name("org.jboss.seam.core.messages")
  | public class SeamMessages extends Messages {
  |   
  |   private transient BundleMap resourceBundleMap = null ;
  |   
  |   @Override
  |   public Map getMessages() {
  |     java.util.ResourceBundle resourceBundle = ResourceBundle.instance() ; 
  |     
  |     if ( getResourceBundleMap() == null || !getResourceBundleMap().getBundle().equals(resourceBundle) ) {
  |       setResourceBundleMap( new BundleMap(resourceBundle) );
  |     }
  |     return getResourceBundleMap() ;
  |   }
  | 
  |   protected BundleMap getResourceBundleMap() {
  |     return this.resourceBundleMap;
  |   }
  | 
  |   protected void setResourceBundleMap(BundleMap resourceBundleMap) {
  |     this.resourceBundleMap = resourceBundleMap;
  |   }
  |   
  | }
  | 

Step 6. optional - use the code in step 5 as a template for extending the ThemeSelector

Step 7. Component.xml extract:

  |   <component name="org.jboss.seam.core.resourceBundle">
  |     <property name="bundleNames">
  |       <value>messages</value>
  |     </property>
  |   </component>
  | 

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4061696#4061696

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4061696



More information about the jboss-user mailing list