找到你要的答案

Q:How can I run some action when my plugin was deployed to Liferay?

Q:我怎么能做一些动作时,我被部署到Liferay插件?

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.

我想运行一些代码只要我的插件(portlet,钩或主题)可在Liferay。

我什么也找不到像liferay-plugin-package.xml,启动监听器liferay-portlet.xml,liferay-hook.xml或liferay-look-and-feel.xml。

answer1: 回答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 ;)

有另一种方式。你可以利用startupaction。它仅仅是一个事件,它在插件的每一个启动时触发。此方法只会在服务器启动或部署时触发一次。承认,这道润法得到的字符串数组作为参数companyids。一个companyid代表门户实例(Liferay内部。不是另一个应用服务器。)

例如,我有一个portlet,我依靠一些自定义字段的存在。所以我有这个整洁的小班级:

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

和setupexpandoaction是:

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) {
        }

    }

}

在你的liferay-hook.xml文件,你做到以下几点:

    <?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>

在portal.properties你加入这一行:

application.startup.events=de.osc.kaleositeaddon.startup.StartupAction

记住替换类名;

answer2: 回答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.

如果你在你的插件有一个portlet,您可以在portlet运行代码。init(PortletConfig)。

但这并不总是可能的,因为

  • 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

在这种情况下,你还有两个选择:

创建一个启动动作即每门实例(见gevatterjan答案)。如果需要为每个门户实例运行代码,这是最好的解决方案。

或者你使用相结合的servletcontextlistener和portallifecycle即开始当插件是可用的。这是最好的解决方案如果你想运行一次,例如创建一个调度程序或更换系统功能覆盖不到的liferay-hook.xml分别。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
    }

}

你可以调用任何版本的功能,但要小心:

您的线程没有连接到任何请求-没有当前的门户实例(公司),站点(组),页面(布局)或用户。你可以找到所有这些使用适当的* servicelocalutil功能。和你的行动需要建立在companythreadlocal线程这些价值,pricipalthreadlocal和permissionthreadlocal。

liferay  liferay-6  portlet