8 Replies Latest reply on Oct 5, 2012 12:19 PM by simone.m

    Suggestion on localization with seam 3 international

    conte

      Hello. I'm building a custom localizer for my web application using Seam3 international module. In my class I have injected the user locale as suggested into Seam3 international documentation. This is my class:

       

      @Named

      @RequestScoped

      public class CustomLocale {

       

       

                @Inject

                private Identity identity;

                @Inject

                private IdentitySession identitySession;

       

       

                @Inject

                private CustomLocaleConfiguration localeConfiguration;

       

                @Inject

                @Client

                @Alter

                private Event<Locale> localeEvent;

       

                @Inject

                @Client

                private Locale currentUserLocale;

       

                @Inject

                private UserLogger userLogger;

       

       

                /* Transaction manager */

                @Resource private UserTransaction utx;

       

       

                /**

                 * Set the user locale based on passed parameter

                 *

                 * @param Locale

                 *            , a {@link Locale}class that represents the new user locale to

                 *            set

                 * @throws UnsupportedLocaleException if the locale that you try to set isn't supported          

                 */

                public void setUserLocale(Locale locale) throws UnsupportedLocaleException {

                          if (localeConfiguration.getSupportedLocaleKeys().contains(locale.getLanguage())) {

                                    localeEvent.fire(locale);

                          } else throw new UnsupportedLocaleException();

                }

       

                /**

                 * Set the user language based on passed parameter

                 *

                 * @param String

                 *            , a {@link String}variable that represents the new user language to

                 *            set

                 * @throws UnsupportedLocaleException if the language that you try to set isn't supported          

                 */

                public void changeUserLanguage(ValueChangeEvent event) throws UnsupportedLocaleException {

                          setUserLocale(new Locale((String) event.getNewValue()));

                }

       

                /**

                 * Save the application preferred language of the user into database

                 *

                 * @return a {@link String} that represents the navigation rule

                 */

                public String savePreferredLanguage() {

                          try {

                                    utx.begin();

       

                                    Attribute preferredLanguage = new SimpleAttribute(Constants.IDENTITY_TYPE_LANGUAGE, (String) currentUserLocale.getLanguage());

                                    identitySession.getAttributesManager().updateAttributes(

                                                        identity.getUser(), new Attribute[] { preferredLanguage });

       

                                    utx.commit();

                          } catch (Exception e) {

                                    try {

                                              utx.rollback();

                                    } catch (Exception e2) {

                                              userLogger.rollbackException(ExceptionUtils.getStackTrace(e2));

                                    }

                                    userLogger.updateLanguageException(ExceptionUtils.getStackTrace(e));

       

      return Constants.EXCEPTION;

                          }

       

                          return null;

                }

       

      }

       

      This class is used by a web page to manage the application preferred language of the user. As you can see, I have a ValueChangeListener (method changeUserLanguage) that is used by a selectbox to change the locale. When the user click on the submit button, the ValueChangeListener changes the locale but, in the action method savePreferredLanguage(), the injected value currentUserLocale is the same as before the change (this because the observer of the org.jboss.seam.international.locale.UserLocaleProducer changes the local reference of the userLocale variable but the injected value into my bean keep following the previous instance of the userLocale object).

      So, I solved this problem putting into two separated request scoped classes the ValueChangeListener method (changeUserLanguage) and the action method (savePreferredLanguage). In this way, when the ValueChangeListener is called, it changes the userLocale (variable of the class org.jboss.seam.international.locale.UserLocaleProducer) and than, when the action is called, the fresh value is injected into bean.

      My question is: is there a better solution that permits to mantain ValueChangeListener and action method on the same class? Putting all logic into ValueChangeListener isn't the correct solution for me ;-)

       

      Thanks

        • 1. Re: Suggestion on localization with seam 3 international
          kenfinni

          Roberto,

           

          CDI works by performing injection on the Bean at instantiation, and as the CustomLocale Bean is only instantiated once, that is why the value of currentUserLocale is not updated when you fire the event.

           

          The simplest solution is to call currentUserLocale = locale within setUserLocale() to update the copy you have.

           

          Ken

          • 2. Re: Suggestion on localization with seam 3 international
            conte

            Thak you Ken. I supposed that your solution was the simplest but I think that have a simple getter of the userLocale into the org.jboss.seam.international.locale.UserLocaleProducer would be appreciated instead having a copy of the userLocale in my bean. Of course this would imply a refactoring of the org.jboss.seam.international.locale.UserLocaleProducer. My post was intended to raise problem and, if possible and correct, improve the org.jboss.seam.international.locale.UserLocaleProducer.

            Thanks again.

             

            Roberto

            • 3. Re: Suggestion on localization with seam 3 international
              kenfinni

              Roberto,

               

              Adding a getter into UserLocaleProducer would circumvent the use of CDI for a very specific use case scenario.

               

              After the event if fired and consumed by UserLocaleProducer, any other Bean being instantiated will pick up the correct locale, so at the moment I can't really see a benefit of adding a getter when you can simply update the local value yourself.

               

              Ken

              • 4. Re: Suggestion on localization with seam 3 international
                conte

                Ken,

                 

                I have another question for you about locale. I have my custom locale class that contains an alternative producer like this:

                 

                @Alternative

                @SessionScoped

                public class CustomLocale implements Serializable {

                 

                       private static final long serialVersionUID = -4145006297447436429L

                 

                       private Locale userLocale

                 

                          /**

                           * Produces locale of the user.

                           *

                           * @return a {@link Locale} object with the user locale for this session

                           */

                          @Produces

                          @Client

                          @Named

                          @Alternative

                          public Locale getUserLocale() {

                                    return this.userLocale;

                          }

                 

                ................................

                 

                 

                Inside another class of my project, I injected user locale in this way

                 

                @Inject

                @Client

                private Locale currentUserLocale;

                 

                and I verified that the producer used is my alternative producer reported up here. Also my facelet pages are localized using this producer. In the class org.jboss.seam.international.status.builder.BundleTemplateMessageImpl there is this injection:

                 

                    @Inject

                    @Client

                    Locale clientLocale;

                 

                and I verified that the producer used to satisfy this dependency isn't my producer but org.jboss.seam.international.locale.UserLocaleProducer. In this way, web pages are correctly localized but faces messages are not.

                Do you have an explanation for this problem?

                Thanks

                 

                Roberto

                • 5. Re: Suggestion on localization with seam 3 international
                  kenfinni

                  I think you're falling into the problem described here: http://docs.jboss.org/weld/reference/latest/en-US/html/specialization.html#d0e4382

                   

                  And I believe the reason is because the Producer in Seam International is not marked @Alternative, which will mean it's always active.  It's just that when you provide your own it's not used, except when Seam 3 International code uses it.

                   

                  Have you tried using Seam 3 Faces to integrate Faces messages using International, as I'm pretty sure they handle this.

                   

                  Ken

                  • 6. Re: Suggestion on localization with seam 3 international
                    simone.m

                    Hi Ken.

                    I'm working with Roberto on this issue.

                     

                    I don't understand why Seam 3 International code uses in org.jboss.seam.international.status.builder.BundleTemplateMessageImpl its producer instead our @alternative while all other @inject @client Locale locale occurrencies use our producer.

                     

                    I'm trying to @specializes our Locale procuder class without results.

                     

                    Tnx.

                    Simone.

                    • 7. Re: Suggestion on localization with seam 3 international
                      kenfinni

                      Simone, as I mentioned in the previous comment, I believe you're experiencing the problem because the producer from Seam 3 International is *not* marked as an @Alternative, which means it's always active.

                       

                      I suspect that in the situation of BundleTemplateMessageImpl it's not using your producer for some reason, but as the Weld doc state, @Alternative can have unexpected behavior in some situations and I believe this to be one of them.

                      • 8. Re: Suggestion on localization with seam 3 international
                        simone.m

                        Hi Ken,

                        thank you very much for your explanation. I feared unexpected Weld behaviour.

                         

                        Thanks again.

                        Simone.