« Back

Sample Expando Hook

Company Blogs March 22, 2010 By Juan Fernández Staff

Hi guys!

Last week I created the sample expando hook, a simple example to show how easy is to extend portal entities on startup without using the UI. 
 
The main goal of this work method is to allow Liferay users to extend portal entities from a plugin, so that they don't need to repeat the same action (the creation of new fields for their entities) in every installation they do. 
 
You can find it ready to use in the plugins' hooks svn (http://svn.liferay.com/browse/plugins/trunk/hooks)
 
I have based this development in this Ray's blog entry (http://www.liferay.com/web/raymond.auge/blog/-/blogs/adding-expandos-from-a-startup-hook) and here's the explaination so that you can adapt it to your concrete use case:
 
In portal.properties you declare your class so that it is launched on startup:
 
application.startup.events=com.liferay.sampleexpando.hook.events.StartupAction
 
In StartupAction, in doRun, you do the main things:
 
 
1.- We get a reference of (or create) the table ExpandoTableConstants.DEFAULT_TABLE_NAME, determining the portal entity we are working with (in this case it'll be the calendar events - CalEvent)
 
                try { expandoTable = ExpandoTableLocalServiceUtil.addTable( CalEvent.class.getName(), ExpandoTableConstants.DEFAULT_TABLE_NAME); } catch (Exception e) { expandoTable = ExpandoTableLocalServiceUtil.getTable( CalEvent.class.getName(), ExpandoTableConstants.DEFAULT_TABLE_NAME); }
 
2.- We add the new column using a custom name ("sampleColumn") and its type (ExpandoColumnConstants.STRING in this case):
 
     ExpandoColumnLocalServiceUtil.addColumn(
   expandoTable.getTableId(), "sampleColumn",
                   ExpandoColumnConstants.STRING);
 
And that's all!
I hope it'll be useful
Regards
Juan Fernández

 

Threaded Replies Author Date
The explained aproach lacks one thing - schema... Pavel Rodionov March 22, 2010 7:19 AM
Why? A simple ... Ray Augé March 22, 2010 8:38 AM
Hm, so your approach is to pollute code with... Pavel Rodionov March 22, 2010 9:28 AM
Hi Pavel: 1.- The idea is to avoid doing this... Juan Fernández March 22, 2010 9:33 AM
I've tried to run this code in LR6, but it... Francisco Aranda July 28, 2010 9:46 AM
Sorry, I didn't look so well. The method is... Francisco Aranda July 28, 2010 9:49 AM
Hi Francisco: thanks for the update. I didn't... Juan Fernández July 29, 2010 12:04 AM
Here is how I did it in LR6. Some extra... Francisco Aranda July 29, 2010 7:35 AM
This example is no longer available, can anyone... Michele Celli July 2, 2011 2:19 PM
Hi Michele! You can get the code from svn... Juan Fernández July 4, 2011 12:01 AM
To checkout the code with SVN :... Leo Pratlong July 12, 2011 8:53 AM
[...] Super ! Merci beaucoup pour ces... Anonymous July 13, 2011 7:14 AM
Hi Juan! This article was really helpful,... Florencia Gadea April 15, 2013 7:01 AM
Hi Juan, I wonder if I can use this approch to... Nabil Bahtat August 6, 2014 2:27 AM

The explained aproach lacks one thing - schema incremental update. If you add/drop some column, you need to drop whole table, or create DML migration scripts for expando tables (which is entertaining task for one entity, but if you have a lot of entities it could take whole day, if not more)
Posted on 3/22/10 7:19 AM.
Why? A simple

ExpandoColumnLocalServiceUtil.deleteColumn(ong companyId, long classNameId, String tableName, String columnName);

will remove the column from the table as well as all values associated with it!
Posted on 3/22/10 8:38 AM in reply to Pavel Rodionov.
Hm, so your approach is to pollute code with such statements? So for every added/removed column some precondition should exist? What if I add 50 columns in a row.
Also I don't understand how it will work if I want to change type of column, for example from ExpandoColumnConstants.STRING to ExpandoColumnConstants.DATE.
Posted on 3/22/10 9:28 AM in reply to Ray Augé.
Hi Pavel:

1.- The idea is to avoid doing this by hand in every installation of the product. If you have a plugin you can deploy it in the server and it'll do all that tasks.

2.- The number of columns is not important: just add it in the hook code.

3.- You can use the type you need for your field using ExpandoColumnConstants and it shouldn't be a problem

Regards
Juan
Posted on 3/22/10 9:33 AM in reply to Pavel Rodionov.
I've tried to run this code in LR6, but it seems that addTable and getTable are deprecated. If I'm not wrong, what is the right way to add expandos in LR6? Thanks.

Podrías darme una manito u orientarme con esto. Gracias!
Posted on 7/28/10 9:46 AM.
Sorry, I didn't look so well. The method is deprecated but it still exists. the new method has a new added companyId parameter. So I'm going to see what happen if I pass the companyId param.
Posted on 7/28/10 9:49 AM in reply to Francisco Aranda.
Hi Francisco:
thanks for the update. I didn't realize this has changed. If you add the companyId to the method it'll be ok.
Tell me if you achieve this and everything works ok
Saludos,
Juan
Posted on 7/29/10 12:04 AM in reply to Francisco Aranda.
Here is how I did it in LR6. Some extra comments in http://www.liferay.com/community/forums/-/message_boards/message/5165696

protecte­d void setupExpandos(long companyId) throws Exception {
ExpandoTable table = null;
try {
table = ExpandoTableLocalServiceUtil.addTable(
companyId, User.class.getName(), ExpandoTableConstants.DEFAULT_TABLE_NAME);
}
catch (DuplicateTableNameException dtne) {
table = ExpandoTableLocalServiceUtil.getTable(companyId, User.class.getName(), ExpandoTableConstants.DEFAULT_TABLE_NAME);
}
String column = "";
column = "alternativeEmail";
try { ExpandoColumnLocalServiceUtil.addColumn(table.getTableId(),column, ExpandoColumnConstants.STRING);
} catch (DuplicateColumnNameException dcne) { System.out.println(column+" already exists!"); }


try {
ExpandoColumn ecolumn = ExpandoColumnLocalServiceUtil.getColumn(companyId, User.class.getName(),ExpandoTableConstants.DEFAULT_TABLE_NAME,column);

//I had to add UPDATE perms to GUEST in order to set column values from the hook.
Permissions.setRolePermissions(companyId,ExpandoColumn.class.getName() ,ecolumn.getPrimaryKey(), RoleConstants.GUEST, new String[] { ActionKeys.VIEW, ActionKeys.UPDATE});

} catch(Exception e) { }
}
Posted on 7/29/10 7:35 AM.
This example is no longer available, can anyone tell me where to get this sample ?
Posted on 7/2/11 2:19 PM in reply to Francisco Aranda.
Hi Michele!
You can get the code from svn plugins trunk -> http://svn.liferay.com/browse/plugins/trunk/hooks

Regards!
Posted on 7/4/11 12:01 AM in reply to Michele Celli.
To checkout the code with SVN : http://svn.liferay.com/repos/public/plugins/trunk/hooks/sample-expando-hook/
logi­n : guest
passwd:
Posted on 7/12/11 8:53 AM in reply to Juan Fernández.
[...] Super ! Merci beaucoup pour ces précisions qui me seront très utiles ! Je vais partir sur les Expandos donc, d'autant plus que le nombre de documents dans le système ne sera pas très élevé (pas plus... [...] Read More
Posted on 7/13/11 7:14 AM.
Hi Juan!

This article was really helpful, thanks. But I have a doubt: How do you set the length of a string column?

Thanks,
Flor.
Posted on 4/15/13 7:01 AM.
Hi Juan,
I wonder if I can use this approch to add custom fields to any entity,
because from GUI Control Pannel/Custom fields only few entities are listed.

Thanks,
Nabil
Posted on 8/6/14 2:27 AM.