Uploaded image for project: 'PUBLIC - Liferay Portal Community Edition'
  1. PUBLIC - Liferay Portal Community Edition
  2. LPS-69134

Using 'component.name' in @Reference annotation of a MVC command override

    Details

      Description

      The recommendation for the @Reference annotation in this tutorial is flawed:

      Per this Liferay extension scheme, a typical MVC command override class needs to declare two things:

      1) What command and portlets it is trying to override: this is achieve by the @Component annotation and these two properties:

      • "javax.portlet.name" (multiple values, one per portlet name)
      • "mvc.command.name" (single value)

      2) The option to call the original Liferay MVC command: this is achieved by the @Reference annotation. This tutorial uses the two properties identical to 1).

      @Component(
          property = {
              "javax.portlet.name=" + LoginPortletKeys.LOGIN,
              "javax.portlet.name=" + LoginPortletKeys.FAST_LOGIN,
              "mvc.command.name=/login/create_account", "service.ranking:Integer=500"
          },
          service = MVCActionCommand.class)
      public class CustomLoginMVCActionCommand extends BaseMVCActionCommand {
      
          @Reference(target = "(&(mvc.command.name=/login/create_account)" +
                  "(javax.portlet.name=" + LoginPortletKeys.LOGIN + ")" +
                  "(javax.portlet.name=" + LoginPortletKeys.FAST_LOGIN + "))")
          protected MVCActionCommand mvcActionCommand;
      }
      

      With that, CustomLoginMVCActionCommand now has the identical property set used to find the original 'mvcActionCommand'. When Liferay OSGi initializes, it loads modules in LIFERAY_HOME/osgi/modules first, making CustomLoginMVCActionCommand the first component in the module registry, ahead of the Liferay MVC command it overrides. Then OSGi will match CustomLoginMVCActionCommand itself while searching the registry for that set of properties to satisfy the @Reference annotation.

      That leads to these errors during Liferay startup and the override component inoperable:

      04:06:06,000 ERROR [localhost-startStop-1][create_account_override:97] [com.acme.create_account.override.action.CustomLoginMVCActionCommand(1208)] Circular reference detected, getService returning null
      04:06:07,785 ERROR [localhost-startStop-1][create_account_override:97] [com.acme.create_account.override.action.CustomLoginMVCActionCommand(1208)] Cannot create component instance due to failure to bind reference mvcActionCommand
      

      The @Reference annotation must use a distinctively different property to find the original MVC command. While debugging this, I found out that every component has property component.name set to its implementation class name. Using that property, both of these versions work:

      @Reference(target = "(&(mvc.command.name=/login/create_account)" +
      "(component.name=com.liferay.login.web.internal.portlet.action.CreateAccountMVCActionCommand))")
      

      or

      @Reference(target = "(&(mvc.command.name=/login/create_account)" +
      "(component.name=com.liferay.login.*.CreateAccountMVCActionCommand))")
      

      The use of 'component.name' should be promoted as the recommended way for the @Reference annotation of an overriding MVC command to find the original Liferay MVC command.

        Attachments

          Activity

            People

            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Days since last comment:
                1 year, 34 weeks, 3 days ago

                Packages

                Version Package
                7.1.0 Beta 3