intra-mart Accel Platform TERASOLUNA Server Framework for Java (5.x) プログラミングガイド 第10版 2016-04-01

参考( TERASOLUNA Server Framework for Java (5.x) on Accel Platform アーキテクチャ )

TERASOLUNA Server Framework for Java (5.x) (http://terasolunaorg.github.io/) は、Spring Framework (http://projects.spring.io/spring-framework/) をベースに構成されるJavaフレームワークです。
TERASOLUNA Server Framework for Java (5.x) の詳細については TERASOLUNA Server Framework for Java (5.x) Development Guideline にて公開されています。
本項では、 intra-mart Accel Platform と TERASOLUNA Server Framework for Java (5.x) によるフルスタックフレームワークについて説明します。

TERASOLUNA Server Framework for Java (5.x) on Accel Platform の構成

intra-mart Accel Platform 上に TERASOLUNA Server Framework for Java (5.x) を組み込んだ「フルスタックフレームワーク」のイメージは下図の通りです。
../../_images/tgfw_stack_on_iap.png
TERASOLUNA Server Framework for Java (5.x) は、下記の通り、Spring Framework がベースで構成され、トランザクショントークンチェック、コードリスト、例外ハンドリングやロギング等の機能を提供し、その活用方法を「 TERASOLUNA Server Framework for Java (5.x) Development Guideline 」として提供しています。
アプリケーション層 Spring MVC / Bean Validation
ドメイン層 Spring Framework
インフラストラクチャ層 MyBatis3
TERASOLUNA Server Framework for Java (5.x) on Accel Platform では、intra-mart Accel Platform が提供する以下の機能を利用して、TERASOLUNA Server Framework for Java (5.x) のアプリケーションを効率よく開発することができます。

コラム

intra-mart Accel Platform が提供する各機能の使い方については上記リンクより参照にしてください。

TERASOLUNA Server Framework for Java (5.x) との対応

TERASOLUNA Server Framework for Java (5.x) Development Guideline で想定している TERASOLUNA Server Framework for Java (5.x) のアーキテクチャの TERASOLUNA Server Framework for Java (5.x) on Accel Platform 上での対応は以下の通りです。

機能 対応 備考
データアクセス(共通編) image_ok シンプルなCRUD操作で動作確認を行っております。
データアクセス(JPA編) image_ng intra-mart Accel Platform では対応していません。
データアクセス(Mybatis3編) image_ok シンプルなCRUD操作で動作確認を行っております。
排他制御 image_ok  
入力チェック image_ok  
ロギング image_notice Logger, MDCは intra-mart Accel Platform のものを使用してください。 また、 「ログ」を参照してください。 TraceLoggingInterceptor, ExceptionLoggerについては、 「TERASOLUNA Server Framework for Java (5.x) Development Guideline」を参照してください。
例外ハンドリング image_ok  
セッション管理 image_notice Spring Securityを使うものについては対象外です。
メッセージ管理 image_ng IntramartMessageSource を使用してください。 また、「多言語化されたメッセージを取得する」を参照してください。
プロパティ管理 image_ok  
ページネーション image_ng imuiTableを使用してください。
二重送信防止 image_ok  
国際化 image_notice IntramartMessageSource, AccountLocaleResolverを使用してください。 また、「国際化」を参照してください。
コードリスト image_ok Bean定義 applicationContext-im_tgfw_web.xml にコードリストの設定を記述しています。 <mvc:mapping>のpath属性は、適用対象のパスを設定してください。
Ajax image_ok  
RESTful Web Service image_ng @RestControllerの代わりにWeb API Makerを使用してください。 service層は、applicationContextからbeanを取得してください。 Web API Makerについては「Web API Maker プログラミングガイド」を参照してください。
RESTクライアント(HTTPクライアント) image_ok  
SOAP Web Service(サーバ/クライアント) image_ng Webサービス Java開発プログラミングガイド」を参照してください。
ファイルアップロード image_notice Servlet 3.0の機能は非対応です。 multipartResolverにはCommonsMultipartResolverを設定しています。 また、「Storage」を参照してください。
ファイルダウンロード image_ok Storage」を参照してください。
E-mail送信(SMTP) image_ng  
Tiles image_ng intra-mart Accel Platform のテーマ機能を使用してください。
システム時刻 image_notice org.terasoluna.gfw.common.date.JdbcAdjustedDateFactory を使用する場合、 dataSourceプロパティにはシェアードデータソースを指定してください。 シェアードデータソースの設定は、 「DataSource」や 「データベース」を参照してください。
ユーティリティ(dozer) image_ok  
ユーティリティ(joda time) image_ok  

TERASOLUNA Server Framework for Java (5.x) Development Guideline に記載されている TERASOLUNA Server Framework for Java (5.x) のセキュリティ対策についての TERASOLUNA Server Framework for Java (5.x) on Accel Platform 上での対応は以下の通りです。

セキュリティ対策 対応 備考
Spring Security (認証、パスワードハッシュ化、認可) image_ng 認証、パスワードハッシュ化、認可機能については、 intra-mart Accel Platform の認証、認可を使用してください。 intra-mart Accel Platform でもパスワードのハッシュ化を行っています。
XSS対策 image_ok  
CSRF対策 image_ng intra-mart Accel PlatformのimSecureTokenタグを使用してください。 「imSecureTokenタグ」、「CSRF対策」を参照してください。

TERASOLUNA Server Framework for Java (5.x) on Accel Platform におけるBean定義の既定値

Spring MVC では、DispatcherServlet というサーブレットクラスが提供されています。
DispatcherServletは、クライアントからの要求に対して、要求情報からコントローラを探し、コントローラを呼び出す役割を担います。
intra-mart Accel Platform では、クライアントからの要求に対して、該当するプログラムを探し、認可のチェックをし、見つかったプログラムを呼び出す「ルーティング機構」があります。
intra-mart Accel Platform では、この「ルーティング機構」からSpring MVCのコントローラを呼び出す機構が組み込まれています。

コラム

「ルーティング機構」の仕組みについては、「認可」ページを参考にしてください。
Spring MVCでは通常、1つのWebアプリケーションに複数のDispatcherServletを登録し、サーブレットごとにBean定義を行うことができますが、
intra-mart Accel Platform では、DispatcherServletを拡張したサーブレットクラスが1つだけ登録されており、このサーブレットクラスを複数登録することはできません。
そのため、intra-mart Accel Platform ではすべてのBean定義はWebアプリケーション上で共有されることになります。
intra-mart Accel Platform では、あらかじめ下記ファイルにてBean定義が行われています。
  • <Jugglingプロジェクト>/classes/META-INF/spring/applicationContext-im_tgfw_common.xml
  • <Jugglingプロジェクト>/classes/META-INF/spring/applicationContext-im_tgfw_web.xml
  • <Jugglingプロジェクト>/classes/META-INF/spring/SpringMVCServlet-servlet.xml
  • <Jugglingプロジェクト>/classes/META-INF/spring/applicationContext-im_tgfw_mybatis3.xml
これらのBean定義は、intra-mart Accel Platform のテナント上で共有されるため、セットアップガイドに記載のない内容以外は基本変更しないようにしてください。
以下、intra-mart Accel Platform へのSpring MVCの組込み内容と上記Bean定義ファイルの初期値について示します。

web.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         metadata-complete="false"
         version="3.0"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

  : (省略)

  <!-- Web アプリケーション起動時に、クラスパス上の/META-INF/spring/内のapplicationContextで始まるBean定義ファイルをロード させる設定-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:/META-INF/spring/applicationContext*.xml</param-value>
  </context-param>
  <listener>
    <listener-class>jp.co.intra_mart.framework.extension.spring.web.servlet.SpringServletContextListener</listener-class>
  </listener>

  : (省略)

  <!-- 「ルーティング機構」用にDispatcherServletを拡張したサーブレットを登録 -->
  <servlet>
    <servlet-name>SpringMVCServlet</servlet-name>
    <servlet-class>jp.co.intra_mart.framework.extension.spring.web.servlet.IntramartDispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:/META-INF/spring/SpringMVCServlet-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <multipart-config/>
  </servlet>

  : (省略)

</web-app>

applicationContext-im_tgfw_common.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- a bean which holds the root application context -->
    <bean class="jp.co.intra_mart.system.extension.spring.context.ApplicationContextHolder" />

    <!-- message source which loads from 'WEB-INF/conf/message/**/*.properties' -->
    <bean id="messageSource" class="jp.co.intra_mart.framework.extension.spring.message.IntramartMessageSource" />

    <!-- bean validation (JSR-303 / JSR-349) -->
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="validationMessageSource" ref="messageSource" />
    </bean>

    <!-- transaction manager (JTA) -->
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

    <!-- enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- intra-mart tenant datasource -->
    <bean id="dataSource" class="jp.co.intra_mart.framework.extension.spring.datasource.TenantDataSource" />

    <!-- intra-mart shared datasource -->
    <!--
         [Note] If you use the shared datasource, please uncomment/enable the following setting
                and set the bean's id and the connectId's value.
    -->
    <!-- 
    <bean id="sharedDataSource" class="jp.co.intra_mart.framework.extension.spring.datasource.SharedDataSource">
        <constructor-arg name="connectId" value="xxxxxxxxxxxxxx" />
    </bean>
     -->

    <!-- property placeholder setting -->
    <context:property-placeholder location="classpath*:/META-INF/spring/*.properties" />

    <!-- dozer setting -->
<!--
    <bean class="org.dozer.spring.DozerBeanMapperFactoryBean">
        <property name="mappingFiles" value="classpath*:/META-INF/dozer/**/*-mapping.xml" />
    </bean>
 -->

    <!-- Exception Code Resolver. -->
    <bean id="exceptionCodeResolver"
        class="org.terasoluna.gfw.common.exception.SimpleMappingExceptionCodeResolver">
        <!-- Setting and Customization by project. -->
        <property name="exceptionMappings">
            <map>
                <entry key="ResourceNotFoundException" value="w.im.fw.0001" />
                <entry key="InvalidTransactionTokenException" value="w.im.fw.0004" />
                <entry key="InvalidSecureTokenException" value="w.im.fw.0005" />
                <entry key="BusinessException" value="w.im.fw.0002" />
            </map>
        </property>
        <property name="defaultExceptionCode" value="e.im.fw.0001" />
    </bean>

    <!-- Exception Logger. -->
    <bean id="exceptionLogger"
        class="org.terasoluna.gfw.common.exception.ExceptionLogger">
        <property name="exceptionCodeResolver" ref="exceptionCodeResolver" />
    </bean>

</beans>

applicationContext-im_tgfw_web.xml

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- locale resolver -->
    <bean id="localeResolver" class="jp.co.intra_mart.framework.extension.spring.web.servlet.i18n.AccountLocaleResolver" />

    <!-- SpringMVCRoute needs HandlerSelector bean. -->
    <bean id="handlerSelector" class="jp.co.intra_mart.system.router.spring.HandlerSelector" init-method="init" />

    <!-- view components -->
    <context:component-scan base-package="jp.co.intra_mart.framework.extension.spring.web.servlet.view" />

    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="0" />
    </bean>
    <!-- prefix for InternalResourceViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="order" value="1" />
    </bean>

    <!-- multipart resolver -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

    <!-- support for annotation-driven MVC controllers -->
    <mvc:annotation-driven conversion-service="conversionService">
        <!-- transaction token -->
        <mvc:argument-resolvers>
            <bean class="org.terasoluna.gfw.web.token.transaction.TransactionTokenContextHandlerMethodArgumentResolver" />
        </mvc:argument-resolvers>
        <!-- jackson message converter -->
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="jp.co.intra_mart.framework.extension.spring.http.converter.json.AccountDateObjectMapper" />
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    <bean id="conversionService"
          class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="formatters">
            <set>
                <bean class="jp.co.intra_mart.framework.extension.spring.format.datetime.AccountDateFormatAnnotationFormatterFactory"/>
                <bean class="jp.co.intra_mart.framework.extension.spring.format.datetime.AccountDateTimeFormatAnnotationFormatterFactory"/>
                <bean class="jp.co.intra_mart.framework.extension.spring.format.datetime.AccountTimeFormatAnnotationFormatterFactory"/>
            </set>
        </property>
    </bean>

    <!-- MVC interceptors -->
    <mvc:interceptors>
        <!-- transaction token -->
        <mvc:interceptor>
            <mvc:mapping path="/**" /> <!-- configure the path to specify the package of controllers. -->
            <bean class="org.terasoluna.gfw.web.token.transaction.TransactionTokenInterceptor">
                <constructor-arg value="10" />
            </bean>
        </mvc:interceptor>
        <!-- code list -->
        <mvc:interceptor>
            <mvc:mapping path="/**" /> <!-- configure the path to specify the package of controllers. -->
            <bean class="org.terasoluna.gfw.web.codelist.CodeListInterceptor">
                <property name="codeListIdPattern" value="CL_.+" />
            </bean>
        </mvc:interceptor>
    </mvc:interceptors>

    <!-- transaction token -->
    <bean name="requestDataValueProcessor" class="org.terasoluna.gfw.web.mvc.support.CompositeRequestDataValueProcessor">
        <constructor-arg>
            <util:list>
                <bean class="org.terasoluna.gfw.web.token.transaction.TransactionTokenRequestDataValueProcessor" />
            </util:list>
        </constructor-arg>
    </bean>

    <!-- secure token validator -->
    <bean id="secureTokenValidator" class="jp.co.intra_mart.framework.extension.spring.web.csrf.SecureTokenValidator" />

    <!-- Setting Exception Handling. -->
    <!-- Exception Resolver. -->
    <bean class="org.terasoluna.gfw.web.exception.SystemExceptionResolver">
        <property name="exceptionCodeResolver" ref="exceptionCodeResolver" />
        <!-- Setting and Customization by project. -->
        <property name="order" value="3" />
        <property name="exceptionMappings">
            <map>
                <entry key="ResourceNotFoundException" value="im_tgfw/common/error/resourceNotFoundError.jsp" />
                <entry key="BusinessException" value="im_tgfw/common/error/businessError.jsp" />
                <entry key="InvalidTransactionTokenException" value="im_tgfw/common/error/transactionTokenError.jsp" />
                <entry key="InvalidSecureTokenException" value="im_tgfw/common/error/secureTokenError.jsp" />
            </map>
        </property>
        <property name="statusCodes">
            <map>
                <entry key="im_tgfw/common/error/resourceNotFoundError" value="404" />
                <entry key="im_tgfw/common/error/businessError" value="200" />
                <entry key="im_tgfw/common/error/transactionTokenError" value="409" />
                <entry key="im_tgfw/common/error/secureTokenError" value="403" />
            </map>
        </property>
        <property name="defaultErrorView" value="im_tgfw/common/error/systemError.jsp" />
        <property name="defaultStatusCode" value="500" />
    </bean>
    <!-- AOP. -->
    <bean id="handlerExceptionResolverLoggingInterceptor"
        class="org.terasoluna.gfw.web.exception.HandlerExceptionResolverLoggingInterceptor">
        <property name="exceptionLogger" ref="exceptionLogger" />
    </bean>
    <aop:config>
        <aop:advisor advice-ref="handlerExceptionResolverLoggingInterceptor"
            pointcut="execution(* org.springframework.web.servlet.HandlerExceptionResolver.resolveException(..))" />
    </aop:config>

</beans>

SpringMVCServlet-servlet.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

</beans>

applicationContext-im_tgfw_mybatis3.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:/META-INF/mybatis/mybatis-config.xml" />
    </bean>

    <!-- setting 'base-package' which is the package in which mapper interface is. -->
<!-- 
    <mybatis:scan base-package="xxxxxx.yyyyyy.zzzzzz.domain.repository" />
 -->

</beans>