How to use Custom Attributes to enhance Users

Howto use Custom Attributes automatically and programatically. #

Out-Of-The-Box Features #

Liferay provides a UI and API to allow for the creation of customized attributes associated with any entity generated by Service Builder. These attributes provide for extensibility without the need for extending the Liferay DB schema.

Out of the box Liferay provides Custom Attributes UI for Users and Organizations.

Creating Custom Attributes for Users #

  • Login as an Administrator
  • Navigate to the 'Control Panel' from the 'Dock'
  • Select 'Custom Fields' from the left hand side navigation bar
  • Select 'User'
  • Click 'Add Custom Attribute'
  • Specify the 'Key' for the Custom Attribute. The help icon for this field reads; "The custom attribute key is used to access the attribute programatically through the <liferay-ui:custom-attribute /> tag." More on this later.
  • The Key must not contain spaces or special characters. Use
    • underscores (my_key)
    • dashes (my-key)
    • or camel case (myKey)
  • Specify the type of the attribute. The help icon for this field reads; "Choose the attribute type carefully as once it is defined it cannot be changed."

Note: Only "java.lang.String" type fields can be made searchable. Consider this at time of creation.

  • Specify if the field is hidden. The help icon for this field reads: "Setting a custom attribute to hidden means that the attribute's value is never shown in any user interface besides this one. This allows the attribute to be used for some more obscure and advanced purposes such as acting as a placeholder for custom permissions." This setting can be changed at any time
  • Click "Save"

Updating Custom Attribute settings #

  • Once the attribute is saved, you are returned to the list. Click the new attribute's link to return to the edit view
  • You will notice that the Name is automatically rendered based on a formatting of the 'key', but also note that this rendering does not grant automatic localization. In order to create true localization, define those in the Language.properties files based on the attribute's 'key'
  • There is now an option to specify a default value
  • If the attribute is of type 'java.lang.String', you have the option to make the custom attribute 'Searchable' (this only currently works for User as the underlying service must support integrated custom attribute indexing). The help icon for this field reads; "Setting a custom attribute to searchable means that the value of the attribute will be indexed when the entity (such as User) is modified. Only java.lang.String attributes can be made searchable. Note that when an attribute is newly made searchable, the indexes must be updated before the data is available to search."
  • Click "Save"

Updating Custom Attribute permissions #

  • Once the attribute is again saved, you are returned to the list. Click the 'Actions' button at the right end of the row for a given attribute
  • Click 'Permissions'
  • Assign the actions to the Roles as desired.
  • Note if the field is 'hidden' the attribute is still only visible in this UI.

Viewing and setting Custom Attributes per User instance #

  • Select any user from the user list or visit the My Account view
  • Choose the 'Custom Attributes' link from the right hand side navigation bar
  • Depending on permissions and settings you are presented with the current list of editable and/or not-editable attributes.
  • If the field is editable, enter a value and click 'Save'

Using Custom Attribute tags to display editable or non-editable values #

Using the <liferay-ui:custom-attribute-list /> jsp tag #

  • This tag generates a list of all the (non-hidden, and VIEWable) tags for a given entity type and instance
  • The available parameters are:
    • className, the fully qualified name of the entity (required = true) e.g. com.liferay.portal.model.User
    • classPK, the primaryKey of the entity instance (or zero (0) if there is not currently an instance) (required = true)
    • editable, is this invocation to check UPDATE permission and show as a input field if check returns true (required = false, default = false)
    • label, is the label of the field rendered, if not simply show the raw output of the attribute value (required = false, default = false)
  • A sample invocation looks like:
		<liferay-ui:custom-attribute-list
			className="<%= User.class.getName() %>"
			classPK="<%= selUser != null ? selUser.getUserId() : 0 %>"
			editable="<%= true %>"
		/>

Using the <liferay-ui:custom-attribute /> jsp tag #

  • This tag generates a view of a specific attribute for a given entity type and instance.
  • The available parameters are:
    • className, the fully qualified name of the entity (required = true) e.g. com.liferay.portal.model.User
    • classPK, the primaryKey of the entity instance (or zero (0) if there is not currently an instance) (required = true)
    • editable, is this invocation to check UPDATE permission and show as a input field if check returns true (required = false, default = false)
    • label, is the label of the field rendered, if not simply show the raw output of the attribute value (required = false, default = false)
    • name, the name of the specific attribute to render (required = true)
  • A sample invocation looks like:
	
		<liferay-ui:custom-attribute
			className="<%= User.class.getName() %>"
			classPK="<%= selUser != null ? selUser.getUserId() : 0 %>"
			editable="<%= true %>"
			name="company-name"
		/>

Performing a custom User search using specific custom attributes #

  • The short method for performing an index search for Users is:
	public Hits search(
			long companyId, String keywords, Boolean active,
			LinkedHashMap<String, Object> params, int start, int end, Sort sort)
		throws SystemException;

e.g. searching for Users by 'company-name' attribute

		LinkedHashMap userParams = new LinkedHashMap();
	
		userParams.put("usersOrgs", new Long(organizationId));
		userParams.put("company-name", "My Company");

		boolean asc = true;
		Sort sort = new Sort("lastName", Sort.STRING_TYPE, asc);

		Hits hits = UserLocalServiceUtil.search(
			companyId, null, true, userParams, 0, 20, sort);
	
		List<User> users = new ArrayList<User>();

		List<Document> hitsList = hits.toList();

		for (Document doc : hitsList) {
			long userId = GetterUtil.getLong(doc.get(Field.USER_ID));

			users.add(UserLocalServiceUtil.getUserById(userId));
		}

e.g. searching for users where a value can be found in any indexed field, as well as in custom attributes

		LinkedHashMap userParams = new LinkedHashMap();


		userParams.put("usersOrgs", new Long(organizationId));


		boolean asc = true;
		Sort sort = new Sort("lastName", Sort.STRING_TYPE, asc);


		Hits hits = UserLocalServiceUtil.search(
			companyId, "My Company", true, userParams, 0, 20, sort);


		List<User> users = new ArrayList<User>();


		List<Document> hitsList = hits.toList();


		for (Document doc : hitsList) {
			long userId = GetterUtil.getLong(doc.get(Field.USER_ID));


			users.add(UserLocalServiceUtil.getUserById(userId));
		}

Setting the value for a specific user programatically. #

	user.getExpandoBridge().setAttribute("company-name", "My Company");
0 Attachments
34686 Views
Average (4 Votes)
Comments

Showing 22 Comments

Ivano Carrara
11/4/08 1:17 AM

Hi ray! Thank you for another very good article!

One only thing... I think it is a good thing to evidentiate in tags or in the text or in everyplace, the Version of Liperay Portal where is applicable the argument of the Article...

Thank you!

Ivano Carrara

Jonas Yuan
12/29/08 5:32 PM

Hi Ray! This is a good feature to use tables: expando-table (and -column, -row, -value, also). The portlet 139 (Expando) is used for custom attributes of users, as shown in above example.

On 4/24/08 6:28, you have shown another usage: expandotable (-column, -row, -value) by article templates. It is really cool!

One question: can it be used for other ClassNameId? such as group_, organization_, user group?

Maybe, just add portlet 139 in control panel as Admin function. Make sense?

Thanks

Jonas Yuan

Jonas Yuan
12/29/08 5:51 PM

One more question: do the attribute name and value support locale?

Thanks

Jonas Yuan

Ray Augé
10/2/09 9:55 AM

Name: yes (use the name "key" of the attribute in the Language-ext files)
Value: no

Ray Augé
10/2/09 9:58 AM

It is available to any entity.

<liferay-portlet:renderURL windowState="<%= WindowState.MAXIMIZED.toString() %>" var="expandoURL" portletName="<%= PortletKeys.EXPANDO %>">
<portlet:param name="struts_action" value="/expando/view_attributes" />
<portlet:param name="redirect" value="<%= currentURL %>" />
<portlet:param name="modelResource" value="<%= User.class.getName() %>" />
</liferay-portlet:renderURL>

<a href="<%= expandoURL %>"><liferay-ui:message key="custom-attributes" /></a>

Change the "modelResource" attribute and replace it with your entity's className.

François LE QUEMENER
10/7/09 7:33 AM

this article show how to display custom attribute, but not how to use them programatically in a form.

Jim Klo
10/29/09 5:53 PM

Hi Ray!

Great article. Question - how would search both regular attributes and custom attributes. In the example "usersOrgs" i'm assuming that maps to the User.getOrganizations(), but how do I find out what the other fields are named?

Thanks,

- Jim

ilke Muhtaroglu
11/17/09 4:59 AM

Hi All,

Instead of setting the value programatically, I want to get it !

instead of user.getExpandoBridge().setAttribute("company-name", "My Company");

user.getExpandoBridge().getAttribute("sessionNo");

but getAttribute returns the result as Serializable !!! But my attribute is int !
how can i change this value? When i just cast it to int the result is "null" !?

any idea is welcome !

ilke

Lucas Roberto Thomaz
12/1/09 11:45 AM

You solve your problem?

Path Finder LifeRay
12/15/09 6:31 AM

Hi all,
can any body say is this custom attribute used for themes also.
If yes, just rep me the link which gives the resolution of that. I m seriously stuck at themes concept.

Thanx in advance,

Regards,
Path finder Liferay.

whyBish valid
12/15/09 10:01 PM

We have added custom attributes, and are doing custom attribute search. It all works OK except that if the search criteria value has a space in it, the results that have the value are not found. E.G. if I create attribute country and create a user with country=New Zealand then I can search for "new" and find the user, "zealand" and find the user, but "new zealand" returns no results at all!!

vikash kumar chaurasia
2/24/10 2:16 AM

Hi Ray,

I want to know, if I have to use Custom Attributes in my portlet code, do I need to switch to Ext envt or is it possible in plugins envt? Currently, I have done the development in plugin envt.

Thanks in advance.

Pablo Krause
4/7/10 11:19 AM

Somebody knows how to retrieve custom properties from a user that was retrieved using the Portal_UserService web service?
When you get hold of a user using the local API, you can get the custom attributes using

1user.getExpandoBridge().getAttribute("myAttribute");
but there is no such method in the UserSoap object that is returned by the Portal_UserService web service.

Any help greatly appreciated.

Maciej Nowicki
6/8/10 2:16 AM

Did you try casting it to "big" Integer?

pooja shah
8/5/10 6:11 AM

What is the meaning of setting the type(Text Box,TextBox indexed,Textfield secret etc.) of custom attribute in ORGANISATION or USER portlet(Liferay 5.0).....will v get texboxes when we assign these attributes,values????
n hw can v access these custom attributes,coz they are not attached in predefined fields?

ankit yakkundi
9/7/10 11:01 PM

i am using liferay 6.i have created some custom attributes for webcontent,blog,user,etc portlets.how can i search using these attibutes..i am not able to search..

Murat ÇOLAK
1/27/11 3:35 AM

You can use

ExpandoValueLocalServiceUtil.addValue(companyId,User.class.getName(),ExpandoT­ableConstants.DEFAULT_TABLE_NAME,"parametername",user.getUserId(),"data");

this one too, emoticon

Abhay Doshi
2/15/11 10:52 PM

Is there an equivalent tutorial for use in Liferay 6?

Moisés Belda
6/2/11 1:24 AM

I create 1 custom attribute, and I put this at create_account.jsp (with EXT plugin).

I need that this field will be REQUIRED... I think the way is checking value returned (jsp) at CreateAccountAction.java , and if equals("") launch exception at CreateAcctountAction.addUser method....

But I don't know how access to the value of liferay-ui:custom-attribute, ParamUtil. returns always "", empty value.

Jakob Fahrner
8/3/11 7:07 AM

Great Explenation
Maybe there should be added some approach from the forum (http://www.liferay.com/de/community/forums/-/message_boards/message/4339723) of getting the Attribute user.getExpandoBridge().getAttribute("myAttribute"); That you have to cast it to the right type and set the right permissions (view permissions for guest)

Pablo Antonio Zamora Ortiz
1/29/12 1:15 PM

How to remove the hours and minutes of such date in a custom field?

not show the hours and minutes in the input

Shantanu Puranik
2/5/12 10:36 PM

I have select list with three values as custom attribute on document of Document library portlet. Need is to display two values in select list to noraml user and all three values to power user. Any possibility to achive this?