4 Replies Latest reply on Apr 18, 2011 6:32 AM by marx3

    Faces Module messages API

    atijms.arjan.tijms.m4n.nl
      The reference guide for the Faces Module mentions a Messages API (http://docs.jboss.org/seam/3/faces/latest/reference/en-US/html/faces.messages.html)

      I wonder if it would be possible to do some tighter integration with how resource bundles are used on Facelets pages and this API. For usage for Facelets one typically declares a resource bundle in faces-config.xml under some name (e.g. "i18n"), and would then reference the bundle via an EL expression like #{i18n['messageKey']}.

      Maybe a variant on Messages could be injected with the correct bundle already selected, e.g:

      @Inject
      @MessageBundle
      MessageBundle i18n; // Injects variant of Messages with "i18n" bundle from faces-config

      public String action() {
         i18n.info("messageKey", "unique");
      }
        • 1. Re: Faces Module messages API
          meetoblivion

          This is a good use case, but really doesn't sound like something that would fall into Seam Faces.  The closest match I see is in the International module, which in their implementation has a ApplicationBundles object, which you can use to automatically register the bundle.


          https://github.com/seam/international/blob/master/api/src/main/java/org/jboss/seam/international/status/ApplicationBundles.java


          You can probably use that to wrap a producer method.  Maybe something like?




          @Inject
          ApplicationBundles applicationBundles;
          
          @Produces
          @Named("myBundle")
          public ResourceBundle createMyBundle() {
             return applicationBundles.get("com.company.myapp.bundles.messages");
          }



          • 2. Re: Faces Module messages API
            atijms.arjan.tijms.m4n.nl

            This is a good use case, but really doesn't sound like something that would fall into Seam Faces.

            Well, it's a kind of cross functionality really. The Messages class is located in the International module, but there's a special paragraph for it in the reference guide of the Faces Module and it obviously has special support for JSF.


            In this case, the code should not just abstract getting any application bundle. It should be an easy handle to precisely the bundle that's declared in faces-config.xml, using exactly the name that's in there.


            Using a producer method, one should thus do a lookup of the bundles declared in faces-config, retrieve a reference to that (maybe indeed via ApplicationBundles), then create a sub or wrapper class for Messages, store the bundle inside it and add info/warn etc methods that only ask a key and optionally parameters.


            It would maybe not be incredibly hard to add, and in fact I've seen utility methods that do just this being created at many places for many projects. Therefor it might be a good candidate for inclusion in a library like Seam, like people seem to invent the wheel for it over and over again.

            • 3. Re: Faces Module messages API
              meetoblivion

              Ok, I think I missed one of your points.  Still, almost all of the code changes to complete this would end up in the international module, not the faces module.  The faces module would simply provide a reference to the specific resource bundle, the international module would need to be refactored slightly to reference a particular bundle.  The main issue would end up being in the MessageFactory class (https://github.com/seam/international/blob/master/api/src/main/java/org/jboss/seam/international/status/MessageFactory.java) where it does the logic of finding the bundle template based on the bundle FQCN and key in that bundle.  if it had an alternate way to behave with having a specific resource bundle in place, then this would be possible.

              • 4. Re: Faces Module messages API
                marx3

                To complete feractoring, now we have methods like:


                messages.warn(new BundleKey("dictionary", "dictionary_cant_remove"));


                and there should be methods like:


                messages.warn(MessageBundle, String);


                (BundleKey can't be used type-safely)