问题
I want to run some code as soon as my plugin (portlet, hook or theme) is available in Liferay.
I can't find anything like a startup listener in liferay-plugin-package.xml
, liferay-portlet.xml
, liferay-hook.xml
or liferay-look-and-feel.xml
.
回答1:
There is another way. You could utilize the StartupAction. It is merely an Event, which get's triggered on every startup of a plugin. This method will only get triggered once on a server start or deploy. Recognize, that the doRun method get's a String array of companyIds as an argument. A companyId is representing a portal instance (the Liferay internal one. Not another application server.)
For instance, I have a portlet where I rely on some custom fields to exist. So I have this neat little class:
package de.osc.kaleositeaddon.startup;
import com.liferay.portal.kernel.events.ActionException;
import com.liferay.portal.kernel.events.SimpleAction;
public class StartupAction extends SimpleAction {
@Override
public void run(String[] companyIds) throws ActionException {
setupExpandoAction.run(companyIds);
importMessagesAction.run(companyIds);
}
private SetupExpandoAction setupExpandoAction = new SetupExpandoAction();
private ImportMessagesAction importMessagesAction = new ImportMessagesAction();
}
And the SetupExpandoAction is:
package de.osc.kaleositeaddon.startup;
import com.liferay.portal.kernel.events.ActionException;
import com.liferay.portal.kernel.events.SimpleAction;
import com.liferay.portal.model.Group;
import com.liferay.portal.model.ResourceConstants;
import com.liferay.portal.model.Role;
import com.liferay.portal.model.RoleConstants;
import com.liferay.portal.security.permission.ActionKeys;
import com.liferay.portal.service.ResourcePermissionLocalServiceUtil;
import com.liferay.portal.service.RoleLocalServiceUtil;
import com.liferay.portlet.expando.DuplicateColumnNameException;
import com.liferay.portlet.expando.DuplicateTableNameException;
import com.liferay.portlet.expando.model.ExpandoColumn;
import com.liferay.portlet.expando.model.ExpandoColumnConstants;
import com.liferay.portlet.expando.model.ExpandoTable;
import com.liferay.portlet.expando.model.ExpandoTableConstants;
import com.liferay.portlet.expando.service.ExpandoColumnLocalServiceUtil;
import com.liferay.portlet.expando.service.ExpandoTableLocalServiceUtil;
import com.liferay.portlet.journal.model.JournalArticle;
import de.osc.kaleositeaddon.service.constants.ExpandoConstants;
public class SetupExpandoAction extends SimpleAction {
@Override
public void run(String[] companyIds) throws ActionException {
for (int i = 0; i < companyIds.length; i++) {
long companyId = Long.parseLong(companyIds[i]);
try {
setupExpandoGroup(companyId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
protected void setupExpandoGroup(long companyId) throws Exception {
ExpandoTable table = null;
try {
table = ExpandoTableLocalServiceUtil.addTable(companyId, Group.class.getName(), ExpandoTableConstants.DEFAULT_TABLE_NAME);
} catch (DuplicateTableNameException dtne) {
table = ExpandoTableLocalServiceUtil.getTable(companyId, Group.class.getName(), ExpandoTableConstants.DEFAULT_TABLE_NAME);
}
/*
* Setup StartDate
*/
try {
ExpandoColumn column = ExpandoColumnLocalServiceUtil.addColumn(table.getTableId(),
ExpandoConstants.EXPANDO_COLUMN_NAME_START_DATE, ExpandoColumnConstants.DATE);
column.setDefaultData("");
Role user = RoleLocalServiceUtil.getRole(companyId, RoleConstants.GUEST);
ResourcePermissionLocalServiceUtil.setResourcePermissions(companyId, ExpandoColumn.class.getName(), ResourceConstants.SCOPE_INDIVIDUAL,
String.valueOf(column.getColumnId()), user.getRoleId(), new String[] { ActionKeys.VIEW});
}
catch (DuplicateColumnNameException dcne) {
}
/*
* Setup EndDate
*/
try {
ExpandoColumn column = ExpandoColumnLocalServiceUtil.addColumn(table.getTableId(),
ExpandoConstants.EXPANDO_COLUMN_NAME_END_DATE, ExpandoColumnConstants.DATE);
column.setDefaultData("");
Role user = RoleLocalServiceUtil.getRole(companyId, RoleConstants.GUEST);
ResourcePermissionLocalServiceUtil.setResourcePermissions(companyId, ExpandoColumn.class.getName(), ResourceConstants.SCOPE_INDIVIDUAL,
String.valueOf(column.getColumnId()), user.getRoleId(), new String[] { ActionKeys.VIEW});
}
catch (DuplicateColumnNameException dcne) {
}
try {
ExpandoColumn column = ExpandoColumnLocalServiceUtil.addColumn(table.getTableId(),
ExpandoConstants.EXPANDO_COLUMN_NAME_CREATE_DATE, ExpandoColumnConstants.DATE);
column.setDefaultData("");
Role user = RoleLocalServiceUtil.getRole(companyId, RoleConstants.GUEST);
ResourcePermissionLocalServiceUtil.setResourcePermissions(companyId, ExpandoColumn.class.getName(), ResourceConstants.SCOPE_INDIVIDUAL,
String.valueOf(column.getColumnId()), user.getRoleId(), new String[] { ActionKeys.VIEW});
}
catch (DuplicateColumnNameException dcne) {
}
}
}
In your liferay-hook.xml file, you do the following:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.0.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_0_0.dtd">
<hook>
<portal-properties>portal.properties</portal-properties>
</hook>
And in portal.properties you add this line:
application.startup.events=de.osc.kaleositeaddon.startup.StartupAction
remember to substitute the class names ;)
回答2:
If you've got a portlet in your plugin, you can run the code in Portlet.init(PortletConfig)
.
But this is not always possible, because
- you've got no portlet
- you've got no own portlet implementation (e.g. because you use JSF)
- the code belongs to no portlet and you don't want to add it randomly to one of them
In that case you have two other options:
Create a startup action which is called for every portal instance (see the answer of gevatterjan). This is the best solution if you need to run code for every portal instance.
Or you use a combination of ServletContextListener
and PortalLifecycle
which is started once when the plugin is available. This is the best solution if you want to run only once, e.g. to create a scheduler or to replace Liferay functions that are not covered by liferay-hook.xml
resp. portal.properties
.
@WebListener
public class MyStartupListener implements ServletContextListener, PortalLifecycle {
@Override
public void contextInitialized(final ServletContextEvent sce) {
// Wait until the portal is ready
PortalLifecycleUtil.register(this, PortalLifecycle.METHOD_INIT);
}
@Override
public void portalInit() {
// Here comes our initialization code
...
}
@Override
public void contextDestroyed(final ServletContextEvent event) {
// Here comes our uninitialization code, if any
...
}
@Override
public void portalDestroy() {
// Ignore
}
}
You can call any Liferay functions, but be careful:
Your thread is not connected to any request - there is no current portal instance (Company
), site (Group
), page (Layout
) or user. You can find all of these using the appropriate *ServiceLocalUtil
functions. And for some actions you need to set these value for the thread in CompanyThreadLocal
, PricipalThreadLocal
and PermissionThreadLocal
.
来源:https://stackoverflow.com/questions/31046786/how-can-i-run-some-action-when-my-plugin-was-deployed-to-liferay