Blogs
I've seen a tone of requests lately for how to add Expando Tables and Columns programatically during some startup proceedure.
The biggest problem seems to be with PermissionChecker. The problem stems from the fact that alot of people are trying to use the ExpandoBridge API to create columns (attributes) during the startup process. The issue with that is that the default implementation of ExpandoBirdge has permission checking built in. This leads to exceptions because there is no PermissionChecker yet bound to the thread during startup.
Have no fear. There is a solution! And, it was written by none other than Brian "The Man" Chan himself, so it's gotta be right. He did this in the WOL portlet plugin that you all know from Liferay.com, so it's even in production.
Here it is verbatim from the 5.2.x branch in SVN:
package com.liferay.wol.hook.events;
import com.liferay.portal.kernel.events.ActionException;
import com.liferay.portal.kernel.events.SimpleAction;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.model.User;
import com.liferay.portlet.expando.DuplicateColumnNameException;
import com.liferay.portlet.expando.DuplicateTableNameException;
import com.liferay.portlet.expando.model.ExpandoColumnConstants;
import com.liferay.portlet.expando.model.ExpandoTable;
import com.liferay.portlet.expando.service.ExpandoColumnLocalServiceUtil;
import com.liferay.portlet.expando.service.ExpandoTableLocalServiceUtil;
/**
* <a href="StartupAction.java.html"><b><i>View Source</i></b></a>
*
* @author Brian Wing Shun Chan
*
*/
public class StartupAction extends SimpleAction {
public void run(String[] ids) throws ActionException {
try {
doRun(GetterUtil.getLong(ids[0]));
}
catch (Exception e) {
throw new ActionException(e);
}
}
protected void doRun(long companyId) throws Exception {
setupExpando();
}
protected void setupExpando() throws Exception {
ExpandoTable table = null;
try {
table = ExpandoTableLocalServiceUtil.addTable(
User.class.getName(), "WOL");
}
catch (DuplicateTableNameException dtne) {
table = ExpandoTableLocalServiceUtil.getTable(
User.class.getName(), "WOL");
}
try {
ExpandoColumnLocalServiceUtil.addColumn(
table.getTableId(), "jiraUserId",
ExpandoColumnConstants.STRING);
}
catch (DuplicateColumnNameException dcne) {
}
try {
ExpandoColumnLocalServiceUtil.addColumn(
table.getTableId(), "aboutMe", ExpandoColumnConstants.STRING);
}
catch (DuplicateColumnNameException dcne) {
}
}
}
Now that is some sweet code!
One small note. These columns were added to a table called "WOL". As such these are NOT what we ferrer to as Custom Attributes.
There needs to be one small change made in order for the ExpandoColumns above to be considered Custom Attributes. They must be added to a special table called "DEFAULT_TABLE" (a.k.a. ExpandoTableConstants.DEFAULT_TABLE_NAME).
try {
table = ExpandoTableLocalServiceUtil.addTable(
User.class.getName(), ExpandoTableConstants.DEFAULT_TABLE_NAME);
}
catch (DuplicateTableNameException dtne) {
table = ExpandoTableLocalServiceUtil.getTable(
User.class.getName(), ExpandoTableConstants.DEFAULT_TABLE_NAME);
}
Columns in this "DEFAULT_TABLE" are the ones which are retreived and manipulated by the ExpandoBridge API (more on that API in another blog post).

