6 Replies Latest reply on Feb 21, 2008 1:08 PM by pmuir

    Passing Values to Beans

    mgoetz

      Hi,


      im stuck with a very stupid question but before i spend furthermore several hours searching google the problem is perhaps solved here within minutes.


      The Problem concerns a login form, extended with one attribute to be passed.


      I've extended the org.jboss.seam.security.Identity class by an own one with one extra String attribute called loginType.


      I like to have one method authenticating and comparing the username/password to three user tables in the db. Which table has to be compared should decide this loginType attribute.


      So i've created three forms with the common username and password fields and need to pass the constant values 1,2 or 3 to loginType attribute of the extended Identity class.


      The question is: how can i pass the parameters in the JSF/Seam xhtml file and inject the loginType field (or request the parameter)?


      The xhtml code is typically:


      <div>
           <h:outputLabel for="username">E-Mail Adresse</h:outputLabel>
           <h:inputText id="username" value="#{identity.username}" style="width: 175px;"/>
           <div class="errors"><h:message for="username"/></div>
      </div>
      <div>
           <h:outputLabel for="password">Kennwort</h:outputLabel>
           <h:inputSecret id="password" value="#{identity.password}" style="width: 175px;"/>
      </div>
      <div class="errors"><h:messages globalOnly="true"/></div>
      <div class="buttonBox"><h:commandButton id="login" action="#{identity.login}" value="Anmelden"/></div>
      



      Thanks for your support!



      Matthias

        • 1. Re: Passing Values to Beans
          mail.micke

          Perhaps you could switch from commandButton to commandLink and use f:param and get those values from the request map?

          • 2. Re: Passing Values to Beans
            damianharvey.damianharvey.gmail.com

            So the user doesn't know if they are 1, 2, or 3? ie. a drop down box on the one page is inappropriate?


            You could always have a login bean with 3 methods loginType1() loginType2() and loginType3(). Each page calls a different method. Each method sets the loginType as appropriate.


            Sound reasonable?


            Cheers,


            Damian.

            • 3. Re: Passing Values to Beans
              mgoetz

              Yeas, thats right. The User must not have to decide, which loginType to use.
              Thing would be easy, if you can specify different authentication methods in components.xml (eg for each page, but this is a workaround and not a perfect solution)


              I like that idea with the three different login methods. But one further problem:


              I have the AuthenticatorAction with the Authenticator Interface like the examples. In the components.xml the authenticate-method is set to

              #{authenticator.authenticate}

              .


              I assume the three Login Methods should be placed in my extended Identity class and are called with the commandButton.
              But the Authentication itself is managed in the Authenticator class where the tables are queried.


              How can i pass the right decision from my login method to the authenticator?


              Perhaps this is not my day - so thanks especially for your support today! ;-)


              Matthias




              • 4. Re: Passing Values to Beans

                I got this working doing like shown below. However, I don't know if it is OK to do like this. I guess any of the court cards in the deck (Muir,Bauer,King) will slap me in the face if this is wrong/unacceptable :-)


                This could probably be done much better if you put some effort into it.


                The strategy is as follows:



                • call a method that exchanges the methodexpression for the identity component

                • manually call identity.login



                Loginbutton:


                <h:commandButton id="login" action="#{login.login(1)}" class="button" value="#{messages['login.button']}" />



                where you exchange the login-parameter as you'd like.


                Then you do something like this in a Login component.


                @Name("login")
                @Scope(ScopeType.CONVERSATION)
                public class LoginAction {
                
                    @In
                    private Identity identity;
                
                    @In
                    private Expressions expressions;
                
                    public void login(int id) {
                
                        MethodExpression m = identity.getAuthenticateMethod();
                
                        switch (id) {
                        case 1:
                            identity.setAuthenticateMethod(expressions.createMethodExpression("#{authenticator.authenticate}", Boolean.class, new Class[0]));
                            break;
                        case 2:
                            identity.setAuthenticateMethod(expressions.createMethodExpression("#{authenticator.authenticate2}", Boolean.class, new Class[0]));
                            break;
                        }
                
                        identity.login();
                
                    }
                



                and finally we have the some kind of authenticator:



                @Name("authenticator")
                public class AuthenticatorAction
                {
                   public boolean authenticate()
                   {
                       return true;
                   }
                
                   
                   public boolean authenticate2()
                   {
                       return true;
                   }
                   
                }



                • 5. Re: Passing Values to Beans

                  Maybe the solution (if I may call it that) above is a bit overkill for the initial problem


                  In LoginAction you could just do a


                  Contexts.getConversationContext().set("loginType", id);
                  identity.login();
                  



                  and then in the authenticate method


                  Integer id = (Integer)Contexts.getConversationContext().get("loginType");
                  switch(id) ...
                  



                  Nicest thing with Seam that there often are MANY ways to solve problems, but I always have a bad feeling thinking 'is this really the way to do it?'. Maybe I should file a JIRA for a best practice chapter in the documentation. That is, if it doesn't exists already :-)

                  • 6. Re: Passing Values to Beans
                    pmuir

                    Daniel Roth wrote on Feb 21, 2008 09:55 AM:


                    I got this working doing like shown below. However, I don't know if it is OK to do like this. I guess any of the court cards in the deck (Muir,Bauer,King) will slap me in the face if this is wrong/unacceptable :-)



                    Hehe. No, this looks fine :)


                    Another option, is to use a <out /> in pages.xml to set the correct value for the page.