oo

MVC Resource Command

MVC Resource Command classes retrieve resources: images, XML, or any other kind of resource from a DXP/Portal instance without triggering any actions or renders. Requests or portlet resource URLs invoke MVC Resource Commands.

You’ll deploy an example portlet that uses an MVC Resource Command and then examine it.

Invoke an MVC Resource Command

The example portlet downloads a simple file using an MVC Resource Command.

Start a new Liferay instance by running

docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.112-ga112

Sign in to Liferay at http://localhost:8080. Use the email address test@liferay.com and the password test. When prompted, change the password to learn.

Then, follow these steps:

  1. Download and unzip the example.

    curl https://resources.learn.liferay.com/dxp/latest/en/building-applications/developing-a-java-web-application/using-mvc/liferay-p8v5.zip -O
    
    unzip liferay-p8v5.zip
    
  2. Build and deploy the example.

    cd liferay-p8v5
    
    ./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
    
    Note

    This command is the same as copying module JARs to /opt/liferay/osgi/modules on the Docker container.

  3. Confirm the deployment in the Docker container console.

    STARTED com.acme.p8v5.web_1.0.0
    
  4. Add the P8V5 Portlet widget from the Samples category to a widget page. The P8V5 Portlet appears.

    You've added the P8V5 Portlet to a page.

    The link invokes an MVC Resource Command to download a simple text file.

  5. Click Download. A file called p8v5.txt downloads to your machine.

  6. Open the p8v5.txt file. Here’s the content:

    Hello P8V5!
    

You’ve downloaded a file using an MVC Resource Command. Now see how it works.

Examine the Portlet

P8V5Portlet is a minimal MVCPortlet.

@Component(
	property = {
		"com.liferay.portlet.display-category=category.sample",
		"javax.portlet.display-name=P8V5 Portlet",
		"javax.portlet.init-param.view-template=/p8v5/view.jsp",
		"javax.portlet.name=com_acme_p8v5_web_internal_portlet_P8V5Portlet"
	},
	service = Portlet.class
)
public class P8V5Portlet extends MVCPortlet {
}

The @Component javax.portlet.name property sets the portlet’s name.

"javax.portlet.name=com_acme_p8v5_web_internal_portlet_P8V5Portlet"
Note

MVCResourceCommands bind to a portlet by the portlet’s name (e.g., the portlet component javax.portlet.name property value).

The portlet’s MVC Resource Command class is next.

Examine the MVCResourceCommand Class

MVC Resource Command classes can implement MVCResourceCommand directly or implement it indirectly by extending BaseMVCResourceCommand. P8V5DownloadMVCResourceCommand directly implements MVCResourceCommand.

@Component(
	property = {
		"javax.portlet.name=com_acme_p8v5_web_internal_portlet_P8V5Portlet",
		"mvc.command.name=/p8v5/download"
	},
	service = MVCResourceCommand.class
)
public class P8V5DownloadMVCResourceCommand implements MVCResourceCommand {

	@Override
	public boolean serveResource(
			ResourceRequest resourceRequest, ResourceResponse resourceResponse)
		throws PortletException {

		try {
			PortletResponseUtil.sendFile(
				resourceRequest, resourceResponse, "p8v5.txt",
				"Hello P8V5!".getBytes(), "text");

			return false;
		}
		catch (IOException ioException) {
			_log.error(ioException, ioException);

			return true;
		}
	}

	private static final Log _log = LogFactoryUtil.getLog(
		P8V5DownloadMVCResourceCommand.class);

}

P8V5DownloadMVCResourceCommand is a Component that provides the MVCResourceCommand service. The component properties apply the P8V5DownloadMVCResourceCommand to the portlet named com_acme_p8v5_web_internal_portlet_P8V5Portlet and map P8V5DownloadMVCResourceCommand to the MVC command name /p8v5/download. The name you specify here must match the name declared in the portlet.

Note

You can associate an MVCResourceCommand component with multiple portlets by declaring separate javax.portlet.name properties for each portlet:

@Component(
    property = {
        "javax.portlet.name=com_acme_p8v5_web_internal_portlet_P8V5Portlet",
        "javax.portlet.name=com_acme_p8v5_web_internal_portlet_P8V6Portlet",
        "mvc.command.name=/p8v5/download"
    },
    service = MVCResourceCommand.class
)

The example serveResource method creates a simple text file and sends it to the user via PortletResponseUtil. The method returns true if an error occurs or false otherwise.

Next you’ll learn how the portlet’s JSP maps a UI component action to the command.

Examine the Portlet Resource URL

The portlet’s view.jsp file renders a link for invoking the MVC Resource Command.

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>

<h4>P8V5 Portlet</h4>

<a href="<portlet:resourceURL id="/p8v5/download" />">Download</a>

The first line makes the Portlet 2.0 tag library available via the portlet prefix. This JSP binds an action to a UI component using the tag library’s portlet:resourceURL tag. The tag’s id attribute uses the MVC Resource Command’s mvc.command.name property value. The following table shows the correlation:

view.jsp Portlet Resource URL P8V5DownloadMVCResourceCommand Component Property
<a href="<portlet:resourceURL id="/p8v5/download" />">Download</a> mvc.command.name=/p8v5/download

Clicking the view’s Download link invokes P8V5DownloadMVCResourceCommand’s serveResource method.

What’s Next

Now you know how to use MVC Resource Commands. If you want to localize your portlet’s content, see Using Localized Messages. If you’re ready to develop model, persistence, and service layers, visit Service Builder.