*Problem: *
Required ability to have access to GWT client 
com.google.gwt.i18n.client.Messages files on server side(e.g. inside 
Servlet).
*Problem reason: *
In my case I needed to generate the PDF representation of the web page + 
save some string values in DB(when someone posts comment).
*Desired behaviour*:
Have a single MessageResource provider that can be executed from both server 
side and from client side:

*Solution:
*
   
   1. First of all *make sure that all GWT message resources are generated 
   from *.properties file via com.google.gwt.i18n.tools.I18NSync tool*(or 
   you have to synchronise i18n .properties files with GWT message interfaces 
   all the times). Otherwise, if you just using interfaces without using 
   *.properties files, this approach will not work.
   2. Now, let's *educate the server how to read GWT i18n *.properties*:
      1. I am using spring framework as server side, so in this example we 
      will educate Spring where the GWT's i18n *.properties are stored in the 
app:
       <bean id="messageSource"
                
      
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
              <property name="basenames">
                  <list>
                      <value>classpath:messages</value>
                      <value>classpath:error_messages</value>
                      
      
<value>classpath:/blabla/project/client/resources/i18n/messages/GlobalRes</value>
                  </list>
              </property>
              <property name="defaultEncoding" value="UTF-8"/>
          </bean>
      the classpath:/blabla/project/client/resources/i18n/messages/GlobalRes 
      is full path to GlobalRes.properties file. Make sure you include this 
file 
      in classpath when yo compile your project.
      2. Basically, after telling spring 
      ReloadableResourceBundleMessageSource where to take the resources is 
pretty 
      enough to have GWT messages being accessed on server side, by just 
injecting 
      messageSource into any place on server and using 
      messagesCourse.getMessage("messageCode",args[],locale). But this is not 
what 
      we want to achieve. The aim is to have the same message resource provider 
      that can be executed on server and on client side the same way.
      3. So next, let's just create this Messages Provider that can be 
   executed on both client and on server side:
   public class MessageResourceProvider {
   
       public static GlobalRes GLOBAL_RES;
       public static GlobalRes SERVER_GLOBAL_RES;
       
       static {
           try {
               GLOBAL_RES = GWT.create(GlobalRes.class);
           } catch (Exception e) {
   
           }
       }
   
       public static GlobalRes getGlobalRes() {
           if (GLOBAL_RES != null) {
               return GLOBAL_RES;
           } else {
               return SERVER_GLOBAL_RES;
           }
       }
   }
   
   First of all, make sure that MessageResourceProvider is stored under *.*
   client.** package, so GWT client side will be able to access it. So here 
   we have two instances for providing resources: one for server part, the 
   other one for client side. With client side everything is clear: we just try 
   to call GWT.create(GlobalRes.class) in static block and if it's successfully 
   executed(which actually means it executed on client side) then the 
   getGlobalResources will return client version of GlobalRes.
   But what about SERVER_GLOBAL_RES? Where should it come from? Obviously - 
   it should come from server.
   4. Ok, let's *tell server part to how inject SERVER_GLOBAL_RES into 
   MessageResourceProvider wher the server starts*.
   in order to do that I just added listener in my* web.xml* 
     <listener>
           <listener-class>
               org.kuali.lum.cmi.server.util.CmiServletListener
           </listener-class>
      </listener>
   so application will call this listener at startup time.
   the listener code is very simple: 
   public class CmiServletListener implements ServletContextListener {
       @Override
       public void contextInitialized(ServletContextEvent sce) {
           ServerMessageResourceFactory serverMessageResourceFactory = 
   (ServerMessageResourceFactory) 
   
WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()).getBean("serverMessageResourceFactory");
           MessageResourceProvider.SERVER_GLOBAL_RES = 
   serverMessageResourceFactory.getGlobalRes();
       }
   
       @Override
       public void contextDestroyed(ServletContextEvent sce) {
   
       }
   }
   As you see at startup time I just set MessageResourceProvider's 
   SERVER_GLOBAL_RES which I take from 
   serverMessageResourceFactory.getGlobalRes().
   5. So this is almost it, except I haven't described the most tricky and 
   interesting part: *how the serverMessageResourceFactory.getGlobalRes() 
   will return the com.google.gwt.i18n.client.Messages resources instance that 
   can de executed from server side and why hadn't we use messageResources, 
   that we've created at 2nd step?:
   *The answer is below: 
   public class ServerMessageResourceFactory {
   
       InvocationHandler handler = new InvocationHandler() {
           @Override
           public Object invoke(Object proxy, Method method, Object[] args) 
   throws Throwable {
               return 
   
messageSource.getMessage(method.getAnnotation(LocalizableResource.Key.class).value(),
 
   args, null);
           }
       };
       private ReloadableResourceBundleMessageSource messageSource;
   
       public GlobalRes getGlobalRes() {
           return (GlobalRes) 
   Proxy.newProxyInstance(GlobalRes.class.getClassLoader(), new 
   Class[]{GlobalRes.class}, handler);
       }
   
       public void setMessageResource(ReloadableResourceBundleMessageSource 
   messageSource) {
           this.messageSource = messageSource;
       }
   }
   
   The ServerMessageResourceFactory contains two functions two fields that 
   do all the tricks:
   - the getGlobalRes() returns proxy for GlobalRes which is handled by 
      handler
      - inside the handler we easily can extract the message key value(*
      method.getAnnotation(LocalizableResource.Key.class).value()*) and 
      passed arguments(*args*). 
      - with messageSource, which already knows how to get the GWT resources 
      from i18n *.property files we jast take all GWT client resources.
   
*Result:
*As a result now, we have MessageResourceProvider.getGolbalRes() that can be 
executed from both: server and client side.  So you never should care 
wherethere you using resources from client side or from server side. Just 
call MessageResourceProvider.getGolbalRes() to get access to the app message 
resources.

-- 
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/google-web-toolkit/-/9q2i3rWbtI4J.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-web-toolkit?hl=en.

Reply via email to