8. ポートレットの開発(Spring 編)¶
注意
目次
8.1. 概要¶
画面開発 (render サイクル)
ポートレットに表示する画面を作成します。モードやウィンドウステータスを判定して切り替えることも可能です。表示モード用の画面は必須です。アクション処理 (processAction サイクル)
ポートレットからサブミットされたデータの処理を作成します。 Controller クラスのメソッドに @ActionMapping アノテーションを設定することによって利用できます。また、Event を設定することによって、別のポートレットと連携することも可能です。イベント処理 (processEvent サイクル)
他のポートレットから発生したイベントの受信処理を作成します。 Controller クラスのメソッドに @EventMapping アノテーションを設定することによって利用できます。アクション処理 で Event を設定された場合のみ実行されます。
render 必須 @RenderMapping processAction 任意 @ActionMapping processEvent 任意 @EventMapping
8.2. Spring Portlet MVC Frameworkのポートレット開発との違い¶
portlet.xmlSpring Portlet MVC Frameworkでは個々のポートレットごとにportlet.xmlに<portlet>を追加していましたが、 intra-mart Accel Platform では、個々には登録しません。%CONTEXT_PATH%/WEB-INF/plugin/jp.co.intra_mart.portal.portlets.spring_8.0.0/plugin.xmlの<portlet-name>SpringPortlet</portlet-name>の設定を元にポートレットを動作させます。portlet-name は、「Springポートレット識別子」に設定した値が設定されます。 portletのcontextのxmlファイルの命名規則と配置場所classpath:META-INF/spring/[Springポートレット識別子]-portlet.xml です。詳細は、「portlet context のxmlファイル 」を参照してください。
8.3. ポートレットAPI¶
8.3.1. PortalManager¶
jp.co.intra_mart.foundation.portal.common.PortalManager
8.4. ポートレットモード¶
8.4.1. ポートレットモードの設定¶
ポートレット定義の変更ポートレットモードの設定は以下のファイルで管理されています。intra-mart Accel Platform を停止して設定後、再起動を行います。設定ファイル%CONTEXT_PATH%/WEB-INF/plugin/jp.co.intra_mart.portal.portlets.spring_8.0.0/plugin.xml設定箇所<?xml version="1.0" encoding="utf-8"?> <plugin> <extension point="jp.co.intra_mart.portal.portlets"> <portlet id="jp.co.intra_mart.portal.portlets.spring" name="SpringPortlet" display-name="%display-name" description="%description" version="8.0.0" rank="1"> <portlet-class>jp.co.intra_mart.foundation.portal.portlets.model.SpringPortlet</portlet-class> <expiration-cache>0</expiration-cache> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> <portlet-mode>EDIT</portlet-mode> <!-- ここにモードを追加 --> </supports> ... </portlet> </extension> </plugin>
8.4.2. ポートレットモードの取得¶
(ex.) PortletMode.VIEW, PortletMode.EDIT
javax.portlet.RenderRequest renderRequest = PortalManager.getRenderRequest(); javax.portlet.PortletMode portletMode = renderRequest.getPortletMode();
8.5. ウィンドウステータス¶
8.5.1. ウィンドウステータスの取得¶
(ex.) WindowState.NORMAL, WindowState.MAXIMIZED, WindowState.MINIMIZED
javax.portlet.RenderRequest renderRequest = PortalManager.getRenderRequest(); javax.portlet.WindowState windowState = renderRequest.getWindowState();
8.6. portlet context のxmlファイル¶
ファイル名[Springポートレット識別子]-portlet.xml 形式で作成してください。(ex.) Springポートレット識別子に 「welcome」 と設定した場合、 welcome-portlet.xml です。 配置場所モジュール・プロジェクトでは、src/main/resources に 「 META-INF/spring」 フォルダを作成し、xmlファイルを配置してください。(ex.) src/main/resources/META-INF/spring/welcome-portlet.xml
<context:component-scan base-package="Controller クラスのパッケージ" />
8.7. 画面開発 (renderサイクル)¶
8.7.1. Controller クラス¶
@Controller アノテーション、 @RequestMapping アノテーション を設定した Controllerクラスを作成し、 @RenderMapping アノテーションを設定したメソッドを作成します。@RequestMapping にはポートレットモード(VIEW または EDIT)を指定します。renderを処理するメソッドに @RenderMapping アノテーションを設定します。パラメータでrenderを処理するメソッドを選択するには、 @RenderMapping(params = “action=list”) のように設定します。RenderRequest、RenderResponseを取得するには、メソッドの引数にRenderRequest、RenderResponseを記述します。@Controller @RequestMapping("VIEW") public class ViewController { // default render @RenderMapping public String view() { return "welcome/view.jsp"; } // renderURL.setParameter("action", "list") に対応するrender @RenderMapping(params = "action=list") public String list() { return "welcome/list.jsp"; } // renderURL.setParameter("action", "another") に対応するrender @RenderMapping(params = "action=another") public String view2(RenderRequest request, RenderResponse response) { // RenderRequest、RenderResponseを取得するには、メソッドの引数にRenderRequest、RenderResponseを記述します。 return "welcome/view2.jsp"; } }
8.7.2. JSP ファイル¶
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <%@ page import="jp.co.intra_mart.foundation.portal.common.PortalManager" %> <%@ page import="javax.portlet.PortletURL" %> <% PortletURL renderURL = PortalManager.createRenderURL(); %> @RenderMapping に対応する。 <a href="<%=renderURL.toString() %>">default render</a> <br/> <% PortletURL renderURL2 = PortalManager.createRenderURL(); renderURL2.setParameter("action", "list"); %> @RenderMapping(params = "action=list") に対応する。 <a href="<%=renderURL2.toString() %>">render (action=list)</a> <br/>
8.7.3. RenderRequest, RenderResponse¶
JSP でのページ引数の取得
<% RenderRequest renderRequest = PortalManager.getRenderRequest(); RenderResponse renderResponse = PortalManager.getRenderResponse(); String value = renderRequest.getParameter("param1"); %>RenderRequest から、現在のポートレットモード、ウィンドウステータスなどが取得できます。
8.7.3.1. RenderRequestのスコープ¶
portal_cd ポートレットが配置されているポータル画面のキー。 portalKind ポートレットが配置されているポータル画面のポータル種別。以下の値が取得される。
user ユーザポータル group グループポータル ポートレットにリクエストパラメータを設定するためには、アクション処理またはイベント処理を実行する必要があります。また、一度設定したリクエストパラメータは、セッションが持続する間、再度アクション処理またはイベント処理が実行されるまで有効です。
8.7.4. ActionURL, RenderURL¶
ActionURL Action 機能を呼び出す URL RenderURL ポータル画面を再表示するための URL これらは、PortalManager を利用して取得できます。
ActionURL, RenderURL の取得
PortletURL actionURL = PortalManager.createActionURL(); PortletURL renderURL = PortalManager.createRenderURL();
JSP
<% PortletURL actionURL = PortalManager.createActionURL(); %> <!-- 何らかの登録処理を行うサービスを呼び出す --> <form action="<%= actionURL.toString() %>" method="POST"> <!-- 登録処理で使用する値 --> <input type="text" name="param1" value=""> <input type="submit" value="実行"> </form>
アクション処理を呼び出すためには、ActionURL にサブミットする以外にありません。 ActionURL はポータル情報を含むため、データ量が多くなります。メソッドは POST を指定するようにしてください。パラメータを指定してAction処理を呼び出す場合<% PortletURL actionURL = PortalManager.createActionURL(); actionURL.setParameter("action", "register"); %> <!-- 何らかの登録処理を行うサービスを呼び出す --> <form action="<%= actionURL.toString() %>" method="POST"> <!-- 登録処理で使用する値 --> <input type="text" name="param1" value=""> <input type="submit" value="実行"> </form>
setParameterを使ってパラメータを設定し、アクション処理を呼び出します。この場合、 「action=register」です。
8.8. アクション処理 (processActionサイクル)¶
8.8.1. Controller クラス¶
@Controller アノテーション、 @RequestMapping アノテーション を設定した Controllerクラスを作成し、 @ActionMapping アノテーションを設定したメソッドを作成します。@RequestMapping にはポートレットモード(VIEW または EDIT)を指定します。import jp.co.intra_mart.foundation.portal.common.handler.ImEvent; @Controller @RequestMapping("VIEW") public class ViewController { // default render @RenderMapping public String view() { return "welcome/view.jsp"; } // renderURL.setParameter("action", "list") に対応するrender @RenderMapping(params = "action=list") public String list() { return "welcome/list.jsp"; } // default action @ActionMapping public void register(@RequestParam("name") String name, ActionResponse response) { // 登録処理 ... // @RenderMapping(params="action=list") のrenderへ遷移させる。 response.setRenderParameter("action", "list"); } // actionURL.setParameter("action", "publish") に対応するaction // eventを発行するaction @ActionMapping(params = "action=publish") public void publish(ActionRequest request, ActionResponse response) { // イベント発行 ImEvent event = new ImEvent(); event.setEvent("hello"); response.setEvent(ImEvent.IM_QNAME, event); } }
8.8.2. JSP ファイル¶
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <%@ page import="jp.co.intra_mart.foundation.portal.common.PortalManager" %> <%@ page import="javax.portlet.PortletURL" %> <% PortletURL renderURL = PortalManager.createRenderURL(); %> @RenderMapping に対応する。 <a href="<%=renderURL.toString() %>">default render</a> <br/> <% PortletURL renderURL2 = PortalManager.createRenderURL(); renderURL2.setParameter("action", "list"); %> @RenderMapping(params = "action=list") に対応する。 <a href="<%=renderURL2.toString() %>">render (action=list)</a> <br/> <% PortletURL actionURL = PortalManager.createActionURL(); %> @ActionMapping に対応する。 <form method="post" action="<%=actionURL.toString() %>"> <input type="text" name="name" value=""> <button type="submit">登録</button> </form> <br/> <% PortletURL actionURL2 = PortalManager.createActionURL(); actionURL2.setParameter("action", "publish"); %> @ActionMapping(params = "action=publish") に対応する。 <a href="<%=actionURL2.toString() %>">イベント発行</a> <br/>
8.8.3. ActionRequest, ActionResponse¶
8.8.4. RenderParameterの設定¶
(ex.) processAction サイクルでの RenderParameter の設定
// ActionResponse response // リクエストパラメータを設定する場合。 response.setRenderParameter("param1", "value1"); // リクエストパラメータを削除する場合。 response.setRenderParameter("param2", null);(ex.) render サイクルでの RenderParameter の利用
String value = request.getParameter("param1");
8.8.5. PortletPreferencesの設定¶
(ex.) javax.portlet.PortletPreferences の利用
// PortletPreferences の取得。 PortletPreferences preferences = request.getPreferences(); // PortletPreferences に設定された情報の取得。 String value = preferences.getValue("key1", "Default Value"); // PortletPreferences に情報を設定する。 preferences.setValue("key1", "value1"); // PortletPreferences を確定する。 // この処理を行わない場合、情報は保存されません。 preferences.store();
8.8.6. イベントの設定¶
(ex.) processAction サイクルでのイベントの設定
@ActionMapping(params = "action=publish") public String publish(ActionRequest request, ActionResponse response) { ImEvent event = new ImEvent(); event.setEvent("hello"); response.setEvent(ImEvent.IM_QNAME, event); }
8.9. イベント処理 (processEventサイクル)¶
8.9.1. Controller クラス¶
@Controller アノテーション、 @RequestMapping アノテーション を設定した Controllerクラスを作成し、 @EventMapping アノテーションを設定したメソッドを作成します。@RequestMapping にはポートレットモード(VIEW または EDIT)を指定します。@EventMapping には、 @EventMapping(“ImEvent”) と ImEvent を指定してください。import jp.co.intra_mart.foundation.portal.common.handler.ImEvent; @Controller @RequestMapping("VIEW") public class AnotherController { // default render @RenderMapping public String view() { return "receive/view.jsp"; } // event @EventMapping("ImEvent") public void event(EventRequest request, EventResponse response) { Event event = request.getEvent(); ImEvent imEvent = (ImEvent) event.getValue(); if (!"hello".equals(imEvent.getEvent())) { // "hello"のイベント以外では、処理を実行しない。 return; } // 何らかの処理... } }
8.9.2. ImEventオブジェクト¶
プロパティ名 型 値 id String アクション処理で設定されたイベント ID省略された場合、文字列「ImEvent」が設定される。value String アクション処理で設定されたイベントの値オブジェクトを設定した場合も文字列として取得される。source String Event を設定したポートレットのポートレットコード
8.9.3. EventRequest, EventResponse¶
8.9.4. RenderParameterの設定¶
(ex.) processEvent サイクルでの RenderParameter の設定
// リクエストパラメータを設定する場合。 response.setRenderParameter("param1", "value1"); // リクエストパラメータを削除する場合。 response.setRenderParameter("param2", null);(ex.) render サイクルでの RenderParameter の利用
request.getParameter(eventId);
8.9.5. PortletPreferencesの設定¶
(ex.) java.portlet.PortletPreferences の利用
// PortletPreferences の取得。 PortletPreferences preferences = request.getPreferences(); // PortletPreferences に設定された情報の取得。 String value = preferences.getValue("key1", "Default Value"); // PortletPreferences に情報を設定する。 preferences.setValue("key1", "value1"); // PortletPreferences を確定する。 // この処理を行わない場合、情報は保存されません。 preferences.store();
8.9.6. イベントの設定¶
(ex.) processEvent サイクルでのイベントの設定
response.setEvent(eventId, eventValue);
8.10. Ajax (serveResourceサイクル)¶
Controllerクラスに @ResourceMapping アノテーションを設定したメソッドを作成します。 portletのbean定義xmlに、Jacksonの設定を追加します。
8.10.1. Controller クラス¶
@Controller アノテーション、 @RequestMapping アノテーション を設定した Controllerクラスを作成し、 @ResourceMapping アノテーションを設定したメソッドを作成します。@RequestMapping にはポートレットモード(VIEW または EDIT)を指定します。Ajaxで呼び出される処理を実行するメソッドに @ResourceMapping アノテーションを設定します。リソースID “sample” と対応付けるには、 @ResourceMapping(“sample”) のように設定します。JSON文字列を返すために、 @ResourceMappingアノテーションを設定したメソッドの返り値のタイプに JsonResult を設定します。@Controller @RequestMapping("VIEW") public class ViewController { // default render @RenderMapping public String view() { return "welcome/view.jsp"; } // resource id = fetch @ResourceMapping("fetch") public JsonResult fetch() { Map<String, String> result; // result にデータをセットする処理 // ... // JsonResultにデータをセットして返す。 return new JsonResult(result); } }
8.10.2. JSP ファイル¶
JsonResultのresultプロパティに設定した情報は、クライアント側では、data.result に設定されています。<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <%@ page import="jp.co.intra_mart.foundation.portal.common.PortalManager" %> <%@ page import="javax.portlet.ResourceURL" %> <% ResourceURL resourceURL = PortalManager.createResourceURL(); resourceURL.setResourceID("fetch"); %> <imui:head> <script type="text/javascript"> (function ($) { fetchData = function () { $.ajax({ dataType : 'json', url : '<%=resourceURL.toString()%>', // resource id = "fetch"のURL type :'GET', success : function (data, textStatus, jqXHR) { var result = data.result; // data.resultとJsonResult().getResult()が対応しています。 // 取得データを使った何らかの処理 } }); }; })(jQuery); </script> </imui:head> <a href="javascript:void(0);" onclick="fetchData();">resource id = "fetch"</a>
8.10.3. portlet context の xmlファイル¶
AnnotationMethodHandlerAdapterのcustomModelAndViewResolverプロパティにJsonModelAndViewResolverを設定します。これにより、コントローラークラスのメソッドの戻り値が JsonResult の場合、viewとして MappingJackson2JsonView を使い、responseにJSONを返します。<bean class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="customModelAndViewResolver"> <bean class="jp.co.intra_mart.framework.extension.spring.web.portlet.mvc.JsonModelAndViewResolver" /> </property> </bean>
8.10.4. java.util.Date型プロパティのJSONでのフォーマットについて¶
Jacksonのデフォルトの設定では、java.util.Date型のプロパティをJSONで出力すると、エポックミリ秒(1970年1月1日からのミリ秒)で出力されます。アカウントごとに定義した日付フォーマットを適用して、Date型のプロパティをフォーマットしてJSONに出力するには、以下のようにします。
モデルクラスのDate型プロパティにアノテーションを設定をする。 portlet context の xmlファイルにアノテーションを有効にする設定をする。モデルクラスへの設定JsonResultにセットするモデルクラスのDate型プロパティに AccountDateFormat、AccountDateTimeFormat、AccountTimeFormat アノテーションを付けます。それぞれのアノテーションについては、 「 APIリスト jp.co.intra_mart.framework.extension.spring.format.annotation パッケージ 」 を参照してください。アノテーションを付けない場合は、エポックミリ秒のままです。import java.util.Date; import jp.co.intra_mart.framework.extension.spring.format.annotation.AccountDateFormat; import jp.co.intra_mart.framework.extension.spring.format.annotation.AccountDateFormat.TYPE; public class DateForm { // アノテーションなし private Date date; // アノテーションあり @AccountDateFormat private Date dateDefault; // アノテーションあり @AccountDateFormat(type = TYPE.SIMPLE) private Date dateSimple; // setter and getter... }portlet context の xmlファイルへの設定JsonModelAndViewResolverのmappingJacksonJsonViewプロパティに、MappingJackson2JsonViewを設定し、このMappingJackson2JsonViewのobjectMapperプロパティにAccountDateObjectMapperを設定します。objectMapperにAccountDateObjectMapperを設定したMappingJackson2JsonViewを使うことにより、モデルをJsonに変換するときに、AccountDateFormat、AccountDateTimeFormat、AccountTimeFormat アノテーションの設定を有効にできます。CVE-2018-11040 対応として、 MappingJackson2JsonView を利用する場合は、 jsonpParameterNames プロパティに空のSetを設定します。<bean class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="customModelAndViewResolver"> <bean class="jp.co.intra_mart.framework.extension.spring.web.portlet.mvc.JsonModelAndViewResolver"> <property name="mappingJacksonJsonView"> <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"> <property name="jsonpParameterNames" value="#{T(java.util.Collections).EMPTY_SET}" /> <property name="objectMapper"> <bean class="jp.co.intra_mart.framework.extension.spring.http.converter.json.AccountDateObjectMapper" /> </property> </bean> </property> </bean> </property> </bean>