Thursday 13 September 2012

How to make users import into Liferay

Hello,
    It is often need to imoprt some users into liferay automatically. This post I'll show you how it can be done.
   

    Importing can be done in few ways:
           1) Use IMacros plugin fo firefox.  This plugin allows you to automate UI registration form filling.
      
           2) Some user import application can be developed. This application will read user data from CSV file, transform it to UserBean, and then store it to Liferay with UserLocalServiceUtil.
            As a source of user data for this application we will use CSV file with next format:
      username;email;firstName;lastName;password;male
      paul;paul@paul.com;Paul;Paul;paul;true
      ann;ann@ann.com;Ann;Ann;ann;false
            First line is column names, we will need it while reading and transforming data

           As CSV reading and parsing library I used Super CSV, it allows to read and transfrom rows as beans, here you may find some samples.
           Main code for reading and parsing users:
  //username,email,firstName,lastName,password,male
  final CellProcessor[] processors = new CellProcessor[] {null, null, null, null, null, new ParseBool()};

  public List&ltUserBean&gt readUsers() {
 ICsvBeanReader inFile = null;
 List&ltUserBean&gt users = new ArrayList&ltUserBean&gt();
 try {
   inFile = new CsvBeanReader(new FileReader(FileUtils.toFile(this.getClass()
    .getResource("/users.csv"))), CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE);

   final String[] header = inFile.getCSVHeader(true);

   LOGGER.info("Reading users with properties: " + Arrays.toString(header) + " from CSV file.");
   UserBean user;
   while ((user = inFile.read(UserBean.class, header, processors)) != null) {
  users.add(user);
   }
   LOGGER.info(users.size() + " users were read from CSV file.");
 } catch (FileNotFoundException fnfe) {
   LOGGER.error("Can't find CSV file with users " + fnfe);
 } catch (IOException ioe) {
   LOGGER.error("IOException " + ioe);
 } finally {
   try {
  inFile.close();
   } catch (IOException e) {
   }
 }
 return users;
  }
        CellProcessor allows to parse fields to appropriate format.
        As you can see method returns list of user beans, which can be used to store users in to liferay, here how it is done:
private User addLiferatUser(final ActionRequest request,
     final UserBean userBean) {
 User user = null;
 try {
   ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);

   long creatorUserId = themeDisplay.getUserId(); // default liferay user
   long companyId = themeDisplay.getCompanyId(); // default company
   boolean autoPassword = false;
   String password1 = userBean.getPassword();
   String password2 = userBean.getPassword();
   boolean autoScreenName = false;
   String screenName = userBean.getUsername();
   String emailAddress = userBean.getEmail();
   long facebookId = 0;
   String openId = "";
   Locale locale = themeDisplay.getLocale();
   String firstName = userBean.getFirstName();
   String middleName = "";
   String lastName = userBean.getLastName();

   int prefixId = 0;

   int suffixId = 0;
   boolean male = userBean.isMale();

   int birthdayMonth = 5;
   int birthdayDay = 5;
   int birthdayYear = 1980;
   String jobTitle = "";

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

   long[] userGroupIds = null;

   boolean sendEmail = false;

   ServiceContext serviceContext = ServiceContextFactory.getInstance(request);

   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);

   user.setPasswordReset(false);
   user = UserLocalServiceUtil.updateUser(user);
   
   UserLocalServiceUtil.updateStatus(user.getUserId(), WorkflowConstants.STATUS_APPROVED);
 } catch (PortalException e) {
   LOGGER.error(e);
 } catch (SystemException e) {
   LOGGER.error(e);
 }
 return user;
  }

    Complete code of userimport portlet you can find here.
    You can deploy it to Liferay:

add to page and press Import:

 it will read users from users.csv:

and add to Liferay:
   
BR,
Paul Butenko

19 comments:

  1. Hello,

    I've been using the portlet you provide and its not working. I get this error when i'm adding user

    03:33:18,677 INFO [UserCSVReader:46] Reading users with properties: [username, email, firstName, lastName, password, male,] from CSV file.
    03:33:19,001 ERROR [render_portlet_jsp:154] Cannot parse "true," to a boolean on line 2 column 5 context: Line: 2 Column: 5 Raw line:

    i really hope you can help me regarding this problem.

    Thank you.

    ReplyDelete
    Replies
    1. Hello,
      I've checked portlet and it works fine for me.

      Reagrding error, check csv file it should contain next:
      username;email;firstName;lastName;password;male
      paul;paul@paul.com;Paul;Paul;paul;true
      ann;ann@ann.com;Ann;Ann;ann;false

      Also you can remove boolean parsing from UserCSVReader:
      final CellProcessor[] processors = new CellProcessor[] {null, null, null, null, null, null};

      but also change UserBean's property type male from bollean to String and write correct getters and setters.

      Delete
    2. Hello.

      Thanks for your reply.
      The portlet is working perfectly right now.
      I need to use the original user.csv file provided to make it work.

      Thanks

      Delete
  2. Hi,

    Thanks for the wonderful article.

    I would like to know where exactly you placed the .csv file in the app server.
    Please let me know the full path from the ROOT of the tomcat.
    I would like to try this out.

    Regards,
    Mano

    ReplyDelete
  3. Hi,

    You can find CSV:
    1) in sources here:
    \userimport-portlet\docroot\WEB-INF\src\users.csv

    2) in app server:
    \liferay-portal-6.1.0-ce-ga1\tomcat-7.0.23\webapps\userimport-portlet\WEB-INF\classes\users.csv

    ReplyDelete
  4. The portlet is awesome. Work like charm.
    Just to know, can this portlet work with custom field?

    ReplyDelete
  5. Yes, portlet can work with custom fields in case you update UserServiceImpl with necessary code.

    ReplyDelete
  6. Hello,

    This is nice portlet and work fine,but i want to import expando table data of user ..

    Help Me

    ReplyDelete
    Replies
    1. In this case you have to extend the portlet.

      Delete
  7. Nice !! Thx for all the code ... Any chance you could turn this into a
    marketplace App?

    ReplyDelete
    Replies
    1. Could be, but for that will have to improve functionality.

      Delete
  8. Hi everyone, I'm new to liferay, I did download the complete code for userimport-portlet. But how can I deploy it? Could someone please write the steps to help me through? Thanks in Advance.

    ReplyDelete
    Replies
    1. Hi,
      Build war file and put it to deploy directory of your liferay installation.

      Delete
  9. Hi Paul, thank you for your work.
    I'm new to Liferay and I used your portlet to build (for excercise) a new one with upload capabilities and some other options.
    You can find on GitHub at: https://github.com/fdelprete/CSV_User_Import-portlet
    Your comments will be appreciated.
    Thank you again.

    ReplyDelete
  10. Hi, I've tried deploying the portlet but when I click on the 'Import' button I see an error message: "Portlet is temporarily unavailable." Is there anything I didn't do right?

    ReplyDelete
  11. Hi there,
    would you care to tell under what license did you publish this code? Thanks

    ReplyDelete
  12. how to do same simple java standalone application to import bulk users

    ReplyDelete