Saturday 10 March 2012

Custom Liferay user registration portlet

Hello,
       In this post I'm going to describe how I developed custom registration portlet. 


       It was needed to create custom portlet for registering new users. User should fill some wizard-like for and fill some additional fileds which was not present at basic Liferay user's table.
       For development of wizard-like form I used Spring MVC portlet, some initial steps and examples you can fin in my previous post. For storing additional fileds I had two alternative ways:
  1. To expando table mechanism, it allows to store additional filed in this way:
  2. com.liferay.portal.service.UserLocalServiceUtil.getUser(userId).getExpandoBridge().setAttribute(userId, attrValue);
    
    AttrName can be added into ControlPanel:
    or progrmatically:
    com.liferay.portal.service.UserLocalServiceUtil.getUser(userId).getExpandoBridge().addAttribute(userAttr);
     
  3. Build own User extension table by using ServiceBuilder.
      I choosed second approach, because with it I will have only one table with additional user data.
      In my spring portlet I created some UserDTO bean to store data from user inputs and after user submits form I used this bean to store it data to Liferay's user table and to userExt table which was generated by ServiceBuilder.
      To store Liferay's user you can check next code:

  private User addUser(final ActionRequest request,
                       final UserData userData) throws PortalException, SystemException {
    ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);

    long creatorUserId = themeDisplay.getUserId(); // default liferay user
    long companyId = themeDisplay.getCompanyId(); // default company
    boolean autoPassword = true;
    String password1 = "";
    String password2 = "";
    boolean autoScreenName = true;
    String screenName = "";
    String emailAddress = userData.getEmail();
    long facebookId = 0;
    String openId = "";
    Locale locale = themeDisplay.getLocale();
    String firstName = userData.getName();
    String middleName = "";
    String lastName = userData.getSurname();
    int prefixId = 0;
    int suffixId = 0;
    boolean male = userData.isMale();    
    int birthdayMonth = Integer.parseInt(userData.getBirthDate().getMonth());
    int birthdayDay = Integer.parseInt(userData.getBirthDate().getDay());
    int birthdayYear = Integer.parseInt(userData.getBirthDate().getYear());
    String jobTitle = userData.getTitle();

    long[] groupIds = null;
    long[] organizationIds = null;
    long[] roleIds = null;
    long[] userGroupIds = null;

    boolean sendEmail = false;

    ServiceContext serviceContext = ServiceContextFactory.getInstance(request);

    User user = UserLocalServiceUtil.addUser(creatorUserId,
                                             companyId,
                                             autoPassword,
                                             password1,
                                             password2,
                                             autoScreenName,
                                             screenName,
                                             emailAddress,
                                             facebookId,
                                             openId,
                                             locale,
                                             firstName,
                                             middleName,
                                             lastName,
                                             prefixId,
                                             suffixId,
                                             male,
                                             birthdayMonth,
                                             birthdayDay,
                                             birthdayYear,
                                             jobTitle,
                                             groupIds,
                                             organizationIds,
                                             roleIds,
                                             userGroupIds,
                                             sendEmail,
                                             serviceContext);
    return user;
  }

  In case if you want to add some addresses or phone to newly added user you can use next approach:

  private void addAddresses(final UserData userData,
                            final User user) throws SystemException, PortalException {
    List addressTypes = ListTypeServiceUtil.getListTypes(Contact.class.getName()
        + ListTypeConstants.ADDRESS);
    int personalAddressTypeId = 0;
 // find personal phone type
    for (ListType addressType : addressTypes) {
      String addressTypeName = addressType.getName();
      if ("personal".equals(addressTypeName)) {
        personalAddressTypeId = addressType.getListTypeId();
      }
    }
    if (StringUtils.isNotEmpty(userData.getAddress())) {
      AddressLocalServiceUtil.addAddress(user.getUserId(),
                                         Contact.class.getName(),
                                         user.getContactId(),
                                         userData.getAddress(),
                                         userData.getAdditionalAddress(),
                                         "",
                                         userData.getPlace(),
                                         userData.getZip(),
                                         0,
                                         0,
                                         personalAddressTypeId,
                                         false,
                                         true);
    }
  } 

  private void addPhones(final UserData userData,
                         final User user) throws SystemException, PortalException {
    List phoneTypes = ListTypeServiceUtil.getListTypes(Contact.class.getName()
        + ListTypeConstants.PHONE);
    int personalPhoneTypeId = 0;
    int faxTypeId = 0;
 // find personal and fax type phones
    for (ListType phoneType : phoneTypes) {
      String phoneTypeName = phoneType.getName();
      if ("personal".equals(phoneTypeName)) {
        personalPhoneTypeId = phoneType.getListTypeId();
      }
      if ("personal-fax".equals(phoneTypeName)) {
        faxTypeId = phoneType.getListTypeId();
      }
    }
    if (StringUtils.isNotEmpty(userData.getPhoneNumber())) {
      PhoneLocalServiceUtil.addPhone(user.getUserId(),
                                     Contact.class.getName(),
                                     user.getContactId(),
                                     userData.getPhoneNumber(),
                                     "",
                                     personalPhoneTypeId,
                                     true);
    }
    if (StringUtils.isNotEmpty(userData.getFaxNumber())) {
      PhoneLocalServiceUtil.addPhone(user.getUserId(),
                                     Contact.class.getName(),
                                     user.getContactId(),
                                     userData.getFaxNumber(),
                                     "",
                                     faxTypeId,
                                     false);
    }
  }

 
   To store additional fileds I used ServiceBuilder who generetes appropriate model and classes to achieve this:

    private void storeUserExpando(final UserDTO userDTO,
                                final User user) throws SystemException {
    // get new id for storing
 long id = CounterLocalServiceUtil.increment(UserExt.class.getName());
 // create new entity
    UserExt userExt = UserExtLocalServiceUtil.createUserExt(id);

    // Set liferays user id
    userExt.setUserId(user.getUserId());

    // Set other fields
    userExt.setOtherField(userDTO.getOtherField());

    userExt.setNew(true);
    UserExtLocalServiceUtil.addUserExt(userExt);

  }

    After that new user will be added to general liferay's table and to UserExt table.

BR,
Paul

4 comments:

  1. how to change the link of create account on sign in page to my custom user registration portlet. in which files do i have to change?
    please help me, it is a immediate requirement for me.

    thanks in advance

    ReplyDelete
  2. Hi,
    Check /html/portlet/login/login.jsp and /html/portlet/login/create_account.jsp

    ReplyDelete
  3. Hi, I have created a custom spring MVC portlet with all the new fields I want to collect from the user and save it to a new table in database. But I am not able to add this user to the liferay user table. I tried to use the addUser function(the first code section in this page). I am getting an error for final UserData userdata. I do not know how to solve it. Please help.

    ReplyDelete
  4. What kind of error do you have?

    ReplyDelete