14 Replies Latest reply on Nov 21, 2008 5:43 PM by hardaur

    convertEntity problem

    hardaur

      Hello all,


        I'm having a bit of a frustrating problem with s:convertEntity and am hoping one of you may be more informed than google ; )


      Seam 2.1.0.GA
      JBoss 4.2.2.GA
      IceFAces 1.7.2


      The xhtml:

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:h="http://java.sun.com/jsf/html"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:s="http://jboss.com/products/seam/taglib"
            xmlns:ice="http://www.icesoft.com/icefaces/component">
      
           <ui:composition template="/layout/home_template.xhtml">
           
                <ui:define name="body">
                     <ice:form id="registrationWizardFormID-1">
                          <center>
                               <ice:panelGroup id="userManagerGroupId-Review" styleClass="displayPanelGroup">
                                    <table class="formTable" cellspacing="0" cellpadding="3">
                                         <tr>
                                              <td class="formTableHeader" colspan="3">
                                                   Create User
                                              </td>
                                         </tr>
                                         <tr>
                                              <td>
                                                   <ice:panelGroup id="accountInformationID" styleClass="displayPanelGroup">
                                                        <table id="accountInformationTableID" class="displayTable" cellspacing="0" cellpadding="3">
                                                             <tr>
                                                                  <td class="displayTableHeader" colspan="3">
                                                                       Account Information
                                                                  </td>
                                                             </tr>
                                                             <s:decorate id="usernameDecoration" template="/layout/edit.xhtml">
                                  <ui:define name="label">Username</ui:define>
                                  <ice:inputText id="username"
                                                 required="true"
                                                 length="64"
                                                 value="#{userAccount.username}"
                                                 validator="#{userManager.validateUniqueUsername}"/>
                              </s:decorate>
      
                              <s:decorate id="passwordDecoration" template="/layout/edit.xhtml">
                                  <ui:define name="label">Password</ui:define>
                                  <ice:inputSecret id="password"
                                                 required="true"
                                                 length="64"
                                                 value="#{userAccount.password}"
                                                 valueChangeListener="#{userManager.validatePasswordChange}"/>
                              </s:decorate>
      
                              <s:decorate id="comfirmPasswordDecoration" template="/layout/edit.xhtml">
                                  <ui:define name="label">Confirm Password</ui:define>
                                  <ice:inputSecret id="confirmPassword"
                                                 required="true"
                                                 length="64"
                                                 value="#{userAccount.confirmPassword}"
                                                 validator="#{userManager.validateConfirmPassword}"/>
                              </s:decorate>
      
                              <s:decorate id="emailDecoration" template="/layout/edit.xhtml">
                                  <ui:define name="label">Email Address</ui:define>
                                  <ice:inputText id="email"
                                                 required="true"
                                                 length="64"
                                                 value="#{user.email}"
                                                 validator="#{userManager.validateUniqueEmail}"/>
                              </s:decorate>
      
                              <s:decorate id="dobDecoration" template="/layout/edit.xhtml">
                                  <ui:define name="label">Birthday</ui:define>
                                  <ice:selectInputDate id="dob"
                                                       value="#{user.dob}"
                                                       renderAsPopup="true"
                                                       required="true"
                                                       partialSubmit="false"
                                                       renderMonthAsDropdown="true"
                                                       renderYearAsDropdown="true">
                                      <f:convertDateTime
                                              pattern="MM/dd/yyyy"/>
                                  </ice:selectInputDate>
                              </s:decorate>
                              
                              <s:decorate id="nicknameDecoration" template="/layout/edit.xhtml" >
                                              <ui:define name="label">Display Name</ui:define>
                                              <ice:inputText id="nickname"
                                                   required="false"
                                                   length="64"
                                                   value="#{user.nickname}"
                                                   validator="#{userManager.validateUniqueNickname}"/>
                                         </s:decorate>
                                                        </table>
                                                   </ice:panelGroup>
                                              </td>
                                              <td valign="top">
                                                   <ice:panelGroup id="subscriptionInformationID" styleClass="displayPanelGroup">
                                                        <table id="subscriptionInformationTableID" class="displayTable" cellspacing="0" cellpadding="3">
                                                             <tr>
                                                                  <td class="displayTableHeader" colspan="3">
                                                                       Subscription Information
                                                                  </td>
                                                             </tr>
                                                             <s:decorate id="s1DecorationID" template="/layout/display.xhtml">
                                                                  <ui:define name="label">Sub Information:</ui:define>
                                                                  Not yet
                                                             </s:decorate>
                                                        </table>
                                                   </ice:panelGroup>
                                              </td>
                                         </tr>
                                         <tr>
                                              <td>
                                                   <ice:panelGroup id="personalInformationID" styleClass="displayPanelGroup">
                                                        <table id="personalInformationTableID" class="displayTable" cellspacing="0" cellpadding="3">
                                                             <tr>
                                                                  <td class="displayTableHeader" colspan="3">
                                                                       Personal Information
                                                                  </td>
                                                             </tr>
                                                             <s:decorate id="firstNameDecorationID" template="/layout/edit.xhtml">
                                                                  <ui:define name="label">First Name:</ui:define>
                                                                       <ice:inputText id="firstName"
                                                                            required="true"
                                                                            length="64"
                                                                            value="#{user.firstName}"/>
                                                             </s:decorate>
                                                             <s:decorate id="middleInitialDecorationID" template="/layout/edit.xhtml">
                                                                  <ui:define name="label">Middle Initial:</ui:define>
                                                                  <ice:inputText id="middleName"
                                                                            required="false"
                                                                            size="1"
                                                                            length="64"
                                                                            value="#{user.middleInitial}"/>
                                                             </s:decorate>
                                                             <s:decorate id="lastNameDecorationID" template="/layout/edit.xhtml">
                                                                  <ui:define name="label">Last Name:</ui:define>
                                                                  <ice:inputText id="lastName"
                                                                            required="true"
                                                                            length="64"
                                                                            value="#{user.lastName}"/>
                                                             </s:decorate>
                                                             <s:decorate id="address1DecorationID" template="/layout/edit.xhtml">
                                                                  <ui:define name="label">Address 1:</ui:define>
                                                                  <ice:inputText id="address1"
                                                                            required="true"
                                                                            length="64"
                                                                            value="#{user.address1}"/>
                                                             </s:decorate>
                                                             <s:decorate id="address2DecorationID" template="/layout/edit.xhtml">
                                                                  <ui:define name="label">Address 2:</ui:define>
                                                                  <ice:inputText id="address2"
                                                                            required="false"
                                                                            length="64"
                                                                            value="#{user.address2}"/>
                                                             </s:decorate>
                                                             <s:decorate id="cityDecorationID" template="/layout/edit.xhtml">
                                                                  <ui:define name="label">City:</ui:define>
                                                                  <ice:inputText id="city"
                                                                            required="true"
                                                                            length="64"
                                                                            value="#{user.city}"/>
                                                             </s:decorate>
                                                             <s:decorate id="territoryDecoration" template="/layout/edit.xhtml" >
                                                             <ui:define name="label">State</ui:define>
                                                             <ice:selectOneMenu id="state"
                                                                  value="#{user.state}"
                                                                  required="true">
                                                                  <f:selectItem itemLabel="Select State" itemValue=""/>
                                                                  <s:selectItems var="_state" value="#{stateList}"
                                                                       label="#{_state.name}"/>
                                                                  <s:convertEntity/>                                             
                                                             </ice:selectOneMenu>
                                                        </s:decorate>
                                                        
                                                        <s:decorate id="zipDecoration" template="/layout/edit.xhtml" >
                                                             <ui:define name="label">Zip Code</ui:define>
                                                             <ice:inputText id="zip"
                                                                  required="true"
                                                                  length="10"
                                                                  size="10"
                                                                  value="#{user.zip}"/>
                                                        </s:decorate>
                                                        
                                                        <s:decorate id="phone1Decoration" template="/layout/edit.xhtml" >
                                                             <ui:define name="label">Phone 1</ui:define>
                                                             <ice:inputText id="phone1"
                                                                  required="true"
                                                                  length="64"
                                                                  value="#{user.phone1}"/>
                                                        </s:decorate>
                                                        
                                                        <s:decorate id="phone2Decoration" template="/layout/edit.xhtml" >
                                                             <ui:define name="label">Phone 2</ui:define>
                                                             <ice:inputText id="phone2"
                                                                  required="false"
                                                                  length="64"
                                                                  value="#{user.phone2}"/>
                                                        </s:decorate>
                                                        </table>
                                                   </ice:panelGroup>
                                              </td>
                                              <td valign="top">
                                                   <ice:panelGroup id="authorizationInformationID" styleClass="displayPanelGroup">
                                                        <table id="authorizationInformationTableID" class="displayTable" cellspacing="0" cellpadding="3">
                                                             <tr>
                                                                  <td class="displayTableHeader" colspan="3">
                                                                       Authorization Information
                                                                  </td>
                                                             </tr>
                                                             <tr>
                                                                  <td>
                                                                       <s:decorate id="authhorizationDecorationID" template="/layout/display.xhtml">
                                                                            <ui:define name="label">Select User Roles:</ui:define>
                                                                            
                                                                            <ice:selectManyCheckbox id="roles"
                                                                            value="#{userAccount.roles}"
                                                                            required="true">
                                                                            <s:selectItems var="_role" value="#{userRoleList}"
                                                                                 label="#{_role.name}"/>
                                                                            <s:convertEntity/>                                             
                                                                       </ice:selectManyCheckbox>
                                                                  </s:decorate>
                                                             </td>
                                                        </tr>
                                                        </table>
                                                   </ice:panelGroup>
                                              </td>
                                              <td valign="bottom">
                                                   <center>
                                                        <ice:panelGrid columns="2">
                                                             <ice:commandButton id="cancel" 
                                                                  immediate="true" 
                                                                  action="cancel"
                                                                  value="Cancel" />
                                                             <ice:commandButton id="save" 
                                                                  action="#{userManager.save}" 
                                                                  value="Register!"/>
                                                        </ice:panelGrid>
                                                   </center>
                                              </td>
                                         </tr>
                                    </table>
                               </ice:panelGroup>
                          </center>
                     </ice:form>
                </ui:define>
           </ui:composition>
      
      </html>



      The seam component:



      package com.domain.application.session.admin;
      
      import java.util.Date;
      
      import javax.faces.component.EditableValueHolder;
      import javax.faces.component.UIComponent;
      import javax.faces.component.UIInput;
      import javax.faces.context.FacesContext;
      import javax.faces.event.ValueChangeEvent;
      import javax.persistence.EntityManager;
      
      import org.jboss.seam.ScopeType;
      import org.jboss.seam.annotations.Begin;
      import org.jboss.seam.annotations.Conversational;
      import org.jboss.seam.annotations.End;
      import org.jboss.seam.annotations.FlushModeType;
      import org.jboss.seam.annotations.In;
      import org.jboss.seam.annotations.Logger;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.Observer;
      import org.jboss.seam.annotations.Out;
      import org.jboss.seam.annotations.Role;
      import org.jboss.seam.annotations.Scope;
      import org.jboss.seam.annotations.Transactional;
      import org.jboss.seam.faces.FacesMessages;
      import org.jboss.seam.log.Log;
      import org.jboss.seam.security.Identity;
      import org.jboss.seam.security.RunAsOperation;
      import org.jboss.seam.security.management.IdentityManager;
      import org.jboss.seam.security.management.JpaIdentityStore;
      import org.jboss.seam.ui.validator.ModelValidator;
      
      import com.domain.application.entity.User;
      import com.domain.application.entity.UserAccount;
      import com.domain.application.session.entity.UserAccountList;
      
      /**
       * Operations pertaining to creating, registering, editing, disabling and deleting
       * UserAccounts. 
       * @author gander
       *
       */
      @Name("userManager")
      // Role registrationWizard replaces RegistrationWizard.java
      //@Role(name = "registrationWizard", scope = ScopeType.CONVERSATION)  
      @Scope(ScopeType.CONVERSATION)
      public class UserManager
      {
           @Logger
           private Log log;
      
           @In
           FacesMessages facesMessages;
      
           @In
           protected EntityManager entityManager;
           
           @In
           protected IdentityManager identityManager;
           
           @In
           private Identity identity;
           
           @In (required=false)
           private UserAccountList userAccountList;
           
           @In (required=false) 
           @Out (required=false)
           private UserAccount userAccount;
      
           @Out (required=false)
           private User user;
      
           private String username;
           private String password;
           private boolean isWizard = true;
           
           /**
            * Delete the UserAccount injected by userAccount
            */
           public String deleteUser()
           
           {
                String username = userAccount.getUsername();
                
                log.info("Deleting user " + username);
                
                if (!identityManager.deleteUser(username))
                {
                     facesMessages.add("User " + username + " NOT deleted");
                     return "fail";
                }
                
                facesMessages.add("User " + username + " deleted");
                
                userAccountList.refresh();
                return "success";
           }
           
           /**
            * Handle the manual creation of a new user through the admin system.
            */
           @Begin(join = true, flushMode=FlushModeType.MANUAL)
           public void startCreateUser()
           {
                facesMessages.add("BLAH BLAH BLAH 1");
                log.info("Create user starting");
                isWizard = false;
                
                // create my objects
                user = new User();
                userAccount = new UserAccount();
                
                // set some defaults
                user.setPasswordLastChanged(new Date());
           }
           
           /**
            * Start the registration process, create the new entities and set
            * some defaults. 
            */
           @Begin(join = true, pageflow = "Registration Wizard", flushMode=FlushModeType.MANUAL)
           public void startWizard()
           {
                facesMessages.add("BLAH BLAH BLAH 2");
                     log.info("User registration wizard starting");
                     isWizard = true;
                     
                     // create my objects
                     user = new User();
                     userAccount = new UserAccount();
                     
                     // set some defaults
                     user.setPasswordLastChanged(new Date());
           }
           
           /**
            * Verify that the password and the verifyPassword match.
            * 
            * @param context
            * @param validatedComponent
            * @param value
            */
           @Conversational
           public void validateConfirmPassword(FacesContext context,
                UIComponent validatedComponent, Object value)
           {
                checkHibernateAnnotations(context, validatedComponent, value);
                
                String verifyPassword = (String) value;
      
                UIComponent passwordField = validatedComponent
                     .findComponent(":registrationWizardFormID-1:passwordDecoration:password");
                String password = (String) ((EditableValueHolder) passwordField)
                     .getValue();
      
                if (!verifyPassword.equals(password))
                {
                     ((UIInput) validatedComponent).setValid(false);
                     facesMessages.addToControl(validatedComponent.getId(),
                          "Passwords do not match!");
                }
           }
           
           /**
            * This validation is primarily for after the user has entered password
            * and confirmPassword and comes back and changes password.  In that case
            * the password confirm will not fire, I'm here to insure that it's taken
            * care of.  I won't do anything if there's been nothing entered for confirm
            * password.
            * @param e
            */
           @Conversational
           public void validatePasswordChange(ValueChangeEvent e)
           {
                String password = (String) e.getNewValue();
                
                UIComponent confirmPasswordField = e.getComponent().findComponent(
                     ":registrationWizardFormID-1:comfirmPasswordDecoration:confirmPassword");
                
                System.out.println("confirmPasswordField is " + confirmPasswordField);
                
                String confirmPassword = 
                     (String) ((EditableValueHolder) confirmPasswordField).getValue();
                
                if (confirmPassword == null || confirmPassword.equals(""))
                     return;
                
                if (!password.equals(confirmPassword))
                {
                     // note that message is being applied to confirm field, not
                     //password field
                     facesMessages.addToControl(confirmPasswordField.getId(),
                          "Passwords do not match!");
                }
           }
      
           /**
            * Verify that the requested username is unique in the database.
            * 
            * @param context
            * @param validatedComponent
            * @param value
            */
           @Conversational
           public void validateUniqueUsername(FacesContext context,
                UIComponent validatedComponent, Object value)
           {
                checkHibernateAnnotations(context, validatedComponent, value);
                
                String username = (String) value;
      
                int num = entityManager.createQuery(
                     "select u.username from UserAccount u where u.username = :username")
                     .setParameter("username", username).getResultList().size();
      
                if (num != 0)
                {
                     ((UIInput) validatedComponent).setValid(false);
                     facesMessages.addToControl(validatedComponent.getId(),
                          "#{value} already used, please choose another!");
                }
           }
           
           /**
            * Verify that the requested nickname is unique in the database.
            * 
            * @param context
            * @param validatedComponent
            * @param value
            */
           @Conversational
           public void validateUniqueNickname(FacesContext context,
                UIComponent validatedComponent, Object value)
           {
                checkHibernateAnnotations(context, validatedComponent, value);
                
                String nickname = (String) value;
      
                int num = entityManager.createQuery(
                     "select u.nickname from User u where u.nickname = :nickname")
                     .setParameter("nickname", nickname).getResultList().size();
      
                if (num != 0)
                {
                     ((UIInput) validatedComponent).setValid(false);
                     facesMessages.addToControl(validatedComponent.getId(),
                          "#{value} already used, please choose another!");
                }
           }
      
           /**
            * Verify that the email the user is using is unique.
            * 
            * @param context
            * @param validatedComponent
            * @param value
            */
           @Conversational
           public void validateUniqueEmail(FacesContext context,
                UIComponent validatedComponent, Object value)
           {
                checkHibernateAnnotations(context, validatedComponent, value);
                
                String email = (String) value;
      
                int num = entityManager.createQuery(
                     "select u.email from User u where u.email = :email").setParameter(
                     "email", email).getResultList().size();
      
                if (num != 0)
                {
                     ((UIInput) validatedComponent).setValid(false);
                     facesMessages.addToControl(validatedComponent.getId(),
                          "#{value} is already in use, please use another!");
                }
           }
           
           @Transactional
           @End(beforeRedirect = true)
           public String save()
           {
                System.out.println("**********************");
                // is the user coming through the registration wizard or is the account
                // being created from the admin interface?
                if (isWizard)
                     log.info("Registering : " + userAccount.getUsername());
                else
                     log.info("Creating account for " + userAccount.getUsername());
                
                System.out.println("Roles are " + userAccount.getRoles());
                
                // save username and password for later use
                username = userAccount.getUsername();
                password = userAccount.getPassword();
                
                // create the UserAccount
                new RunAsOperation()
                {
                     public void execute()
                     {
                          identityManager.createUser(username, password);
                          
                          userAccount.setUser(user);
                          userAccount.setEnabled(true);
                          
                          entityManager.flush();
                          
                          if (isWizard)
                          {
                               // since userAccount doesn't get created until flush and 
                               // grantRole has to have it.  so set role and flush again
                               identityManager.grantRole(username, "user");
                          }
                          
                          
                          entityManager.flush();
                     }
                }.addRole("admin")
                .run();
                
                if (isWizard)
                {
                     // and go ahead and login the user.
                     identity.getCredentials().setUsername(username);
                     identity.getCredentials().setPassword(password);
                     identity.login();
                }
                
                return "success";
           }
           
           /**
            * UserAccount is created, associate the new entity to the local variable.
            * @param userAccount
            */
           @Observer(JpaIdentityStore.EVENT_USER_CREATED)
           public void userAccountCreated(UserAccount userAccount)
           {
                this.userAccount = userAccount;
           }
           
           /**
            * Since we're using JSF validate instead of valueChangeListeners or other
            * we have to force a check of the hibernate annotation constraints.
            * 
            * @param context
            * @param validate
            * @param value
            */
           private void checkHibernateAnnotations(FacesContext context,
                UIComponent validate, Object value) 
           {
                ModelValidator mv = new ModelValidator();
                mv.validate(context, validate, value);
           }
      
      }



      The EntityQuery:



      package com.domain.application.session.entity;
      
      import java.util.Arrays;
      
      import org.jboss.seam.ScopeType;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.Scope;
      import org.jboss.seam.framework.EntityQuery;
      
      import com.domain.application.entity.UserRole;
      
      @Name("userRoleList")
      public class UserRoleList extends EntityQuery(UserRole) {
      
           private static final String EJBQL = "select userRole from UserRole userRole";
      
           private static final String[] RESTRICTIONS = {};
      
           private UserRole userRole = new UserRole();
      
           public UserRoleList() {
                setEjbql(EJBQL);
                setRestrictionExpressionStrings(Arrays.asList(RESTRICTIONS));
                setMaxResults(25);
           }
      
           public UserRole getUserRole() {
                return userRole;
           }
      }



      The entity:


      package com.domain.application.entity;
      // Generated Nov 4, 2008 8:35:52 AM by Hibernate Tools 3.2.2.GA
      
      import java.util.Set;
      
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.GeneratedValue;
      import javax.persistence.Id;
      import javax.persistence.JoinColumn;
      import javax.persistence.JoinTable;
      import javax.persistence.ManyToMany;
      import javax.persistence.Table;
      import javax.persistence.UniqueConstraint;
      
      import org.hibernate.annotations.GenericGenerator;
      import org.hibernate.annotations.Parameter;
      import org.hibernate.validator.NotNull;
      import org.jboss.seam.annotations.Name;
      import org.jboss.seam.annotations.security.management.RoleConditional;
      import org.jboss.seam.annotations.security.management.RoleGroups;
      import org.jboss.seam.annotations.security.management.RoleName;
      
      /**
       * UserRole generated by hbm2java
       */
      @Entity
      @Table(name = "user_role", catalog = "pb_dev", uniqueConstraints = @UniqueConstraint(columnNames = "name"))
      @Name("userRole")
      public class UserRole extends MappedEntity {
      
           private static final long serialVersionUID = 537460588621165918L;
           
           private Long id;
           private String name;
           private boolean conditional;
           
           private Set<UserRole> groups;
      
           public UserRole() {
           }
      
           public UserRole(Long id, boolean conditional) {
                this.id = id;
                this.conditional = conditional;
           }
           public UserRole(Long id, String name, boolean conditional) {
                this.id = id;
                this.name = name;
                this.conditional = conditional;
           }
      
           @Id
           @GenericGenerator(
              name = "sequenceGenerator",
              strategy = "org.hibernate.id.enhanced.TableGenerator",
              parameters = {
                      @Parameter(name = "optimizer", value = "hilo"),
                      @Parameter(name = "initial_value", value = "1000"),
                      @Parameter(name = "segment_value", value = "user_role"),
                      @Parameter(name = "increment_size", value = "10")
              }
           )
           @GeneratedValue(generator = "sequenceGenerator")
           @Column(name = "id", unique = true, nullable = false)
           public Long getId() {
                return this.id;
           }
      
           public void setId(Long id) {
                this.id = id;
           }
      
           @Column(name = "name", unique = true)
           @RoleName
           public String getName() {
                return this.name;
           }
      
           public void setName(String name) {
                this.name = name;
           }
           
           @RoleGroups
           @ManyToMany(targetEntity = UserRole.class)
           @JoinTable(name = "role_groups", 
                joinColumns = @JoinColumn(name = "role_id"),
                inverseJoinColumns = @JoinColumn(name = "member_of_role_id")
           )
           public Set<UserRole> getGroups()
           {
                return groups;
           }
         
           public void setGroups(Set<UserRole> groups)
           {
                this.groups = groups;
           }
              
      
           // Changed from default (BIT) to TINYINT(1) couldn't figure out how to make bit work right.
           @Column(name = "conditional", nullable = false, columnDefinition = "TINYINT(1)")
           @NotNull
           @RoleConditional
           public boolean isConditional() {
                return this.conditional;
           }
      
           public void setConditional(boolean conditional) {
                this.conditional = conditional;
           }
      
      }







      And the error:



      19:21:11,827 INFO  [lifecycle] WARNING: FacesMessage(s) have been enqueued, but may not have been displayed.
      sourceId=registrationWizardFormID-1:authhorizationDecorationID:roles[severity=(ERROR 2), summary=(value could not be converted to the expected type), detail=(value could not be converted to the expected type)]



      The problem is the UserRole multi-select with a s:convertEntity.  I'm using EntityQuery and they load and display fine.  When the form is submitted, I get the above error and processing stops (there are no stacktraces in console or logs).  Honestly, aside from the last 5 hours I've spent googling I don't even know how to troubleshoot this one.


      I do know that it's when convertEntity tries to convert the selected item back to a UserRole.   I'm stumped past that.


      Any pointers would be very, very much appreciated.


      Gerald


      P.S.  Yes, I know that I could use userAction stuff in the form, but due to the interaction between my userAccount and other objects, I don't care for it in that context.

        • 1. Re: convertEntity problem
          joblini

          Set debug breakpoints on getAsString, getAsObject in org.jboss.seam.ui.EntityConverter, in jboss-seam-ui.jar (source is in jboss-seam-ui-sources.jar)

          • 2. Re: convertEntity problem
            rmoore2112

            1. Make sure you are in a long running conversation to ensure you are using the same instance of the entity manager.

            2. Override equals on the entity you are converting, and compare the value selected in the select list to the value on the entity. In your example above, it would be role.name




            @Override
                 public boolean equals(Object obj) {
                      
                      return ((Role)obj).getName().equals(getName());
            }




            • 3. Re: convertEntity problem
              hardaur

              Ingo,  I'm working on it, but having a tough time actually nailing down the specific failure point.  There are so many calls and I'm not super-awesome with the debugger.


              Rodney,  I had actually tried this before, and tried it again after your suggestion:


                   @Override
                   public boolean equals(Object obj)
                   {
                        System.out.println("******************* IN EQUALS obj.getName() = |" + ((UserRole)obj).getName() +"| and this.getName() = |" + this.getName() +"|" );
                        return ((UserRole)obj).getName().equals(getName());
                   }



              Interesting thing is, it's not being called.  Any idea how that could be? 


              Unless I'm misunderstanding something I SHOULD be in a long-running session (see first post action component userManager.startCreateUser.  This method is being called from an ice:commandButton to start the conversation and a page navigation to load the page:


              <navigation from-action="#{userManager.startCreateUser}">
                    <redirect view-id="/admin/editUser.xhtml"/>
                 </navigation>

                (from parent page).


              So I guess with it not executing the equals on the objects, I'm guessing they're null which would imply out of the conversation.  However, I don't see from a code standpoint how that could be?


              Also, I'm not doing anything entityManager-wise outside the default.  So I assume that there's only one instance.


              Very confused,


              Gerald


              P.S.  This is my maiden seam project, so I may be showing signs of daftness.  Any general critiques  on how I'm doing things in general are also welcome.

              • 4. Re: convertEntity problem
                jguglielmin

                I had a nice long answer in here with examples and everything, but when I went to save it, I got kicked out and nothing saved.  Oh well....short answer of things to try (since I seem to be having connection problems).  Your backing bean that extends EntityQuery, you might want to annotate with your conversation scope or at least Page (?). It is creating the list of values that are to be converted. Also, why no partialSubmit on your selectManyCheckBox? (then you can debug with your setter in your backing bean).   Is userAccount an entity bean? (session-scoped perhaps?)

                • 5. Re: convertEntity problem
                  hardaur

                  morns the long answer 


                  In testing I've scoped the EntityQuery to be Conversation and even Session.  Still have the same problem.


                  The UserAccount is an entity.  It was generated by hibernate and doesn't have a scope defined.  I don't think that's my issue, but I'll give it a shot scoped at conversation and see what happens.


                  Good idea on the partialSubmit, hadn't thought of it.  However, I've been looking at the debugger for about 5 hours to no avail, so I'm done for the time being.  My debugger-fu isn't strong today.  I'm having a bear of a time getting it to match source line numbers to calls for superclasses.  I've double checked versions and don't see a problem there sigh.


                  I did get one little hint, but got lost soon thereafter.  The system did blow a caught exception that was something about a call expecting an Array, but the value was a string (the ID of the selected UserRole I think).  That somehow led directly to the goal message ; )


                  Any other tips?  I'll keep plugging and post if I come up with something.


                  Gerald

                  • 6. Re: convertEntity problem
                    hardaur

                    Oops, meant to show UserAccount:


                    package com.domain.application.entity;
                    // Generated Nov 4, 2008 8:35:52 AM by Hibernate Tools 3.2.2.GA
                    
                    import java.util.Set;
                    
                    import javax.persistence.CascadeType;
                    import javax.persistence.Column;
                    import javax.persistence.Entity;
                    import javax.persistence.GeneratedValue;
                    import javax.persistence.Id;
                    import javax.persistence.JoinColumn;
                    import javax.persistence.JoinTable;
                    import javax.persistence.ManyToMany;
                    import javax.persistence.OneToOne;
                    import javax.persistence.Table;
                    import javax.persistence.Transient;
                    import javax.persistence.UniqueConstraint;
                    
                    import org.hibernate.annotations.GenericGenerator;
                    import org.hibernate.annotations.Parameter;
                    import org.hibernate.validator.Length;
                    import org.hibernate.validator.NotNull;
                    import org.jboss.seam.annotations.Name;
                    import org.jboss.seam.annotations.security.management.UserEnabled;
                    import org.jboss.seam.annotations.security.management.UserPassword;
                    import org.jboss.seam.annotations.security.management.UserPrincipal;
                    import org.jboss.seam.annotations.security.management.UserRoles;
                    
                    /**
                     * UserAccount generated by hbm2java
                     */
                    @Entity
                    @Table(name = "user_account", catalog = "pb_dev", uniqueConstraints = @UniqueConstraint(columnNames = "username"))
                    @Name("userAccount")
                    public class UserAccount extends MappedEntity {
                    
                         private static final long serialVersionUID = 8006479799106243993L;
                         
                         private Long id;
                         private String username;
                         private String passwordHash;
                         private String password;
                         private String confirmPassword; 
                         private boolean enabled;
                         
                         private Set<UserRole> roles;
                         private User user;
                    
                         public UserAccount() {
                         }
                    
                         public UserAccount(Long id, String username, String passwordHash,
                                   boolean enabled) {
                              this.id = id;
                              this.username = username;
                              this.passwordHash = passwordHash;
                              this.enabled = enabled;
                         }
                         public UserAccount(Long id, String username, String passwordHash,
                                   boolean enabled, User user) {
                              this.id = id;
                              this.username = username;
                              this.passwordHash = passwordHash;
                              this.enabled = enabled;
                         }
                    
                         @Id
                         @GenericGenerator(
                            name = "sequenceGenerator",
                            strategy = "org.hibernate.id.enhanced.TableGenerator",
                            parameters = {
                                    @Parameter(name = "optimizer", value = "hilo"),
                                    @Parameter(name = "initial_value", value = "1000"),
                                    @Parameter(name = "segment_value", value = "user_account"),
                                    @Parameter(name = "increment_size", value = "10")
                            }
                         )
                         @GeneratedValue(generator = "sequenceGenerator")
                         @Column(name = "id", unique = true, nullable = false)
                         public Long getId() {
                              return this.id;
                         }
                    
                         public void setId(Long id) {
                              this.id = id;
                         }
                    
                         @Column(name = "username", unique = true, nullable = false, length = 64)
                         @NotNull
                         @Length(min = 2, max = 64)
                         @UserPrincipal
                         public String getUsername() {
                              return this.username;
                         }
                    
                         public void setUsername(String username) {
                              this.username = username;
                         }
                    
                         @Column(name = "password_hash", nullable = false, length = 128)
                         @NotNull
                         @Length(min = 6, max = 128)
                         @UserPassword(hash = "MD5")
                         public String getPasswordHash() {
                              return this.passwordHash;
                         }
                    
                         public void setPasswordHash(String passwordHash) {
                              this.passwordHash = passwordHash;
                         }
                         
                         @Transient
                         @Length(min = 6, max = 64)
                         public String getPassword()
                         {
                              return this.password;
                         }
                         
                         public void setPassword(String password)
                         {
                              this.password = password;
                         }
                         
                         @Transient
                         public String getConfirmPassword()
                         {
                              return this.confirmPassword;
                         }
                         
                         public void setConfirmPassword(String confirmPassword)
                         {
                              this.confirmPassword = confirmPassword;
                         }
                         
                         // Changed from default (BIT) to TINYINT(1) couldn't figure out how to make bit work right.
                         @Column(name = "enabled", nullable = false, columnDefinition = "TINYINT(1)")
                         @UserEnabled
                         public boolean isEnabled() {
                              return this.enabled;
                         }
                    
                         public void setEnabled(boolean enabled) {
                              this.enabled = enabled;
                         }
                    
                         
                         @UserRoles
                         @ManyToMany(targetEntity = UserRole.class)
                         @JoinTable(name = "users_roles", 
                              joinColumns = @JoinColumn(name = "user_account_id"),
                              inverseJoinColumns = @JoinColumn(name = "user_role_id")
                         )
                         public Set<UserRole> getRoles()
                         {
                              return roles;
                         }
                       
                         public void setRoles(Set<UserRole> roles)
                         {
                              this.roles = roles;
                         }
                         
                         @OneToOne(cascade = CascadeType.ALL)
                         @JoinColumn(name = "user_id")
                         public User getUser()
                         {
                              return user;
                         }
                            
                         public void setUser(User user)
                         {
                              this.user = user;
                         }
                    }
                    

                    • 7. Re: convertEntity problem
                      jguglielmin

                      You have an instance of userAccount in your Conversation-managed userManager bean, so why not use that instead of whatever you have for the userAccount object?  You have already injected it here, so just change your el on the ice component where that will be read to.  Have to type quick as connection is sporadic.

                      • 8. Re: convertEntity problem
                        hardaur

                        Judy, I'm sorry, I don't think I understand what you're getting at. 


                        I'm instantiating and outjecting the userAccount entity in the userManager.startCreateUser method.  As I understand it that is the object that all of the fields in the JSF form are writing too (well, for userAccount anyway, there's a User object also).


                        Am I misunderstanding something?  Also, just so you guys know, I REALLY appreciate the patience and help on this one.


                        Gerald


                        • 9. Re: convertEntity problem
                          jguglielmin

                          OK....so your el shows

                          ${userAccount.roles}

                          but in your backing bean, you don't have a factory or reference to it there.  I am not the leading reference to outjection(by any stretch) as I tend to avoid it (and use ajax-enabled components which kind of bypass all that).  But I would instead try
                          ${userManager.userAccount.roles}

                          and a partialSubmit on the component to check what is in there and to see if it is indeed referencing this instance of the object. 


                          I also notice you have another convertEntity on

                          ${user.State}

                          in your table.  If you comment out the roles stuff, does this convertEntity work as it should?  It might help you determine what is happening with the userRoles.   

                          • 10. Re: convertEntity problem
                            hardaur

                            judy guglielmin wrote on Nov 21, 2008 14:29:


                            OK....so your el shows
                            ${userAccount.roles}

                            but in your backing bean, you don't have a factory or reference to it there.  I am not the leading reference to outjection(by any stretch) as I tend to avoid it (and use ajax-enabled components which kind of bypass all that).  But I would instead try
                            ${userManager.userAccount.roles}

                            and a partialSubmit on the component to check what is in there and to see if it is indeed referencing this instance of the object. 


                            I also notice you have another convertEntity on
                            ${user.State}

                            in your table.  If you comment out the roles stuff, does this convertEntity work as it should?  It might help you determine what is happening with the userRoles.   



                            I'll give the new EL a shot.  As far as the states convertEntity, I was going to sleep last night when I realized that I need to look at that because I happen to know that it DOES work (making things even wierder IMHO).


                            Just for the sake of my literacy, could you point me to some overview type reference of how you work with things (ajax enabled components).  I'm not a believer in binary answers and like to be aware of as many options as possible ; )


                            Gerald


                            • 11. Re: convertEntity problem
                              jguglielmin

                              It is much easier for me to format on the ICEfaces forum where we have a section devoted to Seam integration.  If you post there requesting a sample of something, I can definitely do that.  I should have a seam and ICEfaces tutorial done in the next couple of weeks that will show some tips and tricks as well as gotchas.

                              • 12. Re: convertEntity problem
                                hardaur

                                Cool.  I've been over there a couple times, I'm using icefaces for this project and have my team looking at it as a standard for my day job (this project is a side project).



                                • 13. Re: convertEntity problem
                                  hardaur

                                  I've tried changing the el to do userManager.userAccount.roles to no avail.  However, I just had a thought.  The roles parameter on the userAccount object has to be a Set (or List, whichever) and I think it might be sending back the objects themselves.  Thus it's trying to convert a UserRole to a List which obviously wouldn't work.


                                  Am I mistaken and convertEntity should handle that, or is there something I have to do that I'm missing?


                                  Gerald


                                  • 14. Re: convertEntity problem
                                    hardaur

                                    Found it!!  Was almost sort of on the right track with my last message (lead to the solution anyway).


                                    When hibernate created my entities (imported from existing DB) it used Set for all of the collections.  However, JSF, for whatever reason, can't talk in Sets only Lists and Arrays.  So icefaces (and h: as well) was sending back a List and the entity was expecting a Set.


                                    Change the properties on the entity to List and boom, problems solved. 


                                    Hopefully this will save the next poor sap in my position the hassle ; )


                                    Thanks again all, especially you Judy.


                                    Gerald