MVCRenderCommandのオーバーライド

LiferayのMVCフレームワークを使用し、MVCRenderCommandコンポーネントを公開するポートレットのMVCRenderCommandをオーバーライドできます。

たとえば、Liferayのブログアプリケーションには、次のコンポーネントを含むEditEntryMVCRenderCommandというクラスがあります。

@Component(
immediate = true,
property = {
"javax.portlet.name=" + BlogsPortletKeys.BLOGS,
"javax.portlet.name=" + BlogsPortletKeys.BLOGS_ADMIN,
"javax.portlet.name=" + BlogsPortletKeys.BLOGS_AGGREGATOR,
"mvc.command.name=/blogs/edit_entry"
},
service = MVCRenderCommand.class
)

このMVCレンダリングコマンドは、MVCコマンドに名前を付けるレンダーURLを呼び出すことにより、javax.portlet.nameパラメーターで指定された任意のポートレットから呼び出すことができます。

<portlet:renderURL var="addEntryURL">
<portlet:param name="mvcRenderCommandName" value="/blogs/edit_entry" />
<portlet:param name="redirect" value="<%= viewEntriesURL %>" />
</portlet:renderURL>

コマンドをオーバーライドするが、元のコンポーネントにリストされているポートレットすべてに適用するわけではない場合はどうしますか。オーバーライドコンポーネントで、オーバーライドを有効にするポートレットのjavax.portlet.nameをリストするだけです。 たとえば、ブログ管理ポートレット(Liferayのサイト管理セクションからアクセスできるブログアプリケーション)に対してのみ/blogs/edit_entry MVC renderコマンドをオーバーライドする場合、コンポーネントは次のようになります。

@Component(
immediate = true,
property = {
"javax.portlet.name=" + BlogsPortletKeys.BLOGS_ADMIN,
"mvc.command.name=/blogs/edit_entry",
"service.ranking:Integer=100"
},
service = MVCRenderCommand.class
)

リストされている最後のプロパティservice.rankingに注目してください。これは、複数のコンポーネントが同じプロパティを持つ同じサービスを登録している場合に、使用するサービスをOSGiランタイムに伝えるためのものです。ここで指定する整数の値が大きいほど、コンポーネントの重みが大きくなります。この場合、このプロパティのデフォルト値は0であるため、元のコンポーネントの代わりにオーバーライドコンポーネントが使用されます。

この後はご自由にカスタマイズ可能です。MVC renderコマンドは、次の目的のためにカスタマイズできます。

既存のMVC renderコマンドにロジックを追加する方法から見ていきましょう。

既存のMVC Renderコマンドにロジックを追加する

MVCコマンドの一般的な手順に従って、MVC renderコマンドにロジックを追加できます。 特にMVC renderコマンドの場合は、MVCRenderCommandインターフェイスを直接実装し、そのrenderメソッドをオーバーライドする必要があります。

たとえば、次のカスタムMVC renderコマンドには、renderメソッドにロジックを追加するためのプレースホルダー(つまり、コメント//Do something here)があります。

public CustomEditEntryRenderCommand implements MVCRenderCommand {
@Override
public String render(RenderRequest renderRequest,
RenderResponse renderResponse)
throws PortletException {

//Do something here

return mvcRenderCommand.render(renderRequest, renderResponse);
}

@Reference(target =
"(component.name=com.liferay.blogs.web.internal.portlet.action.EditEntryMVCRenderCommand)")
protected MVCRenderCommand mvcRenderCommand;
}

この例では、MVCRenderCommandEditEntryMVCRenderCommand実装を参照しています。renderメソッドでは、プレースホルダーを新しいロジックに置き換え、そのrenderメソッドを呼び出して元の実装のロジックを呼び出します。

場合によっては、リクエストをまったく新しいJSPにリダイレクトする必要があります。 これは、カスタムMVC renderコマンドモジュールからも実行できます。

新しいJSPにリダイレクトする

MVCRenderCommandrenderメソッドは、JSPパスを文字列として返します。 デフォルトでは、JSPは元のモジュールに存在する必要があるため、単にオーバーライドモジュールでカスタムJSPへのパスを指定することはできません。新しいモジュールのJSPにリダイレクトするには、定数MVCRenderConstants.MVC_PATH_VALUE_SKIP_DISPATCHクラスを使用して、メソッドで元のJSPへのディスパッチを完全にスキップする必要があります。 次に、独自のディスパッチプロセスを開始して、JSPパスにリクエストを送信する必要があります。実際にどのように見えるかを次に示します。

public class CustomEditEntryMVCRenderCommand implements MVCRenderCommand {

@Override
public String render(
RenderRequest renderRequest, RenderResponse renderResponse) throws
PortletException {

System.out.println("Rendering custom_edit_entry.jsp");

RequestDispatcher requestDispatcher =
servletContext.getRequestDispatcher("/custom_edit_entry.jsp");

try {
HttpServletRequest httpServletRequest =
PortalUtil.getHttpServletRequest(renderRequest);
HttpServletResponse httpServletResponse =
PortalUtil.getHttpServletResponse(renderResponse);

requestDispatcher.include
(httpServletRequest, httpServletResponse);
} catch (Exception e) {
throw new PortletException
("Unable to include custom_edit_entry.jsp", e);
}

return MVCRenderConstants.MVC_PATH_VALUE_SKIP_DISPATCH;
}

@Reference(target = "(osgi.web.symbolicname=com.custom.code.web)")
protected ServletContext servletContext;
}

サーブレットコンテキストは、リクエストディスパッチャへのアクセスを提供します。サーブレットコンテキストがポートレット用に自動的に作成されます。 bnd.bndファイルに次の行を含めることにより、他のモジュール用に作成できます。

Web-ContextPath: /custom-code-web

次の手順に従って、カスタムMVC renderコマンドでポートレットのサーブレットコンテキストを取得します。

  1. ServletContextフィールドを追加します。

    protected ServletContext servletContext;
    
  2. フィールドに@Referenceアノテーションを追加し、ポートレットのモジュールでフィルタリングするようにアノテーションを設定します。慣例により、Liferayは、シンボル名が.webで終わるモジュールにポートレットを配置しています。たとえば、次のサーブレットコンテキスト参照は、シンボル名がcom.custom.code.webのモジュールでフィルタリングします。

    @Reference(target = "(osgi.web.symbolicname=com.custom.code.web)")
    protected ServletContext servletContext;
    

次のようにrenderメソッドを実装します。

  1. モジュールのカスタムJSPへのリクエストディスパッチャを取得します。

    RequestDispatcher requestDispatcher =
    servletContext.getRequestDispatcher("/custom_edit_entry.jsp");
    
  2. HTTPサーブレットのリクエストとレスポンスをリクエストディスパッチャに含めます。

    try {
    HttpServletRequest httpServletRequest =
    PortalUtil.getHttpServletRequest(renderRequest);
    HttpServletResponse httpServletResponse =
    PortalUtil.getHttpServletResponse(renderResponse);
    
    requestDispatcher.include
    (httpServletRequest, httpServletResponse);
    } catch (Exception e) {
    throw new PortletException
    ("Unable to include custom_edit_entry.jsp", e);
    }
    
  3. 定数MVC_PATH_VALUE_SKIP_DISPATCHを介してリクエストディスパッチャを返します

    return MVCRenderConstants.MVC_PATH_VALUE_SKIP_DISPATCH;
    

モジュールをデプロイすると、カスタムMVCRenderCommandコンポーネントの対象となるポートレットが新しいJSPをレンダリングします。

関連トピック

MVC Render Command

Adding Logic to MVC Commands

Converting StrutsActionWrappers to MVCCommands

« MVCコマンドにロジックを追加するMVCActionCommandのオーバーライド »
この記事は役に立ちましたか?
1人中1人がこの記事が役に立ったと言っています