0% found this document useful (0 votes)
1K views2,321 pages

TERASOLUNAServer Framework For Java Development Guideline

TERASOLUNAServerFrameworkForJavaDevelopmentGuideline

Uploaded by

tehnic1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1K views2,321 pages

TERASOLUNAServer Framework For Java Development Guideline

TERASOLUNAServerFrameworkForJavaDevelopmentGuideline

Uploaded by

tehnic1
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

TERASOLUNA Server Framework for

Java (5.x) Development Guideline


Documentation
Release 5.2.0.RELEASE

NTT DATA

October 14, 2016


i

CONTENTS

1 In the Beginning 3
1.1 Terms of Use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 This document covers the following . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Target readers of this document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4 Structure of this document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.5 Reading this document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.6 Tested environments of this document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.7 Criteria based mapping of guideline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.8 Change Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2 Architecture Overview 37
2.1 Stack of TERASOLUNA Server Framework for Java (5.x) . . . . . . . . . . . . . . . . . . . . . 37
2.2 Overview of Spring MVC Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.3 First application based on Spring MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
2.4 Application Layering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

3 Application Development 93
3.1 Create Web application development project . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
3.2 Domain Layer Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
3.3 Implementation of Infrastructure Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
3.4 Implementation of Application Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
3.5 Build development project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292

4 Web Application Development Features 305


4.1 Input Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
4.2 Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
4.3 Session Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
4.4 Pagination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
4.5 Double Submit Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
4.6 Message Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 628
4.7 Internationalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 662
4.8 Codelist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673
4.9 File Upload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716
4.10 File Download . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 759
4.11 Screen Layout using Tiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 771
4.12 JSP Tag Libraries and EL Functions offered by common library . . . . . . . . . . . . . . . . . . 792
4.13 Ajax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 806
4.14 Health Check . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 837

5 Web Services 849


5.1 RESTful Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 849
5.2 REST Client (HTTP Client) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1019
5.3 SOAP Web Service (Server/Client) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1063

6 Data Access 1129


6.1 Database Access (Common) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1129
6.2 Database Access (MyBatis3) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1160
6.3 Database Access (JPA) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1318
6.4 Exclusive Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1426

7 General-purpose functions that do not depend on the application 1467


7.1 Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1467
7.2 Properties Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1498
7.3 Date operations (JSR-310 Date and Time API) . . . . . . . . . . . . . . . . . . . . . . . . . . . 1512
7.4 Date Operations (Joda Time) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1529
7.5 System Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1547
7.6 String Processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1568
7.7 Bean Mapping (Dozer) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1588

8 Messaging 1621
8.1 Sending E-mail (SMTP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1621
8.2 JMS(Java Message Service) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1651

9 Security countermeasures 1713


9.1 Spring Security Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1713
9.2 Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1725
9.3 Authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1794
9.4 Session Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1824
9.5 CSRF Countermeasures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1837
9.6 Coordinating with browser security countermeasure function . . . . . . . . . . . . . . . . . . . . 1848
9.7 XSS Countermeasures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1855
9.8 Encryption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1864
9.9 Implementation Example of Typical Security Requirements . . . . . . . . . . . . . . . . . . . . 1888

10 Tutorials 2027
10.1 Tutorial (Todo Application) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2027
10.2 Tutorial (Todo Application REST) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2127
10.3 Session tutorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2192

ii
10.4 Spring Security Tutorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2256

11 Appendix(Know How) 2291


11.1 Maven Repository Management using NEXUS . . . . . . . . . . . . . . . . . . . . . . . . . . . 2291
11.2 Reducing Boilerplate Code (Lombok) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2299
11.3 Reference Books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2312
11.4 Spring Framework Comprehension Check . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2313

iii
iv
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: If there are any mistakes in the contents or any comments related to the contents, please raise them at
Issues on Github.

1
3

In the Beginning

1.1 Terms of Use

In order to use this document, you are required to agree to abide by the following terms. If you do not agree with
the terms, you must immediately delete or destroy this document and all its duplicate copies.

1. Copyrights and all other rights of this document shall belong to NTT DATA or third party possessing such
rights.

2. This document may be reproduced, translated or adapted, in whole or in part for personal use. However,
deletion of the terms given on this page and copyright notice of NTT DATA is prohibited.

3. This document may be changed, in whole or in part for personal use. Creation of secondary work using
this document is allowed. However, “Reference document: TERASOLUNA Server Framework for Java
(5.x) Development Guideline” or equivalent documents may be mentioned in created document and its
duplicate copies.

4. Document and its duplicate copies created according to Clause 2 may be provided to third party only if
these are free of cost.

5. Use of this document and its duplicate copies, and transfer of rights of this contract to a third party, in
whole or in part, beyond the conditions specified in this contract, are prohibited without the written consent
of NTT Data.

6. NTT DATA shall not bear any responsibility regarding correctness of contents of this document, warranty of
fitness for usage purpose, assurance for accuracy and reliability of usage result, liability for defect warranty,
and any damage incurred directly or indirectly.

7. NTT DATA does not guarantee the infringement of copyrights and any other rights of third party through
this document. In addition to this, NTT DATA shall not bear any responsibility regarding any claim (Includ-
ing the claims occurred due to dispute with third party) occurred directly or indirectly due to infringement
of copyright and other rights.
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Registered trademarks or trademarks of company name and service name, and product name of their respective
companies used in this document are as follows.

• TERASOLUNA is a registered trademark of NTT DATA Corporation.

• All other company names and product names are the registered trademarks or trademarks of their respective
companies.

4 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

1.2 This document covers the following

This guideline provides best practices to develop highly maintainable Web applications using full stack framework
focussing on Spring, Spring MVC and JPA, MyBatis.

This guideline helps to proceed with the software development (mainly coding) smoothly.

1.3 Target readers of this document

This guideline is written for the architects and programmers having software development experience and knowl-
edge of the following.

• Basic knowledge of DI and AOP of Spring Framework

• Web development experience using Servlet/JSP

• Knowledge of SQL

• Experience of building Web Application using Maven

This guideline is not for beginners.

In order to check whether the readers have basic knowledge of Spring Framework, refer to Spring Framework
Comprehension Check. It is recommended to study the following books if one is not able to answer 40% of the
comprehension test.

• Spring 徹底入門 (翔泳社) [Japanese]

• Spring3 入門―Java フレームワーク・より良い設計とアーキテクチャ(技術評論社)[Japanese]

• Pro Spring 4th Edition (Apress)

1.4 Structure of this document

•Architecture Overview Overview of Spring MVC and basic concepts of TERASOLUNA Server Frame-
work for Java (5.x) is explained.

•Application Development Knowledge and methods for application development using TERASOLUNA
Server Framework for Java (5.x) are explained.

•../ArchitectureInDetail/index Method to implement the functions required for general appli-


cation development using TERASOLUNA Server Framework for Java (5.x) or features of each func-
tion is explained.

•Security countermeasures Security measures are explained focusing on Spring Security.

1.2. This document covers the following 5


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

•Tutorials Experience in application development using TERASOLUNA Server Framework for Java (5.x)
through simple application development.

•Appendix(Know How) Describing the additional information when TERASOLUNA Server Framework
for Java (5.x) is being used.

1.5 Reading this document

Firstly read “Architecture Overview”.


Implement “First application based on Spring MVC” for beginners of Spring MVC.
Read “Application Layering” as the terminology and concepts used in this guideline are explained here.

Then continue with “Tutorials”.


Get a feel of application development using TERASOLUNA Global
Framework by firstly trying it as per the proverb “Practice makes perfect”.

Use this tutorial to study the details of application development in “Application Development”.
Since the knowhow for development is explained using Spring MVC in “Implementation of Application Layer”,
it is recommended to read it again and again several times.
One can get a better understanding by studying “Tutorials” once again after reading this chapter.

It is strongly recommended that all the developers who use TERASOLUNA Server Framework for Java
(5.x) read it.

Refer to “../ArchitectureInDetail/index” and “Security countermeasures“


as per the requirement. However, read “Input Validation” since it is normally required for application
development.

The technical leader understands all the contents and checks the type of policy to be decided in the project.

Note: If you do not have sufficient time, first go through the following.

1. First application based on Spring MVC

2. Application Layering

3. Tutorial (Todo Application)

4. Application Development

6 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

5. Tutorial (Todo Application)

6. Input Validation

1.6 Tested environments of this document

For tested environments of contents described in this guideline, refer to “Tested Environment”.

1.6. Tested environments of this document 7


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

1.7 Criteria based mapping of guideline

The chapter 4 of this guideline is structured functionality wise. This section shows a mapping from a point of
view other than functionality. It indicates which part of guideline contains which type of content.

1.7.1 Mapping based on security measures

Using OWASP Top 10 for 2013 as an axis, links to explanation of functionalities related to security have been
given

8 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Item Name Corresponding Guideline


A1 Injection SQL Injection
• Database Access (MyBatis3)
• Database Access (JPA)
(Details about using bind variable at the time of place-
holders for query parameters)
A1 Injection XXE(XML External Entity) Injec-
• Ajax
tion

A1 Injection OS Command Injection


• Input Validation

A1 Injection Email Header Injection


• Email header injection countermeasures

A1 Injection
• Input check validation for security
(Shows how to validate input values)
A2 Broken Authentication and Session Manage-
• Session Management
ment
• Authentication

A3 Cross-Site Scripting (XSS)


• XSS Countermeasures
• Coordinating with browser security countermea-
sure function

A4 Insecure Direct Object References Directory


• Directory traversal attack
Traversal

A5 Security Misconfiguration
• Logging(Mention about message contents of log)
• Method to display system exception code on
screen(Mention about message output at the time
of system exception)

A6 Sensitive Data Exposure


• Properties Management
• Encryption
• Password hashing

A7 Missing Function Level Access Control


• Authorization

A8 Cross-Site Request Forgery (CSRF)


• CSRF Countermeasures

A9 Using Components with Known Vulnerabili- No mention in particular


ties
A10 Unvalidated Redirects and Forwards No mention in particular
1.7. Criteria based mapping of guideline 9
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

1.8 Change Log

Modified on Modified locations Modification details


2016-08-31 - 5.2.0 RELEASE version published
• For details of update, refer Issue list of 5.2.0.

General Correction of errors in the guideline (typos or simple description


errors)
• For details of modifications, refer Issue list of 5.2.0 (clerical
error).
Description details modified
• For details of modification, refer Issue list of 5.2.0 (improve-
ment).
Review of all the chapters
• For details of update, refer Optimize the order of chapters and
sections #1683.
Update common library version to 5.2.0.
• For details of update, refer Check Version #2076.
Description details modified
• Added regarding pom dependency of common library (guide-
line#1982)

Stack of TERASOLUNA Description details added


Server Framework for Java • Embedding status of common library standards of blank
(5.x) project added (guideline#1700)
• mybatis-typehandlers-jsr310, jackson-datatype-jsr310 added
to OSS stack (guideline#1966)
• spring-jms and its dependent libraries added to OSS stack
(guideline#1992)
Version of OSS used (Spring IO Platform version) updated)
• Spring IO Platform version updated to 2.0.6.RELEASE
• Spring Framework version updated to 4.2.7.
• Spring Security version updated to 4.0.4.RELEASE
OSS version used in accordance with Spring IO Platform version
update is updated
Domain Layer Implementa- Description details added
tion • For MyBatis 3.3 + MyBatis-Spring 1.2, “value specified in
timeout attribute of @Transactinal is not used” is added
(guideline#1777)

Continued on Next page

10 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Implementation of Applica- Description details added
tion Layer • HttpSession should not be used as an argument for handler
method (guideline#1313)
• Precautions for using JSR-310 Date and Time API are de-
scribed (guideline#1991)

Input Validation Description details modified


• A method to directly handle a message property file without
conversion from Native to Ascii is added (guideline#994)
• Description for cross-field validation added (guideline#1561)
• @DateTimeFormat description added (guideline#1873)
• Description for ValidationMessages.properties modified
(guideline#1948)
• Precautions for input check which use Method Validation
added (guideline#1998)
Description details added
• Description for OS command injection added (guide-
line#1957)

Exception Handling Modification associated with Spring Framework 4.2.7


• Description details for HTTP response header output modi-
fied (guideline#1965)

Double Submit Protection Description details added


• Description for specifications and implementation methods
of TransactionTokenType.CHECK which was newly
added in type attribute of @TransactionTokenCheck
annotation (guideline#2071)
“How to manage transaction token life cycle in How To Extend pro-
grammatic” deleted.
• When API for application offered by
TransactionTokenContextis used, it impacts the
behaviour of internal framework like inability to maintain
TransactionToken in the appropriate state Current
API is deprecated. Description for how to use function in
accordance with deprecation, deleted.

Continued on Next page

1.8. Change Log 11


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Internationalization Description details modified
• Position of request parameter (default parameter name) de-
scription modified (guideline#1354)

File Upload Description details added


• CVE-2016-3092Precautions for (File Upload vulnerability)
added (guideline#1973)
• Description for directory traversal attack added (guide-
line#2010)

Health Check Added new


• Health check added (guideline#1698)

RESTful Web Service Description details changed / added


• Description for the configuration while using JSR-310 Date
and Time API / Joda Time changed (guideline#1966)
• Precautions while using Jackson in Java SE 7 environment
described (guideline#1966)
• Configuration while using JSR-310 Date and Time API in
JSON described (guideline#1966)

REST Client (HTTP Client) Description details modified


• HTTP Proxy server configuration for RestClient added
(guideline#1856)

SOAP Web Service Description details added


(Server/Client) • Added an option “Do not connect to SOAP server at the time
of SOAP client start (guideline#1871)
• Description for env project of SOAP client modified (guide-
line#1901)
• How to fetch status code at the time of SOAP Web service
exception occurrence added (guideline#2007)

Continued on Next page

12 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Database Access (My- Description details added
Batis3) • “How to avoid tentative WARN log output” deleted (guide-
line#1292)
• “How to configure for using JSR-310 Date and Time API in
Mybatis3.3” described (guideline#1966)
• Precautions while using MyBatis in Java SE 7 environment
described (guideline#1966)

Exclusive Control Description details added


• warning message added to ExclusionControl (guide-
line#1694)

Logging Description details added


• “How to extend in order to output log message with ID” de-
scribed (guideline#1928)

String Processing Description details added


• An example to add terasoluna-gfw-string to dependency is
added (guideline#1699)
• Precautions for surrogate pair added to description of @Size
annotation (guideline#1874)
• Description for JIS characters U+2014(EM DASH)
UCS(Unicode) characters added (guideline#1914)

Bean Mapping (Dozer) Description details added


• Precautions while using JSR-310 Date and Time API de-
scribed (guideline#1966)

JMS(Java Message Service) Added new


• JMS added (guideline#1407)

Authentication Modifications for Spring Security 4.0.4


• Code example modified to include modification of specifica-
tions of authentication-failure-url in Spring 4.0.4 and Note
deleted (guideline#1963)

Continued on Next page

1.8. Change Log 13


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Authorization Description details added
• How to handle CVE-2016-5007 Spring Security / MVC Path
Matching Inconsistencyadded (guideline#1976)

Implementation Example of Description details added


Typical Security Require- • “Input value check for security” added
ments • “Audit log output” added

Reference Books Description details added


• Spring thorough introduction” added as a a reference material
(guideline#2043)

2016-02-24 - 5.1.0 RELEASE version published


• For details of change contents, refer 5.1.0 Issue List.

General Correction of errors in the guideline (typo mistakes and simple de-
scription errors)
Description details modified
• For details of modification, refer 5.1.0 Issue list (improve-
ment).

In the Beginning Description details added


• Description related to operation verification environment of
the details described in the guideline added

Continued on Next page

14 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Stack of TERASOLUNA OSS version to be used (Spring IO Platform version) updated
Server Framework for Java • Spring IO Platform version updated in 2.0.1.RELEASE
(5.x) • Spring Framework version updated in 4.2.4.RELEASE
• Spring Security version updated in 4.0.3.RELEASE
OSS version to be used along with Spring IO Platform version up-
date is updated
• OSS version to be used updated. For update details, refer
version 5.1.0 migration guide.
New project added
• Descriptions for terasoluna-gfw-string,
terasoluna-gfw-codepoints,
terasoluna-gfw-validator,
terasoluna-gfw-web-jsp projects added.
New function of common library added
terasoluna-gfw-string
• Half width to full width conversion
terasoluna-gfw-codepoints
• Codepoint check
• Bean Validation constraint annotation for code point
check
terasoluna-gfw-validator
• Bean Validation constraint annotation for byte length
check
• Bean Validation constraint annotation for field value
comparison correlation check

First application based on Description details modified


Spring MVC • Modification of sample source corresponding to Spring Secu-
rity 4 (guideline#1519)
• AuthenticationPrincipalArgumentResolver
package changed

Continued on Next page

1.8. Change Log 15


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Tutorial (Todo Application) Modifications corresponding to Spring Security 4
• Modification of source corresponding to Spring Security 4
(guideline#1519)
• AuthenticationPrincipalArgumentResolver
package changed
• Since the specification is true by default,
<use-expressions="true"> deleted from sam-
ple source

Create Web application de- Modification of description details


velopment project • A method wherein mvn command is used in the offline envi-
ronment is added (guideline#1197)

Implementation of Applica- Description details modified


tion Layer • A method to create a request URL using EL function is added
(guideline#632)

Database Access (Common) Description details added


• Precautions for Log4jdbcProxyDataSource overhead
added (guideline#1471)

Database Access (My- Description details corresponding to MyBatis 3.3 added


Batis3) • Setup method of defaultFetchSize added (guide-
line#965)
• “Changed the default at the time of delayed reading to
JAVASSIST” added (guideline#1384)
• Sample code which assigns Genrics to ResultHandler
modified (guideline#1384)
• Source example which use newly added @Flush annotation,
and precautions added (guideline#915)

Continued on Next page

16 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Database Access (JPA) Bug correction for the guideline
• Utility which use Like condition modified appropriately
(guideline#1464)
• Incorrect implementation of true value in JPQL corrected
(guideline#1525)
• Incorrect implementation of pagination corrected (guide-
line#1463)
• Incorrect implementation of sample code corrected which im-
plements DateTimeProvider (guideline#1327)
• Incorrect implementation in Factory class for generating an
instance of implementation class for common Repository in-
terface corrected (guideline#1327)
Description details modified
• Default value of hibernate.hbm2ddl.auto corrected
(guideline#1282)

Input Validation Description details modified


• Description for MethodValidation added (guideline#708)

Logging Description details modified


• Description where ServiceLoader mechanism is used in
Logback setting, is added (guideline#1275)
• Sample source corresponding to Spring Security 4 modified
(guideline#1519)
• Since the specification is true by default,
<use-expressions="true"> deleted from the
sample source

Session Management Description details modified


• Description of session scope reference which use SpEL ex-
pression is added (guideline#1306)

Internationalization Description details modified


• Description for appropriately reflecting locale in JSP is added
(guideline#1439)
• Description of defaultLocale of
SessionLocalResolver corrected (guideline#686)

Continued on Next page

1.8. Change Log 17


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
File Upload Description details added
• Description for directory traversal attack added (guide-
line#2010)

Codelist Description details added


• Description which recommends a pattern wherein
JdbcTemplate is specified in JdbcCodeList, is added
(guideline#501)

RESTful Web Service Description details modified


• Creation of ObjectMapper which use
Jackson2ObjectMapperFactoryBean added (guide-
line#1022)
• Modified to a format where MyBatis3 is used as a prereq-
uisite in the implementation of domain layer of REST API
application (guideline#1323)

REST Client (HTTP Client) Added new


• REST client (HTTP client) added (guideline#1307)

SOAP Web Service Added new


(Server/Client) • SOAP Web Service (Server / Client) added (guideline#1340)

File Upload Description details modified


• Basic flow of uploading process and its description modi-
fied to description which use MultipartFilter of Spring
(guideline#193)
• “A method which sends CSRF token by query parameter”
deleted due to issues like security issues, variation in the op-
eration according to AP server etc. Precaution - “when al-
lowable size for file upload exceeds, CSRF token check is not
carried out appropriately in some AP servers” added (guide-
line#1602)

Continued on Next page

18 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
File Download Description details corresponding to Spring Framework4.2 added
• AbstractXlsxView which manages xlsx format, is added
(guideline#996)
Description details modified
• Source example which use
com.lowagie:itext:4.2.1 modified to a format
which uses com.lowagie:itext:2.1.7 for the
specification change of the iText

Sending E-mail (SMTP) Added new


• E-mail sending (SMTP) added (guideline#1165)

Date operations (JSR-310 Added new


Date and Time API) • Date and time operation (JSR-310 Date and Time API) added
(guideline#1450)

Date Operations (Joda Description details added and modified


Time) • The object of sample code which handles the date that does
not use Timezone modified to LocalDate (guideline#1283)
• A method to handle Japanese calendar in Java8 and earlier
versions is added (guideline#1450)

Logging Description details added


• Extension method to output log message with ID is described
(guideline#1928)

String Processing Added new


• String processing added (guideline#1451)

JMS(Java Message Service) Added new


• JMS added (guideline#1407)

Security countermeasures Configuration review


• Password hashingmoved in Authentication
• Session management items are separated as Session Manage-
ment from Authentication

Continued on Next page

1.8. Change Log 19


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Spring Security Overview Modify corresponding to Spring Security 4
• Restructuring overall description
• spring-security-test introduction
• Since the specification is true by default,
<use-expressions="true"> deleted from sam-
ple source
• Description related to RedirectAuthenticationHandlerdeprec
deleted

Spring Security Tutorial Modified corresponding to Spring Security 4


• Modified tutorial source to a format corresponding to Spring
Security 4 (guideline#1519)

Authentication Modified corresponding to Spring Security 4 (guideline#1519)


• Restructuring of overall description
• Deleted auto-config="true"
• Authentication event listener modified to
@org.springframework.context.event.EventListener
• Modified AuthenticationPrincipal package
• Since prefix is assigned by default, ROLE_ prefix deleted
from sample source

Authorization Modified corresponding to Spring Security 4 (guideline#1519)


• Restructuring of overall description
• Since the prefix is assigned by default, ROLE_ prefix deleted
from sample source
• Since the specification is true by default,
<use-expressions="true"> deleted from sam-
ple source
• Definition example of @PreAuthorize added

Continued on Next page

20 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
CSRF Countermeasures Modified corresponding to Spring Security 4
• Restructuring of overall description
• CSRF invalidation settings modified <sec:csrf
disabled="true"/>
• Description details modified
• Items related to multi-part request moved to File Upload
(guideline#1602)

Encryption Added new


• Encryption guidelines added (guideline#1106)

Implementation Example of Added new


Typical Security Require- • Typical implementation example of security requirements
ments added (guideline#1604)

Session tutorial Added new


• Session tutorial added (guideline#1599)

Tutorial (Todo Application Modified corresponding to Spring Security 4


REST) • Modified source corresponding to Spring Security 4 (guide-
line#1519)
• CSRF invalidation settings modified <sec:csrf
disabled="true"/>
• Since the specification is true by default,
<use-expressions="true"> deleted from sam-
ple source

2015-08-05 - Released “5.0.1 RELEASE” version


• For update details, refer to Issue list of 5.0.1

Continued on Next page

1.8. Change Log 21


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Overall modifications Fixed guideline errors (corrected typos, mistakes in description, etc.)
• For modification details, refer to Issue list of 5.0.1 (clerical
error)
Improved the description
• For improvement details, Issue list of 5.0.1 (improvement)
Fixed the description about application server
• Removed the description for the Resin
• Updated the link of reference page

In the Beginning Added the description


• Added description about tested environments for contents de-
scribed in this guideline

Stack of TERASOLUNA Updated the OSS version(Spring IO Platform version) to protect se-
Server Framework for Java curity vulnerability
(5.x) • Spring IO Platform version updated to 1.1.3.RELEASE
• Spring Framework version updated to 4.1.7.RELEASE
(CVE-2015-3192)
• JSTL version updated to 1.2.5 (CVE-2015-0254)
Updated the OSS version by the Spring IO Platform version update
• Updated the OSS version to be used. For update details, refer
to Migration guide of version 5.0.1
Improved the description (guideline#1148)
• Added the description of
terasoluna-gfw-recommended-dependencies,terasolun
and terasoluna-gfw-parent
• Modified the description for some project
• Added the illustration to indicate project dependencies

Create Web application de- Added the description


velopment project • Added how to build a war file (guideline#1146)

Database Access (Common) Added the description


• Added the description of DataSource switching function-
ality (guideline#1071)

Continued on Next page

22 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Database Access (My- Fixed the guideline bug
Batis3) • Modified the description about timing of batch execution
(guideline#903)

Logging Improved the description


• Added the description about additivity attribute of
<logger> tag (guideline#977)

Session Management Improved the description


• Modified the description about how to define a session scope
bean (guideline#1082)

Double Submit Protection Added the description


• Added the description about the transaction token check in
case that response cache is disabled (guideline#1260)

Codelist Added the description


• Added how to display a code name (guideline#1109)

Added the warning about CVE-2015-3192(XML security vulnera-


Ajax bility)
RESTful Web Service • Added the warning at the time of the StAX(Streaming API
for XML) use (guideline#1211)

Modified in accordance with bug fixes of common library


Pagination • Modified the description about f:query specification , in
JSP Tag Libraries and EL accordance with bug fixes of common library (terasoluna-
Functions offered by gfw#297) (guideline#1244)
common library

Continued on Next page

1.8. Change Log 23


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Authentication Improved the description
• Added the notes about handling with
some properties of parent class of
ExceptionMappingAuthenticationFailureHandler
(guideline#812)
• Modified the setting example for the
requiresAuthenticationRequestMatcher prop-
erty of AbstractAuthenticationProcessingFilter
(guideline#1110)

Authorization Fixed the guideline bug


• Modified the setting example for the access attribute of
<sec:authorize> tag (JSP tag library) (guideline#1003)

Elimination of environmen- Added the description


tal dependency • Added how to apply the external classpath(alternative func-
tionality of VirtualWebappLoader of Tomcat7) at the
time of Tomcat8 use (guideline#1081)

2015-06-12 Overall modifications Released English version of “5.0.0 RELEASE”


2015-03-06 RESTful Web Service Guideline bug modification
• Modification of sample code for exception han-
dling (the code that contains the issue of generating
NullPointerException). For improvement details,
refer to guideline#918.

Tutorial (Todo Application Guideline bug modification


REST) • Fixed a problem that generates ‘‘ NullPointerException‘‘ in
the processing of exception handling. For improvement de-
tails, refer to guideline#918.

2015-02-23 - Released “5.0.0 RELEASE” version


• For update details, refer to Issue list of 5.0.0 and Backport
issue list of 1.0.2.

Continued on Next page

24 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Overall modifications Fixed guideline errors (corrected typos, mistakes in description, etc.)
• For modification details, refer to Backport issue list of 1.0.2
(clerical error).
Improved the description
• For improvement details, refer to Issue list of 5.0.0 (improve-
ment) and Backport issue list of 1.0.2 (improvement).
Added new
• Create Web application development project
• Database Access (MyBatis3)
• JSP Tag Libraries and EL Functions offered by common li-
brary
• Reducing Boilerplate Code (Lombok)
Updated in accordance with version 5.0.0
• Deleted MyBatis2

Stack of TERASOLUNA Spring IO Platform compatible


Server Framework for Java • Added a point that except for some libraries, the management
(5.x) of recommended libraries is changed to a structure delegating
it to Spring IO Platform.
Updated the OSS version
• Updated the OSS version to be used. For update details, refer
to Migration guide of version 5.0.0.

First application based on Updated in accordance with version 5.0.0


Spring MVC • Used Spring Framework 4.1
• Reviewed structure of document.

Application Layering Fixed bugs in English translation.


• Fixed translation bugs related to domain layer and other lay-
ers. For modification details, refer to guideline#364 issue.

Tutorial (Todo Application) Updated in accordance with version 5.0.0


• Use of Spring Framework 4.1.
• MyBatis3 support as infrastructure layer.
• Revised document structure.

Continued on Next page

1.8. Change Log 25


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Create Web application de- Added new
velopment project • Added a method to create a project having multi project struc-
ture

Domain Layer Implementa- Modified in accordance with Spring Framework 4.1


tion • Added description about handling @Transactional of
JTA 1.2. For modification details, refer to guideline#562 is-
sue.
• Modified description about handling
@Transactional(readOnly = true) when us-
ing JPA (Hibernate implementation). With SPR-8959
(Spring Framework 4.1 and later versions) support, it has
been improved so that instruction can be given so as to
handle as “Read-only transactions” for JDBC driver.
Added description
• Added notes regarding the cases where “Read-only transac-
tions” are not enabled. For added contents, refer to guide-
line#861 issue.

Implementation of Infras- Modified in accordance with MyBatis3


tructure Layer • Added a method to use MyBatis3 mechanism as implementa-
tion of RepositoryImpl.

Implementation of Applica- Modified in accordance with Spring Framework 4.1


tion Layer • Added description about the attribute (attribute to filter the
Controllers to be used) added in @ControllerAdvice.
For modification details, refer to guideline#549 issue.
• Added description about <mvc:view-resolvers>. For
modification details, refer to guideline#609 issue.

Continued on Next page

26 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Database Access (Common) Modified in accordance with bug fixes of common library
• Added description about handling double byte wild card char-
acters (%, _), in accordance with bug fixes of common li-
brary (terasoluna-gfw#78). For modification details, refer to
guideline#712 issue.
Modified in accordance with Spring Framework 4.1
• Removed the description about the problem
where pessimistic locking error of JPA (Hi-
bernate implementation) is not converted into
PessimisticLockingFailureException of
Spring Framework. This problem is resolved in SPR-10815
(Spring Framework 4.0 and later versions).
Modified in accordance with Apache Commons DBCP 2.0
• Changed the sample code and its description to use compo-
nent for Apache Commons DBCP 2.0.

Database Access (My- Added new


Batis3) • Added method to implement an infrastructure layer using
MyBatis3 as O/R Mapper.

Exclusive Control Fixed guideline bugs


• Modified the sample code of optimistic locking of long trans-
actions (processing when records cannot be fetched). For
modification details, refer to guideline#450 issue.
Modified in accordance with Spring Framework 4.1
• Removed the description about the problem
where pessimistic locking error of JPA (Hi-
bernate implementation) is not converted into
PessimisticLockingFailureException of
Spring Framework. This problem is resolved in SPR-10815
(Spring Framework 4.0 and later versions).
Modified in accordance with MyBatis3
• Added methods to implement exclusive control when using
MyBatis3.

Continued on Next page

1.8. Change Log 27


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Input Validation Fixed guideline bugs
• Modified the description of @GroupSequence. For modi-
fication details, refer to guideline#296 issue.
Modified in accordance with bug fixes of common library
• Added notes about ValidationMessages.properties,
in accordance with bug fixes of common library (terasoluna-
gfw#256). For modification details, refer to guideline#766
issue.
Added description
• Added a method to link with the mechanism of Group Vali-
dation of Bean Validation at the time of correlated item check
using Spring Validator. For added contents, refer to guide-
line#320 issue.
Modified in accordance with Bean Validation 1.1 (Hibernate Valida-
tor 5.1)
• Added description about inclusive attribute of
@DecimalMin and @DecimalMax.
• Added description about Expression Language.
• Described about deprecated API from Bean Validation 1.1.
• Added description about a bug related to
ValidationMessages.properties of Hibernate
Validator 5.1.x (HV-881) and methods to prevent the same.

Exception Handling Added description


• Added a description that simple error page is likely to be dis-
played in Internet Explorer when an error having size lesser
than 513 bytes is sent as response. For added contents, refer
to guideline#189 issue.
Modified in accordance with Spring Framework 4.1
• Removed the description about the problem
where pessimistic locking error of JPA (Hi-
bernate implementation) is not converted into
PessimisticLockingFailureException of
Spring Framework. This problem is resolved in SPR-10815
(Spring Framework 4.0 and later versions).

Continued on Next page

28 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Session Management Modified in accordance with Spring Security 3.2
• Removed the description about a problem where CSRF token
error occurs (SEC-2422 ) instead of session time out at the
time of POST request. A mechanism to detect session time
out is included in formal version of Spring Security 3.2, hence
the problem is resolved.

Message Management Reflected changes of common library


• Added description about newly added message type (warn-
ing) and deprecated messages types (warn), in accor-
dance with the improvement of common library (terasoluna-
gfw#24). For modification details, refer to guideline#74 is-
sue.

Pagination Reflected changes of common library


• Changed description of page link in active state, in accor-
dance with the improvement of common library (terasoluna-
gfw#13). For modification details, refer to guideline#699 is-
sue.
• Changed description of page link in disabled state, in accor-
dance with the improvement of common library (terasoluna-
gfw#14). For modification details, refer to guideline#700 is-
sue.
Modified in accordance with Spring Data Common 1.9
• Added notes for the classes where API specifications (Page
interface, etc.) are changed due to version upgrade.

Continued on Next page

1.8. Change Log 29


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Codelist Modified in accordance with bug fixes of common library
• Added notes about version upgrade and changing message
key of ExistInCodeList in accordance with bug fixes of
common library (terasoluna-gfw#16). For modification de-
tails, refer to guideline#638 issue.
• Added notes about message definition of
@ExistInCodeList in accordance with bug fixes of
common library (terasoluna-gfw#256). For modification
details, refer to guideline#766 issue.
Reflected changes of common library
• Added a method to use EnumCodeList class in accor-
dance with addition of common library functions (terasoluna-
gfw#25).

Ajax Modified in accordance with Spring Security 3.2


• Changed the sample code for CSRF measures (method to cre-
ate <meta> tag for CSRF measures).
Modified in accordance with Jackson 2.4
• Changed the sample code and description to use components
for Jackson 2.4.

RESTful Web Service Improvement in description


• Improve the method to build an URL to be set in location
header and hypermedia link. For improvement details, refer
to guideline#374 issue.
Modified in accordance with Spring Framework 4.1
• Added a description about @RestController. For modi-
fication details, refer to guideline#560 issue.
• Changed the sample code to create ResponseEntity us-
ing builder style API.
Modified in accordance with Jackson 2.4
• Changed the sample code and description to use components
for Jackson 2.4.
Modified in accordance with Spring Data Common 1.9
• Added notes for the classes where API specifications (Page
interface, etc.) are changed due to version upgrade.

Continued on Next page

30 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
File Upload Fixed guideline bugs
• Modified version of Apache Commons FileUpload with re-
solved CVE-2014-0050 (File Upload vulnerabilities). For
modification details, refer to guideline#846 issue.
Added description
• File upload function of Servlet 3 has a problem of garbled
characters on a part of application server. Therefore, added a
method to use Apache Commons FileUpload as a measure to
prevent this event. For added contents, refer to guideline#778
issue.

System Date Reflected changes of common library


• Changed document structure, package name and class name
in accordance with the improvement of common library
(terasoluna-gfw#224). For modification details, refer to
guideline#701 issue.

Screen Layout using Tiles Modified in accordance with Tiles 3.0


• Changed the example of settings and description to use com-
ponent for Tiles 3.0.
Modified in accordance with Spring Framework 4.1
• Added description about <mvc:view-resolvers>,
<mvc:tiles>, <mvc:definitions>. For modifica-
tion details, refer to guideline#609 issue.

Date Operations (Joda Added description


Time) • Added method to use LocalDateTime. For added con-
tents, refer to guideline#584 issue.
Modified in accordance with Joda Time 2.5
• Since DateMidnight class is deprecated in accordance
with version upgrade, changed the method to fetch start time
of specific date (0:00:00.000).

Spring Security Overview Modified in accordance with Spring Security 3.2


• Added “Settings to create secure HTTP header” in appendix.

Continued on Next page

1.8. Change Log 31


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Spring Security Tutorial Updated in accordance with version 5.0.0
• Made changes so as to use MyBatis3 as infrastructure layer.
• Applied Spring Framework 4.1
• Applied Spring Security 3.2
• Revised document structure.

Authentication Fixed guideline bugs


• Modified the erroneous and inadequate de-
scription of <form-login>, <logout>,
<session-management> tag. For modification de-
tails, refer to guideline#754 issue.
• Modified the sample code that indicates extension method of
AuthenticationFilter (added settings to validate CSRF mea-
sures and session fixation attack measures). For details, refer
to guideline#765 issue.
Modified in accordance with Spring Security 3.2
• Added notes about logout method when CSRF measures are
validated.
• Added description of @AuthenticationPrincipal, as
a method to access UserDetails (authentication user in-
formation class) from Controller.
• Added description of changeSessionId, as parame-
ters of session-fixation-protection attribute of
<sec:session-management>.
• Added methods to detect session time-out and notes for same.
• Changed setting method to validate concurrent session
control of identical users (made changes so as to use
<sec:concurrency-control>).
• Added a point that a class of concurrent session control of
identical users is deprecated and other class is provided.

Continued on Next page

32 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
CSRF Countermeasures Modified in accordance with Spring Security 3.2
• Removed description about the component for CSRF mea-
sures of Spring Security 3.2.0 (provisional version before for-
mal release) included in common library of version 1.0.x.
• Changed setting method to validate CSRF measures by
a proper method of Spring Security 3.2 (method using
<sec:csrf>).
• Added description about JSP tag library
(<sec:csrfInput> and <sec:csrfMetaTags>)
for CSRF measures.
• Added methods to detect session time-out and precautions
when CSRF measures are validated.
Modified in accordance with Spring Framework 4.1
• Changed description about the condition where CSRF token
is output as hidden, when <form:form> is used.

Tutorial (Todo Application Improved the description


REST) • Changed to the contents that do not depend on specific in-
frastructure layer (O/R Mapper), by adding REST API in the
project created in Tutorial (Todo Application). For modifica-
tion details, refer to guideline#325 issue.
Updated in accordance with version 5.0.0
• Applied Spring Framework 4.1.
• Applied Spring Security 3.2.
• Applied Jackson 2.4.

Create a new project from a Improved the description


blank project • Supported method to create a project having multi project
structure.
• Updated the method to create a project having single project
structure.

JSP Tag Libraries and EL Added new


Functions offered by com- • Added description about EL functions and JSP tag libraries
mon library provided by common libraries.

Continued on Next page

1.8. Change Log 33


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Reducing Boilerplate Code Added new
(Lombok) • Added description about how to remove a boilerplate code
where Lombok is used.

English version Added English version of the following.


• Create Web application development project
• Database Access (Common)
• Database Access (JPA)
• Database Access (MyBatis3)
• Exclusive Control
• Logging
• Properties Management
• Pagination
• Double Submit Protection
• Internationalization
• Codelist
• Ajax
• RESTful Web Service
• File Upload
• File Download
• Screen Layout using Tiles
• System Date
• Bean Mapping (Dozer)
• Spring Security Overview
• Authentication
• Authorization
• CSRF Countermeasures
• Create a new project from a blank project
• Maven Repository Management using NEXUS
• Elimination of environmental dependency
• Project Structure Standard
• Reducing Boilerplate Code (Lombok)
• Spring Framework Comprehension Check

2014-08-27 - Released “1.0.1 RELEASE” version


Refer to Issue list of 1.0.1 for details.
Overall modifications Fixed guideline bugs (corrected typos, mistakes in description etc.)
Refer to Issue list of 1.0.1 (bug & clerical error) for details.
Continued on Next page

34 1 In the Beginning
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Japanese version Added Japanese version of the following.
• Criteria based mapping of guideline
• RESTful Web Service
• Tutorial (Todo Application REST)

English version Added English version of the following.


• In the Beginning
• Architecture Overview
• Tutorial (Todo Application)
• Application Development
• Input Validation
• Exception Handling
• Message Management
• Date Operations (Joda Time)
• XSS Countermeasures
• Reference Books

Stack of TERASOLUNA Updated the OSS version in accordance with bug fixes.
Server Framework for Java • GroupId (org.springframework ) updated to
(5.x) 3.2.10.RELEASE from 3.2.4.RELEASE
• GroupId (org.springframework.data )/Artifac-
tId(spring-data-commons ) updated to 1.6.4.RE-
LEASE from 1.6.1.RELEASE
• GroupId (org.springframework.data )/Artifac-
tId(spring-data-jpa ) updated to 1.4.3.RELEASE from
1.4.1.RELEASE
• GroupId (org.aspectj ) updated to 1.7.4 from 1.7.3
• Deleted GroupId (javax.transaction )/ArtifactId(jta
)

Implementation of Applica- Added a warning about CVE-2014-1904 (XSS Vulnerability of


tion Layer action attribute in <form:form> tag)
Japanese version Added description about bug fix
Message Management • Fixed bugs of <t:messagesPanel> tag of common li-
brary (terasoluna-gfw#10)

Continued on Next page

1.8. Change Log 35


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 1.1 – continued from previous page


Modified on Modified locations Modification details
Japanese version Updated description about bug fix
Pagination • Fixed bugs of <t:pagination> tag of common library
(terasoluna-gfw#12 )
• Fixed bugs of Spring Data Commons (terasoluna-gfw#22 )

Japanese version Updated description of countermeasures against XXE Injection


Ajax
Japanese version Added a warning about CVE-2014-0050 (File Upload Vulnerability)
File Upload Fixed guideline bugs.
• Added how to handle MultipartException using
error-page functionality of servlet container, because
your application can’t handle MultipartException
using SystemExceptionResolver when used
MultipartFilter. Refer to Issue of guideline#59
for details.

Japanese version Change how to create following projects to be carried out from mvn
archetype:generate
• First application based on Spring MVC
• Tutorial (Todo Application)
• Tutorial (Todo Application)

Japanese version Minor modifications in how to create following Maven archetype


• Spring Security Tutorial
• Create a new project from a blank project

2013-12-17 Japanese version Released “1.0.0 Public Review” version

36 1 In the Beginning
37

Architecture Overview

The architecture adopted in this guideline is explained here.

2.1 Stack of TERASOLUNA Server Framework for Java (5.x)

2.1.1 Summary of Software Framework of TERASOLUNA Server Framework for


Java (5.x)

Software Framework being used in TERASOLUNA Server Framework for Java (5.x) is not a proprietary Frame-
work but a combination of various OSS technologies around Spring Framework.

2.1.2 Main Structural Elements of Software Framework

Libraries which constitute TERASOLUNA Server Framework for Java (5.x) are as follows:

DI Container

Spring Framework is used as DI Container.


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Spring Framework 4.2

MVC Framework

Spring MVC is used as Web MVC Framework.

• Spring MVC 4.2

O/R Mapper

This guideline assumes the use of any one of the below.

• MyBatis 3.3

– MyBatis-Spring is used as library for coordinating with Spring Framework.

• JPA2.1

– Hibernate 4.3 is used as provider.

Note: To be precise MyBatis is a “SQL Mapper”, but it is classified as “O/R Mapper” in this guidelines.

Warning: Every project must not adopt JPA. For situations in which table design has been done and “Most
of the tables are not normalized”, “The number of columns in the table is too large” etc, use of JPA is difficult.
Furthermore, this guideline does not explain the basic usage of JPA. Hence, it is pre-requisite to have JPA
experience people in the team.

38 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

View

JSP is used as View.

Use the following to standardize the view layout.

• Apache Tiles 3.0

Security

Spring Security is used as the framework for Authentication and Authorization.

• Spring Security 4.0

Tip: In addition to providing a mechanism of authentication and authorization in Spring Security 3.2, the mech-
anism has been enhanced to protect a Web application from malicious attackers.

For mechanism to protect Web applications from malicious attackers, Refer,

• CSRF Countermeasures

• Coordinating with browser security countermeasure function

Validation

• For Single item input check, BeanValidation 1.1 is used.

– For implementation, Hibernate Validator 5.2 is used.

• For correlated items check, BeanValidation or Spring Validation is used.

– Refer to Input Validation for determining the proper use.

Logging

• The SLF4J API is used for Logger.

– The Logback API is used for implementation of Logger.

Common Library

• https://github.com/terasolunaorg/terasoluna-gfw

• Refer to Building blocks of Common Library for details.

2.1. Stack of TERASOLUNA Server Framework for Java (5.x) 39


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

2.1.3 OSS Versions

List of OSS being used in version 5.2.0.RELEASE.

Tip: From version 5.0.0.RELEASE onwards, adopted the mechanism of importing


<dependencyManagement> of Spring IO platform.

By importing the <dependencyManagement> of Spring IO platform,

• Spring Framework offering library

• Spring Framework dependent OSS library

• Spring Framework compatible OSS library

dependencies resolved and OSS version to be used in the TERASOLUNA Server Framework for Java (5.x) is
following the rule of Spring IO platform definition.

Furthermore, Spring IO platform version is 2.0.6.RELEASE specified in version 5.2.0.RELEASE.

Type GroupId ArtifactId Version Spring Remarks


IO
plat-
form
Spring org.springframework spring-aop 4.2.7.RELEASE *
Spring org.springframework spring-aspects 4.2.7.RELEASE *
Spring org.springframework spring-beans 4.2.7.RELEASE *
Spring org.springframework spring-context 4.2.7.RELEASE *
Spring org.springframework spring-context-support 4.2.7.RELEASE *
Spring org.springframework spring-core 4.2.7.RELEASE *
Spring org.springframework spring-expression 4.2.7.RELEASE *
Spring org.springframework spring-jdbc 4.2.7.RELEASE *
Spring org.springframework spring-orm 4.2.7.RELEASE *
Spring org.springframework spring-tx 4.2.7.RELEASE *
Spring org.springframework spring-web 4.2.7.RELEASE *
Spring org.springframework spring-webmvc 4.2.7.RELEASE *
Spring org.springframework spring-jms 4.2.7.RELEASE *
Spring org.springframework spring-messaging 4.2.7.RELEASE *
Spring org.springframework.data spring-data-commons 1.11.4.RELEASE *
Spring org.springframework.security spring-security-acl 4.0.4.RELEASE *
Spring org.springframework.security spring-security-config 4.0.4.RELEASE *
Spring org.springframework.security spring-security-core 4.0.4.RELEASE *
Continued on Next page

40 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 2.1 – continued from previous page


Type GroupId ArtifactId Version Spring Remarks
IO
plat-
form
Spring org.springframework.security spring-security-taglibs 4.0.4.RELEASE *
Spring org.springframework.security spring-security-web 4.0.4.RELEASE *
MyBatis3 org.mybatis mybatis 3.3.1 *1
MyBatis3 org.mybatis mybatis-spring 1.2.5 *1
MyBatis3 org.mybatis mybatis-typehandlers- 1.0.1 *1*6
jsr310
JPA(Hibernate) antlr antlr 2.7.7 * *2
JPA(Hibernate) dom4j dom4j 1.6.1 * *2
JPA(Hibernate) org.hibernate hibernate-core 4.3.11.Final * *2
JPA(Hibernate) org.hibernate hibernate-entitymanager 4.3.11.Final * *2
JPA(Hibernate) org.hibernate.common hibernate-commons- 4.0.5.Final * *2 *4
annotations
JPA(Hibernate) org.hibernate.javax.persistence hibernate-jpa-2.1-api 1.0.0.Final * *2 *4
JPA(Hibernate) org.javassist javassist 3.18.1-GA * *2
JPA(Hibernate) org.jboss jandex 1.1.0.Final * *2 *4
JPA(Hibernate) org.jboss.logging jboss-logging-annotations 1.2.0.Final * *2 *4 *5
JPA(Hibernate) org.jboss.spec.javax.transaction jboss-transaction- 1.0.0.Final * *2 *4
api_1.2_spec
JPA(Hibernate) org.springframework.data spring-data-jpa 1.9.4.RELEASE * *2
DI javax.inject javax.inject 1 *
AOP aopalliance aopalliance 1 *
AOP org.aspectj aspectjrt 1.8.9 *
AOP org.aspectj aspectjweaver 1.8.9 *
Log output ch.qos.logback logback-classic 1.1.7 *
Log output ch.qos.logback logback-core 1.1.7 * *4
Log output org.lazyluke log4jdbc-remix 0.2.7
Log output org.slf4j jcl-over-slf4j 1.7.21 *
Log output org.slf4j slf4j-api 1.7.21 *
JSON com.fasterxml.jackson.core jackson-annotations 2.6.7 *
JSON com.fasterxml.jackson.core jackson-core 2.6.7 *
JSON com.fasterxml.jackson.core jackson-databind 2.6.7 *
JSON com.fasterxml.jackson.datatype jackson-datatype-joda 2.6.7 *
JSON com.fasterxml.jackson.datatype jackson-datatype-jsr310 2.6.7 * *6
Input check javax.validation validation-api 1.1.0.Final *
Continued on Next page

2.1. Stack of TERASOLUNA Server Framework for Java (5.x) 41


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table. 2.1 – continued from previous page


Type GroupId ArtifactId Version Spring Remarks
IO
plat-
form
Input check org.hibernate hibernate-validator 5.2.4.Final *
Input check org.jboss.logging jboss-logging 3.3.0.Final * *4
Input check com.fasterxml classmate 1.1.0 * *4
Bean conversion commons-beanutils commons-beanutils 1.9.2 * *3
Bean conversion net.sf.dozer dozer 5.5.1 *3
Bean conversion net.sf.dozer dozer-spring 5.5.1 *3
Bean conversion org.apache.commons commons-lang3 3.3.2 * *3
Date operation joda-time joda-time 2.8.2 *
Date operation joda-time joda-time-jsptags 1.1.1 *3
Date operation org.jadira.usertype usertype.core 3.2.0.GA *2
Date operation org.jadira.usertype usertype.spi 3.2.0.GA *2
Connection pool org.apache.commons commons-dbcp2 2.1.1 * *3
Connection pool org.apache.commons commons-pool2 2.4.2 * *3
Tiles commons-digester commons-digester 2.1 * *3
Tiles org.apache.tiles tiles-api 3.0.5 * *3
Tiles org.apache.tiles tiles-core 3.0.5 * *3
Tiles org.apache.tiles tiles-jsp 3.0.5 * *3
Tiles org.apache.tiles tiles-servlet 3.0.5 * *3
Tiles org.apache.tiles tiles-template 3.0.5 * *3 *4
Tiles org.apache.tiles tiles-autotag-core-runtime 1.1.0 * *3 *4
Tiles org.apache.tiles tiles-request-servlet 1.0.6 * *3 *4
Tiles org.apache.tiles tiles-request-api 1.0.6 * *3
Tiles org.apache.tiles tiles-request-jsp 1.0.6 * *3 *4
Utility com.google.guava guava 17.0 *
Utility commons-collections commons-collections 3.2.2 * *3
Utility commons-io commons-io 2.4 * *3
Servlet org.apache.taglibs taglibs-standard-jstlel 1.2.5 *
Servlet org.apache.taglibs taglibs-standard-spec 1.2.5 * *4
Servlet org.apache.taglibs taglibs-standard-impl 1.2.5 * *4

1. Dependent libraries, when MyBatis3 is used for data access.

2. Dependent libraries, when JPA is used for data access.

3. Libraries which are not dependent on Common Library, but recommended in case of application
development using TERASOLUNA Server Framework for Java (5.x).

4. Libraries that are supported by Spring IO platform, but library that relies individually.

42 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

(Library is not managed as dependencies in Spring IO platform)

5. Library versions that are applied in the Spring IO platform is a Beta or RC (Release Candidate)
(Library that explicitly specify the GA version at TERASOLUNA Server Framework for Java (5.x))

6. A library which considers API of Java SE 8 and further versions,as a prerequisite.


Dependency relation to the library must be explicitly removed in case of versions earlier than Java SE 7

2.1.4 Building blocks of Common Library

Common Library includes + alpha functionalities which are not available in Spring Ecosystem or other depen-
dent libraries included in TERASOLUNA Server Framework for Java (5.x). Basically, application development
is possible using TERASOLUNA Server Framework for Java (5.x) without this library but “convenient to have”
kind of existence. With the default settings, provided two blank projects, Blank project of multi-project and Blank
project of single-project, contains built-in Common Library as shown in the following listing.

2.1. Stack of TERASOLUNA Server Framework for Java (5.x) 43


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

No. Project Name Summary Java source-code Blank Blank


availability project project
of multi- of single-
project project
built-in built-in
(1) terasoluna-gfw- Provide recommended settings for dependent No Yes*1 Yes*1
parent library management and build plug-in.
(2) terasoluna- Define structure of the project which includes No Yes*1 Yes*1
gfw-common- Java source code, among the common li-
libraries braries. It is not necessary to add to pom.xml
as a dependency.
(3) terasoluna-gfw- Define structure of the project which pro- No L*1 L*1
dependencies vides only dependency definition (other than
terasoluna-gfw-parent), among the common
libraries. It is not necessary to add pom.xml
as a dependency.
(4) terasoluna-gfw- Provide a general purpose function that does Yes Yes*2 Yes*2
common not depend on Web. When this library is to be
used, terasoluna-gfw-common-dependencies
is added to pom.xml as a dependency.
(5) terasoluna- Provide definition for dependency while us- No Yes Yes
gfw-common- ing the function offered by terasoluna-gfw-
dependencies common project.
(6) terasoluna-gfw- Provide a function that depends on Joda Yes Yes*2 Yes*2
jodatime Time. When the library is to be used,
terasoluna-gfw-jodatime-dependencies is
added to pom.xml as a dependency. (add
from 5.0.0)
(7) terasoluna- Provide dependency definition while using a No Yes Yes
gfw-jodatime- function offered by terasoluna-gfw-jodatime
dependencies project.
(8) terasoluna-gfw- Provide a function used while creating a Web Yes Yes*2 Yes*2
web application. Functions that do not depend
on View are consolidated. When the library
is used, terasoluna-gfw-web-dependencies is
added to pom.xml as a dependency.
(9) terasoluna- Provide dependency definition while using No Yes Yes
gfw-web- a function offered by terasoluna-gfw-web
dependencies project.
(10) terasoluna-gfw- Provide a function used while creating a Web Yes Yes*2 Yes*2
web-jsp application which adopts JSP in View. When
this library is used, terasoluna-gfw-web-jsp-
dependencies is added to pom.xml as a de-
44 pendency. 2 Architecture Overview
(11) terasoluna- Provide dependency definition while using a No Yes Yes
gfw-web-jsp- function offered by terasoluna-gfw-web-jsp
dependencies project.
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

1. Incorporated as <parent> element of each project and not as a <dependency>element.

2. Incorporated as a transition dependency from <dependency> element and not as a


<dependency>element.

3. With the default settings of Common Library, when MyBatis3 is used for data access.

4. With the default settings of Common Library, when JPA is used for data access.

The project which does not contain the Java source code, only defines library dependencies.

In addition, project dependencies are as follows:

Note: Excluding exceptions, a project assigned with “dependencies” at the end of project name exists in common
library. (For example, terasoluna-gfw-common-dependencies etc corresponding to terasoluna-gfw-common)

In these projects, since a dependency definition for OSS library recommended for use is provided along with
dependency definition for common library, it is recommended to add it to pom.xml as a dependency, for the
project assigned with “dependencies” while using a common library.

2.1. Stack of TERASOLUNA Server Framework for Java (5.x) 45


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

terasoluna-gfw-common

terasoluna-gfw-common provide following components.

Classification Component Name Description


Exception Handling Exception Class Provide general exception classes.
Exception Logger Provide logger class for logging the exception that oc-
curred in application.
Exception Code Provide mechanism (classes) for resolving the excep-
tion code (message ID) that corresponds to the exception
class.
Exception Logging Interceptor Provide interceptor class of AOP for logging the excep-
tion that occurred in domain layer.
System Date System Date Time Factory Provide classes for retrieving the system date time.
Codelist CodeList Provide classes for generating CodeList.
Database Access Query Escape Provide class for escape processing of value to bind into
(Common) the SQL and JPQL.
Sequencer Provide classes for retrieving the sequence value.

terasoluna-gfw-string

terasoluna-gfw-string provides following components.

Classification Component Name Description


String Processing Half width to full width conver- Provide a class which carries out a process wherein half
sion width character of input string is converted to full width
and a process wherein full width character is converted
to half width based on mapping table of half width string
and full width string.

terasoluna-gfw-codepoints

terasoluna-gfw-codepoints provides following components.

Classification Component Name Description


String Processing Codepoint check Provide a class which checks whether the codepoint con-
stituting target string is incorporated in the codepoint set.
Input Validation Bean validation constraint annota- Provide constraint annotation to carry out Bean valida-
tion for codepoint check tion for codepoint check.

terasoluna-gfw-validator

terasoluna-gfw-validator provides following components.

46 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Classification Component name Description


Input Validation Bean Validation constraint anno- Provide a constraint annotation to check whether the byte
tation for byte length check length in the character code of input value is less than or
equal to specified maximum value, and greater than or
equal to specified minimum value, using Bean Valida-
tion.
Bean Validation constraint anno- Provide a constraint annotation to check magnitude cor-
tation for field value comparison relation of two fields using Bean Validation.
correlation check

terasoluna-gfw-jodatime

terasoluna-gfw-jodatime provide following components.

Classification Component Name Description


System Date System Date Time Factory for Provide classes for retrieving the system date time using
Joda Time the Joda Time API.

terasoluna-gfw-web

terasoluna-gfw-web provide following components.

2.1. Stack of TERASOLUNA Server Framework for Java (5.x) 47


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Classification Component Name Description


Double Submit Pro- Transaction Token Check Provide mechanism (classes) for protecting Web Appli-
tection cation from double submitting of request.
Exception Handling Exception Handler Provide exception handler class(sub class of class that
provided by Spring MVC) for integrating with excep-
tion handling components that provided from common
library.
Exception Logging Interceptor Provide interceptor class of AOP for logging the excep-
tion that handled by Spring MVC.
Codelist Populate CodeList interceptor Provide interceptor class of Spring MVC for storing
CodeList information into request scope, for the purpose
of retrieving CodeList from View.
File Download General Download View Provide abstract class for retrieving data from input
stream and writing to stream for download.
Logging ServletFilter for storing Tracking Provide Servlet Filter class for setting Tracking ID into
ID MDC(Mapped Diagnostic Context) and request scope
and response header, for the purpose of improving trace-
ability. (If does not exist a Tracking ID in request header,
generate a Tracking ID by this component)
General ServletFilter for storing Provide abstract class for storing any value into Logger’s
MDC MDC
ServletFilter for clearing MDC Provide ServletFilter class for clearing information that
stored in Logger’s MDC.

terasoluna-gfw-web-jsp

terasoluna-gfw-web-jsp provides following components.

Classification Component name Description


Double Submit Pro- JSP tag for transaction token out- Provide a JSP tag library to output transaction tokens as
tection put hidden items.
Pagination JSP Tag for displaying Pagination Provide JSP Tag Library for displaying Pagination Links
Links using classes that provided by Spring Data Commons.
Message Management JSP Tag for displaying Result Provide JSP Tag Library for displaying Result Messages.
Messages
EL Functions EL Functions for XSS counter- Provide EL Functions for XSS countermeasures.
measures
EL Functions for URL Provide EL Functions for URL as URL encoding.
EL Functions for DOM conver- Provide EL Functions for DOM conversion.
sion
EL Functions for Utilities Provide EL Functions for general utilities processing.

48 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

terasoluna-gfw-security-web

terasoluna-gfw-security-web provide following components.

Classification Component Name Description


Logging ServletFilter for storing name of Provide ServletFilter class for setting name of authenti-
authenticated user cated user into MDC, for the purpose of improving trace-
ability.

2.1. Stack of TERASOLUNA Server Framework for Java (5.x) 49


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

2.2 Overview of Spring MVC Architecture

Official website of Spring MVC says the following

Spring Reference Document.

Spring’s web MVC framework is, like many other web MVC frameworks, request-driven, designed around
a central Servlet that dispatches requests to controllers and offers other functionality that facilitates the
development of web applications. Spring’s DispatcherServlet however, does more than just that. It is
completely integrated with the Spring IoC container and as such allows you to use every other feature that
Spring has.

2.2.1 Overview of Spring MVC Processing Sequence

The processing flow of Spring MVC from receiving the request till the response is returned is shown in the
following diagram.

1. DispatcherServlet receives the request.

2. DispatcherServlet dispatches the task of selecting an appropriate controller to


HandlerMapping. HandlerMapping selects the controller which is mapped to the incoming
request URL and returns the (selected Handler) and Controller to DispatcherServlet.

50 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

3. DispatcherServlet dispatches the task of executing of business logic of Controller to


HandlerAdapter.

4. HandlerAdapter calls the business logic process of Controller.

5. Controller executes the business logic, sets the processing result in Model and returns the logical
name of view to HandlerAdapter.

6. DispatcherServlet dispatches the task of resolving the View corresponding to the View name to
ViewResolver. ViewResolver returns the View mapped to View name.

7. DispatcherServlet dispatches the rendering process to returned View.

8. View renders Model data and returns the response.

2.2.2 Implementation of each component

Among the components explained previously, the extendable components are implemented.

Implementation of HandlerMapping

Class hierarchy of HandlerMapping provided by Spring framework is shown below.

Usually org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
is used. This class reads @RequestMapping annotation from the Controller and uses the method of
Controller that matches with URL as Handler class.

2.2. Overview of Spring MVC Architecture 51


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

In Spring3.1, RequestMappingHandlerMapping is enabled by default when


<mvc:annotation-driven> is set in Bean definition file read by DispatcherServlet. (For the
settings which get enabled with the use of <mvc:annotation-driven> annotation, refer Web MVC
framework.)

Implementation of HandlerAdapter

Class hierarchy of HandlerAdapter provided by Spring framework is shown below.

Usually org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
is used. RequestMappingHandlerAdapter class calls the method of handler class (Controller)
selected by HandlerMapping. In Spring 3.1, this class is also configured by default throught
<mvc:annotation-driven>.

Implementation of ViewResolver

Classes that implement ViewResolver provided by Spring framework and dependent libraries are shown below.

Normally (When JSP is used),

• org.springframework.web.servlet.view.InternalResourceViewResolver is used,

however, when template engine Tiles is to be used

• org.springframework.web.servlet.view.tiles3.TilesViewResolver

and when stream is to be returned for file download

• org.springframework.web.servlet.view.BeanNameViewResolver

Thereby, it is required to use different viewResolver based on the type of the View that needs to be returned.

When View of multiple types is to be handled, multiple definitions of ViewResolver are required.

52 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

A typical example of using multiple ViewResolver is the screen application for which file download process
exists.
For screen (JSP), View is resolved using InternalResourceViewResolver and for File download View
is resolved using BeanNameViewResolver.
For details, refer File Download.

Implementation of View

Classes that implement View provided by Spring framework and its dependent libraries are shown below.

View changes with the type of response to be returned. When JSP is to be returned,
org.springframework.web.servlet.view.JstlView is used. When View not provided by
Spring framework and its dependent libraries are to be handled, it is necessary to extend the class in which View
interface is implemented. For details, refer File Download.

2.2. Overview of Spring MVC Architecture 53


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

54 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

2.3 First application based on Spring MVC

Before entering into the advanced usage of Spring MVC, it is better to understand Spring MVC by actually trying
hands-on web application development using Spring MVC.

2.3.1 Prerequisites

The description of this chapter has been verified on the following environment. (For other environments, replace
the contents mentioned here appropriately)

Classification Product
OS Windows 7
JVM Java 1.8
IDE Spring Tool Suite 3.6.4.RELEASE (Hereafter referred as [STS])
Build Tool Apache Maven 3.3.9 (Hereafter referred as [Maven])
Application Server Pivotal tc Server Developer Edition v3.1 (enclosed in STS)
Web Browser Google Chrome 46.0.2490.80 m

Note: To connect the internet via proxy server, STS Proxy settings and Maven Proxy settings are required for the
following operations.

2.3.2 Create a New Project

Create project using mvn archetype:generate on internet.

mvn archetype:generate -B^


-DarchetypeCatalog=http://repo.terasoluna.org/nexus/content/repositories/terasoluna-gfw-releases^
-DarchetypeGroupId=org.terasoluna.gfw.blank^
-DarchetypeArtifactId=terasoluna-gfw-web-blank-archetype^
-DarchetypeVersion=5.2.0.RELEASE^
-DgroupId=com.example.helloworld^
-DartifactId=helloworld^
-Dversion=1.0.0-SNAPSHOT

Here, created a project on Windows environment.

C:\work>mvn archetype:generate -B^


More? -DarchetypeCatalog=http://repo.terasoluna.org/nexus/content/repositories/terasoluna-gfw-rel
More? -DarchetypeGroupId=org.terasoluna.gfw.blank^
More? -DarchetypeArtifactId=terasoluna-gfw-web-blank-archetype^
More? -DarchetypeVersion=5.2.0.RELEASE^
More? -DgroupId=com.example.helloworld^
More? -DartifactId=helloworld^
More? -Dversion=1.0.0-SNAPSHOT

2.3. First application based on Spring MVC 55


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

[INFO] Scanning for projects...


[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.2:generate (default-cli) > generate-sources @ standalone-pom >
[INFO]
[INFO] <<< maven-archetype-plugin:2.2:generate (default-cli) < generate-sources @ standalone-pom <
[INFO]
[INFO] --- maven-archetype-plugin:2.2:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Batch mode
[INFO] Archetype repository missing. Using the one from [org.terasoluna.gfw.blank:terasoluna-gfw-w
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: terasoluna-gfw-web-blank-ar
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.example.helloworld
[INFO] Parameter: artifactId, Value: helloworld
[INFO] Parameter: version, Value: 1.0.0-SNAPSHOT
[INFO] Parameter: package, Value: com.example.helloworld
[INFO] Parameter: packageInPathFormat, Value: com/example/helloworld
[INFO] Parameter: package, Value: com.example.helloworld
[INFO] Parameter: version, Value: 1.0.0-SNAPSHOT
[INFO] Parameter: groupId, Value: com.example.helloworld
[INFO] Parameter: artifactId, Value: helloworld
[INFO] project created from Archetype in dir: C:\work\helloworld
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.631 s
[INFO] Finished at: 2015-07-31T08:47:12+00:00
[INFO] Final Memory: 11M/26M
[INFO] ------------------------------------------------------------------------
C:\work>

Select the archetype created project from STS menu [File] -> [Import] -> [Maven] -> [Existing Maven Projects]
-> [Next].

Click on [Finish] by selecting C:\work\helloworld in Root Directory and selecting pom.xml of helloworld
in Projects.

Following project is generated in the Package Explorer.

To understand the configuration of Spring MVC, the generated Spring MVC configuration file
(src/main/resources/META-INF/spring/spring-mvc.xml) is described briefly.

<?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.springframewor
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.o
xmlns:aop="http://www.springframework.org/schema/aop"

56 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

2.3. First application based on Spring MVC 57


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/s
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-u
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/sp
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop

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

<!-- (1) Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean
class="org.springframework.data.web.PageableHandlerMethodArgumentResolver" />
<bean
class="org.springframework.security.web.method.annotation.AuthenticationPrincipalA
</mvc:argument-resolvers>
</mvc:annotation-driven>

<mvc:default-servlet-handler />

<!-- (2) -->


<context:component-scan base-package="com.example.helloworld.app" />

<mvc:resources mapping="/resources/**"
location="/resources/,classpath:META-INF/resources/"
cache-period="#{60 * 60}" />

<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/resources/**" />
<mvc:exclude-mapping path="/**/*.html" />
<bean
class="org.terasoluna.gfw.web.logging.TraceLoggingInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/resources/**" />
<mvc:exclude-mapping path="/**/*.html" />
<bean
class="org.terasoluna.gfw.web.token.transaction.TransactionTokenInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/resources/**" />
<mvc:exclude-mapping path="/**/*.html" />
<bean class="org.terasoluna.gfw.web.codelist.CodeListInterceptor">
<property name="codeListIdPattern" value="CL_.+" />
</bean>
</mvc:interceptor>

58 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<!-- REMOVE THIS LINE IF YOU USE JPA


<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/resources/**" />
<mvc:exclude-mapping path="/**/*.html" />
<bean
class="org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor" />
</mvc:interceptor>
REMOVE THIS LINE IF YOU USE JPA -->
</mvc:interceptors>

<!-- (3) Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-I
<!-- Settings View Resolver. -->
<mvc:view-resolvers>
<mvc:jsp prefix="/WEB-INF/views/" />
</mvc:view-resolvers>

<bean id="requestDataValueProcessor"
class="org.terasoluna.gfw.web.mvc.support.CompositeRequestDataValueProcessor">
<constructor-arg>
<util:list>
<bean class="org.springframework.security.web.servlet.support.csrf.CsrfRequestData
<bean
class="org.terasoluna.gfw.web.token.transaction.TransactionTokenRequestDataVal
</util:list>
</constructor-arg>
</bean>

<!-- 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="common/error/resourceNotFoundError"
<entry key="BusinessException" value="common/error/businessError" />
<entry key="InvalidTransactionTokenException" value="common/error/transactionToken
<entry key=".DataAccessException" value="common/error/dataAccessError" />
</map>
</property>
<property name="statusCodes">
<map>
<entry key="common/error/resourceNotFoundError" value="404" />
<entry key="common/error/businessError" value="409" />
<entry key="common/error/transactionTokenError" value="409" />
<entry key="common/error/dataAccessError" value="500" />
</map>
</property>
<property name="defaultErrorView" value="common/error/systemError" />

2.3. First application based on Spring MVC 59


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<property name="defaultStatusCode" value="500" />


</bean>
<!-- Setting 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.resolve
</aop:config>

</beans>

Sr. No. Description


Default settings of Spring MVC are configured by defining <mvc:annotation-driven>. Re-
fer to the official website Enabling the MVC Java Config or the MVC XML Namespace for default
(1)
configuration of Spring framework.

Define the package which will be target of searching components used in Spring MVC.

(2)

Define the location of the JSP by specifying ViewResolver for JSP.

(3)
Tip: <mvc:view-resolvers> element is a XML element that added from Spring Framework
4.1. By using <mvc:view-resolvers> element, it is possible to define ViewResolver simply.
The definition example of using the conventional <bean> element is shown below.
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResol
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>

Next, Controller (com.example.helloworld.app.welcome.HomeController) for displaying the


Welcome page is described briefly.

package com.example.helloworld.app.welcome;

import java.text.DateFormat;
import java.util.Date;

60 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
* Handles requests for the application home page.
*/
@Controller // (4)
public class HomeController {

private static final Logger logger = LoggerFactory


.getLogger(HomeController.class);

/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = {RequestMethod.GET, RequestMethod.POST}) // (5)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);

Date date = new Date();


DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,
DateFormat.LONG, locale);

String formattedDate = dateFormat.format(date);

model.addAttribute("serverTime", formattedDate); // (6)

return "welcome/home"; // (7)


}

2.3. First application based on Spring MVC 61


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


It can be read automatically by DI container if @Controller annotation is used. As stated earlier in
[explanation of Spring MVC configuration files (2)], it is the target of component-scan.
(4)

It gets executed when the HTTP method is GET or POST and the Resource is (or request URL) is “/”.

(5)

Set Model object to be delivered to View.

(6)

Return View name. “WEB-INF/views/welcome/home.jsp” is rendered as per the configuration [Expla-


nation of Spring MVC configuration files (3)] .
(7)

Lastly, JSP (src/main/webapp/WEB-INF/views/welcome/home.jsp) for displaying the Welcome


page is described briefly.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home</title>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/resources/app/css/styles.css">
</head>
<body>
<div id="wrapper">
<h1>Hello world!</h1>
<p>The time on the server is ${serverTime}.</p> <%-- (8) --%>
</div>
</body>
</html>

Sr. No. Description


As stated earlier in [explanation of Controller (6)] the object (serverTime) set in Model is stored
in HttpServletRequest. Therefore the value passed from Controller can be output by mentioning
(8)
${serverTime} in JSP.
However about ${XXX}, it is necessary to perform HTML escaping since there is possibility of
XSS attack.

62 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

2.3.3 Run on Server

Right click “helloworld” project in STS, and start helloworld project by executing “Run As” -> “Run On Server”
-> “localhost” -> “Pivotal tc Server Developer Edition v3.0” -> “Finish”.
Enter “http://localhost:8080/helloworld/” in browser to display the following screen.

Note: Since tc Server internally uses the Tomcat, it is possible to choose below two versions in the STS.

• tomcat-8.0.15.A.RELEASE (version used by default)

• tomcat-7-0.57.A.RELEASE

If you want to switch the Tomcat to be used, change the [Version] field of ts Server by opening the [Edit Server
Runtime Environment] dialog box. Java (JRE) version can also be changed from this dialog box.

2.3. First application based on Spring MVC 63


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

2.3.4 Create an Echo Application

Lets go ahead and create a simple application. It is a typical eco application in which message will be displayed if
name is entered in the text field as given below.

64 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Creating a form object

First create a form object to accept the value of text field.


Create EchoForm class under com.example.helloworld.app.echo package. It is a simple JavaBean
that has only one1 property.

package com.example.helloworld.app.echo;

import java.io.Serializable;

public class EchoForm implements Serializable {


private static final long serialVersionUID = 2557725707095364445L;

private String name;

public void setName(String name) {


this.name = name;
}

2.3. First application based on Spring MVC 65


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

public String getName() {


return name;
}
}

Create a Controller

Next, create the Controller class.


create the EchoController class under com.example.helloworld.app.echo package.

package com.example.helloworld.app.echo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("echo")
public class EchoController {

@ModelAttribute // (1)
public EchoForm setUpEchoForm() {
EchoForm form = new EchoForm();
return form;
}

@RequestMapping // (2)
public String index(Model model) {
return "echo/index"; // (3)
}

@RequestMapping(value = "hello", method = RequestMethod.POST) // (4)


public String hello(EchoForm form, Model model) {// (5)
model.addAttribute("name", form.getName()); // (6)
return "echo/hello";
}
}

66 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Add @ModelAttribute annotation to the method. Return value of such a method is automatically
added to the Model.
Attribute name of the Model can be specified in @ModelAttribute, but the class name with the
first letter in lower case is the default attribute name. In this case it will be “echoForm”. This attribute
name must match with the value of modelAttribute of form:form tag.

(2) When nothing is specified in value attribute of @RequestMapping annotation at the method
level, it is mapped to @RequestMapping added at class level. In this case, index method is
called, if “<contextPath>/echo” is accessed.
When nothing is set in method attribute, mapping is done for any HTTP method.

(3) Since “echo/index” is returned as View name, “WEB-INF/views/echo/index.jsp” is rendered by the


ViewResolver.

(4) Since “hello” is specified in value attribute and RequestMethod.POST is specified in method
attribute of the @RequestMapping annotation method, if “<contextPath>/echo/hello” is accessed
with POST method, hello method is called.

(5) EchoForm object added to the model in (1) is passed as argument.

(6) name entered in form is passed as it is to the View.

Note: The value specified in the method attribute of @RequestMapping annotation is generally varied by
how the data transmitted from the client.

• POST method in case of storing data to the server (in case of updating process).

• GET method or unspecified (any method) in case of not storing data to the server (in case of referring
process).

In echo application,

• index method is not going to save data to the server, it is unspecified (any method)

2.3. First application based on Spring MVC 67


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• hello method is going to save data into Model object, it is POST method

etc are specified.

Create JSP Files

Finally create JSP for input screen and output screen. Each file path must match with View name as follows.

Create input screen (src/main/webapp/WEB-INF/views/echo/index.jsp).

<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>
<%-- (1) --%>
<form:form modelAttribute="echoForm" action="${pageContext.request.contextPath}/echo/hello">
<form:label path="name">Input Your Name:</form:label>
<form:input path="name" />
<input type="submit" />
</form:form>
</body>
</html>

Sr. No. Description

(1) HTML form is constructed using tag library. Specify the name of form object created by Controller in
modelAttribute attribute.
Refer here for tag library.

Note: POST method is used if method attribute of <form:form> tag is omitted.

The generated HTML is as follows

<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>

68 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<form id="echoForm" action="/helloworld/echo/hello" method="post">


<label for="name">Input Your Name:</label>
<input id="name" name="name" type="text" value=""/>
<input type="submit" />
<input type="hidden" name="_csrf" value="43595f38-3edd-4c08-843b-3c31a00d2b15" />
</form>
</body>
</html>

Create output screen (src/main/webapp/WEB-INF/views/echo/hello.jsp).

<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>
<p>
Hello <c:out value="${name}" /> <%-- (2) --%>
</p>
</body>
</html>

Sr. No. Description

(2) Output “name” passed from Controller. Take countermeasures for XSS using c:out tag.

Note: Here, XSS countermeasure taken using c:out standard tag, however, f:h() function provided in com-
mon library can be used easily. Refer to XSS Countermeasures for details.

Implementation of Eco application is completed here.


Start the server and form will be displayed by accessing “http://localhost:8080/helloworld/echo”.

2.3. First application based on Spring MVC 69


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Implement Input Validation

Till this point Input validation is not implemented in this application. In Spring MVC, Bean Validation and
annotation based input validation can be easily implemented. For example name input validation is performed in
Eco Application.

Add annotation for Input check rule to the name of EchoForm.

package com.example.helloworld.app.echo;

import java.io.Serializable;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class EchoForm implements Serializable {


private static final long serialVersionUID = 2557725707095364445L;

@NotNull // (1)
@Size(min = 1, max = 5) // (2)
private String name;

public void setName(String name) {


this.name = name;
}

public String getName() {


return name;
}
}

Sr. No. Description

(1) Whether name parameter exists in HTTP request or not can be checked by @NotNull annotation.

(2) Whether the size of name is more than or equal to 1 and less than or equal to 5 can be checked by
@Size(min = 1, max = 5).

Implement the input check and the error handling when an error occurs in the input check.

70 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

package com.example.helloworld.app.echo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("echo")
public class EchoController {

@ModelAttribute
public EchoForm setUpEchoForm() {
EchoForm form = new EchoForm();
return form;
}

@RequestMapping
public String index(Model model) {
return "echo/index";
}

@RequestMapping(value = "hello", method = RequestMethod.POST)


public String hello(@Validated EchoForm form, BindingResult result, Model model) { // (1)
if (result.hasErrors()) { // (2)
return "echo/index";
}
model.addAttribute("name", form.getName());
return "echo/hello";
}
}

Sr. No. Description

(1) In Controller, add @Validated annotation to the argument on which validation needs to be
executed. Also add BindingResult object to the arguments.
Input validation is automatically performed using Bean Validation and the result is stored in
BindingResult object.

(2) Error can be checked by executing hasErrors method. If there is an input error, it returns View
name to display the input screen.

2.3. First application based on Spring MVC 71


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Add the implementation of displaying input error message on input screen (src/main/webapp/WEB-
INF/views/echo/index.jsp).

<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>
<form:form modelAttribute="echoForm" action="${pageContext.request.contextPath}/echo/hello">
<form:label path="name">Input Your Name:</form:label>
<form:input path="name" />
<form:errors path="name" cssStyle="color:red" /><%-- (1) --%>
<input type="submit" />
</form:form>
</body>
</html>

Sr. No. Description

(1) Add form:errors tag for displaying error message when an error occurs on input screen.

Implementation of input validation is completed.


Error message is displayed in the following conditions:

• When an empty name is sent

• Size is more than 5 characters.

The generated HTML is as follows.

<!DOCTYPE html>
<html>
<head>
<title>Echo Application</title>
</head>
<body>
<form id="echoForm" action="/helloworld/echo/hello" method="post">
<label for="name">Input Your Name:</label>
<input id="name" name="name" type="text" value=""/>

72 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

2.3. First application based on Spring MVC 73


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<span id="name.errors" style="color:red">size must be between 1 and 5</span>


<input type="submit" />
<input type="hidden" name="_csrf" value="6e94a78d-4a2c-4a41-a514-0a60f0dbedaf" />
</form>
</body>
</html>

Summary

The following are the learnings from this chapter.

1. How to create blank project using mvn archetype:generate.

2. Basic Spring MVC configuration set-up

3. Simplified level screen transition

4. Way to pass values between screens

5. Simple input validation

If above points are still not understood, it is recommended to read this chapter again and start again from building
the environment.

74 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

2.4 Application Layering

In this guideline, the application is classified into the following 3 layers.

• Application layer

• Domain layer

• Infrastructure layer

Each layer has the following components.

Both application layer and infrastructure layer depend on domain layer, however domain layer should not depend
on other layers. There can be changes in the application layer with the changes in domain layer, However, there
should be no changes in domain layer with the changes in application layer.

Each layer is explained.

Note: Application layer, domain layer, infrastructure layer are the terms explained in “Domain-Driven Design
(2004, Addison-Wesley)” of Eric Evans. However, though the terms are used, they are not necessarily as per the
concept used in Domain Driven Design.

2.4.1 Layer definition

Flow of data from input to output is Application layer → Domain layer → Infrastructure layer, hence explanation
is given in this sequence.

2.4. Application Layering 75


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Application layer

Application layer does the wiring part of the application.

In this layer, it provides the following implementations:

• Provides UI(User Interface) to input and output information.

• Handles the request from clients.

• Validates the input data from a clients

• Calls components in the domain layer corresponding to the request from clients.

This layer should be as thin as possible and should not contain any business rules.

Controller

Controller is mainly responsible for the below:

• Controls the screen flow (mapping the request and returning the View corresponding to the result)

• Calls services in the domain layer (executing main logic corresponding to the request)

In Spring MVC, POJO class having @Controller annotation becomes the Controller class.

Note: When storing the client input data in the session, controllers also have a role to control the life cycle of
data to be stored in the session.

View

View’s responsibilities is generating output (including the UI provision) to the client. Returns output results in
various formats such as HTML/PDF/Excel/JSON.

In Spring MVC, all this is done by View class.

Tip: If use the JSON or XML format output results for the REST API or Ajax request,
HttpMessageConverter class plays View’s responsibility.

Details refer to “RESTful Web Service”.

76 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Form

Form’s main responsibilities are the following:

• Represents the form of HTML. (sending form information to the Controller, or outputting the processing
result data to form of HTML)

• Declaration of input check rules. (by adding Bean Validation annotation)

In Spring MVC, form object are the POJO class that store request parameters. It is called as form backing bean.

Note: To retain the domain layer independent from the application layer, need to perform following processing
at the application layer.

• Conversion from Form to DomainObject(such as Entity)

• Conversion from DomainObject to Form

If conversion code is too many, recommend to perform of either or both of the following measures and keep
Controller’s source code in simple state.

• Create helper class and delegate conversion logic to helper classes.

• Use the Dozer.

Tip: If use the JSON or XML as input data for REST API or Ajax request, Resource class plays Form’s
responsibility. Also, HttpMessageConverter class plays responsibility to convert JSON or XML input data
into Resource class.

Details refer to “RESTful Web Service”.

Helper

It plays the role of assisting the Controller.

Creating Helper is an option. Please create as POJO class if required.

Note: The main duty of Controller is routing (URL mapping and sepcifying the destination). If there is any
processing required (converting JavaBean etc), then that part must be cut-off from controller and must be delegated

2.4. Application Layering 77


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

to helper classes.

The existance of Helper class improves the visibility of Controller; hence, it is OK to think as a part of Controller.
(Similar to private methods of Controller)

Domain layer

Domain layer is the core of the application, and execute business rules.

In this layer, it provides the following implementations.

• DomainObject

• Checking business rules corresponding to the DomainObject (like whether there is sufficient balance when
crediting amount into the account)

• Executing business rules for the DomainObject (reflects values corresponding to business rules)

• Executing CRUD operations for the DomainObject

Domain layer is independent from other layers and is reusable.

DomainObject

DomainObject is a model that represents resources required for business and items generated in the business
process.

Models are broadly classified into following 3 categories.

• Resource models such as Employee, Customer, Product etc. (generally indicated by a noun)

• Event models such as Order, Payment etc.(generally indicated by a verb)

• Summary model such as YearlySales, MonthlySales etc.

Domain Object is the Entity that represents an object which indicates 1 record of database table.

Note: Mainly Models holding state only are handled in this guideline.

In “Patterns of Enterprise Application Architecture (2002, Addison-Wesley)” of Martin Fowler, Domain Model is
defined as Item having state and behavior. We will not be touching such models in detail.

78 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

In this guideline, Rich domain model proposed by Eric Evans is also not included. However, it is mentioned here
for classification.

Repository

It can be thought of as a collection of DomainObjects and is responsible for CRUD operations such as create, read,
update and delete of DomainObject.

In this layer, only interface is defined.

It is implemented by RepositoryImpl of infrastructure layer. Hence, in this layer, there is no information about
how data access is implemented.

Service

Provides the business logic.

In this guideline, it is recommended to draw the transaction boundary at the method of Service.

Note: Information related to Web such as Form and HttpRequest should not be handled in service.

This information should be converted into domain object in Application layer before calling the Service.

Infrastructure layer

Implementation of domain layer (Repository interface) is provided in infrastructure layer.

It is responsible for storing the data permanently (location where data is stored such as RDBMS, NoSQL etc.) as
well as transmission of messages.

2.4. Application Layering 79


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

RepositoryImpl

Represents implementation of Repository interface of domain layer. It covers life cycle management of Domain-
Object.

With the help of this structure, it is possible to hide implementation details from domain layer.

This layer also can be the transaction boundary depending on the requirements.

Tip: When using MyBatis3 or Spring Data JPA, most RepositoryImpls are created automatically.

O/R Mapper

It is responsible for mapping database with Entity.

This function is provided by MyBatis, JPA and Spring JDBC.

Specifically, the following classes are the O/R Mapper.

• Mapper interface or SqlSession in case of using MyBatis3

• EntityManager in case of using JPA,

• JdbcTemplate in case of using plain Spring JDBC

O/R Mapper used for implementation of Repository.

Note: It is more correct to classify MyBatis and Spring JDBC as “SQL Mapper” and not “O/R Mapper”; however,
in this guideline it is treated as “O/R Mapper”.

Integration System Connector

It integrates a data store other than the database( such as messaging system, Key-Value-Store, Web service, existing
legacy system, external system etc.).

80 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

It is also used for implementation of Repository.

2.4.2 Dependency between layers

As explained earlier, domain layer is the core of the application, and application layer and infrastructure layer are
dependent on it.

In this guideline, it is assumed that,

• Spring MVC is used in application layer

• MyBatis and Spring Data JPA are used in infrastructure layer

Even if there is change in implementation technology, the differences can be absorbed in respective layers and
there should not be any impact on domain layer. Coupling between layers is done by using interfaces and hence
they can be made independent of implementation technology being used in each layer.

It is recommended to make loosely-coupled design by understanding the layering.

Object dependency in each layer can be resolved by DI container.

2.4. Application Layering 81


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Processing and data flow with Repository

The flow from input to output is given in the following figure.

Sequence is explained using the example of update operation.

82 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

No. Description
Controller receives the Request.
1.

(Optional) Controller calls Helper and converts the Form information to DomainObject or DTO.
2.

Controller calls the Service by using DomainObject or DTO.


3.

Service calls the Repository and executes business logic.


4.

Repository calls the O/R Mapper and persists DomainObject or DTO.


5.

(Implementation dependency) O/R Mapper stores DomainObject or DTO information in DB.


6.

Service returns DomainObject or DTO which is the result of business logic execution to Controller.
7.

(Optional) Controller calls the Helper and converts DomainObject or DTO to Form.
8.

Controller returns View name of transition destination.


9.

View outputs Response.


10.

Please refer to the below table to determine whether it is OK to call a component from another component.

Table.2.2 Possibility of calling between components

Caller/Callee Controller Service Repository O/R Mapper

Controller

Service

Repository

Note that calling a Service from another Service is basically prohibited.

If services that can be used even from other services are required, SharedService should be created in order to

2.4. Application Layering 83


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

clarify such a possibility. Refer to Domain Layer Implementation for the details.

Note: It may be difficult to follow the above rules at the initial phase of application development. If looking at
a very small application, it can be created quickly by directly calling the Repository from Controller. However,
when rules are not followed, there will be many maintainability issues when development scope becoms larger.
It may be difficult to understand the impact of modifications and to add common logic which is cross-cutting in
nature. It is strongly recommended to pay attention to dependency from the beginning of development so that
there will be no problem later on.

Processing and data flow without Repository

Hiding the implementation details and sharing of data access logic are the merits of creating a Repository.

However, it is difficult to share data access logic depending on the project team structure (multiple companies may
separately implement business processes and control on sharing may be difficult etc.) In such cases, if abstraction
of data access is not required, O/R Mapper can be called directly from Service as shown in the following diagram,
without creating the repository.

84 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Inter-dependency between components in this case must be as shown below:

Table.2.3 Inter-dependency between components (without Repository)

Caller/Callee Controller Service O/R Mapper

Controller

Service

2.4.3 Project structure

Here, recommended project structure is explained when application layering is done as described earlier.

The standard maven directory structure is pre-requisite.

Basically, it is recommended to create the multiple projects with the following configuration.

Project Name Description


[projectName]-domain Project for storing classes/configuration files related to domain layer
[projectName]-web Project for storing classes/configuration files related to application layer
[projectName]-env Project for storing files dependent on environment

([projectName] is the target project name)

Note: Classes of infrastructure layer such as RepositoryImpl are also included in project-domain. Originally,
[projectName]-infra project should be created separately; however, normally there is no need to conceal the im-
plementation details in the infra project and development becomes easy if implementation is also stored in domain
project. Moreover, when required, [projectName]-infra project can be created.

Tip: For the example of multi-project structure, refer to Sample Application or Test Application of Common
Library.

2.4. Application Layering 85


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

[projectName]-domain

Recommended structure of [projectName]-domain project is as below:

[projectName]-domain
└ src
└ main
├ java
| └ com
| └ example
| └ domain ...(1)
| ├ model ...(2)
| | ├ Xxx.java
| | ├ Yyy.java
| | └ Zzz.java
| ├ repository ...(3)
| | ├ xxx
| | | └ XxxRepository.java
| | ├ yyy
| | | └ YyyRepository.java
| | └ zzz
| | ├ ZzzRepository.java
| | └ ZzzRepositoryImpl.java
| └ service ...(4)
| ├ aaa
| | ├ AaaService.java
| | └ AaaServiceImpl.java
| └ bbb
| ├ BbbService.java
| └ BbbServiceImpl.java
└ resources
└ META-INF
└ spring
├ [projectName]-codelist.xml ...(5)
├ [projectName]-domain.xml ...(6)
└ [projectName]-infra.xml ...(7)

86 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

No. Details
Package to store configuration elements of domain layer.

(1)

Package to store DomainObjects classes.

(2)

Package to store Repository interfaces.


Create a separate package for each Entity. If there are associated Entities to the main entity, then
(3)
Repository interfaces of associated Entities must also be placed in the same package as main Entity.
(For example, Order and OrderLine). If DTO(holds such as search criteria) is also required, it too must
be placed in this package.
RepositoryImpl belongs to Infrastructure layer; however, there is no problem in keeping it in this
project. In case of using different data stores or existance of multiple persistence platforms, Reposito-
ryImpl class must be kept in separate project or separate package so that implementation related details
are concealed.
Package to store Service classes.
Package must be created based on Entity Model or other functional unit. Interface and Implementation
(4)
class must be kept at the same level of package. If input/output classes are also required, then they
must be placed in this package.
Bean definition for CodeList.

(5)

Bean definition pertaining to domain layer.

(6)

Bean definition pertaining to infrastructure layer.

(7)

[projectName]-web

Recommended structure of [projectName]-web

[projectName]-web
└ src
└ main

2.4. Application Layering 87


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

├ java
| └ com
| └ example
| └ app ...(1)
| ├ abc
| | ├ AbcController.java
| | ├ AbcForm.java
| | └ AbcHelper.java
| └ def
| ├ DefController.java
| ├ DefForm.java
| └ DefOutput.java
├ resources
| ├ META-INF
| | └ spring
| | ├ applicationContext.xml ...(2)
| | ├ application.properties ...(3)
| | ├ spring-mvc.xml ...(4)
| | └ spring-security.xml ...(5)
| └ i18n
| └ application-messages.properties ...(6)
└ webapp
├ resources ...(7)
└ WEB-INF
├ views ...(8)
| ├ abc
| | ├ list.jsp
| | └ createForm.jsp
| └ def
| ├ list.jsp
| └ createForm.jsp
└ web.xml ...(9)

88 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

No, Details
Package to store configuration elements of application layer.

(1)

Bean definited related to the entire application.

(2)

Define the properties to be used in the application.

(3)

Bean definitions related to Spring MVC.

(4)

Bean definitions related to Spring Security

(5)

Define the messages and other contents to be used for screen display (internationalization).

(6)

Store static resources(css、js、image, etc)

(7)

Store View(jsp) files.

(8)

Servlet deployment definitions

(9)

[projectName]-env

The recommended structure of [projectName]-env project is below:

[projectName]-env
├ configs ...(1)

2.4. Application Layering 89


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

| └ [envName] ...(2)
| └ resources ...(3)
└ src
└ main
└ resources ...(4)
├ META-INF
| └ spring
| ├ [projectName]-env.xml ...(5)
| └ [projectName]-infra.properties ...(6)
├ dozer.properties
├ log4jdbc.properties
└ logback.xml ...(7)

No. Details
Directory to define configurations depends on the environment for all environments.

(1)

Directory to define configurations depeands on each environment.


The directory name is used as the name to identify the environment.
(2)

Directory to define configurations depeands on each environment.


The sub directory structure and files are same as (4).
(3)

Directory to define configurations depeands on the local development environment.

(4)

Bean definitions that depend on the local development environment (like dataSource etc).

(5)

Property definitions which depend on the local development environment.

(6)

Log output definitions which depend on the local development environment.

(7)

Note: The purpose of separating [projectName]-domain and [projectName]-web into different projects is to
prevent reverse dependency among them.

It is natural that [projectName]-web uses [projectName]-domain; however, [projectName]-domain must not refer
projectname]-web.

90 2 Architecture Overview
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

If configruation elements of both, [projectName]-web and [projectName]-domain, are kept in a single project, it
may lead to an incorrect reference by mistake. It is strongly recommended to prevent reference to [projectName]-
web from [projectName]-domain by separating the project and setting order of reference.

Note: The reason for creating [projectName]-env is to separate the information depending on the environment
and thereby enable switching of environment.

For example, set local development environment by default and at the time of building the application, create war
file without including [projectName]-env. By creating a separate jar for integration test environment or system test
environment, deployment becomes possible just by replacing the jar of corresponding environment.

Further, it is also possible to minimize the changes in case of project where RDBMS being used changes.

If the above point is not considered, contents of configuration files have to changed according to the target envi-
ronment and the project has to be re-build.

2.4. Application Layering 91


93

Application Development

Description of various rules as well as recommended implementation on the use of TERASOLUNA Server Frame-
work for Java (5.x).

The flow of development in this guideline with be as follows.

3.1 Create Web application development project

In this section, how to create a web application development project is described.

In this guideline, it is recommended to adopt multi-project configuration. For description of the recommended
multi-project configuration, refer [Project structure].

3.1.1 Types of Blank Project

Following two types of blank projects are provided depending on usage.


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Type Usage
This should be used when developing a real application that is to be released in commercial
environment.
Blank project of
Following types of project templates are provided as Archetype of Maven.
multi-project structure
• Template that includes settings for MyBatis3
• Template that includes settings for JPA (Spring Data JPA)
This guideline recommends using a project having multi-project structure.
This should be used when creating simple applications such as POC (Proof Of Concept),
prototype, sample, etc.
Blank project of
Following types of project templates are provided as Archetype of Maven. (Projects for
single-project
Eclipse WTP are also provided; however, their description is omitted in this chapter)
structure
• Template that includes settings for MyBatis3
• Template that includes settings for JPA (Spring Data JPA)
• Template that does not depend on O/R Mapper
This guideline follows a procedure wherein various tutorials are performed using a single
project.

3.1.2 Create development project

The multi-project structured development project will be created using the archetype:generate of the Maven
Archetype Plugin .

Note: Prerequisite

In the following description,

• Maven (mvn command) is used

• Internet connection is used

• If internet is connected via proxy, Maven proxy setting needs to be done

are prerequisites.

If prerequisite conditions are not satisfied, it is necessary to perform these setups first.

As an Archetype following two types are provided for creating multi-project.

94 3 Application Development
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Archetype(ArtifactId) Description


terasoluna-gfw-multi-web-blank- Archetype for generating a projec
1.
mybatis3-archetype

terasoluna-gfw-multi-web-blank- Archetype for generating a proje


2.
jpa-archetype Hibernate) as O/R Mapper.

Move to the folder where you want to create project.

cd C:\work

Create project using archetype:generate of Maven Archetype Plugin.

mvn archetype:generate -B^


-DarchetypeCatalog=http://repo.terasoluna.org/nexus/content/repositories/terasoluna-gfw-releases^
-DarchetypeGroupId=org.terasoluna.gfw.blank^
-DarchetypeArtifactId=terasoluna-gfw-multi-web-blank-mybatis3-archetype^
-DarchetypeVersion=5.2.0.RELEASE^
-DgroupId=com.example.todo^
-DartifactId=todo^
-Dversion=1.0.0-SNAPSHOT

3.1. Create Web application development project 95


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Parameter Description
batch mode (skips interaction)

-B

Specify TERASOLUNA Server Framework for Java (5.x) repository.(Fixed)

-DarchetypeCatalog

Specify groupId of the blank project.(Fixed)

-DarchetypeGroupId

Specify archetypeId (ID to identify the template) of the blank project. (Customiza-
tion required)
-DarchetypeArtifactId
specify one of the following archetypeId.
• terasoluna-gfw-multi-web-blank-mybatis3-archetype
• terasoluna-gfw-multi-web-blank-jpa-archetype
In above example, terasoluna-gfw-multi-web-blank-mybatis3-archetype
is specified.
Specify version of the blank project.(Fixed)

-DarchetypeVersion

Specify groupId of the project that you want to create. (Customization required)
In above example, "com.example.todo" is specified.
-DgroupId

Specify artifactId of the project that you want to create. (Customization required)
In above example, "todo" is specified.
-DartifactId

Specify version of the project that you want to create. (Customization required)
In above example, "1.0.0-SNAPSHOT" is specified.
-Dversion

If the project creation successes, following type of log will be printed. (The following output is an example when
project is created using the MyBatis3 Archetype)

(... omit)
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: terasoluna-gfw-multi-web-bl

96 3 Application Development
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.example.todo
[INFO] Parameter: artifactId, Value: todo
[INFO] Parameter: version, Value: 1.0.0-SNAPSHOT
[INFO] Parameter: package, Value: com.example.todo
[INFO] Parameter: packageInPathFormat, Value: com/example/todo
[INFO] Parameter: package, Value: com.example.todo
[INFO] Parameter: version, Value: 1.0.0-SNAPSHOT
[INFO] Parameter: groupId, Value: com.example.todo
[INFO] Parameter: artifactId, Value: todo
[INFO] Parent element not overwritten in C:\work\todo\todo-env\pom.xml
[INFO] Parent element not overwritten in C:\work\todo\todo-domain\pom.xml
[INFO] Parent element not overwritten in C:\work\todo\todo-web\pom.xml
[INFO] Parent element not overwritten in C:\work\todo\todo-initdb\pom.xml
[INFO] Parent element not overwritten in C:\work\todo\todo-selenium\pom.xml
[INFO] project created from Archetype in dir: C:\work\todo
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.929 s
[INFO] Finished at: 2015-07-31T12:03:21+00:00
[INFO] Final Memory: 10M/26M
[INFO] ------------------------------------------------------------------------

If the project creation successes, Maven multi-project gets created. For detail description of the project that you
have created in the Maven Archetype, Refer [Structure of the development project].

todo
├-- pom.xml
├-- todo-domain
├-- todo-env
├-- todo-initdb
├-- todo-selenium
└-- todo-web

3.1.3 Customization of development project

Depending upon the application, there are several locations where customization is required in the Maven
Archetype created project.

3.1. Create Web application development project 97


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

The customization required locations are described below.

• POM file project information

• x.xx.fw.9999 format message ID

• Message wording

• Error screen

• Screen footer copyright

• In-memory database (H2 Database)

• DataSource configuration

Note: The customization points other than the above are,

• Settings of Authentication・Authorization

• Settings to enable File Upload

• Setting to activate Internationalization

• Definition of Logging

• Definition of Exception Handling

• Apply settings of RESTful Web Service

For these customizations, Refer to “How to use” of each section and customize if required.

Note: Part that is expressed as artifactId in the following description needs to be read by replacing the
artifactId which is specified at the time of creating a project.

POM file project information

In the POM file of Maven Archetype created project,

• Project name (name element)

• Project description (description element)

• Project URL (url element)

98 3 Application Development
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Project inception year (inceptionYear element)

• Project license (licenses element)

• Project organization (organization element)

such information set in Archetype projects. The actual settings contents indicated below.

<!-- ... -->

<name>TERASOLUNA Server Framework for Java (5.x) Web Blank Multi Project</name>
<description>Web Blank Multi Project using TERASOLUNA Server Framework for Java (5.x)</description
<url>http://terasoluna.org</url>
<inceptionYear>2014</inceptionYear>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>manual</distribution>
</license>
</licenses>
<organization>
<name>TERASOLUNA Framework Team</name>
<url>http://terasoluna.org</url>
</organization>

<!-- ... -->

Note: Set the appropriate values in the project information.

Customization method and customization targeted files are indicated below.

Sr. No. Targeted File Customization method


POM (Project Object Model) file that defines the Set the appropriate values in the project informa-
1.
overall configuration of multi-project tion.
artifactId/pom.xml

3.1. Create Web application development project 99


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

x.xx.fw.9999 format message ID

In the Maven Archetype created project, the x.xx.fw.9999 format message ID used at the time of,

• Message to be displayed on the error screen

• Error log to be output when an exception occurs

Actual point-of-use (sampling) indicated below.

[application-messages.properties]

e.xx.fw.5001 = Resource not found.

[JSP]

<div class="error">
<c:if test="${!empty exceptionCode}">[${f:h(exceptionCode)}]</c:if>
<spring:message code="e.xx.fw.5001" />
</div>

[applicationContext.xml]

<bean id="exceptionCodeResolver"
class="org.terasoluna.gfw.common.exception.SimpleMappingExceptionCodeResolver">
<!-- ... -->
<entry key="ResourceNotFoundException" value="e.xx.fw.5001" />
<!-- ... -->
</bean>

The x.xx.fw.9999 format message ID is a message ID system that is introduced in [Message Management] of
this guideline but, the value of the project division is in the state of provisional value [xx].

Note:

• If the message ID system introduced in this guideline is used, specify the appropriate values to the
project classification. For the message ID system introduced in this guideline, Refer [Result messages].

• If the message ID system introduced in this guideline is not used, it is necessary to replace all the message
IDs those are used in the customization targeted file indicated below.

100 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Customization method and customization targeted files are indicated below.

Sr. No. Targeted File Customization method


Message definition file The provisional value [xx] of project classification
1.
message ID specified in the property key needs to
artifactId/artifactId-web/src/main/resources/i18n/application-messages.proper
be modified by appropriate value.
Error screen JSP The provisional value [xx] of project classification
2.
message ID specified in the code attribute of the
artifactId/artifactId-web/src/main/webapp/WEB-INF/views/common/error/ *.jsp
element <spring:message> needs to be modi-
fied by appropriate value.
Bean definition file to create an application context The provisional value [xx] of project classification
3.
for Web applications exception code (message ID) specified in the Bean
definition of "exceptionCodeResolver"
artifactId/artifactId-web/src/main/resources/META-INF/spring/applicationConte
needs to be modified by appropriate value.

Message wording

In the Maven Archetype created project, number of message definitions are provided but, message wordings are
simple messages. Actual messages (sampling) are indicated below.

[application-messages.properties]

e.xx.fw.5001 = Resource not found.

# ...

# typemismatch
typeMismatch="{0}" is invalid.

# ...

Note: Modify the message wording depending upon the application requirements (such as message terms)

Customization method and customization targeted files are indicated below.

3.1. Create Web application development project 101


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Targeted File Customization method


Message definition file Modify the messages in accordance with the appli-
1.
cation requirements.
artifactId/artifactId-web/src/main/resources/i18n/application-messages.proper
The message to be displayed (Bean Validation mes-
sages) when there is an error in input check needs
to be modified (override default messages) depend-
ing upon the application requirement. For overrid-
ing the default messages, Refer [Definition of error
messages].

Error screen

In the Maven Archetype created project, JSP and HTML are provided for displaying an error screen for every kind
of errors but,

• screen layout

• screen title

• wording of the message

etc are simple implementation. Actual JSP implementation (sampling) is indicated below.

[JSP]

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Resource Not Found Error!</title>
<link rel="stylesheet"
href="${pageContext.request.contextPath}/resources/app/css/styles.css">
</head>
<body>
<div id="wrapper">
<h1>Resource Not Found Error!</h1>
<div class="error">
<c:if test="${!empty exceptionCode}">[${f:h(exceptionCode)}]</c:if>
<spring:message code="e.xx.fw.5001" />
</div>
<t:messagesPanel />
<br>
<!-- ... -->
<br>
</div>

102 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

</body>
</html>

Note: Modify the JSP and HTML depending upon the application requirements (such as UI terms) used
for displaying an error screen.

Customization method and customization targeted files are indicated below.

Sr. No. Targeted File Customization method


JSP for the error screen Modify depending upon the application require-
1.
ments (such as UI terms).
artifactId/artifactId-web/src/main/webapp/WEB-INF/views/common/error/ *.jsp
Refer [Coding points (JSP) of Exception Handling]
for customizing the JSP to display an error screen.
HTML for the error screen Modify depending upon the application require-
2.
ments (such as UI terms).
artifactId/artifactId-web/src/main/webapp/WEB-INF/views/common/error/unhandle

Screen footer copyright

In the Maven Archetype created project, screen layouts are configured using Tiles but, the copyright of the screen
footer portion is in a state of provisional value [Copyright &copy; 20XX CompanyName]. Actual JSP
implementation (sampling) is indicated below.

[template.jsp]

<div class="container">
<tiles:insertAttribute name="header" />
<tiles:insertAttribute name="body" />
<hr>
<p style="text-align: center; background: #e5eCf9;">Copyright
&copy; 20XX CompanyName</p>
</div>

Note: If screen layouts are configured using Tiles, specify appropriate value to the copyright.

3.1. Create Web application development project 103


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Customization method and customization targeted files are indicated below.

Sr. No. Targeted File Customization method


Template JSP for Tiles Modify the provisional value [Copyright
1.
&copy; 20XX CompanyName ] of the copy-
artifactId/artifactId-web/src/main/webapp/WEB-INF/views/layout/template.jsp
right with an appropriate value.

In-memory database (H2 Database)

In the Maven Archetype created project, in-memory database (H2 Database) setting is configured but, these set-
tings are done for the small operation (Prototyping and POC (Proof Of Concept)) verification. Therefore, these
could be unnecessary settings while having regular application development.

[artifactId-env.xml]

<jdbc:initialize-database data-source="dataSource"
ignore-failures="ALL">
<jdbc:script location="classpath:/database/${database}-schema.sql" />
<jdbc:script location="classpath:/database/${database}-dataload.sql" />
</jdbc:initialize-database>

└-- src
└-- main
└-- resources
├-- META-INF
(...)
├-- database
| ├-- H2-dataload.sql
| └-- H2-schema.sql

Note: While having regular application development, remove the directory which is maintained for defini-
tion and SQL files for setting up a In-memory database (H2 Database)

Customization method and customization targeted files are indicated below.

104 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Targeted File Customization method


Bean definition file for defining environment de- Remove the <jdbc:initialize-database>
1.
pendent components element.
artifactId-env/src/main/resources/META-INF/spring/artifactId-env.xml
Directory that contains the SQL for configuring In- Remove the directory.
2.
memory database (H2 Database)
artifactId/artifactId-env/src/main/resources/database/

DataSource configuration

In the Maven Archetype created project, DataSource setting is done for accessing in-memory database (H2
Database) but, these settings are done for the small operation (Prototyping and POC (Proof Of Concept)) veri-
fication. Therefore it is necessary to change the DataSource settings for accessing the actual running database
application while having regular application development.

[artifactId/artifactId-domain/pom.xml]

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

[artifactId-infra.properties]

database=H2
database.url=jdbc:h2:mem:todo;DB_CLOSE_DELAY=-1
database.username=sa
database.password=
database.driverClassName=org.h2.Driver
# connection pool
cp.maxActive=96
cp.maxIdle=16
cp.minIdle=0
cp.maxWait=60000

[artifactId-env.xml]

<bean id="realDataSource" class="org.apache.commons.dbcp2.BasicDataSource"


destroy-method="close">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
<property name="defaultAutoCommit" value="false" />

3.1. Create Web application development project 105


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<property name="maxTotal" value="${cp.maxActive}" />


<property name="maxIdle" value="${cp.maxIdle}" />
<property name="minIdle" value="${cp.minIdle}" />
<property name="maxWaitMillis" value="${cp.maxWait}" />
</bean>

Note: Change the DataSource settings for accessing the actual running database application while having
regular application development.

In the Maven Archetype created project, the use of Apache Commons DBCP is configured but, there are many
cases that adopting a method of accessing a DataSource via JNDI (Java Naming and Directory Interface) by use
of DataSource provided by the application server.

Again there are some cases where Apache Commons DBCP is used on development environment and DataSource
provided by the application server is used on test as well as production environment.

For how to set-up the DataSource, Refer [Datasource settings of Database Access (Common)].

Customization method and customization targeted files are indicated below.

106 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Targeted File Customization method


POM file Remove in-memory database (H2 Database) JDBC
1.
• artifactId/pom.xml driver from the dependency library.
• artifactId/artifactId-domain/pom.xml
Add the JDBC driver in dependency library for ac-
cessing the actual running application database.
Property file for defining environment dependent If Apache Commons DBCP is used as a Data-
2.
setting Source, specify the connection information for ac-
cessing the actual running application database in
artifactId/artifactId-env/src/main/resources/META-INF/spring/artifactId-infra
below property.
• database
• database.url
• database.username
• database.password
• database.driverClassName
Remove unnecessary property except the following
property if DataSource provided by the application
server is used.
• database

Bean definition file for defining environment de- If DataSource provided by the application server
3.
pendent components is used, change the configuration to use the Data-
Source that is obtained via JNDI.
artifactId/artifactId-env/src/main/resources/META-INF/spring/artifactId-env.x
For how to set-up the DataSource, Refer [Data-
source settings of Database Access (Common)].

Note: About the database property of the property file for defining environment dependent setting

The database property is unnecessary property if MyBatis is used as O/R Mapper. You may remove this but
you may leave the settings in order to specify the database being used.

Tip: How to add the JDBC driver

It is fine to remove the comment out of POM file in case of PostgreSQL or Oracle database is used.. Modify the
JDBC driver version by actual use of the corresponding database version.

However, if Oracle is used, it is necessary to install the Oracle JDBC driver in the local repository of Maven before
removing the comment.

The following is an example of setting in case of PostgreSQL is used.

• artifactId/pom.xml

3.1. Create Web application development project 107


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
<!-- <dependency> -->
<!-- <groupId>com.oracle</groupId> -->
<!-- <artifactId>ojdbc7</artifactId> -->
<!-- <version>${ojdbc.version}</version> -->
<!-- </dependency> -->

<!-- ... -->

<postgresql.version>9.3-1102-jdbc41</postgresql.version>
<ojdbc.version>12.1.0.2</ojdbc.version>

• artifactId/artifactId-domain/pom.xml

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>provided</scope> -->
</dependency> -->
<!-- <dependency> -->
<!-- <groupId>com.oracle</groupId> -->
<!-- <artifactId>ojdbc7</artifactId> -->
<!-- <scope>provided</scope> -->
<!-- </dependency> -->

3.1.4 Structure of the development project

Explained the structure of the project created in Maven Archetype.

Below is the structure of the project created in Maven Archetype.

• Project structure of each layer that is recommended in this guideline

• Project structure that takes into account the exclusion of environmental dependency introduced in this
guideline

• Project structure that conscious the CI (Continuous Integration)

In addition, various settings have been included that is recommended in this guideline

108 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Web application configuration file (web.xml)

• Spring Framework Bean definition file

• Bean definition file for the Spring MVC

• Bean definition file for the Spring Security

• O/R Mapper configuration file

• Tiles configuration file

• Property file (such as message definition file)

and, as a simple component implementation of low (=necessary to develop every kind of application) dependency
on the application requirements,

• Controller and JSP for displaying Welcome page

• JSP to display an error screen (HTML)

• Template JSP for Tiles

• Include JSP for reading configuration such as JSP tag library

• CSS file that defines the screen style of entire application

etc are provided.

Warning: Components provided as a simple implementation


Components provided as a simple implementation can be corresponding to one of the following.
• Modification to meet the application requirements
• Removal of unnecessary components

Note: Procedure to create the REST API project

In the Maven Archetype created project, the recommended settings are done which are required for building a
traditional Web application (application that receives the request parameters and respond the HTML).

Therefore, unnecessary setting exists in building a REST API for handling JSON or XML. If you want to create
a project for building REST API, need to apply the REST API related settings by referring to the [Application
settings of RESTful Web Service].

Note: Part that is expressed as artifactId in the following description needs to be read by replacing the
artifactId which is specified at the time of creating a project.

3.1. Create Web application development project 109


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Multi-project structure

Initially entire multi-project structure is explained.

artifactId
├-- pom.xml ... (1)
├-- artifactId-web ... (2)
├-- artifactId-domain ... (3)
├-- artifactId-env ... (4)
├-- artifactId-initdb ... (5)
└-- artifactId-selenium ... (6)

110 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

The entire multi-project configuration is defined in POM (Project Object Model) file.
Mainly following definitions are done in this file.
(1)
• Version of the dependent libraries
• Build plug-ins settings (setting of how to build)
Refer [Hierarchical structure of the project] for the hierarchical relationship of multi-project.
Module that manages the application layer (Web layer) components.
Mainly following components and files are managed in this module.
(2)
• Controller class
• Validator class for relational check
• Form class (the Resource class in case of REST API)
• View (JSP)
• CSS file
• JavaScript file
• JUnit for the application layer components
• Bean definition file for defining the application layer components
• Web application configuration file (web.xml)
• Message definition file

Module that manages the domain layer components.


Mainly following components and files are managed in this module.
(3)
• Domain object such as Entity
• Repository
• Service
• DTO
• JUnit for the domain layer components
• Bean definition file for defining the domain layer components

Module that manages the environmental dependency settings files.


Mainly following files are managed in this module.
(4)
• Bean definition file for defining the environment dependent components
• Property file for defining the environment dependent properties value

Module that manages the database initialization SQL files.


Mainly following files are managed in this module.
(5)
• SQL file to create the database objects such as tables
• SQL file to insert the initial data such as master data
• SQL file to insert the test data used for E2E (End To End) test

Module that manages the Selenium used E2E testing components


Mainly following files are managed in this module.
(6)
3.1. Create Web application development
• JUnit testing project
using Selenium operation 111
• Expected value file used while Assert (if necessary)
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: About a terminology definition of [multi-project] in this guideline

The project created in Maven Archetype is the exact multi-module structured project.

This is supplement that the multi-module and multi-project is being used as the same meaning in this guideline.

Note: Development projects required for two Web applications and one common library

• bar-parent

• bar-initdb

• bar-common

• bar-common-web

• bar-domain-a

• bar-domain-b

• bar-web-a

• bar-web-b

• bar-env

• bar-web-a-selenium

• bar-web-b-selenium

The contents of each project are as follows.

• bar-parent

Project called as a parent-pom (parent POM). A simple project consisting of only pom.xml file. It never
contains other source code or configuration files. Common setting information specified in the parent POM
can be reflected in other project by specifying this bar-parent project into <parent> tag.

• bar-initdb

Stores RDBMS table definitions (DDL) and SQL statements for INSERT the initial data. This also managed
as a maven project. By defining sql-maven-plugin in pom.xml, it is possible to automate the execution of
DDL statements and initial data INSERT statements for any RDBMS in the course of the build lifecycle.

• bar-common

Stores common library in the project. Web related classes are placed in the bar-common-web by making it
as a web-independent.

112 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• bar-common-web

Stores common web library in the project.

• bar-domain-a

Stores unit test cases and domain layer java classes related to “a” domain. Finally *.jar file is created.

• bar-domain-b

Stores domain layer java classes related to “b” domain.

• bar-web-a

Stores application layer java classes, jsps, configuration files, unit test cases. Finally created *.war file is
created as the Web application. bar-web-a having dependency on bar-common and bar-env.

• bar-web-b

This is a Web application as one more subsystem. Structure is the same as the bar-web-a.

• bar-env

Collects only the configuration files having environment dependency.

• bar-web-a-selenium

Project that stores test cases using Selenium WebDriver for web-a project.

• bar-web-b-selenium

Project that stores test cases using Selenium WebDriver for web-b project.

Structure of Web module

Module that manages the application layer (Web layer) components are explained.

artifactId-web
├-- pom.xml ... (1)

Sr. No. Description

The web module configuration is defined in POM (Project Object Model) file. Following definitions
are done in this file.
(1)
• Definition of dependent libraries and build plug-ins
• Definition to create a war file

3.1. Create Web application development project 113


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: About the module name of the web module while creating a project for REST API

The application type can be easily distinguished, if the module name is assigned the name of artifactId-api
while building a REST API.

└-- src
├-- main
| ├-- java
| | └-- com
| | └-- example
| | └-- project
| | └-- app ... (2)
| | └-- welcome
| | └-- HelloController.java ... (3)
| ├-- resources
| | ├-- META-INF
| | | ├-- dozer ... (4)
| | | └-- spring ... (5)
| | | ├-- application.properties ... (6)
| | | ├-- applicationContext.xml ... (7)
| | | ├-- spring-mvc.xml ... (8)
| | | └-- spring-security.xml ... (9)
| | └-- i18n ... (10)
| | └-- application-messages.properties ... (11)

114 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

Package for storing the application layer classes.


The component type can be easily distinguished, if the package name is assigned the name of api
(2)
while building a REST API.

The controller class for receiving a request to display the Welcome page.

(3)

The directory in which a mapping definition file of Dozer (Bean Mapper) is stored, Refer to [Bean
Mapping (Dozer)] for Dozer.
(4)
It is an empty directory at the time of creation. If the mapping file is required (if high mapping is
required), it gets automatically read in case of stored under this directory.

Note: Following files are stored under this directory.


• Definition file for mapping the application layer JavaBean with domain layer JavaBean
• Definition file for each other mapping of application layer JavaBean
It is recommended to store each other mapping of domain layer JavaBean in domain layer directory.

Directory contains the property file and Spring Framework bean definition file.

(5)

Properties file that defines the settings to be used in the application layer.
It is an empty file at the time of creation.
(6)

Bean definition file to create an application context for Web applications.


Following beans are defined in this file.
(7)
• Components to be used in the entire Web application
• Domain layer components (Import the bean definition file in which domain layer components
are defined)

Bean definition file to create an application context for the DispatcherServlet.


Following beans are defined in this file.
(8)
• Spring MVC components
• application layer components
The application type can be easily distinguished, if the file name is assigned the name of
spring-mvc-api.xml while building a REST API.
Bean definition file for defining the Spring Security components.
This file is read when you create an application context for the Web application.
(9)

3.1. Create Web application


Directory development
that contains project
the message definition file to be used in the application layer. 115

(10)

Property file that defines the messages to be used in the application layer.
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: Refer [Relationship of bean definition file and application context structure] for the application context
and bean definition file related.

| └-- webapp
| ├-- WEB-INF
| | ├-- tiles ... (12)
| | | └-- tiles-definitions.xml
| | ├-- views ... (13)
| | | ├-- common
| | | | ├-- error ... (14)
| | | | | ├-- accessDeniedError.jsp
| | | | | ├-- businessError.jsp
| | | | | ├-- dataAccessError.jsp
| | | | | ├-- invalidCsrfTokenError.jsp
| | | | | ├-- missingCsrfTokenError.jsp
| | | | | ├-- resourceNotFoundError.jsp
| | | | | ├-- systemError.jsp
| | | | | ├-- transactionTokenError.jsp
| | | | | └-- unhandledSystemError.html
| | | | └-- include.jsp ... (15)
| | | ├-- layout ... (16)
| | | | ├-- header.jsp
| | | | └-- template.jsp
| | | └-- welcome
| | | └-- home.jsp ... (17)
| | └-- web.xml ... (18)
| └-- resources ... (19)
| └-- app
| └-- css
| └-- styles.css ... (20)
└-- test
├-- java
└-- resources

116 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

Directory that contains the Tiles configuration files. Refer [Screen Layout using Tiles] for the Tiles
configuration files.
(12)

Directory that contains the View generation templates (jsp etc).

(13)

Directory that contains the JSP and HTML for displaying error screens.
At the time of creation, JSPs (HTMLs) are stored corresponding to the errors that may occur during
(14)
application execution.

Note: Error screen JSP and HTML should be modified according to the application require-
ments (Such as UI Terms).

Common JSP files for include.


This file is included at the beginning of all JSP files. Refer [Creating common JSP for include] for
(15)
common JSP files for include.

Directory that contains the JSP files for the Tiles layout. Refer [Screen Layout using Tiles] for JSP
files for the Tiles layout.
(16)

JSP file that displays the Welcome page.

(17)

Configuration definition file for the Web application.

(18)

Directory that contains the static resource files.


This directory contains such files whose response contents are not going to change depending upon the
(19)
request contents. Specifically following files are stored.
• JavaScript files
• CSS files
• Image files
• HTML files
Here adopted a dedicated directory mechanism for managing static resources offered by Spring MVC.
CSS file that defines the screen style applied to the entire application.

(20)

3.1. Create Web application development project 117


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Structure of Domain module

Module that manages the domain layer components are explained.

artifactId-domain
├-- pom.xml ... (1)

Sr. No. Description

The domain module configuration is defined in POM (Project Object Model) file. Following definitions
are done in this file.
(1)
• Definition of dependent libraries and build plug-ins
• Definition to create a jar file

└-- src
├-- main
| ├-- java
| | └-- com
| | └-- example
| | └-- project
| | └-- domain ... (2)
| | ├-- model
| | ├-- repository
| | └-- service
| └-- resources
| └-- META-INF
| ├-- dozer ... (3)
| └-- spring ... (4)
| ├-- artifactId-codelist.xml ... (5)
| ├-- artifactId-domain.xml ... (6)
| └-- artifactId-infra.xml ... (7)

118 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

Package for storing the domain layer classes.

(2)

The directory in which a mapping definition file of Dozer (Bean Mapper) is stored, Refer to [Bean
Mapping (Dozer)] for Dozer.
(3)
It is an empty directory at the time of creation. If the mapping file is required (if high mapping is
required), it gets automatically read in case of stored under this directory.

Note: Following files are stored under this directory.


• Definition file for each other mapping of domain layer JavaBean

Directory contains the property file and Spring Framework bean definition file.

(4)

Bean definition file for defining the code list.

(5)

Bean definition file for defining the domain layer components.


Following beans are defined in this file.
(6)
• Domain layer components (Service, Repository etc)
• Infrastructure layer components (Import the bean definition file that the component has been
defined in the Infrastructure layer)
• Components for transaction management provided from Spring Framework.

Bean definition file for defining the Infrastructure layer components.


O/R Mapper etc beans are defined in this file.
(7)

└-- test
├-- java
| └-- com
| └-- example
| └-- project

3.1. Create Web application development project 119


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

| └-- domain
| ├-- repository
| └-- service
└-- resources
└-- test-context.xml ... (8)

Sr. No. Description

Bean definition file for defining the domain layer unit test components.

(8)

In case of project created for MyBatis3

└-- src
├-- main
| ├-- java
(...)
| └-- resources
| ├-- META-INF
| | ├-- dozer
| | ├-- mybatis ... (9)
| | | └-- mybatis-config.xml ... (10)
| | └-- spring
(...)
| └-- com
| └-- example
| └-- project
| └-- domain
| └-- repository ... (11)
| └-- sample
| └-- SampleRepository.xml ... (12)

120 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

Directory that contains the MyBatis3 configuration files

(9)

MyBatis3 configuration files.


Some of the recommended settings are defined at the time of creation.
(10)

Directory that contains the MyBatis3 Mapper files.

(11)

Sample file of MyBatis3 Mapper file.


Sample implementation is in commented out state at the time of creation Lastly, these files will not
(12)
required.

Structure of Env module

Module that manages the environment dependent configuration files are explained.

artifactId-env
├-- configs ... (1)
| ├-- production-server ... (2)
| | └-- resources
| └-- test-server
| └-- resources
├-- pom.xml ... (3)

3.1. Create Web application development project 121


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

Directory for managing the environment dependent configuration files.


Manage environment dependent configuration file by creating subdirectories of each environment.
(1)

Directory for managing the each environment configuration file.


At the time of creation, following directories (directory template) are provided as most simple config-
(2)
uration.
• production-server (Directory that contains the production environment configuration files)
• test-server (Directory that contains the test environment configuration files)

The env module configuration is defined in POM (Project Object Model) file. Following definitions
are done in this file.
(3)
• Definition of dependent libraries and build plug-ins
• Definition of Profile to create a jar file for each environment

└-- src
└-- main
└-- resources ... (4)
├-- META-INF
| └-- spring
| ├-- artifactId-env.xml ... (5)
| └-- artifactId-infra.properties ... (6)
├-- database ... (7)
| ├-- H2-dataload.sql
| └-- H2-schema.sql
├-- dozer.properties ... (8)
├-- log4jdbc.properties ... (9)
└-- logback.xml ... (10)

122 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

Directory for managing configuration files of the development.

(4)

Bean definition file that defines the environment dependent components.


Following beans are defined in this file.
(5)
• Datasource
• JodaTimeDateFactory offered by common library (In case of different implementations
depending on the environment)
• Components for transaction management provided by Spring Framework (In case of different
implementations depending on the environment)

Property file that defines the environment dependent settings.


At the time of creation, the DataSource settings are defined (Setting of the connection and connection
(6)
pool)

Directory that contains the SQL to set up an in-memory database (H2 Database).
This directory is prepared while performing small operation verification . Basically remove this di-
(7)
rectory because this directory is not intended to use in the actual application development.

Property file for carrying out the Dozer (Bean Mapper) global settings. For Dozer refer [Bean Mapping
(Dozer)].
(8)
It is an empty file at the time of creation. (The warning log appears at the start-up time if file is not
exist, the empty file is prepared in order to prevent it)
Property file for carrying out the Log4jdbc-remix (library to perform the JDBC-related log output)
global settings. For Log4jdbc-remix, refer [JDBC debug log settings].
(9)
At the time of creation, new line character related setting are specified for those SQLs which are going
to be printed in log.
Configuration file of the Logback (log output). For the log output refer [Logging].

(10)

Structure of Initdb module

Module that manages the SQL file to initialize the database is explained.

3.1. Create Web application development project 123


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

artifactId-initdb
├-- pom.xml ... (1)
└-- src
└-- main
└-- sqls ... (2)

Sr. No. Description

The initdb module configuration is defined in POM (Project Object Model) file. Following definitions
are done in this file.
(1)
• Definition of build plug-ins (SQL Maven Plugin)
Simple configuration for PostgreSQL is defined at the time of creation.
Directory for storing the database initialization SQL files.
It is an empty directory at the time of creation. For how to create, Refer Sample application of initdb
(2)
project.

Note: Can be executed SQL using sql:execute of SQL Maven Plugin.

mvn sql:execute

Structure of Selenium module

Module that manages the E2E (End To End) testing components used in Selenium explained.

artifactId-selenium
├-- pom.xml ... (1)
└-- src
└-- test ... (2)
├-- java
| └-- com
| └-- example
| └-- project
| └-- selenium
| └-- welcome
| └-- HelloTest.java ... (3)
└-- resources
└-- META-INF
└-- spring
├-- selenium.properties ... (4)
└-- seleniumContext.xml ... (5)

124 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

The selenium module configuration is defined in POM (Project Object Model) file.
Following definitions are done in this file.
(1)
• Definition of dependent libraries and build plug-ins
• Definition to create a war file

Directory that contains the configuration files and testing components.


For how to create, Refer Sample application of selenium project.
(2)

Sample test class using Selenium WebDriver.


At the time of creation, it has the test method for asserting a title of the Welcome page.
(3)

Properties file that defines the settings to be used in the test.


The URL of the application server is http://localhost:8080/at the time of creation.
(4)

Bean definition file for defining the test components.


At the time of creation, it defines required settings for executing the sample test.
(5)

3.1.5 Appendix

Hierarchical structure of the project

The hierarchical structure of the project indicated below which is created in Maven Archetype.

3.1. Create Web application development project 125


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

Project created in Maven Archetype.


The project created in Maven Archetype has become a multi-module configuration, parent project and
(1)
each sub-module have a cross-reference relationship.
In the project created in version 5.2.0.RELEASE Maven Archetype, [org.terasoluna.gfw:terasoluna-
gfw-parent:5.2.0.RELEASE] is specified as a parent project.
TERASOLUNA Server Framework for Java (5.x) Parent project.
In the TERASOLUNA Server Framework for Java (5.x) Parent project,
(2)
• Plug-ins settings for build
• Customization of libraries that is managed through Spring IO Platform (adjusted version)
• Version management of recommended libraries that is not managed by Spring IO Platform
are performed.
Furthermore, in order to version management of the dependent libraries via Spring IO Platform, im-
ported the [Spring IO Platform] into <dependencyManagement> of the project.
Spring IO Platform Version (the current project using) is described in OSS Versions.
Spring IO Platform project.
Since [org.springframework.boot:spring-boot-starter-parent:1.2.5.RELEASE] is specified as a parent
(3)
project, the definition of <dependencyManagement> defined into pom file of the spring-boot-
starter-parent also imported into pom file of the terasoluna-gfw-parent.
Spring Boot Starter Parent project.
Since [org.springframework.boot:spring-boot-dependencies:1.2.5.RELEASE] is specified as a parent
(4)
project, the definition of <dependencyManagement> defined into pom file of the spring-boot-
dependencies also imported into pom file of the terasoluna-gfw-parent.
Spring Boot Dependencies project.
126
(5) 3 Application Development
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Tip: The configuration has been changed like <dependencyManagement> of Spring IO Platform is imported
from version 5.0.0.RELEASE, we have adopted a style that version management of recommended libraries are
done in Spring IO Platform.

Warning: Since the configuration has been changed like <dependencyManagement> of Spring IO Plat-
form is imported from version 5.0.0.RELEASE, You are no longer able to access the version management
properties from the child project.
Therefore, if property values are referring or overwriting at the child project, pom file should be modified while
upgrading from version 1.0.x.
Furthermore, it is possible to access the conventional version management properties for recommended li-
braries (TERASOLUNA Server Framework for Java (5.x) recommended library) which are not managed by
the Spring IO Platform.

Relationship of bean definition file and application context structure

Relationship of bean definition file and structure of the Spring Framework application context (DI container)
indicated below.

3.1. Create Web application development project 127


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

Application context for the Web application.


As shown in above diagram, Components defined in
(1)
• artifactId-web/src/main/resource/META-INF/spring/applicationContext.xml
• artifactId-domain/src/main/resource/META-INF/spring/artifactId-domain.xml
• artifactId-domain/src/main/resource/META-INF/spring/artifactId-infra.xml
• artifactId-env/src/main/resource/META-INF/spring/artifactId-env.xml
• artifactId-domain/src/main/resource/META-INF/spring/artifactId-codelist.xml
• artifactId-web/src/main/resource/META-INF/spring/spring-security.xml
are registered in the application context (DI container) for the Web application..
Components registered in the application context for the Web application are mechanized such a way
that it can be referred by the application context of each DispatcherServlet.
Application context for DispatcherServlet.
As shown in above diagram, Components defined in
(2)
• artifactId-web/src/main/resource/META-INF/spring/spring-mvc.xml
are registered in the application context (DI container) for the DispatcherServlet.
Components not stored in the application context for the DispatcherServlet are mechanized
such a way that it can be obtained by referring the application context of the Web application (parent
context), hence it is possible to inject domain layer components for the application layer component.

Note: About the operation when registered the same components in both application contexts.

If same components are registered in both application context for web application and application context for
DispatcherServlet, injected component will be the registered component in the same application con-
text(Application context for DispatcherServlet) and this point is supplemented here.

In particular, it is necessary to be careful that do not register the domain layer component (such as Service and
Repository) to application context for the DispatcherServlet.

If domain layer components are registered to the application context for the DispatcherServlet, trouble like
the database operations are not committed occurs due to component that performs the transaction control (AOP)
is not enabled.

Furthermore, the settings are done in the project created using Maven Archetype so that the above events don’t
occur. It is necessary to be careful while performing modification or addition of the settings.

128 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Description of the configuration file

Todo

In order to increase the understanding of various settings, planning to add explanation of a configuration file.

• If functional description is explained somewhere, Reference to the functional description will be noted
down.

• If functional description is explained anywhere, description will be done here.

Specific time-line is not decided yet.

Application development in offline environment

In “Create development project”, a method to create a development project of multi-project configuration by using
archetype:generate of Maven Archetype Plugin is described. Although Maven is used for the operations in the
online environment, a method is described below for how to use it in offline environment as well.

To continue project development in the offline environment, the files like libraries and plugins necessary for
development must be copied in advance. The operation below should be performed in online environment.

Move to root directory of development project. Here, the project created using “Create development project” is
used for the explanation.

cd C:\work\todo

Copy the files like libraries and plugins necessary for project development. Files are copied by executing
dependency:go-offline of Maven Archetype Plugin.

mvn dependency:go-offline -Dmaven.repo.local=repository

3.1. Create Web application development project 129


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Parameter Description
Specify copy destination. A new destination is created if a copy destination does not
exist. At present, copy destination is specified as a repository.
–Dmaven.repo.local

Create a war file or a jar file in order to facilitate the distribution of deliverables. At that time, files like libraries
and plugins necessary for build are copied.

mvn package -Dmaven.repo.local=repository

When build is successful, the log shown below is output.

(... omit)
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] TERASOLUNA Server Framework for Java (5.x) Web Blank Multi Project (MyBa
tis3) SUCCESS [ 0.006 s]
[INFO] todo-env ........................................... SUCCESS [ 46.565 s]
[INFO] todo-domain ........................................ SUCCESS [ 0.684 s]
[INFO] todo-web ........................................... SUCCESS [ 12.832 s]
[INFO] todo-initdb ........................................ SUCCESS [ 0.067 s]
[INFO] todo-selenium ...................................... SUCCESS [01:13 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:14 min
[INFO] Finished at: 2015-10-01T10:32:34+09:00
[INFO] Final Memory: 36M/206M
[INFO] ------------------------------------------------------------------------

Above, files like libraries and plugins necessary for project development are copied. Operation is completed
when the repository is copied to ${HOME}/.m2 of offline environment machine. If a process which has not been
executed even once in online environment is executed in offline environment, necessary files like libraries and

130 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

plugins cannot be fetched resulting in the process failure. However, by copying the files, the development can be
continued uninterrupted even after moving to offline environment.

Warning: Precautions for the development in offline environment


Since it is not possible to fetch a new dependency relation from internet in the offline environment, POM
(Project Object Model) file should not be edited. It is necessary to return to online environment again for
editing POM file.

3.1. Create Web application development project 131


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

3.2 Domain Layer Implementation

3.2.1 Roles of domain layer

Domain layer implements business logicto be provided to the application layer.

Implementation of domain layer is classified into the following.

Sr. No. Classification Description

1. Implementation of Entity Creation of classes (Entity class) to hold business data.

2. Implementation of Repository Implementation of the methods to operate on business data.


These methods are provided to Service classes.
These are in particular the CRUD operations on Entity object.

3. Implementation of Service Implementation of the methods for executing business logic.


These methods are provided to the application layer.
Business data required by the business logic is fetched as the
Entity object through the Repository.

This guideline recommends the structure of creating Entity classes and Repository for the following reasons.

1. By splitting the overall logic into business logic (Service) and the logic to access business data, the
implementation scope of business logic gets limited to the implementation of business rules,

2. Access logic to business data is standardized by consolidating the operations of business data in the
Repository.

Note: Though this guideline recommends a structure to create Entity classes and Repository, it is not
mandatory to perform development in this structure.

Decide a structure by taking into account the characteristics of the application as well as the project (struc-
ture of development team and development methodology).

3.2.2 Flow of development of domain layer

Flow of development of domain layer and allocation of roles is explained here.

132 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

A case where application is created by multiple development teams is assumed; however, the flow itself remains
same even if developed by a single team.

3.2. Domain Layer Implementation 133


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Team in-charge Description

(1) Common Common development team designs and creates Entity classes.
development team

(2) Common Common development team works out access pattern for the Entity
development team classes extracted in (1) and designs methods of Repository interface.
Common development team should implement the methods to be shared
by multiple development teams.

(3) Common Common development team provides Entity classes and Repository
development team created in (1) and (2) to the business application development team.
At this time, it requests each business application development team to
implement the Repository interface.

(4) Business application Business application development team takes charge of the
development team implementation of Repository interface.

(5) Business application Business application development team develops Service interface and
development team Service class using the Entity class and Repository provided by
the common development team and the Repository implementation class
created by the team itself.

Warning: A system having a large development scope is often developed by assigning the application
to multiple teams. In that case, it is strongly recommended to provide a common team to design Entity
classes and Repository.
When there is no common team, O/R Mapper(MyBatis, etc.) should be called directly from Service and
a method to access business data should be adopted without creating Entity classes and Repository .

3.2.3 Implementation of Entity

Policy of creating Entity class

Create an Entity using the following method.

134 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Specific creation method is shown in Example of creating Entity class.

Sr. No. Method Supplementary

1. Create Entity class for each table. However, Entity class is not required for mapping tables
which represent the relationship between the tables.
Further, when the tables are not normalized, Entity class
for each table rule may not be applicable. Refer to the
Warning as well as Note outside this table
for the approach related to not-normalized tables.

2. When there is a FK (Foreign Key) in When there is 1:N relationship with FK destination table,
the table, the Entity class of FK use either java.util.List<E> or
destination table must be defined as java.util.Set<E>.
one of the properties of this Entity. The Entity corresponding to the FK destination table is
called as the related Entity in this guideline.

3. Treat the code related tables as Code related tables are to manage the pairs of code value
java.lang.String rather than and name.
as an Entity. When there is a need to bifurcate the process as per code
values, enum class corresponding to code value should be
created and it must be defined as property.

3.2. Domain Layer Implementation 135


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Warning: When table is not normalized, check whether to use the method of creating the Entity
classes and Repository by considering the following points. Since the unnormalized tables do not have
good compatibility with JPA, it is better not to use JPA.
• Creating an appropriate Entity class may often not be possible because of increased difficulty in
creating entities if the tables are not normalized.
In addition, efforts to create an Entity classes also increases.
Two viewpoints must be taken into consideration here. Firstly “Can we assign an engineer who
can perform normalization properly?” and secondly “Is it worth taking efforts for creating
normalized Entity classes?”.
• If the tables are not normalized, the logic to fill the gap of differences between the Entity class
and structure of table is required in data access.
Here the viewpoint to be considered is, “Is it worth taking efforts to fill the gap of differences
between the Entity class and structure of table ?”.
The method of creating Entity classes and Repository is recommended; however, the characteristics of
the application as well as the project (structure of development team and development methodology)
must also be taken into account.

Note: If you want to operate business data as application, and as normalized Entity even if the tables
are not normalized, it is recommended to use MyBatis as an implementation of RepositoryImpl of the
infrastructure layer.

MyBatis is the O/R Mapper developed to map the SQL with object and not to map the database table record
with object. Therefore, mapping to the object independent of table structure is possible depending on the
implementation of SQL, .

Example of creating Entity class

The creation of Entity class is explained using specific examples.


Following is an example of creating the business data of Entity classes required for purchasing a product on some
shopping site.

Table structure

The table structure is as given below:

136 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Classification Table name Description

(1) Transaction related t_order Table to store orders. 1 record is stored for 1 order.

(2) t_order_item Table to store the products purchased in 1 order. Record


of each product is stored when multiple products are
purchased in 1 order.

(3) t_order_coupon Table to store the coupon used in a single order. Record of
each coupon is stored when multiple coupons are used in
1 order. No record is stored when coupon is not used.

(4) Master related m_item Master table to define products.

3.2. Domain
(5) Layer Implementation m_category Master table to define product category. 137

(6) Master table to define the category of the product.


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Entity structure

If Entity classes are created with the help of policy defined by the above table, it results into the following structure.

138 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Class name Description

(1) Order Entity class indicating 1 record of t_order table.


Multiple OrderItem and OrderCoupon are stored as the related
Entity.

(2) OrderItem Entity class indicating 1 record of t_order_item table.


Item is stored as the related Entity.

(3) OrderCoupon Entity class indicating 1 record of t_order_coupon table.


Coupon is stored as the related Entity.

(4) Item Entity class indicating 1 record of m_item table.


Multiple Category are stored as the related Entity. The association
between Item and Category is done using m_item_category
table.

(5) Category Entity class indicating 1 record of m_category table.

(6) ItemCategory Entity class is not created since m_item_category table is the
mapping table to store the relationship between m_item table and
m_category table.

(7) Coupon Entity class indicating 1 record of m_coupon table.

(8) OrderStatus Entity class is not created since c_order_status table is code table.

As it can be observed from the above entity diagram, it might first seem that Order class is the only main entity
class in the shopping site application; however, there are other main entity class as well other than Order class.

Below is the classification of main Entity classes as well as Entity class which are not main.

3.2. Domain Layer Implementation 139


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

The following 4 Entities are treated as the main Entity for creating shopping site application.

140 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Entity class Reasons for treating as the main Entity.

(1) Order class It is one of the most important Entity class in the shopping site.
Order class is the Entity indicating the order itself and a
shopping site cannot be created without the Order class.

(2) Item class It is one of the most important Entity class in the shopping site.
Item class is the Entity indicating the products handled in the
shopping site and a shopping site cannot be created without
Item class.

(3) Category class Product categories are displayed usually on the top page or as a
common menu in shopping sites. In such shopping sites,
Category becomes a main entity. Usually operations like
‘search category list’ can be expected.

(4) Coupon class Often discounts through coupons are offered in the shopping
sites as a measure of promoting sales of the products.
In such shopping sites, Coupon becomes a main entity. Usually
operations like ‘search coupon list’ can be expected.

The following are not main Entities for creating shopping site application.

Sr. No. Entity class Reason of not treating Entity as main Entity

(5) OrderItem class This class indicates 1 product purchased in 1 order and exists
only as the related Entity of Order class.
So OrderItem class should not be considered as main Entity.

(6) OrderCoupon This class indicates 1 coupon used in 1 order and exists only as
the related Entity of Order class.
So, OrderCoupon class should not be considered as main Entity.

3.2. Domain Layer Implementation 141


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

3.2.4 Implementation of Repository

Roles of Repository

Repository has following 2 roles.

1. To provide to Service, the operations necessary to control Entity lifecycle (Repository interface).
The operations for controlling Entity lifecycle are CRUD operations.

2. To provide persistence logic for Entity (implementation class of Repository interface).


Entity object should persist irrespective of the lifecycle (start and stop of server) of application.
Mostly relational database is the permanent destination of Entity. However, NoSQL database, cache
server, external system and file (shared disk) can also be the permanent destination.
The actual persistence processing is done using O/R Mapper API.
This role is implemented in the RepositoryImpl of the infrastructure layer. Refer to Implementation of
Infrastructure Layer for details.

Structure of Repository

Repository consists of Repository interface and RepositoryImpl and performs the following roles.

142 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Class(Interface) Role Description

(1) Repository interface Defines methods to control Defines methods for CRUD operations of
Entity lifecycle required for the Entity and is not dependent on
implementing business logic persistence layer.
(Service). Repository interface belongs to the
domain layer since it plays the roles of
defining the operations on Entity required
for implementing business logic (Service).

(2) RepositoryImpl Implements the methods Implements CRUD operations of the


defined in Repository interface. Entity and is dependent on persistence
layer. Performs actual CRUD processes
using API that performs persistence
3.2. Domain Layer Implementation 143
provided by Spring Framework, O/R
Mapper and middleware.
RepositoryImpl belongs to infrastructure
layer since it plays the role of
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

In case of multiple destinations in persistence layer, the resulting configuration as follows.


due to this, the logic depending on persistence platform of Entity is hidden from business logic (Service).

Note: Is it possible to hide 100% of persistence platform dependent logic from the Service class ?

In some cases it cannot be hidden completely due to constraints of persistence platform and the libraries
used to access the platform. As much as possible, platform dependent logic should be implemented in
RepositoryImpl instead of Service class. When it is difficult to exclude the platform dependent logic and
merits of doing so are less, persistence platform dependent logic can be implemented as a part of business
logic (Service) process.

A specific example of this is given here. There are cases when unique
constraints violation error is needed to be handled when save method of
org.springframework.data.jpa.repository.JpaRepository interface provided by
Spring Data JPA is called. In case of JPA, there is a mechanism of cache entity operations and SQL is
executed when transactions are committed. Therefore, since SQL is not executed even if save method of
JpaRepository is called, unique constraints violation error cannot be handled in logic. There is a method
(flush method) to reflect cached operations as means to explicitly issue SQLs in JPA. saveAndFlush

144 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

and flush methods are also provided in JpaRepository for the same purpose. Therefore, when unique
constraints violation error needs to be handled using JpaRepository of Spring Data JPA, JPA dependent
method (saveAndFlush or flush) must be called.

Warning: The most important purpose of creating Repository is not to exclude the persistence platform
dependent logic from business logic. The most important purpose is to limit the implementation scope
of business logic (Service) to the implementation of business rules. This is done by separating the
operations to access business data in Repository. As an outcome of this, persistence platform dependent
logic gets implemented in Repository instead of business logic (Service).

Creation of Repository

Repository must be created using the following policy only.

Sr. No. Method Supplementary

1. Create Repository for the main This means separate Repository for operations of related
Entity only. Entity is not required.
However, there are case when it is better to provide
Repository for the related Entity in specific applications
(for example,
application having high performance requirements etc).

2. Place Repository interface and Repository interface belongs to domain layer and
RepositoryImpl in the same package RepositoryImpl belongs to infrastructure layer. However,
of domain layer. Java package of RepositoryImpl can be same as the
Repository interface of domain layer.

3. Place DTO used in Repository in the For example, DTO to store search criteria or summary
same package as Repository DTO for that defines only a few items of Entity.
interface.

Example of creating Repository

An example of creating Repository is explained here.


An example of creating Repository of Entity class used in the explanation of Example of creating Entity class is

3.2. Domain Layer Implementation 145


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

as follows.

Structure of Repository

Entity class used in the explanation of Example of creating Entity class is used as an example, the resulting
configuration is as follows:

Repository is created for the main Entity class.


Refer to Project structure for the recommended package structure.

Definition of Repository interface

Creation of Repository interface

An example of creating Repository interface is introduced below.

• SimpleCrudRepository.java

This interface provides only simple CRUD operations.

146 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Method signature is created by referring to CrudRepository interface and


PagingAndSortingRepository provided by Spring Data.

public interface SimpleCrudRepository<T, ID extends Serializable> {


// (1)
T findOne(ID id);
// (2)
boolean exists(ID id);
// (3)
List<T> findAll();
// (4)
Page<T> findAll(Pageable pageable);
// (5)
long count();
// (6)
T save(T entity);
// (7)
void delete(T entity);
}

3.2. Domain Layer Implementation 147


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Method to fetch the Entity object of specified ID.

(2) Method to determine if the Entity of specified ID exists or not.

(3) Method to retrieve the list of all Entities. In Spring Data, it was java.util.Iterable.
Here as a sample, it is set to java.util.List.

(4) Method to fetch collection of Entity objects corresponding to the specified pagination
information (start position, record count, sort information).
Pageable and Page are the interfaces provided by Spring Data.

(5) Method to fetch total number of Entity objects.

(6) Method to save (create, update) the specified Entity collection.

(7) Method to delete the specified Entity.

• TodoRepository.java

An example of creating Repository of Todo Entity, which was created in tutorial, on the basis of
SimpleCrudRepository interface created above is shown below.

// (1)
public interface TodoRepository extends SimpleCrudRepository<Todo, String> {
// (2)
long countByFinished(boolean finished);
}

148 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) TodoRepository interface is created by specifying Todo entity in the generic type parameter “T”
and
String class in the generic type parameter “ID”.

(2) Methods not provided by SimpleCrudRepository interface are added in this interface.
In this case, “Method for acquiring count of Todo entity objects for which specified tasks have
been finished” is added.

Method definition of Repository interface

It is recommended to have the same signature as CrudRepository and


PagingAndSortingRepository provided by Spring Data for the methods performing general CRUD
operations.
However, in case of returning collection, (java.util.Collection or java.util.List) interfaces
which can be handled in a better way in logic are better than java.lang.Iterable.
In real development environment, it is difficult to develop an application using only general CRUD operations.
Hence additional methods are required.
It is recommended to add the methods as per the following rules.

3.2. Domain Layer Implementation 149


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Types of methods Rules


Method for searching
1. 1. Method name beginning with findOneByto indicate that this method
a single record
fetches a single record that matches with the condition.
2. In the method name after “findOneBy”, physical or logical name of the
field used as search condition must be specified. Hence, the method
name must be such that it becomes possible to estimate “the kind of
entity that can be fetched using this method”.
3. There must be an argument for each search condition. However, when
there are many conditions, DTO containing all search conditions can
be provided.
4. Return value must be Entity class.

Method for searching


2. 1. Method name beginning with findAllByto indicate that this method
multiple records
fetches all the records that matches with the condition.
2. In the method name after “findAllBy”, physical or logical name of the
field used as search condition must be specified. Hence, the method
name must be such that it becomes possible to estimate “the kind of
entity that can be fetched using this method”.
3. There must be an argument for each search condition. However, when
there are many conditions, DTO containing all search conditions can
be provided.
4. Return value must be collection of Entity class.

Method for searching


3. 1. Method name beginning with findPageByto indicate that this method
multiple records with
fetches pages that matches with the condition.
pagination
2. In the method name after “findPageBy”, physical or logical name
of the field used as search condition must be specified. Hence, the
method name must be such that it becomes possible to estimate “the
kind of entity that can be fetched using this method”.
3. There must be an argument for each search condition. However, when
there are many conditions, DTO containing all search conditions can
be provided. Pageable provided by Spring Data should be the in-
terface for pagination information (start position, record count, sort
information).
4. Return value should be Page interface provided by Spring Data.

Count related
4. 1. Method name beginning with countBy to indicate that this method
method
fetches count of Entities which matches with the condition.
2. Return value must be long type.
3. In the method name after “countBy”, physical or logical name of the
field used as search condition must be specified. Hence, the method
150 name must be such that it becomes possible to
3 Application estimate “the kind of
Development
entity that can be fetched using this method”.
4. There must be an argument for each search condition. However, when
there are many conditions, DTO containing all search conditions can
be provided.
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: In case of methods related to update processing, it is recommended to construct methods in the
same way as shown above. “find” in the method name above can be replaced by “update” or “delete”.

• Todo.java (Entity)

public class Todo implements Serializable {


private String todoId;
private String todoTitle;
private boolean finished;
private Date createdAt;
// ...
}

• TodoRepository.java

public interface TodoRepository extends SimpleCrudRepository<Todo, String> {


// (1)
Todo findOneByTodoTitle(String todoTitle);
// (2)
List<Todo> findAllByUnfinished();
// (3)
Page<Todo> findPageByUnfinished();
// (4)
long countByExpired(int validDays);
// (5)
boolean existsByCreateAt(Date date);
}

3.2. Domain Layer Implementation 151


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Example of method that fetches TODO objects whose title matches with specified value
(TODO in which todoTitle=[argument value]).
Physical name(todoTitle) of condition field is specified after findOneBy.

(2) Example of method that fetches unfinished TODO objects (TODO objects where
finished=false).
Logical condition name is specified after findAllBy.

(3) Example of method that fetches pages of unfinished TODOs (TODO objects where
finished=false).
Logical condition name is specified after findPageBy.

(4) Example of method that fetches count of TODO objects for which the finish deadline has
already passed (TODO for which createdAt < sysdate - [finish deadline in days] &&
finished=false).
Logical condition name is specified after countBy.

(5) Example of method that checks whether a TODO is created on a specific date
(createdAt=specified date).
Physical name (createdAt) is specified after existsBy.

Creation of RepositoryImpl

Refer to Implementation of Infrastructure Layer for the implementation of RepositoryImpl.

3.2.5 Implementation of Service

Roles of Service

Service plays the following 2 roles.

1. Provides business logic to Controller.

152 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Business logic consists of create, update, consistency check etc of business data as well as all the
processes related to business logic.
Create and update process of business data should be delegated to Repository(or O/R Mapper) and service
should be limited to implementation of business rules.

Note: Regarding distribution of logic between Controller and Service

In this guideline, the logic to be implemented by Controller and Service should be as per the rules given
below.

1. For the data requested from the client, single item check and correlated item check is to be performed
in Controller (Bean Validation or Spring Validator).

2. Conversion processes (Bean conversion, Type conversion and Format conversion) for the data to be
passed to Service, must be performed in Controller instead of Service.

3. Business rules should be implemented in Service.Access to business data is to be delegated to Repos-


itory or O/R Mapper.

4. Conversion processes (Type conversion and Format conversion) for the data received from Service
(data to respond to the client), must be performed in Controller (View class etc).

2. Declare transaction boundary.


Declare transaction boundary when business logic is performing any operation which requires ensuring
data consistency (mainly data update process).
Even in case of logic that just read the data, often there are cases where transaction management is
required due to the nature of business requirements. In such cases, declare transaction boundary.
Transaction boundary must be set in Service layer as a principle rule. If it is found to be set in
application layer (Web layer), there is a possibility that the extraction of business logic has

3.2. Domain Layer Implementation 153


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

not been performed correctly.

Refer to Regarding transaction management for details.

Structure of Service class

Service consists of Service classes and SharedService classes and plays the following role.
In this guideline, POJO (Plain Old Java Object) having @Service annotation is defined as Service or
SharedService class.
We are not preventing the creation of interface and base classes that limit the signature of methods.

154 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Class Role Notes related to dependency relationship


Service class
1. 1. It is prohibited to call a method of Ser-
Provides business logic to the vice class from another Service class
specific Controller. method (Figure 1-1).For shared logic, cre-
Service class methods must ate SharedService class.
not implement logic that need 2. Method of Service class can be called from
to be reused. multiple Controllers (Figure 1-2). How-
ever, it must be created for each con-
troller when processing is to be branched
based on the calling controller.In such a
scenario, create a method in SharedService
class and call that method from the individ-
ual Service class methods.

2 SharedService
1. Methods of other SharedService classes can
class
Provides shared (reusable) be called from a SharedService (Figure 2-
logicfor multiple Controllers 1). However, Calling hierarchy should
and Service classes. not become complicated. If calling hier-
archy becomes complicated, there is a risk
of reduction in maintainability.
2. Methods of SharedService classes can be
called from Controller (Figure 2-2). How-
ever, it can be only be done if there is
no problem from transaction manage-
ment perspective.If there is a problem
from transaction management perspective,
first create a method in Service class and
implement transaction management in this
method.
3. It is prohibited to call methods of Service
class from SharedService (Figure 2-3).

Dependency relationship of Service class and SharedService class is shown below.


The numbers inside the diagram are related to the numbering in “Notes related to dependency relationship”
column of the above table.

3.2. Domain Layer Implementation 155


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Reason for separating Service and SharedService

Logic that cannot be (should not be) reused and logic that can be (should be) reused exist in the business logic.
To implement these 2 logics in the same class, it is difficult to decide whether a method can be re-used or not.
To avoid this problem, it is strongly recommended to implement the method to be re-used in the
SharedService classin this guideline.

Reason for prohibiting the calling of other Service classes from Service class

In this guideline, calling methods of other Service classes from a Service class is prohibited.
Service provides business logic to a specific controller and is not created with the assumption of using it from
other services.
If it is called directly from other Service classes, the following situations can easily occur and there is a risk of
reduced maintainability.

156 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Situations that can occur

1.
The logic that must be implemented in the calling service class, gets implemented in the called
service class for reasons like “having the logic at a single location” etc.
As a result, arguments for identifying the caller, get added to the method easily;
Ultimately, the logic is incorrectly abstracted out as shared logic (like utilities). It results
into a modular structure without much insight.

2.
If the stack patterns or stack of services calling each other is large in number, understanding
the impact of modifications in source-code due to change in specifications or bug fixes,
becomes difficult.

Regarding interface and base classes to limit signature of method

In order to bring consistency in development of business logic, interfaces and base classes are created which limit
the signature of the methods.
The purpose is also to prevent the injection of differences due to development style of each developer by limiting
the signature through interfaces and base classes.

Note: In large scale development, there are situations where not every single developer is highly skilled
or situations like having consistency in development of business logic considering maintainability after
servicing. In such situations, limiting the signature through interfaces can be an appropriate decision.

In this guideline, we do not specifically recommended to create interface to limit signature; however, type
of architecture must be selected on the basis of characteristics of the project. decide the type of architecture
taking into account the project properties.

Note: Sample of implementation of interface and base classes to limit signature - Interface to limit
signature

// (1)
public interface BLogic<I, O> {
O execute(I input);
}

3.2. Domain Layer Implementation 157


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Interface to limit signature of implementation method of business logic.


In the above example, it is defined as generic type of input (I) and output (O) information
having one method (execute) for executing business logic.
In this guideline, the above interface is called BLogic interface.

• Controller

// (2)
@Inject
XxxBLogic<XxxInput, XxxOutput> xxxBLogic;

public String reserve(XxxForm form, RedirectAttributes redirectAttributes) {

XxxInput input = new XxxInput();


// omitted

// (3)
XxxOutput output = xxxBlogic.execute(input);

// omitted

redirectAttributes.addFlashAttribute(output.getTourReservation());
return "redirect:/xxx?complete";
}

Sr. No. Description

(2) Controller injects calling BLogic interface.

(3) Controller calls execute method of BLogic interface and executes business logic.

To standardize process flow of business logic when a fixed common process is included in Service, base
classes are created to limit signature of method.

• Base classes to limit signature

public abstract class AbstractBLogic<I, O> implements BLogic<I, O> {

public O execute(I input){


try{

// omitted

158 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

// (4)
preExecute(input);

// (5)
O output = doExecute(input);

// omitted

return output;
} finally {
// omitted
}

protected abstract void preExecute(I input);

protected abstract O doExecute(I input);

Sr. No. Description

(4) Call the method to perform pre-processing before executing business logic from base
classes.
In the preExecute method, business rules are checked.

(5) Call the method executing business logic from the base classes.

Sample of extending base classes to limit signature is shown below.

• BLogic class (Service)

public class XxxBLogic extends AbstractBLogic<XxxInput, XxxOutput> {

// (6)
protected void preExecute(XxxInput input) {

// omitted
Tour tour = tourRepository.findOne(input.getTourId());
Date reservationLimitDate = tour.reservationLimitDate();
if(input.getReservationDate().after(reservationLimitDate)){
throw new BusinessException(ResultMessages.error().add("e.xx.xx.0001"));
}

3.2. Domain Layer Implementation 159


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

// (7)
protected XxxOutput doExecute(XxxInput input) {
TourReservation tourReservation = new TourReservation();

// omitted

tourReservationRepository.save(tourReservation);
XxxOutput output = new XxxOutput();
output.setTourReservation(tourReservation);

// omitted
return output;
}

Sr. No. Description

(6) Implement pre-process before executing business logic.


Business rules are checked.

(7) Implement business logic.


Logic is implemented to satisfy business rules.

Patterns of creating service class

There are mainly 3 patterns for creating Service.

160 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Unit Creation method Description

1.
For each Entity Create Service paired with Main Entity is in other words, business data. If the
the main Entity. application is to be designed and implemented
with focus on business data, then Service classes
should be created in this way.

If service is created in this way, business logic will


also be created for each entity and it will become to
extract shared logic.
However, if Service is created using this pattern, its
affinity is not so good with the type of application
which has to be developed
by introducing a large number of developers at the
same time.
It can be said that the pattern is suitable when for the
developing small or medium sized application.

2.
For each Create Service paired with If the application is to be designed and
use-case the use-case. implemented with focus on events on the screen,
Service should be created in this way.

If the Service is created using this pattern, it is


possible to assign a person to each use case; hence,
its affinity is good with
the type of application which has to be developed by
introducing a large number of developer at the same
time.

On the other hand, if Service is created using this


pattern, shared logic within use case can be extracted
to a single location;
however, shared logic which spans across multiple
use-case might not get extracted to a single location.
When it is very important to have extract shared
logic out to a single location, it becomes necessary
devise measures like having
a separate team to look after designing shared
components of business logic that span across
3.2. Domain Layer Implementation multiple use cases. 161

3.
For each event Create Service paired with If the application is to be designed and
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Warning: The pattern of Service creation must be decided by taking into account the features of
application to be developed and the structure of development team.
It is not necessary to narrow down to any one pattern out of the 3 indicated patterns. Creating Ser-
vices using different patterns randomly should be avoided for sure; however, patterns can be used in
combinations, if policy of usage of patterns in certain specific conditions has been well-thought
decision and has been directed by the architect. For example, the following combinations are possi-
ble.
[Example of usage of patterns in combination]
• For the business logic very important to the whole application, create as SharedService class for
each Entity.
• For the business logic to be processed for the events from the screen, create as Service class for
each Controller.
• In the Service class for each controller, implement business logic by calling the sharedService as
and when required.

Tip: BLogic is generated directly from design documents when using “TERASOLUNA ViSC”.

Image of Application development - Creating Service for each Entity

Following is the image of application development when creating a Service for each Entity.

Note: An example of a typical application in which a Service is created for each Entity is a REST applica-
tion. REST application provides CRUD operations (POST, GET, PUT, DELETE of HTTP) for published
resources on HTTP. Most of the times, the resources published on HTTP are business data (Entity) or part
of business data (Entity), they have good compatibility with the pattern of creating Service for each Entity.

In case of REST application, most of the times, use-cases are also extracted on a “per Entity” basis. Hence,
the structure is similar to the case when Service is created for on a “per use-case” basis.

162 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Implement Service by assigning a person for each Entity.


If there is no specific reason, it is desirable that Controller must also be created for each Entity
and must be developed by the same developer who created the Service class.

(2) Implement SharedService if there is shared logic between multiple business logics.
In the above figure, different person is assigned as the in-charge. However, he may be the same
person as (1) depending per the project structure.

Image of Application development - Creating Service for each use case

Following is the image of application development when creating a Service for each use-case.
In case of use-case which performs CRUD operations on the Entity, structure is same as in case of creating

3.2. Domain Layer Implementation 163


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Service for each Entity.

Sr. No. Description

(1) Implement Service by assigning a person for each use-case.


If there is no specific reason, it is desirable that Controller must also be created for each
use-case and must be developed by the same developer who created the Service class.

(2) Implement SharedService if there is shared logic between multiple business logics.
In the above figure, different person is assigned as the in-charge. However, he may be the same
person as (1) depending per the project structure.

Note: With an increase in the size of the use-cases, the development scope of a person increases. At
such a point of time, it becomes difficult to divide the work of this use-case with other developers. In case
of application which has to be developed by introducing a large number of developer at the same time,
the use-case can be further split into finer use-cases and which can then be allocated to more number of

164 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

developers.

Below is the image of application development when the use-case is further split.
Splitting a use-case has no impact on SharedService. Hence, the explanation is omitted here.

3.2. Domain Layer Implementation 165


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Divide the use-case into finer processes which make-up the complete use-case. Assign each
fine process to a developer. Each developer creates the Service for assigned process.
Note that the processes here are operations like search, create, update, delete etc. and these
processes do not have a direct mapping to the processing required to be done for
each event generated on screen.
For example, if it the event generated on screen is “Update”, it includes multiple finer processes
such as “Fetching the data to be updated”, “Compatibility check of update contents” etc.
If there is no specific reason, it is desirable that Controller must also be created for each of these
finer processes and must be developed by the same developer who creates the Service class.

Tip: In some projects, “group of use-cases” and “use-cases” are used in place of “use-case” and “pro-
cesses” used in this guideline.

Image of Application development - Creating Service for each use event

Following is the image of application development when creating a Service(BLogic) for each event.

166 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Implement Service(BLogic) by assigning a person for each event.


Above example is an extreme case where separate developer is assigned for each
service(BLogic).
In reality, a single person must be assigned for a use-case.

(2) If there is no specific reason, controller also should be created on “per use-case” basis.

(3) Even if the separate Service(BLogic) is created for each event, it is recommended that same
person is the in-charge of the complete use-case.
3.2. Domain Layer Implementation 167

(4) Implement in SharedService to share the logic with multiple business logics.
In the above figure, different person is assigned as the in-charge. However, he may be the same
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: With an increase in the size of the use-cases, the development scope of a person increases. At
such a point of time, it becomes difficult to divide the work of this use-case with other developers. In case
of application which has to be developed by introducing a large number of developer at the same time,
the use-case can be further split into finer use-cases and which can then be allocated to more number of
developers.

Below is the image of application development when the use-case is further split.
Splitting a use-case has no impact on SharedService. Hence, the explanation is omitted here.

168 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Divide the use-case into finer processes which make-up the complete use-case. Assign each
fine process to a developer. Each developer creates the Service for assigned process.
Note that the processes here are operations like search, create, update, delete etc. and these
processes do not have a direct mapping to the processing required to be done for
each event generated on screen.
For example, if it the event generated on screen is “Update”, it includes multiple finer processes
such as “Fetching the data to be updated”, “Compatibility check of update contents” etc.
If there is no specific reason, it is desirable that Controller must also be created for each of these
finer processes and must be developed by the same developer who creates the Service class.

Creation of Service class

Methods of creating Service class

Below are the points to be taken care of while creating Service class.

• Creation of Service interface

public interface CartService { // (1)


// omitted
}

Sr. No. Description

(1) It is recommended to create Service interface.


By providing an interface, it is possible to execute the method published as Service explicitly.

Note: Merits from architecture perspective

1. If interface is there, When using AOP, Dynamic proxies functionality of standard JDK is used. In
case of no interface, CGLIB included in Spring Framework is used. In case of CGLIB there are certain
restrictions like “Advice cannot be applied on final methods” etc. Refer to Spring Reference Document
-Aspect Oriented Programming with Spring(Proxying mechanisms)-for details.

2. It becomes easier to create a stub of business logic. When application layer and domain layer are
developed in parallel using different development teams, stubs of Service are required. When there is
a need to create stubs, it is recommended to have interface .

3.2. Domain Layer Implementation 169


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Creation of Service class

@Service // (1)
@Transactional // (2)
public class CartServiceImpl implements CartService { // (3) (4)
// omitted
}

<context:component-scan base-package="xxx.yyy.zzz.domain" /> <!-- (1) -->

Sr. No. Description

(1) Add @Service annotation to class.


By adding the above annotation, bean definition in configuration file is not required.
Specify package for component scanning in base-package attribute of
<context:component-scan> element.
In case of this example, all the classes in “xxx.yyy.zzz.domain” is registered in container.

(2) Add @Transactional annotation to class.


By adding the above annotation, transaction boundary is set for to the all the methods of the
Service class.
value attribute should be specified as required.
Refer to Information required for “Declarative transaction management” for details.

Moreover, to understand the points to be noted when using @Transactional annotation, it


is advisable to confirm with “Settings for using transaction management”.

(3) Consider interface name as XxxService and class name as XxxServiceImpl.


Any naming conventions can be used. However, it is recommended to use distinguishable
naming conventions for Service class and SharedService class.

(4) Service class must not maintain state. Register it in container as bean of singleton scope .
Objects (POJO such as Entity/DTO/VO) and values (primitive type, primitive wrapper class)
where state changes in each thread should not be maintained in class level fields.
Setting scope to any value other than singleton (prototype, request, session) using @Scope
annotation is also prohibited.

170 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: Reason for adding @Transactional annotation to class

Transaction boundary is required only for the business logic that updates the database. However, it is
recommended to apply the annotation at class level to prevent bugs due to skipped annotation. However,
defining @Transactional annotation only at required places (methods which update the database) is
also fine.

Note: Reason to prohibit non-singleton scopes

1. prototype, request, session are the scopes for registering bean that maintains state. Hence they must
not be used in Service class.

2. When scope is set to request or prototype, performance is affected as the bean generation frequency is
high in DI container.

3. When scope is set to request or session, it cannot be used in non Web applications (for example, Batch
application).

Creation of methods of Service class

Below are the points to be taken care of while writing methods of Service class.

• Creation of method of Service interface

public interface CartService {


Cart createCart(); // (1) (2)
Cart findCart(String cartId); // (1) (2)
}

• Creation of methods of Service class

@Service
@Transactional
public class CartServiceImpl implements CartService {

@Inject
CartRepository cartRepository;

public Cart createCart() { // (1) (2)


Cart cart = new Cart();
// ...
cartRepository.save(cart);
return cart;
}

3.2. Domain Layer Implementation 171


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@Transactional(readOnly = true) // (3)


public Cart findCart(String cartId) { // (1) (2)
Cart cart = cartRepository.findByCartId(cartId);
// ...
return cart;
}

Sr. No. Description

(1) Create a method of Service class for each business logic.

(2) Define methods in Service interface and implement business logic in its implementation
class.

(3) Add @Transactional annotation for changes to default transaction definition (class level
annotation).
Attributes should be specified as per the requirement.
Refer to Information required for “Declarative transaction management” for details.

Moreover, to understand the points to be noted when using @Transactional annotation, it


is advisable to confirm with “Settings for using transaction management”.

Tip: Transaction definition of business logic for reference

When business logic for reference is to be implemented, by specifying @Transactional(readOnly


= true), instruction can be given to run the SQL under “Read-only transactions” for JDBC driver.

The way of handling read-only transactions depends on the implementation of JDBC driver; hence, confirm
the specifications of JDBC driver to be used.

Note: Points to be noted when using “Read-only transactions”

If it is set to “perform health check” when retrieving a connection from connection pool, “Read-only
transactions” may not be enabled. For details on this event and to avoid the same, refer to About cases
where “Read-only transactions” are not enabled.

172 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: Transaction definition when a new transaction is required to be started

Set @Transactional(propagation = Propagation.REQUIRES_NEW) to start a new trans-


action without participating in the transaction of the caller method.

Regarding arguments and return values of methods of Service class

The below points must be considered for arguments and return values of methods of Service class.

Serializable classes (class implementing java.io.Serializable) must be used for arguments and return
values of Service class.
Since there is possibility of Service class getting deployed as distributed application, it is recommended to allow
only Serializable class.

Typical arguments and return values of the methods are as follows.

• Primitive types (int, long)

• Primitive wrapper classes (java.lang.Integer, java.lang.Long)

• java standard classes (java.lang.String, java.util.Date)

• Domain objects (Entity, DTO)

• Input/output objects (DTO)

• Collection (implementation class of java.util.Collection) of above types

• void

• etc ...

Note: Input/Output objects

1. Input object indicates the object that has all the input values required for executing Service method.

2. Output object indicates the object that has all the execution results (output values) of Service method.

If business logic(BLogic class) is generated using “TERASOLUNA ViSC” then, input and output
objects are used as argument and return value of the of BLogic class.

Values that are forbidden as arguments and return values are as follows.

3.2. Domain Layer Implementation 173


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Objects (javax.servlet.http.HttpServletRequest ,
javax.servlet.http.HttpServletResponse , javax.servlet.http.HttpSession
, org.springframework.http.server.ServletServerHttpRequest) which are de-
pendent on implementation architecture of application layer (Servlet API or web layer API of
Spring).

• Model(Form, DTO) classes of application layer

• Implementation classes of java.util.Map

Note: Reason for prohibition

1. If objects depending on implementation architecture of application layer are allowed, then application
layer and domain layer get tightly coupled.

2. java.util.Map is too generalized. Using it for method arguments and return values makes it
difficult to understand what type of object is stored inside it. Further, since the values are managed
using keys, the following problems may occur.

• Values are mapped to a unique key and hence cannot be retrieved by specifying a key name which is
different from the one specified at the time of inserting the value.

• When key name has to be changed, it becomes difficult to determine the impacted area.

How to sharing the same DTO between the application layer and domain layer is shown below.

• DTO belonging to the package of domain layer can be used in application layer.

Warning: Form and DTO of application layer should not be used in domain layer.

Implementation of SharedService class

Creation of SharedService class

Below are the points to be taken care of while creating SharedService class.
Only the points which are different from Service class are explained here.

1. Add @Transactional annotation to class as and when required.


@Transactional annotation is not required when data access is not involved.

2. Interface name should be XxxSharedService and class name should be XxxSharedServiceImpl.


Any other naming conventions can also be used. However, it is recommended to use distinguishable
naming conventions for Service class and SharedService class.

174 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Creation of SharedService class method

Below are the points to be taken care of while writing methods of SharedService class.
Only the points which are different from Service class are explained here.

1. Methods in SharedService class must be created for each logic which is shared between multiple
business logics.

2. Add @Transactional annotation to class as and when required.


Annotation is not required when data access is not involved.

Regarding arguments and return values of SharedService class method

Points are same as Regarding arguments and return values of methods of Service class.

Implementation of logic

Implementation in Service and SharedService is explained here.

Service and SharedService has implementation of logic related to operations such as data fetch, update, consis-
tency check of business data and implementation related to business rules.

Example of a typical logic is explained below.

Operate on business data

Refer to the following for the examples of data (Entity) fetch and update.

• When using MyBatis3, Database Access (MyBatis3)

• When using JPA, Database Access (JPA)

Returning messages

Warning message and business error message are the two type of messages which must be resolved in Service
(refer to the figure in red broken line below).
Other messages should be resolved in application layer.
Refer to Message Management for message types and message pattern.

Note: Regarding resolving message

3.2. Domain Layer Implementation 175


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

In service, instead of the actual message the information required for building the message (message
code, message insert value) is resolved.

Refer to the following for detailed implementation method.

• Returning warning message

• Notifying business error

Returning warning message

Message object must be returned for warning message. If domain object such as Entity needs to be returned with
it,
message object and domain object should inserted into output object (DTO) and this output object must be
returned.

Message object ( org.terasoluna.gfw.common.message.ResultMessages ) is provided as


common library. When the class provided in common library
does not fulfill the requirements, message object should be created for each project.

• Creation of DTO

176 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

public class OrderResult implements Serializable {


private ResultMessages warnMessages;
private Order order;

// omitted

• Implementation of method of Service class

Following is an example of implementation of displaying a warning message. The message is “Products


may not be delivered together since the order includes products which are not available right now”.

public OrderResult submitOrder(Order order) {

// omitted

boolean hasOrderProduct = orderRepository.existsByOrderProduct(order); // (1)

// omitted

Order order = orderRepository.save(order);

// omitted

ResultMessages warnMessages = null;


// (2)
if(hasOrderProduct) {
warnMessages = ResultMessages.warn().add("w.xx.xx.0001");
}
// (3)
OrderResult orderResult = new OrderResult();
orderResult.setOrder(order);
orderResult.setWarnMessages(warnMessages);
return orderResult;
}

3.2. Domain Layer Implementation 177


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) When the order includes products which are not available right now, set hasOrderProduct
to true.

(2) In the above example, when the order includes products which are not available right now, a
warning message occurs.

(3) In the above example, the registered Order object and warning message are returned by
storing objects in a DTO called OrderResult.

Notifying business error

Business exception is thrown when business rules are violated while executing business logic.
The following can be the cases.

• When reservation date exceeds deadline while making tour reservation

• When the product is out of stock at the time of placing an order

• etc ...

Business exception ( org.terasoluna.gfw.common.exception.BusinessException ) is


provided as common library.
When business exception class provided in common library does not fulfill the requirements, business exception
class should be created in the project.
It is recommended to create business exception class as subclass of java.lang.RuntimeException.

Note: Reason for considering business exception as an unchecked exception

Since business exceptions need to be handled in controller class, they can be configured as checked ex-
ception. However in this guideline, it is recommended that business exception be subclass of unchecked
exception (java.lang.RuntimeException). By default, if there is a RuntimeException, transaction
will be rolled back. Hence, doing this will prevent leaving a bug in the source-code due to inadequate
settings of @Transactional annotation. Obviously, if settings are changed such that transaction rollbacks

178 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

even in case checked exceptions, business exception can be configured as subclass of checked exceptions.

Example of throwing business exception.


Below example notifies that reservation is past the deadline and a business error.

// omitted

if(currentDate.after(reservationLimitDate)) { // (1)
throw new BusinessException(ResultMessages.error().add("e.xx.xx.0001"));
}

// omitted

Sr. No. Description


Business exception is thrown since reservation date is past the deadline at the time of making
reservation.
(1)

Refer to Exception Handling for details of entire exception handling.

Notifying system error

System exception is thrown when error occurs in system while executing business logic.
The following can be the cases.

• When master data, directories and files that should already exist, do not exist

• When a checked exception generated by a library method is caught and this exception indicates abnormal
system state.

• etc ...

System exception (org.terasoluna.gfw.common.exception.SystemException) is provided as


common library.
When system exception class provided in common library does not fulfill the requirements, system exception
class should be created in the project.
It is recommended to create system exception class as subclass of java.lang.RuntimeException.
The reason is system exception should not be handled by application code and rollback target of
@Transactinal annotation is set to java.lang.RuntimeException by default.

3.2. Domain Layer Implementation 179


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Example of throwing system exception.


Example notifying the non-existence of the specific product in product master as system error is shown below.

ItemMaster itemMaster = itemMasterRepository.findOne(itemCode);


if(itemMaster == null) { // (1)
throw new SystemException("e.xx.fw.0001",
"Item master data is not found. item code is " + itemCode + ".");
}

Sr. No. Description


System exception is thrown since master data that should already exist does not exist. Example
of case when system error is detected in logic)
(1)

Example that throws system exception while catching IO exception while copying the file is shown below.

// ...

try {
FileUtils.copy(srcFile, destFile);
} catch(IOException e) { // (1)
throw new SystemException("e.xx.fw.0002",
"Failed file copy. src file '" + srcFile + "' dest file '" + destFile + "'.", e);
}

Sr. No. Description

(1) System exception that is classified into invalid system state is thrown by the library method.
The exception generated by library must be passed to system exception class as cause
exception.
If cause exception is lost, error occurrence location and basic error cause cannot be traced from
the stack trace.

Note: Regarding handling of data access error

When data access error occurs in Repository and O/R Mapper while executing business logic, it is con-
verted to subclass of org.springframework.dao.DataAccessException and thrown. Error
can be handled in application layer instead of catching in business logic. However, some errors like unique
constraints violation error should be handled in business logic as per business requirements. Refer to
Database Access (Common) for details.

180 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

3.2.6 Regarding transaction management

Transaction management is required in the logic where data consistency must be ensured.

Method of transaction management

There are various transaction management methods. However, in this guideline, it is recommended to use
“Declarative Transaction Management” provided by Spring Framework.

Declarative transaction management

In “Declarative transaction management”, the information required for transaction management can be declared
by the following 2 methods.

• Declaration in XML(bean definition file).

• Declaration using annotation (@Transactional) (Recommended).

Refer to Spring Reference Document -Transaction Management(Declarative transaction management)- for the
details on “Declarative type transaction management” provided by Spring Framework.

Note: Reason for recommending annotation method

1. The transaction management to be performed can be understood by just looking at the source code.

2. AOP settings for transaction management is not required if annotations are used and so XML becomes
simple.

Information required for “Declarative transaction management”

Specify @Transactional annotation for at class level or method level which are considered as target of
transaction management and specify the information required for
transaction control in attributes of @Transactional annotation.

Note: In this guideline, it is a prerequisite to use @org.springframework.transaction.annotation.Transac


annotation provided by Spring Framework.

Tip: From Spring 4, it is possible to use @javax.transaction.Transactional annotation added


from JTA 1.2.

3.2. Domain Layer Implementation 181


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

However, in this guideline, it is recommended to use an annotation of Spring Framework that can specify
the information required for “Declarative transaction management” in a much more detailed way.

Following attributes can be specified if Spring Framework annotation is used.

• NESTED(JDBC savepoint) as an attribute value of the propagation method of transaction


(propagation attribute).

• Isolation level of transaction (isolation attribute)

• Timeout period of transaction (timeout attribute)

• Read-only flag of transaction (readOnly attribute)

182 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Attribute Description


name
1 propagation

Specify transaction propagation method.

[REQUIRED]
Starts transaction if not started. (default when omitted)
[REQUIRES_NEW]
Always starts a new transaction.
[SUPPORTS]
Uses transaction if started. Does not use if not started.
[NOT_SUPPORTED]
Does not use transaction.
[MANDATORY]
Transaction should start. An exception occurs if not started.
[NEVER]
Does not use transaction (never start). An exception occurs if started.
[NESTED]
save points are set. They are valid only in JDBC.

2 isolation

Specify isolation level of transaction.


Since this setting depends on DB specifications, settings should be decided by
checking DB specifications.

[DEFAULT]
Isolation level provided by DB by default.(default when omitted)
[READ_UNCOMMITTED]
Reads (uncommitted) data modified in other transactions.
[READ_COMMITTED]
Does not read (uncommitted) data modified in other transactions.
[REPEATABLE_READ]
Data read by other transactions cannot be updated.
[SERIALIZABLE]
Isolates transactions completely.

Isolation level of transaction is considered as the parameter related to exclusion


control.
3.2. Domain Layer Implementation 183
Refer to Exclusive Control for exclusion control.

3 timeout

Specify timeout of transaction (seconds).


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: Location to specify the @Transactional annotation

It is recommended to specify the annotation at the class level or method level of the class. Must
be noted that it should not interface or method of interface. For the reason, refer to 2nd Tips of Spring
Reference Document -Transaction Management(Using @Transactional)-.

Warning: Default operations of rollback and commit when exception occurs


When rollbackFor and noRollbackFor is not specified, Spring Framework performs the following oper-
ations.
• Rollback when unchecked exception of (java.lang.RuntimeException and java.lang.Error) class
or its subclass occurs.
• Commit when checked exception of (java.lang.Exception) class or its subclass occurs. (Neces-
sary to note)

Note: Regarding value attributes of @Transactional annotation

There is a value attribute in @Transactional annotation. However, this attribute specifies which
Transaction Manager to be used when multiple Transaction Managers are declared. It is not required
to specify when there is only one Transaction Manager. When multiple Transaction Managers need to be
used, refer to Spring Reference Document -Transaction Management(Multiple Transaction Managers with
@Transactional)-.

Note: Default isolation levels of main DB are given below.

Default isolation levels of main DB are given below.

• Oracle : READ_COMMITTED

• DB2 : READ_COMMITTED

• PostgreSQL : READ_COMMITTED

• SQL Server : READ_COMMITTED

• MySQL : REPEATABLE_READ

Note: Cases where “Read-only transactions” are not enabled

A mechanism is provided to run SQL under “Read-only transactions” by specifying readOnly = true;
however, when all of the following conditions are satisfied, there will be a JDBC driver where “Read-only
transactions” are not enabled.

184 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

[Conditions to generate this event]

• Perform health check when retrieving a connection from connection pool.

• Disable ‘Auto commit’ of connection retrieved from connection pool.

• Use DataSourceTransactionManager or JpaTransactionManager as


PlatformTransactionManager. (This event does not occur when using
JtaTransactionManager).

[JDBC driver where occurrence of this event is confirmed]

• org.postgresql:postgresql:9.3-1102-jdbc41 (JDBC 4.1 compatible JDBC driver for


PostgreSQL 9.3)

[Method to avoid this event]

In a case where “Read-only transactions” are not enabled, if readOnly = true is specified, it ends up
carrying out the unnecessary processes. Therefore, it is recommended to execute the SQL under “Updatable
transactions” even for the reference processes.

Other methods to avoid this event are as follows:

• Do not perform health check when retrieving a connection from connection pool.

• Enable ‘Auto commit’ of the connection retrieved from connection pool. (Disable ‘Auto commit’ only
when transaction management is required)

However, However, do not change the design for ‘health check’ and ‘auto commit’ to avoid this event.

[Remarks]

• Reproduction of this event is confirmed on PostgreSQL 9.3 and Oracle 12c. It is not performed on any
other database and versions.

• In PostgreSQL 9.3, SQLException occurs when java.sql.Connection#setReadOnly(boolean)


method is called.

• When SQL or API call of JDBC is logged in using log4jdbc, SQLException occurred from JDBC
driver is output to log with ERROR level.

• SQL Exception occurred from JDBC driver is ignored by exception handling of Spring Frame-
work. Hence, even though it is not an error as application behavior, the “Read-only transactions”
is not enabled.

• Occurrence of this event is not confirmed in Oracle 12c.

[Reference]

When following log is output using log4jdbc, it will be treated as a case corresponding to this event.

3.2. Domain Layer Implementation 185


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

date:2015-02-20 16:11:56 thread:main user: X-Track: level:ERROR l


org.postgresql.util.PSQLException: Cannot change transaction read-only property in the mi
at org.postgresql.jdbc2.AbstractJdbc2Connection.setReadOnly(AbstractJdbc2Connection.j
...

Note: timeout attribute of @Transactional annotation

Although @Transactionalannotation consists of timeoutattribute, value specified in


timeoutattribute is ignored in MyBatis3.3 and MyBatis-Spring 1.2 combination and is not used.

Propagation of transaction

In most of the cases, Propagation method of transaction is “REQUIRED”.


However, since “REQUIRES_NEW” is also used according to the requirements of Application, transaction
control flow in case of “REQUIRED” and “REQUIRES_NEW” is explained below.
The explanation of other propagation methods is omitted in this guideline since their usage frequency is very low.

Transaction control flow when propagation method of transaction is set to “REQUIRED”


When propagation method of transaction is set to “REQUIRED”, all sequential processes called from controller
are processed in the same transaction.

186 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

1. Controller calls a method of Service class. At this time, since started transaction does not exist, transaction
is started using TransactionInterceptor.

2. TransactionInterceptor calls the method of service class after starting the transaction.

3. Service class calls a method of SharedService. This method is also under transaction control. At this
time, though started transaction exists, TransactionInterceptor participates in the started transac-
tion without starting a new transaction.

4. TransactionInterceptor calls the method under transaction control after participating in the started
transaction.

5. TransactionInterceptor performs commit or rollback according to result of processing and ends


the transaction.

Note: Reason for occurrence of org.springframework.transaction.UnexpectedRollbackException

When propagation method of transaction is set to “REQUIRED”, though there is only one physical transaction, in-
ternally Spring Framework creates transaction boundaries. In case of above example, when a method of SharedSer-
vice is called, a TransactionInterceptor is started which internally provides transaction control boundary at Shared-
Service level. Therefore, when an exception (which is set as target of rollback) occurs in SharedService
method, status of transaction is set to rollback (rollback-only) by TransactionInterceptor. This trans-
action now cannot be committed. Going further, if the Service method tries to commit this transaction
due to conflicting settings of rollback target exception between Service method and SharedShared method,
UnexpectedRollbackException is generated by Spring Framework notifying that there is inconsistency
in transaction control settings. When UnexpectedRollbackException is generated, it should be checked that there
is no inconsistency in rollbackFor and noRollbackFor settings.

Transaction management flow when propagation method of transaction is set to “REQUIRES_NEW”


When propagation method of transaction is set to “REQUIRES_NEW”, a part of the sequence of processing
(Processing done in SharedService) are processed in another transaction when called from Controller.

1. Controller calls a method of Service class. This method is under transaction control. At this time, since
started transaction does not exist, transaction is started by TransactionInterceptor (Hereafter, the
started transaction is referred as “Transaction A”).

2. TransactionInterceptor calls the method of service class after transaction (Transaction A) is


started.

3. Service class calls a method of SharedService class. At this time, though started transaction (Transac-
tion A) exists, since propagation method of transaction is “REQUIRES_NEW”, new transaction is started

3.2. Domain Layer Implementation 187


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

by TransactionInterceptor. (Hereafter, started transaction is referred as “Transaction B”). At this


time, “Transaction A” is interrupted and the status changes to ‘Awaiting to resume’.

4. TransactionInterceptor calls the method of SharedService class after Transaction B is started.

5. TransactionInterceptor performs commit or rollback according to the process result and ends the
Transaction B. At this time, “Transaction A” is resumed and status is changed to Active.

6. TransactionInterceptor performs commit or rollback according to the process result and ends the
Transaction A.

Way of calling the method which is under transaction control

Since “Declarative transaction management” provided by Spring Framework is implemented using AOP,
transaction management is applied only for method calls for which AOP is enabled.
Since the default mode of AOP is “proxy” mode, transaction control will be applied only when public
method is called from another class.
Note that transaction control is not applied if the target method is called from an internal method even if
the target method is a public method.

• Way of calling the method which is under transaction control

188 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Way of calling the method which is not under transaction control

Note: In order to bring internal method calls under transaction control

It is possible to enable transaction control for internal method calls as well by setting the AOP mode
to "aspectj". However, if internal method call of transaction management is enabled, the route of
transaction management may become complicated; hence it is recommended to use the default “proxy” for
AOP mode.

Settings for using transaction management

The settings required for using transaction management are explained.

3.2. Domain Layer Implementation 189


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

PlatformTransactionManager settings

In order to have transaction management done, it is necessary to define the bean of


PlatformTransactionManager.
Spring Framework has provided couple of classes based on the purpose; any class can be specified that meets the
requirement of the application.

• xxx-env.xml

Example of settings for managing the transaction using JDBC connection which is fetched from DataSource
is given below.

<!-- (1) -->


<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

Sr. No. Description

(1) Specify the implementation class of PlatformTransactionManager.


It is recommended to set id as “transactionManager”.

Note: When transaction management (Global transaction management) is required for multiple
DBs (Multiple resources)

• It is necessary to use org.springframework.transaction.jta.JtaTransactionManager


and manage transactions by using JTA functionality provided by application server.

• When JTA is to be used in WebSphere and Oracle WebLogic Server, a JtaTransactionManager


which is extended for the application server is automatically set by specifying <tx:jta-transaction-
manager/>.

190 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Table.3.1 Implementation class of PlatformTransactionManager provided by Spring Framework

Sr. No. Class name Description

1.
Implementation class for managing the transaction by
org.springframework.jdbc.datasource.
calling API of JDBC(java.sql.Connection).
DataSourceTransactionManager
Use this class when MyBatis and JdbcTemplate is to
be used.

2.
org.springframework.orm.jpa. Implementation class for managing the transaction by
JpaTransactionManager calling API of
JPA(javax.persistence.EntityTransaction).
Use this class when JPA is to be used.

3.
org.springframework.transaction.jta. Implementation class for managing the transaction by
JtaTransactionManager calling API of
JTA(javax.transaction.UserTransaction).
Use this class to manage transaction with resources
(Database/Messaging service/General-purpose
EIS(Enterprise Information System) etc.) using JTS (Java
Transaction Service) provided by application server.
When it is necessary to execute the operations with
multiple resources in a single transaction, it is necessary
to use JTA for managing transactions.

Settings for enabling @Transactional

In this guideline, it is recommended to manage transaction by using “Declarative transaction management”


where @Transactional annotation is used.
Here, the settings required for using @Transactional annotation are explained.

• xxx-domain.xml

3.2. Domain Layer Implementation 191


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<tx:annotation-driven /> <!-- (1) -->

Sr. No. Description


With use of <tx:annotation-driven> element in XML (bean definition file), transaction control
gets enabled at the locations where @Transactional annotation is used.
(1)

Note: Regarding drawbacks of transaction management

There is a description regarding “Understanding drawbacks of transaction” in IBM DeveloperWorks. Read


this article about pitfalls of transaction management and pitfalls while using @Transactional of Spring
Framework. Refer to Article on IBM DeveloperWorksfor details.

Since the article of IBM DeveloperWorks is an old article (year 2009), some of the content is different than
the behavior when using Spring Framework 4.1.

Specifically, the contents of “Listing 7. Using read-only with REQUIRED propagation mode - JPA”.

From Spring Framework 4.1, when Hibernate ORM 4.2 or higher version is used as JPA provider, it has
been improved so that instruction can be given to run the SQL under “Read-only transactions” for JDBC
driver (SPR-8959).

The way of handling read-only transactions depends on the implementation of JDBC driver; hence, confirm
the specifications of JDBC driver to be used.

Note: Programmatic transaction management

In this guideline, “Declarative transaction management” is recommended. However, programmatic


transaction management is also possible. Refer to Spring Reference Document -Transaction Manage-
ment(Programmatic transaction management)- for details.

Regarding attributes of <tx:annotation-driven> element

Various attributes can be specified in <tx:annotation-driven> and default behavior can be customized.

• xxx-domain.xml

<tx:annotation-driven
transaction-manager="txManager"
mode="aspectj"
proxy-target-class="true"
order="0" />

192 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Attribute Description


1 transaction- Specify PlatformTransactionManager bean. When omitted, bean reg-
manager istered with the name “transactionManager” is used.
2 mode Specify AOP mode. When omitted, "proxy" is the default value.
"aspectj" can be also be specified. It is recommended to use "proxy".
3 proxy-target- Flag to specify whether proxy target is limited to class (this is valid only in case
class of mode=”proxy”). When omitted, it will be “false”.
• In case of false, if the target class has an interface, proxy is done using
dynamic proxies functionality of standard JDK. When there is no interface,
proxy is done using GCLIB functionality.
• In case of true, proxy is done using GCLIB function irrespective of whether
interface is available or not.

4 order Order of Advice of AOP (Priority). When omitted, it will be “Last (Lowest
priority)”.

3.2.7 Tips

Method of dealing with violation of business rules as field error

When it is necessary to output the error of business rules for each field, the mechanism of (Bean Validation or
Spring Validator) on the Controller side should be used.
In this case, It is recommended to implement check logic as Service class and then to call the method of Service
class from Bean Validation or Spring Validator.
Refer to Input Validation business logic approach for details.

3.2. Domain Layer Implementation 193


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

3.3 Implementation of Infrastructure Layer

Implementing RepositoryImpl is carried out in infrastructure layer.

RepositoryImpl implements the method defined in Repository interface.

3.3.1 Implementing RepositoryImpl

Methods to create a Repository for relational database using MyBatis3 and JPA are introduced below.

• Implementing Repository using MyBatis3

• Implementing Repository using JPA

Implementing Repository using MyBatis3

When MyBatis3 is to be used as persistence API with relational database, RepositoryImpl need not be imple-
mented, if Repository interface is created using “Mapper interface mechanism” provided by MyBatis3.

This is because it is a mechanism where MyBatis3 automatically maps the method of Mapper interface and the
statement (SQL) to be called.

When using MyBatis3, an application developer creates:

• Repository interface (method definition)

• Mapping file (SQL and O/R mapping definition)

An example of creating Repository interface and mapping file is given below.


For details on how to use MyBatis3, refer to: Database Access (MyBatis3).

• An example of creating Repository interface (Mapper interface)

package com.example.domain.repository.todo;

import com.example.domain.model.Todo;

// (1)
public interface TodoRepository {
// (2)
Todo findOne(String todoId);
}

194 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Create as an interface of POJO.
It is not necessary to specify MyBatis3 interface, annotation, etc.
(1)

Define a method of Repository.


Basically it is not necessary to assign MyBatis3 annotation; however, annotation may also be
(2)
specified in some cases.

• An example of creating mapping file

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- (3) -->
<mapper namespace="com.example.domain.repository.todo.TodoRepository">

<!-- (4) -->


<select id="findOne" parameterType="string" resultMap="todoResultMap">
SELECT
todo_id,
title,
finished
FROM
t_todo
WHERE
todo_id = #{todoId}
</select>

<!-- (5) -->


<resultMap id="todoResultMap" type="Todo">
<result column="todo_id" property="todoId" />
<result column="title" property="title" />
<result column="finished" property="finished" />
</resultMap>

</mapper>

3.3. Implementation of Infrastructure Layer 195


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Create a mapping file for each Repository interface.
Specify FQCN (Fully Qualified Class Name) of Repository interface in namespace of mapping
(3)
file (namespace attribute of mapper element).

Define statement (SQL) to be run for each method defined in Repository interface.
Specify a method name of Repository interface in statement ID of each statement element (id
(4)
attribute of select/insert/update/delete element).

When a query is to be raised, define O/R mapping as required.


Auto mapping can be used for simple O/R mapping; however, individual mapping definition is
(5)
needed for complex O/R mapping.
In the above example, auto mapping can also be used for mapping definition as it is simple O/R
mapping.

Implementing Repository using JPA

When JPA is to be used as persistence API with relational database, Repository can be very easily created if
org.springframework.data.jpa.repository.JpaRepository of Spring Data JPA is used.
For details on how to use Spring Data JPA, refer to Database Access (JPA).

When Spring Data JPA is used, only an interface with inherited JpaRepository is required to be created for basic
CRUD operations. In other words, RepositoryImpl is not required.
However, RepositoryImpl is needed for using dynamic query (JPQL).
Refer to Database Access (JPA) for implementing RepositoryImpl when using Spring Data JPA.

• TodoRepository.java

public interface TodoRepository extends JpaRepository<Todo, String> { // (1)


// ...
}

Sr. No. Description


Only by defining the interface that inherits JpaRepository, basic CRUD operations for Todo
entity can be performed without being implemented.
(1)

Describe the case to add operations which are not provided by JpaRepository.
When Spring Data JPA is used, if it is a static query, it is advisable to add a method to the interface and to specify
the query (JPQL) to be executed when that method is called, using the annotation.

196 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• TodoRepository.java

public interface TodoRepository extends JpaRepository<Todo, String> {


@Query("SELECT COUNT(t) FROM Todo t WHERE finished = :finished") // (1)
long countByFinished(@Param("finished") boolean finished);
// ...
}

Sr. no. Description


Specify a query (JPQL) using @Query annotation.

(1)

Implementing Repository to link with external system using RestTemplate

Todo

TBD

Details will be provided in the next version.

3.3. Implementation of Infrastructure Layer 197


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

3.4 Implementation of Application Layer

This chapter explains implementation of application layer of a web application that uses HTML forms.

Note: Refer to the following page for the implementation required for Ajax development and REST API.

• Ajax

Implementation of application layer is given in the following 3 steps.

1. Implementing Controller
Controller receives the request, calls business logic, updates model, decides View. Thereby, controls one
complete round of operations after receiving the request.
It is the most important part in the implementation of application layer.

2. Implementing form object


Form object transfers the values between HTML form and application.

3. Implementing View
View (JSP) acquires the data from model (form object, domain object etc.) and generates screen (HTML).

3.4.1 Implementing Controller

Implementation of Controller is explained below.


The Controller performs the following roles.

1. Provides a method to receive the request.


Receives requests by implementing methods to which @RequestMapping annotation is assigned.

2. Performs input validation of request parameter.


For request which requires input validation of request parameters, it can be performed by specifying
@Validated annotation to form object argument of method which receives the request.
Perform single item check using Bean Validation and correlation check using Spring Validator or Bean
Validation.

3. Calls business logic.

198 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Controller does not implement business logic but delegates by calling Service method.

4. Reflects the output of business logic to Model.


The output can be referred in View by reflecting domain object returned from Service method to Model.

5. Returns View name corresponding to business logic output.


Controller does not implement the logic of rendering the view. Rendering is done in View technologies
like JSP etc.
Controller only returns the name of the view in which the rendering logic is implemented.
The View corresponding to view name is resolved by ViewResolver provided by Spring Framework.

Figure.3.1 Picture - Logic of controller

Note: It is recommended that controller implements only the routing logic such as calling business logic,
reflecting output of the business logic to Model, deciding the View name is implemented in the Controller.

The implementation of Controller is explained by focusing on the following points.

• Creating Controller class

3.4. Implementation of Application Layer 199


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Mapping request and handler method

• Regarding arguments of handler method

• Regarding return value of handler method

Creating Controller class

Controller class is created with @Controller annotation added to POJO class (Annotation-based
Controller).
Controller in Spring MVC can also be created by implementing
org.springframework.web.servlet.mvc.Controller interface (Interface-based Controller).
However, it is preferred to avoid using it as it is Deprecated from Spring 3 onwards.

@Controller
public class SampleController {
// ...
}

Mapping request and handler method

@RequestMapping annotation is assigned to the method that receives request.


In this document, the method to which @RequestMapping is added, is called as “handler method”.

@RequestMapping(value = "hello")
public String hello() {
// ...
}

200 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

The rules for mapping the incoming request with a handler method can be specifying as attributes of
@RequestMapping annotation.

Sr. No. Attribute Description


name
value
1.
Specify request path which needs to be mapped (multiple values allowed).

method
2.
Specify HTTP method (RequestMethod type) which needs to be mapped
(multiple methods allowed).
GET/POST are mainly used for mapping requests from HTML form, while other
HTTP methods (such as PUT/DELETE) are used for mapping requests from REST
APIs as well.

params
3.
Specify request parameters which need to be mapped (multiple parameters allowed).
Request parameters are mainly used for mapping request from HTML form. If this
mapping method is used, the case of mapping multiple buttons on HTML page can
be implemented easily.

headers
4.
Specify request headers which need to be mapped (multiple headers allowed).
Mainly used while mapping REST API and Ajax requests.

consumes
5.
Mapping can be performed using Content-Type header of request. Specify media
type which needs to be mapped (multiple types allowed).
Mainly used while mapping REST API and Ajax requests.

produces
6.
Mapping can be performed using Accept header of request. Specify media type
which needs to be mapped (multiple types allowed).
Mainly used while mapping REST API and Ajax requests.

Note: Combination of mapping

Complex mapping can be performed by combining multiple attributes, but considering maintainability,

3.4. Implementation of Application Layer 201


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

mapping should be defined and designed in the simplest way possible . It is recommended to consider
combining 2 attributes (value attribute and any other 1 attribute).

6 examples of mapping are shown below.

• Mapping with request path

• Mapping by HTTP method

• Mapping by request parameter

• Mapping using request header

• Mapping using Content-Type header

• Mapping using Accept header

In the following explanation, it is prerequisite to define the handler method in the Controller class.

@Controller // (1)
@RequestMapping("sample") // (2)
public class SampleController {
// ...
}

Sr. No. Description


With @Controller, it is recognized as Annotation-based controller class and becomes the
target of component scan.
(1)

All the handler methods in this class are mapped to URLs with “sample” by adding
@RequestMapping("sample") annotation at class level.
(2)

202 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Mapping with request path

In case of the following definition, if the URL "sample/hello" is accessed, then hello() method is exe-
cuted.

@RequestMapping(value = "hello")
public String hello() {

When multiple values are specified, it is handled by ‘OR’ condition.


In case of following definition, if "sample/hello" or "sample/bonjour" is accessed, then hello()
method is executed.

@RequestMapping(value = {"hello", "bonjour"})


public String hello() {

Pattern can be specified instead of a specific value for request path. For details of specifying patterns, refer to
reference documentation of Spring Framework.

• URI Template Patterns

• URI Template Patterns with Regular Expressions

• Path Patterns

• Patterns with Placeholders

Mapping by HTTP method

In case of the following definition, if the URL "sample/hello" is accessed with POST method, then
hello() method is executed. For the list of supported HTTP methods, refer to Javadoc of RequestMethod.
When not specified, all supported HTTP methods are mapped.

@RequestMapping(value = "hello", method = RequestMethod.POST)


public String hello() {

When multiple values are specified, it is handled by ‘OR’ condition.


In case of following definition, if "sample/hello" is accessed with GET or HEAD method, then hello()
method is executed.

3.4. Implementation of Application Layer 203


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@RequestMapping(value = "hello", method = {RequestMethod.GET, RequestMethod.HEAD})


public String hello() {

Mapping by request parameter

In case of following definition, if the URL "sample/hello?form" is accessed, then hello() method is
executed.
When request is sent as a POST request, request parameters may exist in request body even if they do not exist in
URL.

@RequestMapping(value = "hello", params = "form")


public String hello() {

When multiple values are specified, it is handled by ‘AND’ condition.


In case of following definition, if the URL "sample/hello?form&formType=foo" is accessed, then
hello() method is executed.

@RequestMapping(value = "hello", params = {"form", "formType=foo"})


public String hello(@RequestParam("formType") String formType) {

Supported formats are as follows.

Sr. No. Format Explanation


paramName Mapping is performed when request parameter of the specified parame-
1.
Name exists.

!paramName Mapping is performed when request parameter of the specified parame-


2.
Name does not exist.

paramName=paramValue Mapping is performed when value of the specified parameName is


3.
paramValue.

paramName!=paramValue Mapping is performed when value of the specified parameName is not


4.
paramValue.

204 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Mapping using request header

Refer to the details on the following page to mainly use the controller to map REST API and Ajax requests.

• Ajax

Mapping using Content-Type header

Refer to the details on the following page to mainly use the controller to map REST API and Ajax requests.

• Ajax

Mapping using Accept header

Refer to the details on the following page to mainly use the controller to map REST API and Ajax requests.

• Ajax

Mapping request and handler method

Mapping by the following method is recommended.

• Grouping of URL of request is done for each unit of business flow or functional flow.
URL grouping means defining @RequestMapping(value = "xxx") as class level annotation.

• Use the same URL for requests for screen transitions within same functional flow
The same URL means the value of ‘value’ attribute of @RequestMapping(value = "xxx") must
be same.
Determining which handler method is used for a particular request with same functional flow is performed
using HTTP method and HTTP parameters.

The following is an example of mapping between incoming request and handler method by a sample application
with basic screen flow.

• Overview of sample application

• Request URL

• Mapping request and handler method

• Implementing form display

3.4. Implementation of Application Layer 205


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Implementing the display of user input confirmation screen

• Implementing ‘redisplay of form’

• Implementing ‘create new user’ business logic

Overview of sample application

Functional overview of sample application is as follows.

• Provides functionality of performing CRUD operations of Entity.

• Following 5 operations are provided.

Sr. No. Operation name Overview


Fetching list of Enti- Fetch list of all the created Entities to be displayed on the list screen.
1.
ties

Create Entity Create a new Entity with the specified contents. Screen flow (form screen,
2.
confirmation screen, completion screen) exists for this process.

Fetching details of Fetch Entity of specified ID to be displayed on the details screen.


3.
Entity

Entity update Update Entity of specified ID. Screen flow (form screen, confirmation
4.
screen, completion screen) exists for this process.

Entity delete Delete Entity of specified ID.


5.

• Screen flow of all functions is as follows.


It is not mentioned in screen flow diagram however, when input validation error occurs, form screen is
displayed again.

Request URL

Design the URL of the required requests.

• Request URLs of all the requests required by the process flow are grouped.

206 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Figure.3.2 Picture - Screen flow of entity management function

This functionality performs CRUD operations of Entity called ABC, therefore URL that starts with
"/abc/" is considered.

• Design request URL for each operation of the functionality.

Sr. No. Operation name URL for each operation (pattern)


Fetching list of Entities /abc/list
1.

Create Entity /abc/create


2.

Fetching details of Entity /abc/{id}


3.

Entity update /abc/{id}/update


4.

Entity delete /abc/{id}/delete


5.

Note: "{id}" specified in URL of ‘Fetching details of Entity’, ‘Entity update’, ‘Entity delete’ operations
is called as, URI Template Pattern and any value can be specified. In this sample application, Entity ID is
specified.

Assigned URL of each operation of screen flow diagram is mapped as shown below:

3.4. Implementation of Application Layer 207


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Figure.3.3 Picture - Screen flow of entity management function and corresponding assigned URL

Mapping request and handler method

Design the mapping between incoming request and handler method.


The following is the mapping design which is designed according to mapping policy.

208 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. Operation name URL Request name HTTP HTTP Handler


No. Method Parameter method

Fetching list of Enti- /abc/list List display GET - list


1.
ties

Create New Entity /abc/create Form display - form createForm


2.

Displaying input con- POST confirm createConfirm


3.
firmation

Form re-display POST redo createRedo


4.

Entity Creation POST - create


5.

Displaying completion GET complete createComple


6.
of Entity Creation

Fetching details of /abc/{id} Display details of En- GET - read


7.
Entity tity

Entity update /abc/{id}/update Displaying Form - form updateForm


8.

Displaying confirma- POST confirm updateConfirm


9.
tion of user input

Form re-display POST redo updateRedo


10.

Update POST - update


11.

Displaying completion GET complete updateComple


12.
of update process

Entity delete /abc/{id}/delete Delete POST - delete


13.

Displaying completion GET complete deleteComple


14.
of delete process

Multiple requests exist for each of Create Entity, Entity Update and Entity Delete functions. Therefore switching

3.4. Implementation of Application Layer 209


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

of handler methods is done using HTTP method and HTTP parameters.


The following is the flow of requests in case of multiple requests in a function like “Create New Entity”.
All URLs are "/abc/create" and determining the handler method is done based on combination of HTTP
method and HTTP parameters.

Figure.3.4 Picture - Request flow of entity create processing

Implementation of handler method for “Create New Entity” is shown below.


Here, the purpose is to understand mapping between request and handler method and therefore focus must on
@RequestMapping.
The details of argument and return value (view name and view) of handler method are explained in the next
chapter.

• Implementing form display

• Implementing the display of user input confirmation screen

• Implementing ‘redisplay of form’

210 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Implementing ‘create new user’ business logic

• Implementing notification of create new user process completion

• Placing multiple buttons on HTML form

Implementing form display

In order to display the form, form is specified as HTTP parameter.

@RequestMapping(value = "create", params = "form") // (1)


public String createForm(AbcForm form, Model model) {
// omitted
return "abc/createForm"; // (2)
}

Sr. No. Description


Specify "form" as value of params attribute.

(1)

Return view name of JSP to render form screen.

(2)

Note: In this handler method, method attribute is not specified since it is not required for HTTP GET
method.

Example of implementation of sections other than handler method is explained below.

Besides implementing the handler method for form display, points mentioned below are required:

• Implement generation process of form object. Refer to Implementing form object for the details of form
object.

• Implement View of form screen. Refer to Implementing View for the details of View.

Use the following form object.

3.4. Implementation of Application Layer 211


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

public class AbcForm implements Serializable {


private static final long serialVersionUID = 1L;

@NotEmpty
private String input1;

@NotNull
@Min(1)
@Max(10)
private Integer input2;

// omitted setter&getter
}

Creating an object of AbcForm.

@ModelAttribute
public AbcForm setUpAbcForm() {
return new AbcForm();
}

Create view(JSP) of form screen.

<h1>Abc Create Form</h1>


<form:form modelAttribute="abcForm"
action="${pageContext.request.contextPath}/abc/create">
<form:label path="input1">Input1</form:label>
<form:input path="input1" />
<form:errors path="input1" />
<br>
<form:label path="input2">Input2</form:label>
<form:input path="input2" />
<form:errors path="input2" />
<br>
<input type="submit" name="confirm" value="Confirm" /> <!-- (1) -->
</form:form>

Sr. No. Description


Specify name="confirm" parameter for submit button to transit to confirmation screen.

(1)

The operations are explained below.

212 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sending the request for form display.


Access "abc/create?form" URL.
Since form is specified in the URL as an HTTP parameter, createForm method of controller is called and
form screen is displayed.

Implementing the display of user input confirmation screen

To check user input in the form, data is sent by POST method and confirm is specified as HTTP parameter.

@RequestMapping(value = "create", method = RequestMethod.POST, params = "confirm") // (1)


public String createConfirm(@Validated AbcForm form, BindingResult result,
Model model) {
if (result.hasErrors()) {
return createRedo(form, model); // return "abc/createForm"; (2)
}
// omitted
return "abc/createConfirm"; // (3)
}

3.4. Implementation of Application Layer 213


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Specify “RequestMethod.POST” in method attribute and “confirm” in params attribute.

(1)

In case of input validation errors, it is recommended to call the handler method of form re-
display.
(2)

Return view-name of JSP to render the screen for user input confirmation.

(3)

Note: POST method is specified to prevent displaying confidential information such as password and other
personal information etc. in the address bar. (Needless to say that these security measures not sufficient
and needs more secure measures such as SSL etc.)

Example of implementation of sections other than handler method is explained below.

Besides implementing handler method for user input confirmation screen, points mentioned below are required.

• Implement view of user-input confirmation screen. Refer to Implementing View for the details of view.

Create the view (JSP) for user input confirmation screen.

<h1>Abc Create Form</h1>


<form:form modelAttribute="abcForm"
action="${pageContext.request.contextPath}/abc/create">
<form:label path="input1">Input1</form:label>
${f:h(abcForm.input1)}
<form:hidden path="input1" /> <!-- (1) -->
<br>
<form:label path="input2">Input2</form:label>
${f:h(abcForm.input2)}
<form:hidden path="input2" /> <!-- (1) -->
<br>
<input type="submit" name="redo" value="Back" /> <!-- (2) -->
<input type="submit" value="Create" /> <!-- (3) -->
</form:form>

214 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


The values entered on form screen is set as the hidden fields of HTML form since they must be
sent back to the server when Create or Back buttons are clicked.
(1)

Specify name="redo" parameter for submit button to return to form screen.

(2)

Parameter name need not be specified for submit button. Submit button will do the actual create
operation.
(3)

Note: In the above example, HTML escaping is performed as an XSS countermeasure using f:h()
function while displaying the user input values. For details, refer to Cross Site Scripting.

The operations are explained below.

Send the request for displaying user input confirmation.


Enter "aa" in Input1 and "5" in Input2 and click Confirm button on form screen.
After clicking Confirm button, "abc/create?confirm" URI gets accessed using POST method.
Since HTTP parameter confirm is present in the URI, createConfirm method of controller is called and
user input confirmation screen is displayed.

Since HTTP parameters are sent across through HTTP POST method after clicking the Confirm button, it does
not appear in URI. However, “confirm” is included as HTTP parameter.

3.4. Implementation of Application Layer 215


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Implementing ‘redisplay of form’

“redo” is specified as HTTP parameter to indicate that form needs to be redisplayed.

@RequestMapping(value = "create", method = RequestMethod.POST, params = "redo") // (1)


public String createRedo(AbcForm form, Model model) {
// omitted
return "abc/createForm"; // (2)
}

216 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Specify “RequestMethod.POST” in method attribute and “redo” in params attribute.

(1)

Return view name of JSP to render the form screen.

(2)

Operation is described below.

Send the request to redisplay the form screen.


Click Back button on user input confirmation screen.
When Back button is clicked, “abc/create?redo” URI gets accessed through HTTP POST method.
Since “redo” HTTP parameter is present in the URI, createRedo method of controller is invoked and form
screen is redisplayed.

Since HTTP parameters are sent across through HTTP POST method after clicking the Back button, it does not
appear in URI. However, “redo” is included as HTTP parameter. Moreover, since input values of form had been
sent as hidden fields, input values can be restored on redisplayed form screen.

3.4. Implementation of Application Layer 217


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: In order to implement back button functionality, setting


onclick="javascript:history.back()" is also one of the ways. Both the methods differ in
the following ways. Appropriate method must be selected as per requirement.

• Behavior when Back button on browser is clicked.

• Behavior when page having Back button is accessed and Back button is clicked.

• History of browser

218 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Implementing ‘create new user’ business logic

To register input contents of form, the data (hidden parameters) to be registered is sent with HTTP POST method.
Sorting is not carried out using HTTP parameters since new request will be the main request of this operation.
Since the state of database changes in this process, it should not be executed multiple times due to double
submission.
Therefore, it is ‘redirected’ to the next screen (create complete screen) instead of directly displaying View
(screen) after
completing this process. This pattern is called as POST-Redirect-GET(PRG) pattern. For the details of PRG
(Post-Redirect-Get) pattern
refer to Double Submit Protection .

@RequestMapping(value = "create", method = RequestMethod.POST) // (1)


public String create(@Validated AbcForm form, BindingResult result, Model model) {
if (result.hasErrors()) {
return createRedo(form, model); // return "abc/createForm";
}
// omitted
return "redirect:/abc/create?complete"; // (2)
}

Sr. No. Description


Specify RequestMethod.POST in method attribute. Do not specify params attribute.

(1)

Return URL to the request needs to be redirected as view name in order to use PRG pattern.

(2)

Note: It can be redirected to “/xxx” by returning “redirect:/xxx” as view name.

Warning: PRG pattern is used to avoid double submission when the browser gets reloaded by clicking F5
button. However, as a countermeasure for double submission, it is necessary to use TransactionTokenCheck
functionality. For details of TransactionTokenCheck, refer to Double Submit Protection .

Operation is described below.

3.4. Implementation of Application Layer 219


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Click ‘Create’ button on input confirmation screen.


After clicking ‘Create’ button, "abc/create" URL is accessed through POST method.
Since HTTP parameters are not sent for identifying a button, it is considered as main request of Entity create
process and ‘create’ method of Controller is invoked.

‘Create’ request does not return to the screen directly, but it is redirected to create complete display
("/abc/create?complete"). Hence HTTP status is changed to 302.

Implementing notification of create new user process completion

In order to notify the completion of create process, complete must be present in the request as HTTP parameter.

@RequestMapping(value = "create", params = "complete") // (1)


public String createComplete() {
// omitted
return "abc/createComplete"; // (2)
}

220 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Specify "complete" in params attribute.

(1)

Return View name of JSP to render the create completion screen.

(2)

Note: In this handler method, method attribute is not specified since it is not required for HTTP GET
method.

Operation is described below.

After completing creation of user, access URI ("/abc/create?complete") is specified as redirect


destination.
Since HTTP parameter is complete, createComplete() method of controller is called and create completion
screen is displayed.

Note: Since PRG pattern is used, even if browser is reloaded, create completion screen is only re-displayed

3.4. Implementation of Application Layer 221


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

without re-executing create process.

Placing multiple buttons on HTML form

To place multiple buttons on a single form, send HTTP parameter to identify the corresponding button and so
that the handler method of controller can be switched. An example of Create button and Back button on input
confirmation screen of sample application is explained here.

‘Create’ button to perform ‘user creation’ and ‘Back’ button to redisplay ‘create form’ exists on the form of input
confirmation screen as shown below.

To redisplay ‘create form’ using request ( "/abc/create?redo" ) when Back button is clicked, the following
code is required in HTML form.

<input type="submit" name="redo" value="Back" /> <!-- (1) -->


<input type="submit" value="Create" />

Sr. No. Description


In input confirmation screen ( "abc/createConfirm.jsp" ), specify name="redo" pa-
rameter for Back button.
(1)

For the operations when Back button is clicked, refer to Implementing ‘redisplay of form’.

222 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Figure.3.5 Picture - Multiple button in the HTML form

Source code of controller of sample application

Source-code of controller after implementing create process of sample application are shown below.
Fetching list of Entities, Fetching detail of Entity, Entity update, Entity delete are implemented using the same
guidelines.

@Controller
@RequestMapping("abc")
public class AbcController {

@ModelAttribute
public AbcForm setUpAbcForm() {
return new AbcForm();
}

// Handling request of "/abc/create?form"


@RequestMapping(value = "create", params = "form")
public String createForm(AbcForm form, Model model) {
// omitted
return "abc/createForm";
}

// Handling request of "POST /abc/create?confirm"


@RequestMapping(value = "create", method = RequestMethod.POST, params = "confirm")
public String createConfirm(@Validated AbcForm form, BindingResult result,

3.4. Implementation of Application Layer 223


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Model model) {
if (result.hasErrors()) {
return createRedo(form, model);
}
// omitted
return "abc/createConfirm";
}

// Handling request of "POST /abc/create?redo"


@RequestMapping(value = "create", method = RequestMethod.POST, params = "redo")
public String createRedo(AbcForm form, Model model) {
// omitted
return "abc/createForm";
}

// Handling request of "POST /abc/create"


@RequestMapping(value = "create", method = RequestMethod.POST)
public String create(@Validated AbcForm form, BindingResult result, Model model) {
if (result.hasErrors()) {
return createRedo(form, model);
}
// omitted
return "redirect:/abc/create?complete";
}

// Handling request of "/abc/create?complete"


@RequestMapping(value = "create", params = "complete")
public String createComplete() {
// omitted
return "abc/createComplete";
}

Regarding arguments of handler method

The arguments of handler method can be used to fetch various values; however, as a principle rule, the following
should not be fetched using arguments of handler method of controller.

• ServletRequest

• HttpServletRequest

• org.springframework.web.context.request.WebRequest

224 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• org.springframework.web.context.request.NativeWebRequest

• java.io.InputStream

• java.io.Reader

• java.io.OutputStream

• java.io.Writer

• java.util.Map

• org.springframework.ui.ModelMap

Note: When generalized values like getAttribute/setAttribute of HttpServletRequest and get/put of Map
are allowed, liberal use of these can degrade the maintainability of the project with an increase in project size.

For the above reason, using HttpSession is not reccomended in the case when there are alternatives.

When common parameters (request parameters) need to be stored in JavaBean and passed as an argument to a
method of controller, it can be implemented using Implementing HandlerMethodArgumentResolver as described
later.

Arguments depending on the purpose of usage are described below.

• Passing data to screen (View)

• Retrieving values from URL path

• Retrieving request parameters individually

• Retrieving request parameters collectively

• Performing input validation

• Passing data while redirecting request

• Passing request parameters to redirect destination

• Inserting values in redirect destination URL path

• Acquiring values from Cookie

• Writing values in Cookie

• Retrieving pagination information

3.4. Implementation of Application Layer 225


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Retrieving uploaded file

• Displaying result message on the screen

Passing data to screen (View)

To pass data to be displayed on screen (View), fetch org.springframework.ui.Model (Hereafter called


as Model) as argument of handler method and add the data (Object) to Model object.

• SampleController.java

@RequestMapping("hello")
public String hello(Model model) { // (1)
model.addAttribute("hello", "Hello World!"); // (2)
model.addAttribute(new HelloBean("Bean Hello World!")); // (3)
return "sample/hello"; // returns view name
}

• hello.jsp

Message : ${f:h(hello)}<br> <%-- (4) --%>


Message : ${f:h(helloBean.message)}<br> <%-- (5) --%>

• HTML of created by View(hello.jsp)

Message : Hello World!<br> <!-- (6) -->


Message : Bean Hello World!<br> <!-- (6) -->

226 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Fetch Model object as argument.

(1)

(2) Call addAttribute method of Model object received as argument, and add the data to
Model object.
For example, "HelloWorld!" string is added to the attribute name "hello".

(3) If first argument of addAttribute method is omitted, the class name beginning with lower
case letter will become the attribute name.
For example, the result of model.addAttribute("helloBean", new
HelloBean()); is same as the result of model.addAttribute(new
HelloBean());

(4) In View (JSP), it is possible to acquire the data added to Model object by specifying
“${Attribute name}”.
For example, HTML escaping is performed using “${f:h(Attribute name)}” function of EL
expression.
For details of functions of EL expression that perform HTML escaping, refer to Cross Site
Scripting.

(5) The values of JavaBean stored in Model can be acquired by specifying “${Attribute
name.property name}”.

(6) JSP is output in HTML format.

Note: Even though the Model is not used, it can be specified as an argument. Even if it is not required
at the initial stage of implementation, it can be used later (so that the signature of methods need not be
changed in future).

Note: The value can also be referred from the module which is not managed under Spring MVC

3.4. Implementation of Application Layer 227


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

(for example, ServletFilter, etc.) since addAttribute in Model performs a setAttribute in


HttpServletRequest.

Retrieving values from URL path

To retrieve values from URL path, add @PathVariable annotation to argument of handler method of
controller.
In order to retrieve values from the path using @PathVariable annotation, value of @RequestMapping
annotation must contain those values in the form of variables (for example, {id}).

@RequestMapping("hello/{id}/{version}") // (1)
public String hello(
@PathVariable("id") String id, // (2)
@PathVariable Integer version, // (3)
Model model) {
// do something
return "sample/hello"; // returns view name
}

228 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Specify the portion to be extracted as path variable in the value of @RequestMapping
annotation. Specify path variable in “{variable name}” format.
For example, 2 path variables such as "id" and "version" are specified.

(2) Specify variable name of path variable in @PathVariable annotation.


For example, when the URL "sample/hello/aaaa/1" is accessed, the string "aaaa" is
passed to argument “id”.

(3) Value attribute of @PathVariable annotation can be omitted. When it is omitted, the
argument name is considered as the request parameter name.
In the above example, when the URL "sample/hello/aaaa/1" is accessed, value "1" is
passed to argument “version”.
However, in this method compilation needs to be done by specifying either of:

• -g option (mode to output debug information)


• -parameters option added from Java8 (mode to generate metadata for reflection in the
method parameters)

Note: Binding argument can be of any data type other than string. In case of different data type,
org.springframework.beans.TypeMismatchException is thrown and default response is
400 (Bad Request). For example, when the URL "sample/hello/aaaa/v1" is accessed, an ex-
ception is thrown since "v1" cannot be converted into Integer type.

Warning: When omitting the value attribute of @PathVariable annotation, the application to be
deployed needs to be compiled by specifying -g option or -parameters option which is added
from Java8. When these options are specified, there is a likely impact on memory and processing
performance since information or processing required for debugging gets appended to the class after
compilation. Basically, it is recommended to explicitly specify the value attribute.

3.4. Implementation of Application Layer 229


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Retrieving request parameters individually

To retrieve request parameters individually, add @RequestParam annotation to argument.

@RequestMapping("bindRequestParams")
public String bindRequestParams(
@RequestParam("id") String id, // (1)
@RequestParam String name, // (2)
@RequestParam(value = "age", required = false) Integer age, // (3)
@RequestParam(value = "genderCode", required = false, defaultValue = "unknown") Strin
Model model) {
// do something
return "sample/hello"; // returns view name
}

230 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Specify request parameter name in the value attribute of @RequestParam annotation.
For example, when the URL "sample/hello?id=aaaa" is accessed, the string "aaaa"
is passed to argument “id”.

(2) value attribute of @RequestParam annotation can be omitted. When it is omitted, the
argument name becomes the request parameter name.
For example, when the URL "sample/hello?name=bbbb&...." is accessed, string
"bbbb" is passed to argument “name”.
However, in this method compilation needs to be done by specifying either of:

• -g option (mode to output debug information)


• -parameters option added from Java8 (mode to generate metadata for reflection in the
method parameters)

(3) By default, an error occurs if the specified request parameter does not exist. When request
parameter is not required, specify false in the required attribute.
For example, when it is accessed where request parameter age does not exist, null is passed
to argument “age”.

(4) When default value is to be used if the specified request parameter does not exist, specify the
default value in defaultValue attribute.
For example, when it is accessed where request parameter genderCode does not exist,
"unknown" is passed to argument “genderCode”.

Note: When it is accessed without specifying mandatory parameters,


org.springframework.web.bind.MissingServletRequestParameterException
is thrown and default operation is responded with 400 (Bad Request). However, when defaultValue
attribute is specified, the value specified in defaultValue attribute is passed without throwing exception.

Note: Binding argument can be of any data type. In case the data type do not match,
org.springframework.beans.TypeMismatchException is thrown and default response is
400 (Bad Request). For example, when "sample/hello?age=aaaa&..." URL is accessed, ex-

3.4. Implementation of Application Layer 231


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

ception is thrown since aaaa cannot be converted into Integer.

Binding to form object must be done only when any of the following conditions are met.

• If request parameter is an item in the HTML form.

• If request parameter is not an item in HTML form, however, input validation other than mandatory check
needs to be performed.

• If error details of input validation error needs to be output for each parameter.

• If there are 3 or more request parameters. (maintenance and readability point of view)

Retrieving request parameters collectively

Use form object to collectively fetch all the request parameters.


Form object is JavaBean representing HTML form. For the details of form object, refer to Implementing form
object.

Following is an example that shows the difference between handler method that fetches each request parameter
using @RequestParam and the same handler method when fetching request parameters in a form object

Handler method that receives request parameter separately using @RequestParam is as shown below.

@RequestMapping("bindRequestParams")
public String bindRequestParams(
@RequestParam("id") String id,
@RequestParam String name,
@RequestParam(value = "age", required = false) Integer age,
@RequestParam(value = "genderCode", required = false, defaultValue = "unknown") Strin
Model model) {
// do something
return "sample/hello"; // returns view name
}

232 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Create form object class


For jsp of HTML form corresponding to this form object, refer to Binding to HTML form.

public class SampleForm implements Serializable{


private static final long serialVersionUID = 1477614498217715937L;

private String id;


private String name;
private Integer age;
private String genderCode;

// omit setters and getters

Note: Request parameter name should match with form object property name.

When parameters "id=aaa&name=bbbb&age=19&genderCode=men?tel=01234567" are sent to the above fo


the values of id , name , age , genderCode matching with the property name, are stored, however
tel is not included in form object, as it does not have matching property name.

Make changes such that request parameters which were being fetched individually using
@RequestParam now get fetched as form object.

@RequestMapping("bindRequestParams")
public String bindRequestParams(@Validated SampleForm form, // (1)
BindingResult result,
Model model) {
// do something
return "sample/hello"; // returns view name
}

Sr. No. Description


Receive SampleForm object as argument.

(1)

Note: When form object is used as argument, unlike @RequestParam, mandatory check is not per-
formed. When using form object, Performing input validation should be performed as described below.

3.4. Implementation of Application Layer 233


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Warning: Domain objects such as Entity, etc. can also be used as form object without any changes required.
However, the parameters such as password for confirmation, agreement confirmation checkbox, etc. should
exist only on WEB screen. Since the fields depending on such screen items should not be added to domain
objects, it is recommended to create class for form object separate from domain object. When a domain object
needs to be created from request parameters, values must first be received in form object and then copied to
domain object from form object.

Performing input validation

When performing input validation for the form object, add @Validated annotation to form object ar-
gument, and specify org.springframework.validation.BindingResult (Hereafter called as
BindingResult) to argument immediately after form object argument.

Refer to Input Validation for the details of input validation.

Add annotations required in input validation to the fields of form object class.

public class SampleForm implements Serializable {


private static final long serialVersionUID = 1477614498217715937L;

@NotNull
@Size(min = 10, max = 10)
private String id;

@NotNull
@Size(min = 1, max = 10)
private String name;

@Min(1)
@Max(100)
private Integer age;

@Size(min = 1, max = 10)


private Integer genderCode;

// omit setters and getters


}

Add @Validated annotation to form object argument.


Input validation is performed for the argument with @Validated annotation before the handler method of
controller is executed. The check result is stored in the argument BindingResult which immediately follows

234 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

form object argument.


The type conversion error that occurs when a data-type other than String is specified in form object, is also stored
in BindingResult.

@RequestMapping("bindRequestParams")
public String bindRequestParams(@Validated SampleForm form, // (1)
BindingResult result, // (2)
Model model) {
if (result.hasErrors()) { // (3)
return "sample/input"; // back to the input view
}
// do something
return "sample/hello"; // returns view name
}

Sr. No. Description


Add @Validated annotation to SampleForm argument, and mark it as target for input vali-
dation.
(1)

Specify BindingResult in the argument where input validation result is stored.

(2)

Check if input validation error exists. If there is an error, true is returned.

(3)

Passing data while redirecting request

To redirect after executing a handler method ofcontroller and to pass data along with it, fetch
org.springframework.web.servlet.mvc.support.RedirectAttributes (Henceforth called
as RedirectAttributes) as an argument of handler method, and add the data to RedirectAttributes
object.

• SampleController.java

@RequestMapping("hello")
public String hello(RedirectAttributes redirectAttrs) { // (1)
redirectAttrs.addFlashAttribute("hello", "Hello World!"); // (2)
redirectAttrs.addFlashAttribute(new HelloBean("Bean Hello World!")); // (3)
return "redirect:/sample/hello?complete"; // (4)
}

3.4. Implementation of Application Layer 235


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@RequestMapping(value = "hello", params = "complete")


public String helloComplete() {
return "sample/complete"; // (5)
}

• complete.jsp

Message : ${f:h(hello)}<br> <%-- (6) --%>


Message : ${f:h(helloBean.message)}<br> <%-- (7) --%>

• HTML of created by View(complete.jsp)

Message : Hello World!<br> <!-- (8) -->


Message : Bean Hello World!<br> <!-- (8) -->

236 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Fetch RedirectAttributes object as argument of the handler method of controller.

(1)

(2) Call addFlashAttribute method of RedirectAttributes and add the data to


RedirectAttributes object.
For example, the string data "HelloWorld!" is added to attribute name "hello".

(3) If first argument of addFlashAttribute method is omitted, the class name beginning with
lower case letter becomes the attribute name.
For example, the result of model.addFlashAttribute("helloBean", new
HelloBean()); is same as model.addFlashAttribute(new HelloBean());.

(4) Send a redirect request to another URL which will display the next screen instead of displaying
screen (View) directly.

(5) In the handler method after redirection, return view name of the screen that displays the data
added in (2) and (3).

(6) In the View (JSP) side, the data added to RedirectAttributes object can be obtained by
specifying “${attribute name}”.
For example, HTML escaping is performed using “${f:h(attribute name)}” function of EL
expression.
For the details of functions of EL expression that performs HTML escaping, refer to Cross Site
Scripting.

(7) The value stored in RedirectAttributes can be obtained from JavaBean by using
“${Attribute name.Property name}”.

(8) HTML output.

3.4. Implementation of Application Layer 237


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Warning: The data cannot be passed to redirect destination even though it is added to Model.

Note: It is similar to the addAttribute method of Model. However survival time of data differs. In
addFlashAttribute of RedirectAttributes, the data is stored in a scope called flash scope. Data of
only 1 request (G in PRG pattern) can be referred after redirect. The data from the second request onwards is
deleted.

Figure.3.6 Picture - Survival time of flush scope

Passing request parameters to redirect destination

When request parameters are to be set dynamically to redirect destination, add the values to be passed to
RedirectAttributes object of argument.

@RequestMapping("hello")
public String hello(RedirectAttributes redirectAttrs) {
String id = "aaaa";
redirectAttrs.addAttribute("id", id); // (1)
// must not return "redirect:/sample/hello?complete&id=" + id;
return "redirect:/sample/hello?complete";
}

238 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Specify request parameter name in argument name and request parameter value
in argument ‘‘value and call addAttribute method of RedirectAttributes
object.
In the above example, it is redirected to "/sample/hello?complete&id=aaaa".

Warning: In the above example, the result is the same as of return


"redirect:/sample/hello?complete&id=" + id; (as shown in the commented out line
in the above example). However, since URL encoding is also performed if addAttribute method of
RedirectAttributes object is used, the request parameters that needs to be inserted dynamically should
be set to the request parameter using addAttribute method and should not be set to redirect URL
specified as return value. The request parameters which are not to be inserted dynamically (“complete” as in
the above example), can be directly specified in the redirect URL specified as the return value.

Inserting values in redirect destination URL path

To insert values in redirect destination URL path dynamically, add the value to be inserted in
RedirectAttributes object of argument as shown in the example to set request parameters.

@RequestMapping("hello")
public String hello(RedirectAttributes redirectAttrs) {
String id = "aaaa";
redirectAttrs.addAttribute("id", id); // (1)
// must not return "redirect:/sample/hello/" + id + "?complete";
return "redirect:/sample/hello/{id}?complete"; // (2)
}

Sr. No. Description

(1) Specify attribute name and the value using addAttribute method of
RedirectAttributes object.

(2) Specify the path of the variable “{Attribute name}” to be inserted in the redirect URL.
In the above example, it is redirected to "/sample/hello/aaaa?complete".

3.4. Implementation of Application Layer 239


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Warning: In the above example, the result is same as of "redirect:/sample/hello/" + id +


"?complete"; (as shown in the commented out line in the above example). However, since URL encoding
is also performed when using addAttribute method of RedirectAttributes object, the path values
to be inserted dynamically should be inserted using addAttribute method and path variable and should
not be set to redirect URL specified as return value.

Acquiring values from Cookie

Add @CookieValue annotation to the argument of handler method to acquire the values from a cookie.

@RequestMapping("readCookie")
public String readCookie(@CookieValue("JSESSIONID") String sessionId, Model model) { // (1)
// do something
return "sample/readCookie"; // returns view name
}

Sr. No. Description

(1) Specify name of the cookie in the value attribute of @CookieValue annotation.
In the above example, “JSESSIONID” value is passed from cookie to sessionId argument.

Note:

As in the case of @RequestParam , it has required attribute and defaultValue attribute. Also, the data type of the a
Refer to Retrieving request parameters individually for details.

Writing values in Cookie

To write values in cookie, call addCookie method of HttpServletResponse object directly and add the
value to cookie.
Since there is no way to write to cookie in Spring MVC (3.2.3 version), ** Only in this case,
HttpServletResponse can fetched as an argument of handler method of controller.**

240 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@RequestMapping("writeCookie")
public String writeCookie(Model model,
HttpServletResponse response) { // (1)
Cookie cookie = new Cookie("foo", "hello world!");
response.addCookie(cookie); // (2)
// do something
return "sample/writeCookie";
}

Sr. No. Description


Specify HttpServletResponse object as argument to write to cookie.

(1)

(2) Generate Cookie object and add to HttpServletResponse object.


For example, "hello world!" value is assigned to Cookie name "foo".

Tip: No difference compared to use of HttpServletResponse which fetched as an argument of handler


method, however, org.springframework.web.util.CookieGenerator class is provided by Spring
as a class to write values in cookie. It should be used if required.

Retrieving pagination information

Pagination related information is required for the requests performing list search.
Fetching org.springframework.data.domain.Pageable (henceforth called as Pageable) object
as an argument of handler method enables to handle pagination related information (page count, fetch record
count) easily.

Refer to Pagination for details.

3.4. Implementation of Application Layer 241


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Retrieving uploaded file

Uploaded file can be obtained in 2 ways.

• Provide MultipartFile property in form object.

• Use org.springframework.web.multipart.MultipartFile as an argument of handler


method having @RequestParam annotation.

Refer to File Upload for details.

Displaying result message on the screen

Model object or RedirectAttributes object can be obtained as an argument of handler method and re-
sult message of business logic execution can be displayed by adding ResultMessages object to Model or
RedirectAttributes.

Refer to Message Management for details.

Regarding return value of handler method

For return values of handler methods, various values can be fetched ; however, only the following values should
be used.

• String (for logical name of view)

Return types depending on the purpose of usage are described below:

• HTML response

• Responding to downloaded data

242 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

HTML response

To get HTML response to display the output of handler method, it has to return view name of JSP.
ViewResolver when generating HTML using JSP will be an inherited class of UrlBasedViewResolver
(InternalViewResolver and‘‘TilesViewResolver‘‘, etc).

An example using InternalViewResolver for JSP is given below; however, it is recommended to use
TilesViewResolver when the screen layout is in a templated format.
Refer to Screen Layout using Tiles for the usage of TilesViewResolver.

• spring-mvc.xml

Example of definition when <bean> element is to be used

<!-- (1) -->


<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" /> <!-- (2) -->
<property name="suffix" value=".jsp" /> <!-- (3) -->
<property name="order" value="1" /> <!-- (4) -->
</bean>

Example of definition when using <mvc:view-resolvers> element added from Spring Framework
4.1

<mvc:view-resolvers>
<mvc:jsp prefix="/WEB-INF/views/" /> <!-- (5) -->
</mvc:view-resolvers>

• SampleController.java

@RequestMapping("hello")
public String hello() {
// omitted
return "sample/hello"; // (6)
}

3.4. Implementation of Application Layer 243


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Define InternalViewResolver for JSP.

(1)

Specify base directory (prefix of file path) where JSP files are stored.
By specifying prefix, there is no need to specify physical storage location of JSP files at the time
(2)
of returning View name in Controller.

Specify extension (suffix of file path) of JSP file.


By specifying suffix, specifying extension of JSP files at the time of returning View name in
(3)
Controller is no longer needed.

Specify execution order when multiple ViewResolver are specified.


It can be specified in the range of Integer and executed sequentially from smallest value.
(4)

Define InternalViewResolver for JSP using <mvc:jsp> element added from Spring
Framework 4.1.
(5)
• In prefix attribute, specify base directory (prefix of file path) where JSP file is stored.
• It need not be explicitly specified in suffix attribute as ".jsp" is used as default value.

Note: When <mvc:view-resolvers> element is used, it is possible to de-


fine ViewResolver in simple way. Hence this guideline recommends to use
<mvc:view-resolvers>.

When View name "sample/hello" is the return value of handler method,


"/WEB-INF/views/sample/hello.jsp" is called and HTML is sent as response.
(6)

Note: HTML output is generated using JSP in the above example, however, even if HTML is generated using
other template engine such as Velocity, FreeMarker, return value of handler method will be "sample/hello".
ViewResolver takes care of task to determine which template engine is to be used.

244 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Responding to downloaded data

In order to return the data stored in db as download data ("application/octet-stream"), it is


recommended to create a view
for generating response data (download process).The handler method adds the data to be downloaded to Model
and returns
name of the view which performs the actual download process.

The solution to create a separate ViewResolver to resolve a view using its view name, however,
BeanNameViewResolver provided by Spring Framework is recommended.
Refer to File Download for the details of download processing.

• spring-mvc.xml

Example of definition when <bean> element is to be used

<!-- (1) -->


<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="0"/> <!-- (2) -->
</bean>

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

Example of definition when using <mvc:view-resolvers> element added from Spring Framework
4.1

<mvc:view-resolvers>
<mvc:bean-name /> <!-- (3) -->
<mvc:jsp prefix="/WEB-INF/views/" />
</mvc:view-resolvers>

• SampleController.java

@RequestMapping("report")
public String report() {
// omitted
return "sample/report"; // (4)
}

• XxxExcelView.java

3.4. Implementation of Application Layer 245


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@Component("sample/report") // (5)
public class XxxExcelView extends AbstractExcelView { // (6)
@Override
protected void buildExcelDocument(Map<String, Object> model,
HSSFWorkbook workbook, HttpServletRequest request,
HttpServletResponse response) throws Exception {
HSSFSheet sheet;
HSSFCell cell;

sheet = workbook.createSheet("Spring");
sheet.setDefaultColumnWidth(12);

// write a text at A1
cell = getCell(sheet, 0, 0);
setText(cell, "Spring-Excel test");

cell = getCell(sheet, 2, 0);


setText(cell, (Date) model.get("serverTime")).toString());
}
}

246 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Define BeanNameViewResolver.
BeanNameViewResolver is a class that resolves View by searching for the bean which
(1)
matches with the returned View name, from application context.

When InternalViewResolver for JSP and TilesViewResolver are to be used to-


gether, it is recommended to give it a higher priority compared to these ViewResolver. In
(2)
the above example, by specifying "0", View is resolved by BeanNameViewResolver prior
to InternalViewResolver.
Define BeanNameViewResolver using <mvc:bean-name> element added from Spring
Framework 4.1.
(3)
When defining ViewResolver using <mvc:view-resolvers> element, definition order
of ViewResolver specified in child element will be the priority order. In the above example,
by defining it above (<mvc:jsp>) element in order to define InternalViewResolver for
JSP, View is resolved by BeanNameViewResolver prior to InternalViewResolver
for JSP.

Note: When <mvc:view-resolvers> element is used, it is possible to de-


fine ViewResolver in a simple way. Hence, this guideline recommends to use
<mvc:view-resolvers>.

When View name "sample/report" is the return value of handler method, the data gener-
ated by View instance which is registered in step (5), is responded as download data.
(4)

Register View object as Bean by specifying View name to the name of component.
In above example, x.y.z.app.views.XxxExcelView instance is registered as a bean
(5)
with bean name (view name) as "sample/report" .

Example of View implementation.


Implementation of View class that inherits org.springframework.web.servlet.view.document
(6)
and generates Excel data.

Implementing the process

The point here is that do not implement business logic in controller .


Business logic must be implemented in Service. Controller must call the service methods in which the business
logic is implemented.

3.4. Implementation of Application Layer 247


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Refer to Domain Layer Implementation for the details of implementation of business logic.

Note: Controller should be used only for routing purposes (mapping requests to corresponding business logic)
and deciding the screen transition for each request as well as setting model data. Thereby, controller should be
simple as much as possible. By consistently following this policy, the contents of controller become clear which
ensures maintainability of controller even if the size of development is large.

Operations to be performed in controller are shown below:

• Correlation check of input value

• Calling business logic

• Reflecting values to domain object

• Reflecting values to form object

Correlation check of input value

Correlation check of input values should be done using Validation class which implements
org.springframework.validation.Validator interface.
Bean Validation can also be used for correlation check of input values.
Refer to Input Validation for the details of implementation of correlation check.

The implementation of correlation check itself should not be written in the handler method of controller.
However, it is necessary to add the Validator to
org.springframework.web.bind.WebDataBinder.

@Inject
PasswordEqualsValidator passwordEqualsValidator; // (1)

248 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@InitBinder
protected void initBinder(WebDataBinder binder){
binder.addValidators(passwordEqualsValidator); // (2)
}

Sr. No. Description


Inject Validator that performs correlation check.

(1)

(2) Add the injected Validator to WebDataBinder.


Adding the above to WebDataBinder enables correlation check by executing Validator
before the handler method gets called.

Calling business logic

Execute business logic by injecting the Service in which business logic is implemented and calling the injected
Service method.

@Inject
SampleService sampleService; // (1)

@RequestMapping("hello")
public String hello(Model model){
String message = sampleService.hello(); // (2)
model.addAttribute("message", message);
return "sample/hello";
}

Sr. No. Description

(1) Inject the Service in which business logic is implemented.

Call the injected Service method to execute business logic.

(2)

3.4. Implementation of Application Layer 249


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Reflecting values to domain object

In this guideline, it is recommended to bind the data sent by HTML form to form object instead of the domain
object.
Therefore, the controller should perform the process of reflecting the values of form object to domain object
which is then passed to the method of service class.

@RequestMapping("hello")
public String hello(@Validated SampleForm form, BindingResult result, Model model){
// omitted
Sample sample = new Sample(); // (1)
sample.setField1(form.getField1());
sample.setField2(form.getField2());
sample.setField3(form.getField3());
// ...
// and more ...
// ...
String message = sampleService.hello(sample); // (2)
model.addAttribute("message", message); // (3)
return "sample/hello";
}

Sr. No. Description

(1) Create domain object and reflect the values bound to form object in the domain object.

(2) Call the method of service class to execute business logic.

(3) Add the data returned from business logic to Model.

The process of reflecting values to domain object should be implemented by the handler method of controller.
However considering the readability of processing
method in case of large amount of code, it is recommended to delegate the process to Helper class.
Example of delegating the process to Helper class is shown below:

• SampleController.java

250 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@Inject
SampleHelper sampleHelper; // (1)

@RequestMapping("hello")
public String hello(@Validated SampleForm form, BindingResult result){
// omitted
String message = sampleHelper.hello(form); // (2)
model.addAttribute("message", message);
return "sample/hello";
}

• SampleHelper.java

public class SampleHelper {

@Inject
SampleService sampleService;

public String hello(SampleForm form){ // (3)


Sample sample = new Sample();
sample.setField1(form.getField1());
sample.setField2(form.getField2());
sample.setField3(form.getField3());
// ...
// and more ...
// ...
String message = sampleService.hello(sample);
return message;
}
}

Sr. No. Description


Inject object of Helper class in controller.

(1)

Value is reflected to the domain object by calling the method of the injected Helper class. Dele-
gating the process to Helper class enables to keep the implementation of controller simple.
(2)

Call the Service class method to execute the business logic after creating domain object.

(3)

Note: Bean conversion functionality can be used as an alternative way to delegate the process of reflecting
form object values, to Helper class. Refer to Bean Mapping (Dozer) for the details of Bean conversion
functionality.

3.4. Implementation of Application Layer 251


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Reflecting values to form object

In this guideline, it is recommended that form object (and not domain object) must be used to for that data which
is to be bound to HTML form.
For this, it is necessary to reflect the values of domain object (returned by service layer) to form object. This
conversion should be performed in controller class.

@RequestMapping("hello")
public String hello(SampleForm form, BindingResult result, Model model){
// omitted
Sample sample = sampleService.getSample(form.getId()); // (1)
form.setField1(sample.getField1()); // (2)
form.setField2(sample.getField2());
form.setField3(sample.getField3());
// ...
// and more ...
// ...
model.addAttribute(sample); // (3)
return "sample/hello";
}

Sr. No. Description

(1) Call the method of service class in which business logic is implemented and fetch domain
object.

(2) Reflect values of acquired domain object to form object.

(3) When there are fields only for display, add domain object to Model so that data can be referred.

Note: In JSP, it is recommended to refer the values from domain object instead of form object for the
fields to be only displayed on the screen.

The process of reflecting value to form object should be implemented by the handler method of controller. How-
ever considering the readability of handler method in case of large amount of code, it is recommended to delegate
the process to Helper class method.

252 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• SampleController.java

@RequestMapping("hello")
public String hello(@Validated SampleForm form, BindingResult result){
// omitted
Sample sample = sampleService.getSample(form.getId());
sampleHelper.applyToForm(sample, form); // (1)
model.addAttribute(sample);
return "sample/hello";
}

• SampleHelper.java

public void applyToForm(SampleForm destForm, Sample srcSample){


destForm.setField1(srcSample.getField1()); // (2)
destForm.setField2(srcSample.getField2());
destForm.setField3(srcSample.getField3());
// ...
// and more ...
// ...
}

Sr. No. Description

(1) Call the method to reflect the values of domain object to form object.

(2) Reflect the values of domain object to form object.

Note: Bean conversion functionality can be used as an alternative method to delegate the process to Helper
class. Refer to Bean Mapping (Dozer) for the details of Bean conversion functionality.

3.4.2 Implementing form object

Form object is the object (JavaBean) which represents HTML form and plays the following role.

1. Holds business data stored in the database so that it can be referred by HTML form (JSP).

2. Holds request parameters sent by HTML form so that they can be referred by handler method of

3.4. Implementation of Application Layer 253


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

controller.

Implementation of form object can be described by focusing on the following points.

• Creating form object

• Initializing form object

• Binding to HTML form

• Binding request parameters

Creating form object

Create form object as a JavaBean. Spring Framework provides the functionality to convert and bind the request
parameters (string) sent by HTML form to the format defined in form object. Hence, the fields to be defined in
form object need not only be in java.lang.String format.

public class SampleForm implements Serializable {


private String id;
private String name;
private Integer age;

254 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

private String genderCode;


private Date birthDate;
// omitted getter/setter
}

Tip: Regarding the mechanism provided by Spring Framework that performs format conversion

Spring Framework executes format conversion using the following 3 mechanisms and supports conversion
to basic format as standard. Refer to linked page for the details of each conversion function.

• Spring Type Conversion

• Spring Field Formatting

• java.beans.PropertyEditor implementations

Warning: In form object, it is recommended to maintain only the fields of HTML form and
not the fields which are just displayed on the screen. If display only fields are also maintained
in form object, more memory will get consumed at the time of storing form object in HTTP ses-
sion object causing memory exhaustion. In order to display the values of display only fields on the
screen, it is recommended to add objects of domain layer (such as Entity) to request scope by using
(Model.addAttribute).

Number format conversion of fields

Number format can be specified for each field using @NumberFormat annotation.

public class SampleForm implements Serializable {


@NumberFormat(pattern = "#,#") // (1)
private Integer price;
// omitted getter/setter
}

Sr. No. Description

(1) Specify the number format of request parameter sent by HTML form. For example, binding of
value formatted by ”,” is possible since “”#, #”” format is specified as pattern.
When value of request parameter is “”1,050””, Integer object of “”1050”” will bind to the
property price of form object.

3.4. Implementation of Application Layer 255


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Attributes of @NumberFormat annotation are given below.

Sr. No. Attribute Description


name
style Specify number format style. For details refer to Javadoc of NumberFormat.Style.
1.

pattern Specify number format of Java. Refer to ‘Javadoc of DecimalFormat


2.
<http://docs.oracle.com/javase/8/docs/api/java/text/DecimalFormat.html>’_for
details.

Date and time format conversion of fields

Date and time format for each field can be specified using @DateTimeFormat annotation.

public class SampleForm implements Serializable {


@DateTimeFormat(pattern = "yyyyMMdd") // (1)
private Date birthDate;
// omitted getter/setter
}

Sr. No. Description


Specify the date and time format of request parameter sent by HTML form. For exam-
ple, "yyyyMMdd" format is specified as pattern. When the value of request parameter is
(1)
"20131001", Date object of 1st October, 2013 will bind to property birthDate of form
object.

Attributes of @DateTimeFormat annotation are given below.

256 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Attribute Description


name
iso Specify ISO date and time format. For details refer to Javadoc of DateTimeFor-
1.
mat.ISO.

pattern Specify Java date and time format. Refer to ‘Javadoc of SimpleDateFormat
2.
<http://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html>’_for
details.
style
3.
Specify style of date and time as two-digit string.
First digit will be style of date and second digit will be style of time.
Values that can be specified as style are given below.

S : Format same as java.text.DateFormat.SHORT.


M : Format same as java.text.DateFormat.MEDIUM.
L : Format same as java.text.DateFormat.LONG.
F : Format same as java.text.DateFormat.FULL.
- : A style meaning omissions.

Example of specification and conversion)


MM : Dec 9, 2013 3:37:47 AM
M- : Dec 9, 2013
-M : 3:41:45 AM

Warning: @DateTimeFormat’s formatter is not strict in case of pattern attribute specified with
java.time.LocalDate on JSR-310 Date and Time API ("20150229" is invalid , but it will be regarded
as 28st February, 2015). Specifications are improved in Spring Framework 4.3 , but are affected because they
use Spring Framework 4.2 in TERASOLUNA Server Framework for JAVA (5.x). For details reference to
‘@DateTimeFormat’s JSR-310 formatter is not strict in case of pattern‘

DataType conversion in controller

@InitBinder annotation can be used to define datatype conversions at controller level.

3.4. Implementation of Application Layer 257


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@InitBinder // (1)
public void initWebDataBinder(WebDataBinder binder) {
binder.registerCustomEditor(
Long.class,
new CustomNumberEditor(Long.class, new DecimalFormat("#,#"), true)); // (2)
}

@InitBinder("sampleForm") // (3)
public void initSampleFormWebDataBinder(WebDataBinder binder) {
// ...
}

Sr. No. Description

(1) If a method with @InitBinder annotation is provided, it is called before executing the
binding process and thereby default operations can be customized.

(2) For example, "#. #" format is specified for a field of type Long. This enables binding of
value formatted with ”,”.

(3) Default operation for each form object can be customized by specifying it in the value attribute
of @InitBinder annotation.
In the above example, the method is called before binding form object "sampleForm".

Specifying annotation for input validation

Since form object is validated using Bean Validation, it is necessary to specify the annotation which indicates
constraints of the field. Refer to Input Validation for the details of input validation.

258 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Initializing form object

Form object can also be called as form-backing bean and binding can be performed using @ModelAttribute
annotation. Initialize form-backing bean by the method having @ModelAttribute annotation. In this guide-
line, such methods are called as ModelAttribute methods and defined with method names like setUpXxxForm.

@ModelAttribute // (1)
public SampleForm setUpSampleForm() {
SampleForm form = new SampleForm();
// populate form
return form;
}

@ModelAttribute("xxx") // (2)
public SampleForm setUpSampleForm() {
SampleForm form = new SampleForm();
// populate form
return form;
}

@ModelAttribute
public SampleForm setUpSampleForm(
@CookieValue(value = "name", required = false) String name, // (3)
@CookieValue(value = "age", required = false) Integer age,
@CookieValue(value = "birthDate", required = false) Date birthDate) {
SampleForm form = new SampleForm();
form.setName(name);
form.setAge(age);
form.setBirthDate(birthDate);
return form;
}

3.4. Implementation of Application Layer 259


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Class name beginning with lower case letter will become the attribute name to add to Model.
In the above example, "sampleForm" is the attribute name.
The returned object is added to Model and an appropriate process
model.addAttribute(form) is executed.

(2) When attribute name is to be specified to add to Model, specify it in the value attribute of
@ModelAttribute annotation. In the above example, "xxx" is the attribute name.
For returned object, appropriate process “model.addAttribute(“xxx”, form)”is executed and it is
returned to Model.
When attribute name other than default value is specified, it is necessary to specify
@ModelAttribute("xxx") at the time of specifying form object as an argument of
handler method.

(3) ModelAttribute method can pass the parameters required for initialization as with the case of
handler method. In the above example, value of cookie is specified using @CookieValue
annotation.

Note: When form object is to be initialized with default values, it should be done using ModelAttribute method.
In point (3) in above example , value is fetched from cookie, However, fixed value defined in constant class can
be set directly.

Note: Multiple ModelAttribute methods can be defined in the controller. Each method is executed before calling
handler method of controller.

Warning: If ModelAttribute method is executed for each request, initialization needs to be repeated for each
request and unnecessary objects will get created. So, for form objects which are required only for specific
requests, should be created inside handler method of controller and not through the use of ModelAttribute
method.

260 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Binding to HTML form

It is possible to bind form object added to the Model to HTML form(JSP) using <form:xxx> tag.
For the details of <form:xxx> tag, refer to Using Spring’s form tag library.

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <!-- (1) -->

<form:form modelAttribute="sampleForm"
action="${pageContext.request.contextPath}/sample/hello"> <!-- (2) -->
Id : <form:input path="id" /><form:errors path="id" /><br /> <!-- (3) -->
Name : <form:input path="name" /><form:errors path="name" /><br />
Age : <form:input path="age" /><form:errors path="age" /><br />
Gender : <form:input path="genderCode" /><form:errors path="genderCode" /><br />
Birth Date : <form:input path="birthDate" /><form:errors path="birthDate" /><br />
</form:form>

Sr. No. Description


Define taglib to use <form:form> tag.

(1)

Specify form object stored in Model in the modelAttribute attribute of <form:form>


tag.
(2)

Specify property name of form object in path attribute of <form:input> tag.

(3)

Binding request parameters

It is possible to bind the request parameters sent by HTML form to form object and pass it as an argument to the
handler method of controller.

@RequestMapping("hello")
public String hello(
@Validated SampleForm form, // (1)
BindingResult result,
Model model) {
if (result.hasErrors()) {
return "sample/input";
}
// process form...

3.4. Implementation of Application Layer 261


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

return "sample/hello";
}

@ModelAttribute("xxx")
public SampleForm setUpSampleForm() {
SampleForm form = new SampleForm();
// populate form
return form;
}

@RequestMapping("hello")
public String hello(
@ModelAttribute("xxx") @Validated SampleForm form, // (2)
BindingResult result,
Model model) {
// ...
}

Sr. No. Description

(1) Form object is passed as an argument to the handler method of controller after reflecting
request parameters to the form object.

(2) When the attribute name is specified in ModelAttribute method, it is necessary to explicitly
specify attribute name of form object as @ModelAttribute("xxx").

Warning: When attribute name specified by ModelAttribute method and attribute name specified in the
@ModelAttribute("xxx") in the argument of handler method are different, it should be noted that a
new instance is created other than the instance created by ModelAttribute method. When attribute name is not
specified with @ModelAttribute in the argument to handler method, the attribute name is deduced as the
class name with first letter in lower case.

Determining binding result

Error (including input validation error) that occurs while binding request parameter sent by HTML form to form
object, is stored in org.springframework.validation.BindingResult.

262 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@RequestMapping("hello")
public String hello(
@Validated SampleForm form,
BindingResult result, // (1)
Model model) {
if (result.hasErrors()) { // (2)
return "sample/input";
}
// ...
}

Sr. No. Description


When BindingResult is declared immediately after form object, it is possible to refer to the
error inside the handler method of controller.
(1)

Calling BindingResult.hasErrors() can determine whether any error occurred in the


input values of form object.
(2)

It is also possible to determine field errors, global errors (correlated check errors at class level) separately. These
can be used separately if required.

Sr. No. Method Description


hasGlobalErrors() Method to determine the existence of global errors.
1.

hasFieldErrors() Method to determine the existence of field errors.


2.

hasFieldErrors(String field) Method to determine the existence of errors related to


3.
specified field.

3.4.3 Implementing View

View plays the following role.

1. View generates response (HTML) as per the requirements of the client.


View retrieves the required data from model (form object or domain object) and generates response in the
format which is required by the client for rendering.

3.4. Implementation of Application Layer 263


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Implementing JSP

Implement View using JSP to generate response(HTML) as per the requirement of the client.
Use the class provided by Spring Framework as the ViewResolver for calling JSP. Refer to HTML response
for settings of ViewResolver.

Basic implementation method of JSP is described below.

• Creating common JSP for include

• Displaying value stored in model

• Displaying numbers stored in model

• Displaying date and time stored in model

• Generate request URL

• Binding form object to HTML form

• Displaying input validation errors

• Displaying message of processing result

• Displaying codelist

• Displaying fixed text content

• Switching display according to conditions

• Repeated display of collection elements

• Displaying link for pagination

• Switching display according to authority

In this chapter, usage of main JSP tag libraries are described. However, refer to respective documents for the
detailed usage since all JSP tag libraries are not described here.

264 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. JSP tag library name Document


Spring’s form tag library
1. • http://docs.spring.io/spring/docs/4.2.7.RELEASE/spring-
framework-reference/html/view.html#view-jsp-formtaglib
• http://docs.spring.io/spring/docs/4.2.7.RELEASE/spring-
framework-reference/html/spring-form-tld.html

Spring’s tag library


2. • http://docs.spring.io/spring/docs/4.2.7.RELEASE/spring-
framework-reference/html/spring-tld.html

JSTL
3. • http://download.oracle.com/otndocs/jcp/jstl-1.2-mrel2-
eval-oth-JSpec/

Common library’s tags & el


4. • [JSP Tag Libraries and EL Functions offered by common
functions
library] of this guideline

Warning: If terasoluna-gfw-web 1.0.0.RELEASE is being used, action tag must be always be


specified while using <form:form> tag of Spring’s form tag library.
terasoluna-gfw-web 1.0.0.RELEASE has a dependency on Spring MVC(3.2.4.RELEASE). In this ver-
sion of Spring MVC, if action attribute of <form:form> tag is not specified, it will expose a
vulnerability of XSS(Cross-site scripting). For further details regarding the vulnerability, refer to CVE-
2014-1904 of National Vulnerability Database (NVD).
Also, terasoluna-gfw-web 1.0.1.RELEASE have been upgraded to Spring MVC(3.2.10.RELEASE and
above); hence this vulnerability is not present.

Creating common JSP for include

Create a JSP that contains directive declaration which are required by all the JSP files of the project. By specifying
this JSP in <jsp-config>/<jsp-property-group>/<include-prelude> element of web.xml,
eliminates the need to declare these directives and each and every JSP file of the project. Further, this file is
provided in blank project also.

• include.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%-- (1) --%>


<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>

<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%> <%-- (2) --%>

3.4. Implementation of Application Layer 265


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>


<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec"%>

<%@ taglib uri="http://terasoluna.org/functions" prefix="f"%> <%-- (3) --%>


<%@ taglib uri="http://terasoluna.org/tags" prefix="t"%>

• web.xml

<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>false</el-ignored>
<page-encoding>UTF-8</page-encoding>
<scripting-invalid>false</scripting-invalid>
<include-prelude>/WEB-INF/views/common/include.jsp</include-prelude> <!-- (4) -->
</jsp-property-group>
</jsp-config>

Sr. No. Description

(1) JSP tag libraries of JSTL are declared. In this example, core and fmt are used.

(2) JSP tag libraries of Spring Framework are declared. In this example, spring, form and sec
are used.

(3) JSP tag libraries provided by common library are declared.

(4) The contents specified in JSP to be included (/WEB-INF/views/common/include.jsp)


are included at the beginning of each JSP (file specified in <url-pattern>).

Note: Refer to JSP.1.10 Directives of JavaServer Pages Specification(Version2.2)for details of


directives.

Note: Refer to JSP.3.3 JSP Property Groups of JavaServer Pages Specification(Version2.2)for


details of <jsp-property-group> element.

266 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Displaying value stored in model

To display the value stored in Model (form object or domain object) in HTML, use EL expressions or JSP tag
libraries provided by JSTL.

Display using EL expressions.

• SampleController.java

@RequestMapping("hello")
public String hello(Model model) {
model.addAttribute(new HelloBean("Bean Hello World!")); // (1)
return "sample/hello"; // returns view name
}

• hello.jsp

Message : ${f:h(helloBean.message)} <%-- (2) --%>

Sr. No. Description

(1) Add HelloBean object to Model object.

(2) In View(JSP), data added to the Model object can be retrieved by describing ${Attribute
name.Property name of JavaBean}.
In this example, HTML escaping is performed using ${f:h(Attribute
name.Property name of JavaBean)} function of EL expression.

Note: Since HTML escaping function (f:h) is provided in the common components, always use it if
EL expressions are used to output values in HTML. For details of function of EL expression that perform
HTML escaping, refer to Cross Site Scripting.

Display using <c:out> tag provided by JSP tag library of JSTL.

Message : <c:out value="${helloBean.message}" /> <%-- (1) --%>

3.4. Implementation of Application Layer 267


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Specify the values fetched using EL expressions in value attribute of <c:out> tag. HTML
escaping is also performed.

Note: Refer to CHAPTER 4 General-Purpose Actions of JavaServer Pages Standard Tag Li-
brary(Version 1.2)for the details of <c:out>.

Displaying numbers stored in model

Use JSP tag library provided by JSTL to output format number.

Display using <fmt:formatNumber> tag provided by JSP tag library of JSTL.

Number Item : <fmt:formatNumber value="${helloBean.numberItem}" pattern="0.00" /> <%-- (1) --

Sr. No. Description

(1) Specify the value acquired by EL expressions in the value attribute of


<fmt:formatNumber> tag. Specify the format to be displayed in pattern attribute. For
example, “0.00” is specified .
When the value acquired in ${helloBean.numberItem} is “1.2” temporarily, “1.20”
is displayed on the screen.

Note: Refer to CHAPTER 9 Formatting Actions of JavaServer Pages Standard Tag Library(Version
1.2)for the details of <fmt:formatNumber>.

268 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Displaying date and time stored in model

Use JSP tag library provided by JSTL to output format date and time value.

Display using <fmt:formatDate> tag provided by JSP tag library of JSTL.

Date Item : <fmt:formatDate value="${helloBean.dateItem}" pattern="yyyy-MM-dd" /> <%-- (1) --

Sr. No. Description

(1) Specify the value fetched using EL expression in value attribute of <fmt:formatDate>
tag. Specify the format to be displayed in pattern attribute. In this example,
“yyyy-MM-dd” is specified.
When value received for ${helloBean.dateItem} is 2013-3-2, “2013-03-02” is
displayed on the screen.

Note: Refer to CHAPTER 9 Formatting Actions of JavaServer Pages Standard Tag Library(Version 1.2)
for details of <fmt:formatDate>.

Note: JSP tag library provided by Joda Time should be used to use org.joda.time.DateTime as date and
time object type. Refer to Date Operations (Joda Time) for the details of Joda Time.

Generate request URL

When a request URL (a URL for calling Controller method) is to be set for action attribute of <form> el-
ement(<form:form> element of JSP tag library) of HTML and href attribute of <a> element, a URL is
generated using either of the methods described below.

• Build a request URL as a character string

• Build a request URL using EL function which has been added from Spring Framework 4.1

Note: Although either of these methods can be used, using both the methods together in a single application
should be avoided since it may result in decrease in maintainability.

3.4. Implementation of Application Layer 269


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

An implementation sample of the Controller method used further in the description is shown.
In the description hereafter, an implementation method is described wherein a request URL is generated for
calling the method given below.

package com.example.app.hello;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@RequestMapping("hello")
@Controller
public class HelloController {

// (1)
@RequestMapping({"", "/"})
public String hello() {
return "hello/home";
}

Sr. No. Description


Request URL assigned to the method is “{Context path}/hello".

(1)

Building a request URL as a character string

First, the method to build a request URL using a character string is explained.

<form action="${pageContext.request.contextPath}/hello"> <!-- (2) -->


<!-- ... -->
</form>

Sr. No. Description


Fetch context path assigned to Web application from pageContext (implicit object of
JSP)(${pageContext.request.contextPath}), add servlet path (/hello in the ex-
(2)
ample above) assigned to the Controller method that has been called, after the context path.

270 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Tip:

• <c:url> offered by JSTL

• <spring:url> offered by Spring Framework

are available as JSP tag libraries which build URL. A request URL can also be built using these JSP tag
libraries.

When it is necessary to build a request URL dynamically, a URL is preferably built by using these JSP tag
libraries.

Building a request URL by using EL function added from Spring Framework 4.1

Next, a method to build a request URL using EL function (spring:mvcUrl) added from Spring Framework
4.1 is described.

If spring:mvcUrl function is used, a request URL can be built by linking with meta information of Controller
method (method signature and annotation etc).

<form action="${spring:mvcUrl('HC#hello').build()}"> <!-- (3) -->


<!-- ... -->
</form>

3.4. Implementation of Application Layer 271


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Specify a request mapping name assigned to the Controller method which has been called, in the
spring:mvcUrl function argument.
(3)
An object of class (MvcUriComponentsBuilder.MethodArgumentBuilder)
which builds a request URL is returned from spring:mvcUrl function.
MvcUriComponentsBuilder.MethodArgumentBuilder class offers following
methods
• arg method
• build method
• buildAndExpand method
which play roles described below respectively.
• arg method specifies the value to be passed to argument of Controller method.
• build method generates a request URL.
• buildAndExpand method generates a request URL after specifying a value embedded in
dynamic part (path variable etc) which has not been declared as an argument of Controller
method.
In the example above, since a request URL is static, a request URL is generated only by calling
build method. When the request URL is dynamic (a URL wherein a path variable and a query
string exists), arg method and buildAndExpand method must be called.
Refer to “Spring Framework Reference Documentation(Building URIs to Controllers and meth-
ods from views)” for the basic usage of arg method and buildAndExpand method.

Note: Regarding request mapping name

In the default implementation (org.springframework.web.servlet.mvc.method.RequestMappingInfoHa


implementation), the request mapping name is represented as “Class name in upper case (short name of
class) + "#" + method name”.

Request mapping name must not be duplicated. When the name is duplicated, a unique name must be
specified in name attribute of @RequestMapping annotation.

When a request mapping name assigned to Controller method is to be verified, settings given below should
be added to logback.xml.

<logger name="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandler
<level value="trace" />
</logger>

If the program is rebooted after applying the settings given above, the log shown below is output.

date:2014-12-09 18:34:29 thread:RMI TCP Connection(2)-127.0.0.1 X-Track: l

272 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Binding form object to HTML form

Use JSP tag library provided by Spring Framework to bind form object to HTML form and to display the values
stored in form object.

Bind using <form:form> tag provided by Spring Framework.

<form:form action="${pageContext.request.contextPath}/sample/hello"
modelAttribute="sampleForm"> <%-- (1) --%>
Id : <form:input path="id" /> <%-- (2) --%>
</form:form>

Sr. No. Description


Specify attribute name of form object stored in Model in modelAttribute attribute of
<form:form> tag.
(1)

Specify name of property to bind in the path attribute of <form:xxx> tag. xxx part changes
along with each input element.
(2)

Note: For the details of <form:form> , <form:xxx> tag refer to Using Spring’s form tag library.

Displaying input validation errors

To display the contents of input validation error, use JSP tag library provided by Spring Framework.

Display using <form:errors> tag provided by Spring Framework.


Refer to Input Validation for details.

<form:form action="${pageContext.request.contextPath}/sample/hello"
modelAttribute="sampleForm">
Id : <form:input path="id" /><form:errors path="id" /><%-- (1) --%>
</form:form>

3.4. Implementation of Application Layer 273


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Specify name of the property to display the error in path attribute of <form:errors> tag.

Displaying message of processing result

To display the message notifying the output of processing the request, use JSP tag library provided in common
components.

Use <t:messagesPanel> tag provided in common components.


Refer to Message Management for details.

<div class="messages">
<h2>Message pattern</h2>
<t:messagesPanel /> <%-- (1) --%>
</div>

Sr. No. Description

(1) Messages stored with attribute name “resultMessages” are output.

Displaying codelist

To display the codelist (provided in common components), use JSP tag library provided by Spring Framework.

Codelist can be referred from JSP in the same way as java.util.Map interface.
Refer to Codelist for details.

Display codelist in select box.

274 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<form:select path="orderStatus">
<form:option value="" label="--Select--" />
<form:options items="${CL_ORDERSTATUS}" /> <%-- (1) --%>
</form:select>

Sr. No. Description


Codelist (java.util.Map interface) is stored with name ("CL_ORDERSTATUS") as at-
tribute name. Therefore, in JSP, codelist (java.util.Map interface) can be accessed using
(1)
EL expression. Codelist can be displayed in select box by passing the object of Map interface to
items attribute of <form:options>.

Label part is displayed on the screen for the value selected in select box.

Order Status : ${f:h(CL_ORDERSTATUS[orderForm.orderStatus])}

Sr. No. Description


In the same way as in case of creating select box, Codelist (java.util.Map interface) is
stored with name ("CL_ORDERSTATUS") as attribute name. If value selected in select box is
(1)
specified as key of the fetched Map interface, it is possible to display the code name.

Displaying fixed text content

Strings for screen name, element name and guidance etc can be directly written in JSP when internationalization
is not required.
However, when internationalization is required, display the values acquired from property file using JSP tag
library provided by Spring Framework.

Display using <spring:message> tag provided by Spring Framework.


Refer to Internationalization for details.

• properties

# (1)
label.orderStatus=Order status

• jsp

<spring:message code="label.orderStatus" text="Order Status" /> : <%-- (2) --%>


${f:h(CL_ORDERSTATUS[orderForm.orderStatus])}

3.4. Implementation of Application Layer 275


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Define the string of label in properties file.

(1)

If key in the properties file is specified in code attribute of <spring:message>, string


corresponding to the key is displayed.
(2)

Note: The value specified in text attribute is displayed when property value could not be acquired.

Switching display according to conditions

When display is to be switched according to some value in model, use JSP tag library provided by JSTL.

Switch display using <c:if> tag or <c:choose> provided by JSP tag library of JSTL.

Switching display by using <c:if>.

<c:if test="${orderForm.orderStatus != 'complete'}"> <%-- (1) --%>


<%-- ... --%>
</c:if>

Sr. No. Description


Put the condition for entering the branch in test attribute of <c:if>. In this example, when
order status is not ’complete’, the contents of the branch will be displayed.
(1)

Switching display using <c:choose>.

<c:choose>
<c:when test="${customer.type == 'premium'}"> <%-- (1) --%>
<%-- ... --%>
</c:when>
<c:when test="${customer.type == 'general'}">
<%-- ... --%>
</c:when>
<c:otherwise> <%-- (2) --%>
<%-- ... --%>
</c:otherwise>
</c:choose>

276 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Put the condition for entering the branch in test attribute of <c:when>. In this example, when
customer type is ’premium’, the contents of the branch will be displayed. When condition
(1)
specified in test attribute is false, next <c:when> tag is processed.

When result of test attribute of all <c:when> tags is false, <c:otherwise> tag is eval-
uated.
(2)

Note: Refer to CHAPTER 5 Conditional Actions of JavaServer Pages Standard Tag Library(Version
1.2)for details.

Repeated display of collection elements

To repeat display of collection stored in model, use JSP tag library provided by JSTL.

Repeated display can be done using <c:forEach> provided by JSP tag library of JSTL.

<table>
<tr>
<th>No</th>
<th>Name</th>
</tr>
<c:forEach var="customer" items="${customers}" varStatus="status"> <%-- (1) --%>
<tr>
<td>${status.count}</td> <%-- (2) --%>
<td>${f:h(customer.name)}</td> <%-- (3) --%>
</tr>
</c:forEach>
</table>

3.4. Implementation of Application Layer 277


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


By specifying the collection object in items attribute of <c:forEach> tag, <c:forEach>
tag is repeatedly executed to iterate over the collection. While iterating over the collection, if
(1)
the current element is to be referred inside <c:forEach> tag, it can be done by specifying a
variable name for the current element in var attribute.
By specifying a variable name in varStatus attribute, current position
(count) of iteration in <c:forEach> tag can be fetched. Refer to JavaDocof
(2)
javax.servlet.jsp.jstl.core.LoopTagStatus for attributes other than count.

This is the value acquired from the object stored in variable specified by var attribute of
<c:forEach> tag.
(3)

Note: Refer to CHAPTER 6 Iterator Actions of JavaServer Pages Standard Tag Library(Version 1.2)for
details.

Displaying link for pagination

To display links of pagination on the screen while displaying the list, use JSP tag library provided in common
components.

Display the link for pagination using <t:pagination> provided in common components. Refer to Pagination
for details.

Switching display according to authority

To switch display according to authority of the user who has logged in, use JSP tag library provided by Spring
Security.

Switch display using <sec:authorize> provided by Spring Security. Refer to Authorization for details.

278 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Implementing JavaScript

When it is necessary to control screen items (controls of hide/display, activate/deactivate, etc.) after screen ren-
dering, control items using JavaScript.

Todo

TBD

Details will be included in the coming versions.

Implementing style sheet

It is recommended to specify attribute values related to screen design in style sheet (css file) and not in
JSP(HTML) directly.
In JSP(HTML), specify id attribute to identify the items uniquely and class attribute which indicates
classification of elements.
While, specify values related to actual location of elements or appearance should be specified in style sheet (css
file).
By configuring in this way, it is possible to reduce the design related aspects from the implementation of JSP.
Simultaneously, if there is any change in design, only style sheet (css file) is modified and not JSP.

Note: When form is created using <form:xxx>, id attribute will be set automatically. Application developer
should specify class attribute.

3.4.4 Implementing common logic

3.4. Implementation of Application Layer 279


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Implementing common logic to be executed before and after calling controller

Here, common logic indicates processes which are required to be executed before and after execution the con-
troller.

Implementing Servlet Filter

Common processes independent of Spring MVC are implemented using Servlet Filter.
However, when common processes are to be executed only for the certain requests mapped with handler method
of controller,
then it should be implemented using Handler Interceptor and not Servlet Filter.

Samples of Servlet Filter are given below.


In sample code, value is stored in MDC in order to output the log of IP address of client.

• java

public class ClientInfoPutFilter extends OncePerRequestFilter { // (1)

private static final String ATTRIBUTE_NAME = "X-Forwarded-For";


protected final void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain) throws ServletException, I
String remoteIp = request.getHeader(ATTRIBUTE_NAME);
if (remoteIp == null) {
remoteIp = request.getRemoteAddr();
}
MDC.put(ATTRIBUTE_NAME, remoteIp);
try {
filterChain.doFilter(request, response);
} finally {
MDC.remove(ATTRIBUTE_NAME);
}
}
}

• web.xml

<filter> <!-- (2) -->


<filter-name>clientInfoPutFilter</filter-name>
<filter-class>x.y.z.ClientInfoPutFilter</filter-class>
</filter>

280 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<filter-mapping> <!-- (3) -->


<filter-name>clientInfoPutFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Sr. No. Description


In sample, it is guaranteed that it is executed only once for
similar requests by creating the Servlet Filter as subclass of
(1)
org.springframework.web.filter.OncePerRequestFilter provided by
Spring Framework.
Register the created Servlet Filter in web.xml.

(2)

Specify URL pattern to apply the registered Servlet Filter.

(3)

Servlet Filter can also be defined as Bean of Spring Framework.

• web.xml

<filter>
<filter-name>clientInfoPutFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <!-- (1
</filter>
<filter-mapping>
<filter-name>clientInfoPutFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

• applicationContext.xml

<bean id="clientInfoPutFilter" class="x.y.z.ClientInfoPutFilter" /> <!-- (2) -->

Sr. No. Description


In sample, process is delegated to Servlet Filter defined in step (2) by specify-
ing org.springframework.web.filter.DelegatingFilterProxy provided by
(1)
Spring Framework in Servlet Filter class.

Add the Servlet Filter class to Bean definition file (applicationContext.xml). At this
time, id attribute of bean definition should be assigned with the filter name (value specified in
(2)
<filter-name> tag) specified in web.xml.

3.4. Implementation of Application Layer 281


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Implementing HandlerInterceptor

Common processes dependent on Spring MVC are implemented using HandlerInterceptor.


HandlerInterceptor can execute common processes only for the requests which are allowed by the application
since it is called after the determining the handler method
to which the request is to be mapped to.

HandlerInterceptor can execute the process keeping in mind the following 3 points.

• Before executing handler method of controller


Implemented as HandlerInterceptor#preHandle method.

• After successfully executing handler method of controller


Implemented as HandlerInterceptor#postHandle method.

• After completion of handler method of controller (executed irrespective of Normal / Abnormal)


Implemented as HandlerInterceptor#afterCompletion method.

Sample of HandlerInterceptor is given below.


In sample code, log of info level is output after successfully executing controller process.

public class SuccessLoggingInterceptor extends HandlerInterceptorAdapter { // (1)

private static final Logger logger = LoggerFactory


.getLogger(SuccessLoggingInterceptor.class);

@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method m = handlerMethod.getMethod();
logger.info("[SUCCESS CONTROLLER] {}.{}", new Object[] {
m.getDeclaringClass().getSimpleName(), m.getName()});
}

• spring-mvc.xml

<mvc:interceptors>
<!-- ... -->
<mvc:interceptor>
<mvc:mapping path="/**" /> <!-- (2) -->

282 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<mvc:exclude-mapping path="/resources/**" /> <!-- (3) -->


<mvc:exclude-mapping path="/**/*.html" />
<bean class="x.y.z.SuccessLoggingInterceptor" /> <!-- (4) -->
</mvc:interceptor>
<!-- ... -->
</mvc:interceptors>

Sr. No. Description


In sample, HandlerInterceptor is created as the subclass of
org.springframework.web.servlet.handler.HandlerInterceptorAdapter
(1)
provided by Spring Framework. Since HandlerInterceptorAdapter provides blank
implementation of HandlerInterceptor interface, it is not required to implement
unnecessary methods in the subclass.
Specify the pattern of path, where the created HandlerInterceptor is to be applied.

(2)

Specify the pattern of path, where the created HandlerInterceptor need not be applied.

(3)

Add the created HandlerInterceptor to <mvc:interceptors> tag of spring-mvc.xml.

(4)

Implementing common processes of controller

Here, common process indicates the process that should be commonly implemented in all the controllers.

Implementing HandlerMethodArgumentResolver

When an object that is not supported by default in Spring Framework is to be passed as controller argument,
HandlerMethodArgumentResolver is to be implemented in order to enable controller to be able to receive the
argument.

Sample of HandlerMethodArgumentResolver is given below.


In sample code, common request parameters are converted to JavaBean which are then passed to handler method
of controller.

3.4. Implementation of Application Layer 283


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• JavaBean

public class CommonParameters implements Serializable { // (1)

private String param1;


private String param2;
private String param3;

// ....

• HandlerMethodArgumentResolver

public class CommonParametersMethodArgumentResolver implements


HandlerMethodArgumentResolver { // (2)

@Override
public boolean supportsParameter(MethodParameter parameter) {
return CommonParameters.class.equals(parameter.getParameterType()); // (3)
}

@Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
CommonParameters params = new CommonParameters(); // (4)
params.setParam1(webRequest.getParameter("param1"));
params.setParam2(webRequest.getParameter("param2"));
params.setParam3(webRequest.getParameter("param3"));
return params;
}

• Controller

@RequestMapping(value = "home")
public String home(CommonParameters commonParams) { // (5)
logger.debug("param1 : {}",commonParams.getParam1());
logger.debug("param2 : {}",commonParams.getParam2());
logger.debug("param3 : {}",commonParams.getParam3());
// ...
return "sample/home";

• spring-mvc.xml

<mvc:annotation-driven>
<mvc:argument-resolvers>
<!-- ... -->
<bean class="x.y.z.CommonParametersMethodArgumentResolver" /> <!-- (6) -->
<!-- ... -->

284 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

</mvc:argument-resolvers>
</mvc:annotation-driven>

Sr. No. Description


JavaBean that retains common parameters.

(1)

Implement org.springframework.web.method.support.HandlerMethodArgumentResolv
interface.
(2)

Determine parameter type. For example, when type of JavaBean that retains common parameters
is specified as argument of controller, resolveArgument method of this class is called.
(3)

Fetch the values of request parameters, set the parameters and return the JavaBean that retains
the value of common parameters.
(4)

(5) Specify JavaBean that retains common parameters in the argument of handler method of
controller.
Object returned in step (4) is passed.

Add the created HandlerMethodArgumentResolver to <mvc:argument-resolvers> tag


of spring-mvc.xml.
(6)

Note: When parameters are to be passed commonly to handler methods of all controllers, it is effective to convert
the parameters to JavaBean using HandlerMethodArgumentResolver. Parameters referred here are not restricted
to request parameters.

Implementing “@ControllerAdvice”

In a class with @ControllerAdvice annotation, implement common processes which are to be executed in
multiple Controllers.

When a class with @ControllerAdvice annotation is created, processes implemented using

3.4. Implementation of Application Layer 285


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• method with @InitBinder

• method with @ExceptionHandler

• method with @ModelAttribute

can be applied to multiple Controllers.

Tip: @ControllerAdvice annotation is a mechanism added from Spring Framework 3.2; however, since the
processing was applied to all Controllers, it could only implement common processes of entire application.

From Spring Framework 4.0, it has been improved in such a way that controller can be specified flexibly for
applying common processes. With this improvement, it is possible to implement a common process in various
granularities.

Methods to specify Controller (methods to specify attributes) for applying common processes are described below.

286 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Attribute Description and example of specification


annotations Specify annotation.
Common processes are applied for the Controllers with specified annotations. An
(1)
example of specifications is given below.
@ControllerAdvice(annotations = LoginFormModelAttributeSetter.Lo
public class LoginFormModelAttributeSetter {
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public static @interface LoginFormModelAttribute {}
// ...
}
@LoginFormModelAttribute
@Controller
public class WelcomeController {
// ...
}
@LoginFormModelAttribute
@Controller
public class LoginController {
// ...
}
In the above example, @LoginFormModelAttribute annotation is assigned to
WelcomeController and LoginController, hence, common processes are
applied to WelcomeController and LoginController.
Specify a class or an instance.
assignableTypes
Common processes are applied for the Controllers which can be assigned (can be
(2)
casted) to the specified class or interface. When using this attribute, it is recommended
to adopt a style that specifies a marker interface to indicate that it is a Controller using
common process, in attribute value. When this style is adopted, only the marker
interface for common processes to be used needs to be implemented at Controller
side. An example of specifications is given below.
@ControllerAdvice(assignableTypes = ISODateInitBinder.ISODateApp
public class ISODateInitBinder {
public static interface ISODateApplicable {}
// ...
}
@Controller
public class SampleController implements ISODateApplicable {
// ...
}
In the above example, SampleController implements
@ISODateApplicable interface (Marker interface), hence, common processes
are applied to SampleController.
3.4. Implementation of Application Layer
Specify
basePackageClasses a class or an interface. 287
Common processes are applied for the Controllers under the package of specified
(3)
class or interface.
When using this attribute, it is recommended to adopt a style that specifies,
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Tip: basePackageClasses attribute / basePackages attribute / value attribute are the at-
tributes to specify base package that stores the Controller for applying common processes. However, when
basePackageClasses attribute is used,

• It is possible to prevent specifying the package that does not exist.

• It is possible to get linked and change the package name on IDE.

Therefore, it is known as Type-safe specification method.

Implementation sample of @InitBinder method is given below.


In sample code, date that can be specified in request parameter is set to "yyyy/MM/dd" .

@ControllerAdvice // (1)
@Order(0) // (2)
public class SampleControllerAdvice {

// (3)
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class,
new CustomDateEditor(dateFormat, true));
}

Sr. No. Description


It indicates that it is Bean of ControllerAdvice by assigning the @ControllerAdvice anno-
tation.
(1)

Specify priority for common processes by assigning the @Order annotation. It should be speci-
fied when multiple ControllerAdvice have ordering for example there are dependencies between
(2)
them. Otherwise it is not necessary.

Implement @InitBinder method. @InitBinder method is applied to all Controllers.

(3)

288 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Implementation sample of @ExceptionHandler method is given below.


In sample code, View of lock error screen is returned by handling
org.springframework.dao.PessimisticLockingFailureException.

// (1)
@ExceptionHandler(PessimisticLockingFailureException.class)
public String handlePessimisticLockingFailureException(
PessimisticLockingFailureException e) {
return "error/lockError";
}

Sr. No. Description


Implement @ExceptionHandler method. @ExceptionHandler method is applied to all
Controllers.
(1)

Implementation sample of @ModelAttribute method is given below.


In sample code, common request parameters are converted to JavaBean and stored in Model.

• ControllerAdvice

// (1)
@ModelAttribute
public CommonParameters setUpCommonParameters(
@RequestParam(value = "param1", defaultValue="def1") String param1,
@RequestParam(value = "param2", defaultValue="def2") String param2,
@RequestParam(value = "param3", defaultValue="def3") String param3) {
CommonParameters params = new CommonParameters();
params.setParam1(param1);
params.setParam2(param2);
params.setParam3(param3);
return params;
}

• Controller

@RequestMapping(value = "home")
public String home(@ModelAttribute CommonParameters commonParams) { // (2)
logger.debug("param1 : {}",commonParams.getParam1());

3.4. Implementation of Application Layer 289


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

logger.debug("param2 : {}",commonParams.getParam2());
logger.debug("param3 : {}",commonParams.getParam3());
// ...
return "sample/home";
}

Sr. No. Description


Implement @ModelAttribute method. @ModelAttribute method is applied to all Con-
trollers.
(1)

Object created by @ModelAttribute method is passed.

(2)

3.4.5 Prevention of double submission

Measures should be taken to prevent double submission as the same process gets executed multiple times by
clicking Send button multiple times or refreshing (refresh using F5 button) the Finish screen.

For the problems occurring when countermeasures are not taken and details of implementation method, refer to
Double Submit Protection .

3.4.6 Usage of session

In the default operations of Spring MVC, model (form object, domain object etc.) is not stored in session.
When it is to be stored in session, it is necessary to assign @SessionAttributes annotation to the controller
class.
When input forms are split on multiple screens, usage of @SessionAttributes annotation should be studied
since model (form object, domain object etc.)
can be shared between multiple requests for executing a series of screen transitions.
However, whether to use @SessionAttributes annotation should be determined after confirming the
warning signs of using the session.

290 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

For details of session usage policy and implementation at the time of session usage, refer to Session Management
.

3.4. Implementation of Application Layer 291


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

3.5 Build development project

3.5.1 Build development project

The method to create a war file to be deployed on application server and a jar file of env module (module to store
the file environment dependent file) is described below.

In case of a project created using Maven Archetype, the following 2 methods are provided as methods to create a
war file.

• Build method wherein jar file of env module is not included in war file (recommended)

• Build method wherein jar file of env module is included in war file

Note: About the recommended build method

This guideline recommends Build method wherein jar file of env module is not included in war file. Other build
method apart from those mentioned here can also be used.

However, the war file and jar file to be released in test environment and production environment should not
be created using the functionality provided by IDE such as Eclipse. In some of the IDE functionalities like
Eclipse, class files are created using an independent compiler which has been optimized for development, hence
there could be a risk of unexpected error during the application execution due to difference in the compiler.

Note: Rule for the project structure

Consider the following project structure.

1. Make sure to have a multi-project structure. 2.As far as possible, consolidate the configuration files (ex. log-
back.xml, jdbc.properties) having environment dependency in one project. Hereafter, this project is expressed
as *-env.

• ex. terasoluna-tourreservation-env

3. Projects other than *-env never have a setting for environment dependency.

• However, it is allowed to store the environment dependency configuration files for test under
src/test/resources.

4. Manage all software packaged binaries by storing them in package repository.

• Deploy not only *.jar files but also *.war files as work products in package repository. Consequently, these
jar/war files should not include environment dependencies.

5. Configure *-env project as follows:

292 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Store the configuration values required for operations on the developer’s PC in the file under
src/main/resources, as default values.

• Store the configuration files that differ with each environment such as test server, production server, in the
folder other than src/main/resources (ex. configs/test-server). Then, use “profile” function of Maven that
automatically replaces the configuration values depending on environment in order to build *-env-x.y.z.jar
file.

The above structure facilitates proper development in all the scenarios of software development lifecycle.

1. In local development environment, check out both main project and *-env project and include env project
in build path of the main project so as to do coding and testing in the local development environment.

2. On CI server, execute the test and perform packaging using a build tool (Maven) and deploy the artifact in
package repository whenever required.

3. Application can work on test server and production server by adding *-env project built as per the applica-
tion release environment, to the main project which is stored in package repository.

For details, refer to Sample application.

Warning: About build environment


In the example below, Windows environment is used for the build. However, you can use your own environ-
ment for doing the build. This guideline recommends that you should do the build using the same OS and
JDK version as that of the application execution environment.

When build is done using Maven, confirm whether home directory of JDK which is used during compilation in
the environment variable JAVA_HOME, has been specified.
If the environment variable is not set or the home directory of JDK having different version has been specified, an
appropriate home directory should be specified in environment variable.

[In case of Windows]

echo %JAVA_HOME%
set JAVA_HOME={Please set home directory of JDK}

[In case of Linux]

echo $JAVA_HOME
JAVA_HOME={Please set home directory of JDK}

3.5. Build development project 293


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: It is advisable to set the environment variable JAVA_HOME in the user environment variable of OS user
wherein build is to be done.

Build method wherein jar file of env module is not included in war file

Create war file

Open the root directory of development project.

cd C:\work\todo

Specify warpack in Maven profile (-P parameter) and run Maven install.

mvn -P warpack clean install

If the Maven package is run successfully, a war file that does not include jar file of env module is created in the
target directory of web module.
(Example: C:\work\todo\todo-web\target\todo-web.war)

Note: About the goal to be specified

In the above example, install is specified in goal and war file is installed in local repository, however it is
advisable to specify

• package in goal when only creating a war file

• deploy in goal when deploying in remote repository like Nexus

294 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Create jar file of env module

Open env module directory.

cd C:\work\todo\todo-env

Specify Profile ID to identify environment in Maven profile (-P parameter) and run Maven package.

mvn -P test-server clean package

If Maven package is run successfully, jar file for the specified environment is created in target directory of env
module.
(Example:
C:\work\todo\todo-env\target\todo-env-1.0.0-SNAPSHOT-test-server.jar)

Note: About profile ID to identify environment

In case of a project created using Maven Archetype, following profile IDs are defined by default.

• local: Profile for local environment of the developer (for IDE development environment) (default profile)

• test-server: Profile for test environment

• production-server: Profile for production environment

The above 3 profiles are provided by default; however you can add or modify them as per the environment config-
uration of the system to be developed.

3.5. Build development project 295


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Build method wherein jar file of env module is included in war file

Create war file

Warning: Points to be noted when including a jar file of env module in war file
When jar file of env module is included in war file, the war file cannot be deployed in other environment;
hence war file should be managed so that it is not deployed to other environment (especially in production
environment) by mistake.
Moreover, when using a method in which war file is created for each environment and released in each en-
vironment, it should be noted that war file released in production environment can never be the war file for
which testing is complete. This is for the re-compilation at the time of creating war file for the production en-
vironment. When creating the war file and releasing the same for each environment, it is especially important
to use the VCS (Version Control System) functionality (Tag functionality etc.) like Git or Subversion and to
establish a mechanism to create a war file which is to be released in production environment and various test
environments, through the use of tested source files.

Open the root directory of development project.

cd C:\work\todo

In Maven profile (-P parameter), specify Profile ID to identify environmentdefined in env module and
warpack-with-env, and then run the Maven package.

mvn -P warpack-with-env,test-server clean package

If Maven package is run successfully, war file which includes jar file of env module is created in target directory
of web module.
(Example: C:\work\todo\todo-web\target\todo-web.war)

296 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Deploy

Deploy on Tomcat

Deployment method (procedure) when Tomcat is used as an application server is given below.

1. Specify the profile of Maven as per the AP server environment in which the application is to be released
and build *-env project.

2. Place *-env-x.y.z.jar file built above in the folder of AP server decided in advance. ex. /etc/foo/bar/abcd-
env-x.y.z.jar

3. Unjar the *.war file deployed in package repository under [CATALINA_HOME]/webapps.

4. If Tomcat 7 is used, add /etc/foo/bar/*.jar into class path using VirtualWebappLoader function of the Tom-
cat.

• The following definition should be added in [CATALINA_HOME]/conf/[contextPath].xml file.

• For details, refer to http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/loader/VirtualWebappLoader.html


and configs folder of terasoluna-tourreservation-env.

• Example of VirtualWebappLoader function usages :

<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
virtualClasspath="/etc/foo/bar/*.jar" />

• In addition, VirtualWebappLoader can also be used in the Tomcat 6.

5. If Tomcat 8 is used, add /etc/foo/bar/*.jar into class path using Resource function of the Tomcat.

• The following definition should be added in [CATALINA_HOME]/conf/[contextPath].xml file.

• For details, refer to https://tomcat.apache.org/migration-8.html#Web_application_resources and con-


figs folder of terasoluna-tourreservation-env.

• Example of Resource function usages :

<Resources className="org.apache.catalina.webresources.StandardRoot">
<PreResources className="org.apache.catalina.webresources.DirResourceSet"
base="/etc/foo/bar/"
internalPath="/"
webAppMount="/WEB-INF/lib" />
</Resources>

Note:

• autoDeploy attribute of Host tag of [CATALINA_HOME]/conf/server.xml should be set to false. Otherwise


[CATALINA_HOME]/conf/[contextPath].xml gets deleted each time web application is restarted.

3.5. Build development project 297


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• When autoDeploy is disabled, Web application does not start by just placing the war file in
[CATALINA_HOME]/webapps. war file should always be unjarred (unzipped).

Deployment to other application server

Pprocedure to deployment on other (not tomcat) application server is explained.

When releasing the Web application on application servers (Example: WebSphere, WebLogic, JBoss) where
a mechanism for adding a class path for each web application (which is provided in VirtualWebappLoader of
Tomcat) is not provided, the method to release it after adding *-env-x.y.z.jar file under WEB-INF/lib of war file is
the easiest.

1. Specify profile of Maven as per the AP server environment in which application is to be released and build
*-env project.

2. Copy *.war file deployed in the package repository to the working directory.

3. Add it under WEB-INF/lib of war file using add option of jar command as follows.

4. Release foo-x.y.z.war on AP server.

Note: For a method to deploy a war file on application server, refer to the manual of application server to be used.

Here, a method to embed the jar file of env module in war file using jar command is given.

Open the working directory.


Here the in the example below, work is performed in env project.

cd C:\work\todo\todo-env

298 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Copy the created war file to the working directory.


Here in the example below, war file is fetched from Maven repository. (war file is required to be installed or
deployed.)

mvn org.apache.maven.plugins:maven-dependency-plugin:2.5:get^
-DgroupId=com.example.todo^
-DartifactId=todo-web^
-Dversion=1.0.0-SNAPSHOT^
-Dpackaging=war^
-Ddest=target/todo-web.war

If the command is run successfully, the specified war file is copied to the target directory of env module.
(Example: C:\work\todo\todo-env\target\todo-web.war)

Note:

• An appropriate value should be specified in -DgroupId, -DartifactId, -Dversion, -Ddest.

• When run on Linux, ^ at the end of the line should be read as \ .

Copy the created jar file to working directory (target\WEB-INF\lib) once and add it to the war file.

[In case of Windows]

mkdir target\WEB-INF\lib
copy target\todo-env-1.0.0-SNAPSHOT-test-server.jar target\WEB-INF\lib\.
cd target
jar -uvf todo-web.war WEB-INF\lib

[In case of Linux]

mkdir -p target/WEB-INF/lib
cp target/todo-env-1.0.0-SNAPSHOT-test-server.jar target/WEB-INF/lib/.
cd target
jar -uvf todo-web.war WEB-INF/lib

Note: Measures to be taken when jar command is not found

3.5. Build development project 299


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

The problem when jar command is not found can be resolved using either of the following measures.

• Add JAVA_HOME/bin to environment variable “PATH”.

• Specify the jar command with full path. In case of Windows, %JAVA_HOME%\bin\jar and in case of
Linux, ${JAVA_HOME}/bin/jar can be specified.

Continuous deployment

Continuous deployment is constantly releasing the target software through continuous looping of project (source
code tree) structure, version control, inspection, build operations and lifecycle management.

During development, release the software of SNAPSHOT version in the package repository and development
AP server and execute the test. To release the software officially, tagging to source code tree in VCS needs be
performed after assigning a version number. In this way, the flow of build and deployment slightly differs in the
snapshot release and official release.

To deploy the application on AP server that provides Web service, irrespective of snapshot version or official
release version, a group of environment dependency configuration files and *.war file should be deployed in a set
as per the target release AP server environment.

Separating the operation of registering libraries (jar, war) without environment dependency settings, in Maven
repository and the operation of actually deploying them on AP server facilitates deployment.

Note: In Maven, it is automatically distinguished whether it is a SNAPSHOT version or RELEASE version


according to the contents of <version> tag of pom.xml.

• It is considered as SNAPSHOT if it ends with -SNAPSHOT. Example: <version>1.0-


SNAPSHOT</version>

• It is considered as RELEASE if it does not end with -SNAPSHOT. Example: <version>1.0</version>

Please note that there are 2 types of repositories in Maven package repository i.e. snapshot repository and release
repository with a few limitations.

• Software of SNAPSHOT version cannot be registered in release repository. release repository also cannot
be registered in snapshot repository.

• In release repository, artifact having the same GAV information can be registered only once.
(GAV=groupId, artifactId, version)

• In snapshot repository, artifact having the same GAV information can be re-registered many times.

Operations of SNAPSHOT version A simple delivery flow of SNAPSHOT version software is as shown in
the following figure.

300 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

1. Check out the source code from development trunk.

2. Compile, measure the code metrics and execute test.

• In case of compilation error, certain violations of code metrics or in case the test fails, the subsequent
operations should be stopped.

3. Upload (mvn deploy) the artifact (jar, war file) on Maven package repository server. |

Operations of RELEASE version In case of official release, since it is necessary to assign the version number,
the flow becomes slightly more complex than the SNAPSHOT release.

1. Decide the version number to be assigned for release. (Example:1.0.1)

2. Check out the source code from development trunk (or release branch).

3. Change <version> tag of pom.xml. (Example:<version>1.0.1</version>)

4. Assign tag to VCS. (Example: tags/1.0.1)

5. Compile, measure the code metrics and execute test.

• In case of compilation error, certain violations of code metrics or in case the test fails, the subsequent
operations should be stopped.

• If the test fails, delete the tag of VCS.

6. Upload (mvn deploy) the artifact (jar, war file) on Maven package repository server.

Todo

Here, should the version tag of pom.xml of trunk source tree be written at the end till it is replaced by the next
SNAPSHOT version and committed?

3.5. Build development project 301


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: <version> tag of pom.xml file can be changed in versions-maven-plugin .

mvn versions:set -DnewVersion=1.0.0

Version tag in pom.xml can be edited as <version>1.0.0</version> by the above commands.

Release on Application Server To release the application on AP server that provides Web service, release the
*.war file registered in Maven package repository and the group of environment dependency configuration files in
a set according to the target release AP server environment. This has same flow irrespective of snapshot release or
official release.

1. Download war file of the version to be released from Maven package repository.

2. Check out *-resources project (that consolidates environment dependency configuration files) from VCS.

3. Using “profile” function of Maven, replace the contents with group of configuration files according to the
target release environment, package the resources project and create *-resources-x.y.z.jar.

4. Add the created *-resources-x.y.z.jar file under WEB-INF/lib folder of war file.

• In case of Tomcat, instead of adding *-resources-x.y.z.jar to war file, copy it to any path of Tomcat server
and specify that path in the extended class path of VirtualWebappLoader.

302 3 Application Development


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

5. Deploy the war file on application server.

Note: War file can be downloaded from Maven package repository with “get goal” of maven-dependency-plugin.

mvn org.apache.maven.plugins:maven-dependency-plugin:2.5:get \
-DgroupId=com.example \
-DartifactId=mywebapp \
-Dversion=0.0.1-SNAPSHOT \
-Dpackaging=war \
-Ddest=${WORKSPACE}/target/mywebapp.war

With this, mywebapp.war file is downloaded under the target directory.

Package of environment dependency configuration files can be added to mywebapp.war file using the following
commands.

mkdir -p $WORKSPACE/target/WEB-INF/lib
cd $WORKSPACE/target
cp ./mywebapp-resources*.jar WEB-INF/lib
jar -ufv mywebapp.war WEB-INF/lib

3.5. Build development project 303


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

For the definition of layers, refer to Application Layering .

304 3 Application Development


305

Web Application Development Features

The web function architecture adopted in this guideline is explained in detail.

4.1 Input Validation

4.1.1 Overview

It is mandatory to check whether the value entered by the user is correct. Validation of input value is broadly
classified into

1. Validation to determine whether the input value is valid by just looking at it irrespective of the context such
as size and format.

2. Validation of whether the changes in input value are valid depending on the system status.

1. is an example of mandatory check and number of digits check and 2. is an example of check of whether EMail
is registered and whether order count is within the count of the available stock.

In this section, 1. is explained and this check is called “Input validation”. 2. is called “Business logic check”. For
business logic check, refer to Domain Layer Implementation.

In this guideline, validation check should be performed in application layer whereas business logic check should
be performed in domain layer.

Input validation of Web application is performed at server side and client side (JavaScript). It is mandatory to
check at the Server Side. However, if the same check is performed at the client side also, usability improves since
validation results can be analyzed without communicating with the server.

Warning: Input validation should be performed at the server side as the process at client side may be altered
using JavaScript. If the validation is performed only at the client side without performing at the server side,
the system may be exposed to danger.
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Todo

Input validation at client side will be explained later. Only input validation at the server side is mentioned in the
first version.

Classification of input validation

Input validation is classified into single item check and correlation item check.

Type Description Example Implementation method


Single item
check
Check completed in single field Input mandatory check Bean Validation (Hibernate
Digit check Validator is used as

Type check implementation library)

Correlation item
check
Check comparing multiple fields Password and confirm Bean Validation or Validation
password check class implementing
org.springframework.validation.Validator
interface

Spring supports Bean Validation which is a Java standard. This Bean Validation is used for single item check.
Bean Validation or org.springframework.validation.Validator interface provided by Spring is
used for correlation item check.

4.1.2 How to use

Adding dependent libraries

When Bean validation 1.1 (Hibernate Validator 5.x) or higher version is to be used, in addition to jar file of
Hibernate Validator and jar file storing API specifications class (javax.validation package class) of Bean
Validation, libraries that store the following classes are required.

• API specifications class of Expression Language 2.2 or higher version (javax.el package class)

• Reference implementation class of Expression Language 2.2 or higher version

If the file is run by deploying on application server, dependent libraries need not be added; since these libraries
are provided by application server. However, when it is run in standalone environment (JUnit etc.), these libraries
need to be added as dependent libraries.

306 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

An example of adding libraries which are required when running Bean Validation 1.1 or higher version in stan-
dalone environment is given below.

<!-- (1) -->


<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-el</artifactId>
<scope>test</scope> <!-- (2) -->
</dependency>

Sr. No. Description


Add a library wherein a class for Expression Language is stored, in pom.xml file of the project to be
run in standalone environment.
(1)
In the above example, libraries provided for Apache Tomcat to be embedded are specified. API spec-
ifications classes of Expression Language and reference implementation classes are both stored in jar
file of tomcat-embed-el.
When dependent libraries are required to execute JUnit, an appropriate scope is test.

(2)

Note: In the above example of settings, it is a prerequisite that version of dependent libraries should be stored in
the parent project. Therefore, <version> element is not specified.

Single item check

For the implementation of single item check,

• Bean Validation annotation should be assigned to the field of form class

• @Validated annotation should be assigned in Controller for validation

• Tag for displaying validation error message should be added to JSP

Note: <mvc:annotation-driven> settings are carried out in spring-mvc.xml, Bean Validation is enabled.

Basic single item check

Implementation method is explained using “New user registration” process as an example. Rules for checking
“New user registration” form are provided below.

4.1. Input Validation 307


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Field name Type Rules

name java.lang.String Mandatory input


Between 1 and
20 characters

email java.lang.String Mandatory input


Between 1 and
50 characters
Email format

age java.lang.Integer Mandatory input


Between 1 and
200

• Form class

Assign Bean Validation annotation to each field of form class.

package com.example.sample.app.validation;

import java.io.Serializable;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;

public class UserForm implements Serializable {

private static final long serialVersionUID = 1L;

@NotNull // (1)
@Size(min = 1, max = 20) // (2)
private String name;

@NotNull
@Size(min = 1, max = 50)
@Email // (3)
private String email;

308 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@NotNull // (4)
@Min(0) // (5)
@Max(200) // (6)
private Integer age;

// omitted setter/getter
}

4.1. Input Validation 309


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Assign javax.validation.constraints.NotNull indicating that the target field is


not null.

In Spring MVC, when form is sent with input fields left blank,
empty string instead of null bindsto form object by default.
This @NotNull checks that name exists as request parameter.

(2) Assign javax.validation.constraints.Size indicating that the string length (or


collection size) of the target field is within the specified size range.

Since empty string binds to the field where string is left blank by default in Spring MVC,
‘1 or more character’ rule indicates Mandatory input.

(3) Assign org.hibernate.validator.constraints.Email indicating that the target


field is in RFC2822-compliant E-mail format.
When E-mail format requirements are flexible than RFC2822-compliant constraints, regular
expression should be specified using javax.validation.constraints.Pattern
instead of @Email.

(4) When form is sent without entering any number in input field, null binds to form object so
@NotNull indicates mandatory input of age.

(5) Assign javax.validation.constraints.Min indicating that the target field value


must be greater than the specified value.

(6) Assign javax.validation.constraints.Max indicating that the target field value


must be less than the specified value.

Tip: Refer to Bean Validation check rules and Hibernate Validator check rules for standard annotations of

310 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Bean Validation and annotations provided by Hibernate.

Tip: Refer to Binding null to blank string field for the method of binding null when input field is left
blank.

• Controller class

Assign @Validated to form class for input validation.

package com.example.sample.app.validation;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("user")
public class UserController {

@ModelAttribute
public UserForm setupForm() {
return new UserForm();
}

@RequestMapping(value = "create", method = RequestMethod.GET, params = "form")


public String createForm() {
return "user/createForm"; // (1)
}

@RequestMapping(value = "create", method = RequestMethod.POST, params = "confirm")


public String createConfirm(@Validated /* (2) */ UserForm form, BindingResult /* (3) */ res
if (result.hasErrors()) { // (4)
return "user/createForm";
}
return "user/createConfirm";
}

@RequestMapping(value = "create", method = RequestMethod.POST)


public String create(@Validated UserForm form, BindingResult result) { // (5)
if (result.hasErrors()) {
return "user/createForm";
}
// omitted business logic
return "redirect:/user/create?complete";
}

4.1. Input Validation 311


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@RequestMapping(value = "create", method = RequestMethod.GET, params = "complete")


public String createComplete() {
return "user/createComplete";
}
}

Sr. No. Description

(1) Display “New user registration” form screen.

(2) Assign org.springframework.validation.annotation.Validated to the


form class argument to perform input validation.

(3) Add org.springframework.validation.BindingResult that stores check result


of input validation performed in step (2).
This BindingResult must be specified immediately after the form argument.

When not specified immediately,


org.springframework.validation.BindException is thrown.

(4) Use BindingResult.hasErrors() method to determine the check result of step (2).
When the result of hasErrors() is true, return to form display screen as there is an error
in input value.

(5) Input validation should be executed againeven at the time of submission on the confirmation
screen.
There is a possibility of data tempering and hence Input validation must be performed just
before entering business logic.

Note: @Validated is not a standard Bean Validation annotation. It is an independent annotation pro-
vided by Spring. Bean Validation standard javax.validation.Valid annotation can also be used.
However, @Validated is better as compared to @Valid annotation. Validation group can be specified
in case of @Validated and hence @Validated is recommended in this guideline.

312 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• JSP

When there is input error, it can be displayed in <form:errors> tag.

<!DOCTYPE html>
<html>
<%-- WEB-INF/views/user/createForm.jsp --%>
<body>
<form:form modelAttribute="userForm" method="post"
action="${pageContext.request.contextPath}/user/create">
<form:label path="name">Name:</form:label>
<form:input path="name" />
<form:errors path="name" /><%--(1) --%>
<br>
<form:label path="email">Email:</form:label>
<form:input path="email" />
<form:errors path="email" />
<br>
<form:label path="age">Age:</form:label>
<form:input path="age" />
<form:errors path="age" />
<br>
<form:button name="confirm">Confirm</form:button>
</form:form>
</body>
</html>

Sr. No. Description

(1) Specify target field name in path attribute of <form:errors> tag.


Error message is displayed next to input field of each field.

Form is displayed as follows.

Error message is displayed as follows if this form is sent with all the input fields left blank.

4.1. Input Validation 313


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Error messages state that Name and Email are blank and Age is null.

Note: In Bean Validation, null is a valid input value except the following annotations.

• javax.validation.constraints.NotNull

• org.hibernate.validator.constraints.NotEmpty

• org.hibernate.validator.constraints.NotBlank

In the above example, error messages related to @Min and @Max annotations are not displayed. This is because
null is a valid value for @Min and @Max annotations.

Next, send the form by entering any value in the field.

Error message is not displayed since input value of Name fulfills validation conditions.
Error message is displayed since input value of Email is not in Email format though it fulfills the conditions
related to string length.
Error message is displayed since input value of Age exceeds maximum value.

Change the form as follows to change the style at the time of error.

<form:form modelAttribute="userForm" method="post"


class="form-horizontal"
action="${pageContext.request.contextPath}/user/create">
<form:label path="name" cssErrorClass="error-label">Name:</form:label><%-- (1) --%>
<form:input path="name" cssErrorClass="error-input" /><%-- (2) --%>
<form:errors path="name" cssClass="error-messages" /><%-- (3) --%>
<br>
<form:label path="email" cssErrorClass="error-label">Email:</form:label>
<form:input path="email" cssErrorClass="error-input" />
<form:errors path="email" cssClass="error-messages" />
<br>
<form:label path="age" cssErrorClass="error-label">Age:</form:label>
<form:input path="age" cssErrorClass="error-input" />
<form:errors path="age" cssClass="error-messages" />
<br>

314 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<form:button name="confirm">Confirm</form:button>
</form:form>

Sr. No. Description

(1) Specify class name for <label> tag in cssErrorClass attribute at the time of error.

(2) Specify class name for <input> tag in cssErrorClass attribute at the time of error.

(3) Specify class name for error messages in cssClass attribute.

For example, if the following CSS is applied to this JSP, error screen is displayed as follows.

.form-horizontal input {
display: block;
float: left;
}

.form-horizontal label {
display: block;
float: left;
text-align: right;
float: left;
}

.form-horizontal br {
clear: left;
}

.error-label {
color: #b94a48;
}

.error-input {
border-color: #b94a48;
margin-left: 5px;
}

.error-messages {
color: #b94a48;
display: block;
padding-left: 5px;
overflow-x: auto;
}

4.1. Input Validation 315


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

CSS can be customized as per the requirements of screen.

Instead of displaying the error messages next to each input field, output them collectively.

<form:form modelAttribute="userForm" method="post"


action="${pageContext.request.contextPath}/user/create">
<form:errors path="*" element="div" cssClass="error-message-list" /><%-- (1) --%>

<form:label path="name" cssErrorClass="error-label">Name:</form:label>


<form:input path="name" cssErrorClass="error-input" />
<br>
<form:label path="email" cssErrorClass="error-label">Email:</form:label>
<form:input path="email" cssErrorClass="error-input" />
<br>
<form:label path="age" cssErrorClass="error-label">Age:</form:label>
<form:input path="age" cssErrorClass="error-input" />
<br>
<form:button name="confirm">Confirm</form:button>
</form:form>

Sr. No. Description

(1) By specifying * in path attribute of <form:errors> in <form:form> tag,


all error messages related to Model specified in modelAttribute attribute of <form:form> can
be output.
Tag name including these error messages can be specified in element attribute. By default, it is
span. However,
specify div to output error message list as block element.
Specify CSS class in cssClass attribute.

An example of error message is shown when the following CSS class is applied.

.form-horizontal input {
display: block;
float: left;
}

.form-horizontal label {
display: block;
float: left;

316 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

text-align: right;
float: left;
}

.form-horizontal br {
clear: left;
}

.error-label {
color: #b94a48;
}

.error-input {
border-color: #b94a48;
margin-left: 5px;
}

.error-message-list {
color: #b94a48;
padding:5px 10px;
background-color: #fde9f3;
border:1px solid #c98186;
border-radius:5px;
margin-bottom: 10px;
}

By default, field name is not included in error message, hence it is difficult to understand which error message
corresponds to which field.
Therefore, when an error message is to be displayed in a list, it is necessary to define the message such that field
name is included in the error message.
For method of defining error messages, refer to “Definition of error messages”.

Note: Points to be noted when displaying error messages in a list

Error messages are output in a random order and the output order cannot be controlled by standard function.
Therefore, when an output order needs to be controlled (to be kept constant), an extended implementation such as

4.1. Input Validation 317


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

sorting the error information, etc. is required.

In the method of “Displaying error messages in a list”,

• Error message definition in feed unit

• Extended implementation to control the output order of error messages

are required. Therefore, the cost is higher as compared to “displaying error messages next to input field”. This
guideline recommends the method of “displaying error messages next to input field” when there are no
constraints due to screen requirements.

Further, following method can be considered as extended methods to


control output order of error message. Creating inherited class of
org.springframework.validation.beanvalidation.LocalValidatorFactoryBean pro-
vided by Spring Framework, and sorting error information by overriding processConstraintViolations
method, etc.

Note: About @GroupSequence annotation

A mechanism of @GroupSequence annotation is provided to control the check sequence; however, add a note that
this mechanism is not to control the output order of error message as operations given below are performed.

• When an error occurs, checking for subsequent groups is not executed.

• If multiple errors (errors in multiple fields) occur in the check of identical groups, then the output order of
error messages would be random.

Note: Use <spring:nestedPath> tag to display error messages collectively outside the <form:form>
tag.

<spring:nestedPath path="userForm">
<form:errors path="*" element="div"
cssClass="error-message-list" />
</spring:nestedPath>
<hr>
<form:form modelAttribute="userForm" method="post"
action="${pageContext.request.contextPath}/user/create">
<form:label path="name" cssErrorClass="error-label">Name:</form:label>
<form:input path="name" cssErrorClass="error-input" />
<br>
<form:label path="email" cssErrorClass="error-label">Email:</form:label>
<form:input path="email" cssErrorClass="error-input" />
<br>
<form:label path="age" cssErrorClass="error-label">Age:</form:label>
<form:input path="age" cssErrorClass="error-input" />

318 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<br>
<form:button name="confirm">Confirm</form:button>
</form:form>

Date and time format check

In case of performing the date and time format check, it is recommend the use of @DateTimeFormat
annotation offered by Spring rather than the use of Bean Validation mechanism.
About how to use the @DateTimeFormat annotation, refer Date and time format conversion of fields.
It is also possible to check the date and time format using @Pattern annotation of the Bean Validation.
However, it is necessary to write the date and time format in regular expressions while using @Pattern
annotation. If you want to check the date and time that does not exist, the description is complicated.
Therefore @DateTimeFormat annotation is more simpler than the @Pattern annotation.

Since @DateTimeFormat annotation is one of the type conversion mechanism provided by Spring, instead of
the error messages of Bean Validation, the error message of the type mismatch exception
(TypeMismatchException) has been displayed on screen at the time of input error.
In order to avoid the actual exception message gets displayed on the screen, it is necessary to configure the error
message in the property file which will be displayed at the time of type mismatch is occurred.
For more detail, refer Type mismatch.

Single item check of nested Bean

The method to validate nested Bean using Bean Validation is explained below.

“Ordering” process of an EC site is considered as an example. Rules for checking “Order” form are provided
below.

4.1. Input Validation 319


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Field name Type Rules Description

coupon java.lang.String 5 or less characters Coupon code


Single byte alphanumeric
characters

receiverAddress.name java.lang.String Mandatory input Receiver name


Between 1 and
50 characters

java.lang.String Mandatory input Receiver postal code


receiverAddress.postcode
Between 1 and
10 characters

java.lang.String Mandatory input Receiver address


receiverAddress.address
Between 1 and
100 characters

senderAddress.name java.lang.String Mandatory input Sender name


Between 1 and
50 characters

java.lang.String Mandatory input Sender postal code


senderAddress.postcode
Between 1 and
10 characters

java.lang.String Mandatory input Sender address


senderAddress.address
Between 1 and
100 characters

320 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Use the same form class since receiverAddress and senderAddress are objects of the same class.

• Form class

package com.example.sample.app.validation;

import java.io.Serializable;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

public class OrderForm implements Serializable {


private static final long serialVersionUID = 1L;

@Size(max = 5)
@Pattern(regexp = "[a-zA-Z0-9]*")
private String coupon;

@NotNull // (1)
@Valid // (2)
private AddressForm receiverAddress;

@NotNull
@Valid
private AddressForm senderAddress;

// omitted setter/getter
}

package com.example.sample.app.validation;

import java.io.Serializable;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class AddressForm implements Serializable {


private static final long serialVersionUID = 1L;

@NotNull
@Size(min = 1, max = 50)
private String name;

@NotNull
@Size(min = 1, max = 10)
private String postcode;

@NotNull
@Size(min = 1, max = 100)

4.1. Input Validation 321


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

private String address;

// omitted setter/getter
}

Sr. No. Description

(1) This indicates that the child form is mandatory.


When not set, it will be considered as valid even if null is set in receiverAddress.

(2) Assign javax.validation.Valid annotation to enable Bean Validation of the nested


Bean.

• Controller class

It is not different from the Controller described earlier.

package com.example.sample.app.validation;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@RequestMapping("order")
@Controller
public class OrderController {

@ModelAttribute
public OrderForm setupForm() {
return new OrderForm();
}

@RequestMapping(value = "order", method = RequestMethod.GET, params = "form")


public String orderForm() {
return "order/orderForm";
}

@RequestMapping(value = "order", method = RequestMethod.POST, params = "confirm")


public String orderConfirm(@Validated OrderForm form, BindingResult result) {
if (result.hasErrors()) {
return "order/orderForm";
}
return "order/orderConfirm";

322 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

}
}

• JSP

<!DOCTYPE html>
<html>
<%-- WEB-INF/views/order/orderForm.jsp --%>
<head>
<style type="text/css">
/* omitted (same as previous sample) */
</style>
</head>
<body>
<form:form modelAttribute="orderForm" method="post"
class="form-horizontal"
action="${pageContext.request.contextPath}/order/order">
<form:label path="coupon" cssErrorClass="error-label">Coupon Code:</form:label>
<form:input path="coupon" cssErrorClass="error-input" />
<form:errors path="coupon" cssClass="error-messages" />
<br>
<fieldset>
<legend>Receiver</legend>
<%-- (1) --%>
<form:errors path="receiverAddress"
cssClass="error-messages" />
<%-- (2) --%>
<form:label path="receiverAddress.name"
cssErrorClass="error-label">Name:</form:label>
<form:input path="receiverAddress.name"
cssErrorClass="error-input" />
<form:errors path="receiverAddress.name"
cssClass="error-messages" />
<br>
<form:label path="receiverAddress.postcode"
cssErrorClass="error-label">Postcode:</form:label>
<form:input path="receiverAddress.postcode"
cssErrorClass="error-input" />
<form:errors path="receiverAddress.postcode"
cssClass="error-messages" />
<br>
<form:label path="receiverAddress.address"
cssErrorClass="error-label">Address:</form:label>
<form:input path="receiverAddress.address"
cssErrorClass="error-input" />
<form:errors path="receiverAddress.address"
cssClass="error-messages" />
</fieldset>
<br>
<fieldset>
<legend>Sender</legend>

4.1. Input Validation 323


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<form:errors path="senderAddress"
cssClass="error-messages" />
<form:label path="senderAddress.name"
cssErrorClass="error-label">Name:</form:label>
<form:input path="senderAddress.name"
cssErrorClass="error-input" />
<form:errors path="senderAddress.name"
cssClass="error-messages" />
<br>
<form:label path="senderAddress.postcode"
cssErrorClass="error-label">Postcode:</form:label>
<form:input path="senderAddress.postcode"
cssErrorClass="error-input" />
<form:errors path="senderAddress.postcode"
cssClass="error-messages" />
<br>
<form:label path="senderAddress.address"
cssErrorClass="error-label">Address:</form:label>
<form:input path="senderAddress.address"
cssErrorClass="error-input" />
<form:errors path="senderAddress.address"
cssClass="error-messages" />
</fieldset>

<form:button name="confirm">Confirm</form:button>
</form:form>
</body>
</html>

Sr. No. Description

(1) When receiverAddress.name, receiverAddress.postcode,


receiverAddress.address are not sent as
request parameters due to invalid operation, receiverAddress is considered as null and
error message is displayed.

(2) Fields of nested bean are specified as [parent field name].[child field name].

Form is displayed as follows.

Error message is displayed as follows if this form is sent with all the input fields left blank.

Validation of nested bean is enabled for collections also.

Add a field such that up to 3 addresses can be registered in “user registration” form explained at the beginning.

• Add list of AddressForm as a field in the form class.

324 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

package com.example.sample.app.validation;

import java.io.Serializable;
import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;

public class UserForm implements Serializable {

private static final long serialVersionUID = 1L;

@NotNull
@Size(min = 1, max = 20)
private String name;

@NotNull
@Size(min = 1, max = 50)
@Email
private String email;

@NotNull

4.1. Input Validation 325


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@Min(0)
@Max(200)
private Integer age;

@NotNull
@Size(min = 1, max = 3) // (1)
@Valid
private List<AddressForm> addresses;

// omitted setter/getter
}

Sr. No. Description

(1) It is possible to use @Size annotation for checking size of collection as well.

• JSP

<!DOCTYPE html>
<html>
<%-- WEB-INF/views/user/createForm.jsp --%>
<head>
<style type="text/css">
/* omitted (same as previous sample) */
</style>
</head>
<body>

<form:form modelAttribute="userForm" method="post"


class="form-horizontal"
action="${pageContext.request.contextPath}/user/create">
<form:label path="name" cssErrorClass="error-label">Name:</form:label>
<form:input path="name" cssErrorClass="error-input" />
<form:errors path="name" cssClass="error-messages" />
<br>
<form:label path="email" cssErrorClass="error-label">Email:</form:label>
<form:input path="email" cssErrorClass="error-input" />
<form:errors path="email" cssClass="error-messages" />
<br>
<form:label path="age" cssErrorClass="error-label">Age:</form:label>
<form:input path="age" cssErrorClass="error-input" />
<form:errors path="age" cssClass="error-messages" />
<br>
<form:errors path="addresses" cssClass="error-messages" /><%-- (1) --%>
<c:forEach items="${userForm.addresses}" varStatus="status"><%-- (2) --%>
<fieldset class="address">
<legend>Address${f:h(status.index + 1)}</legend>
<form:label path="addresses[${status.index}].name"
cssErrorClass="error-label">Name:</form:label><%-- (3) --%>

326 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<form:input path="addresses[${status.index}].name"
cssErrorClass="error-input" />
<form:errors path="addresses[${status.index}].name"
cssClass="error-messages" />
<br>
<form:label path="addresses[${status.index}].postcode"
cssErrorClass="error-label">Postcode:</form:label>
<form:input path="addresses[${status.index}].postcode"
cssErrorClass="error-input" />
<form:errors path="addresses[${status.index}].postcode"
cssClass="error-messages" />
<br>
<form:label path="addresses[${status.index}].address"
cssErrorClass="error-label">Address:</form:label>
<form:input path="addresses[${status.index}].address"
cssErrorClass="error-input" />
<form:errors path="addresses[${status.index}].address"
cssClass="error-messages" />
<c:if test="${status.index > 0}">
<br>
<button class="remove-address-button">Remove</button>
</c:if>
</fieldset>
<br>
</c:forEach>
<button id="add-address-button">Add address</button>
<br>
<form:button name="confirm">Confirm</form:button>
</form:form>
<script type="text/javascript"
src="${pageContext.request.contextPath}/resources/vendor/js/jquery-1.10.2.min.js"></s
<script type="text/javascript"
src="${pageContext.request.contextPath}/resources/app/js/AddressesView.js"></script>
</body>
</html>

Sr. No. Description

(1) Display error message related to address field.

(2) Process the collection of child forms in a loop using <c:forEach> tag.

(3) Inside the loop, Specify the field of child form using [parent field
name][Index].[child field name].

4.1. Input Validation 327


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

• Controller class

package com.example.sample.app.validation;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("user")
public class UserController {

@ModelAttribute
public UserForm setupForm() {
UserForm form = new UserForm();
List<AddressForm> addresses = new ArrayList<AddressForm>();
addresses.add(new AddressForm());
form.setAddresses(addresses); // (1)
return form;
}

@RequestMapping(value = "create", method = RequestMethod.GET, params = "form")


public String createForm() {
return "user/createForm";
}

@RequestMapping(value = "create", method = RequestMethod.POST, params = "confirm")


public String createConfirm(@Validated UserForm form, BindingResult result) {
if (result.hasErrors()) {
return "user/createForm";
}
return "user/createConfirm";
}
}

Sr. No. Description

(1) Edit the form object to display a single address form at the time of initial display of “user
registration” form.

• JavaScript

Below is the JavaScript to dynamically add address input field. However, the explanation of this code is

328 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

omitted as it is not required.

// webapp/resources/app/js/AddressesView.js

function AddressesView() {
this.addressSize = $('fieldset.address').size();
};

AddressesView.prototype.addAddress = function() {
var $address = $('fieldset.address');
var newHtml = addressTemplate(this.addressSize++);
$address.last().next().after($(newHtml));
};

AddressesView.prototype.removeAddress = function($fieldset) {
$fieldset.next().remove(); // remove <br>
$fieldset.remove(); // remove <fieldset>
};

function addressTemplate(number) {
return '\
<fieldset class="address">\
<legend>Address' + (number + 1) + '</legend>\
<label for="addresses' + number + '.name">Name:</label>\
<input id="addresses' + number + '.name" name="addresses[' + number + '].name" type="text
<label for="addresses' + number + '.postcode">Postcode:</label>\
<input id="addresses' + number + '.postcode" name="addresses[' + number + '].postcode" ty
<label for="addresses' + number + '.address">Address:</label>\
<input id="addresses' + number + '.address" name="addresses[' + number + '].address" type
<button class="remove-address-button">Remove</button>\
</fieldset>\
<br>\
';
}

$(function() {
var addressesView = new AddressesView();

$('#add-address-button').on('click', function(e) {
e.preventDefault();
addressesView.addAddress();
});

$(document).on('click', '.remove-address-button', function(e) {


if (this === e.target) {
e.preventDefault();
var $this = $(this); // this button
var $fieldset = $this.parent(); // fieldset
addressesView.removeAddress($fieldset);
}
});

4.1. Input Validation 329


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

});

Form is displayed as follows.

Add 2 address forms by clicking “Add address” button twice.

Error message is displayed as follows if this form is sent with all the input fields left blank.

Grouped validation

By creating validation group, input validation rules for a field can be specified for each group.

In the “new user registration” example, add “Must be an adult” rule for the age field. Add country field also
as “Adult” rules differ with country.

To specify group in Bean Validation, set any java.lang.Class object representing a group in group attribute
of the annotation.

330 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Create the following 3 groups (interface) here.

Group Adult condition


Chinese 18 years or more
Japanese 20 years or more
Singaporean 21 years or more

An example of executing validation using these groups is shown here.

• Form class

package com.example.sample.app.validation;

import java.io.Serializable;
import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;

public class UserForm implements Serializable {

private static final long serialVersionUID = 1L;

4.1. Input Validation 331


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

// (1)
public static interface Chinese {
};

public static interface Japanese {


};

public static interface Singaporean {


};

@NotNull
@Size(min = 1, max = 20)
private String name;

@NotNull
@Size(min = 1, max = 50)
@Email
private String email;

@NotNull
@Min.List({ // (2)
@Min(value = 18, groups = Chinese.class), // (3)
@Min(value = 20, groups = Japanese.class),
@Min(value = 21, groups = Singaporean.class)
})
@Max(200)
private Integer age;

@NotNull
@Size(min = 2, max = 2)
private String country; // (4)

// omitted setter/getter
}

332 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Define each group as an interface.

(2) @Min.List annotation is used to specify multiple @Min rules on a single field.
It is same even while using other annotations.

(3) Specify corresponding group class in the group attribute, in order to define rules for each
group.
When group attribute is not specified, javax.validation.groups.Default group is
used.

(4) Add a field which will be used to determine which group is to be applied.

• JSP

There are no major changes in JSP.

<form:form modelAttribute="userForm" method="post"


class="form-horizontal"
action="${pageContext.request.contextPath}/user/create">
<form:label path="name" cssErrorClass="error-label">Name:</form:label>
<form:input path="name" cssErrorClass="error-input" />
<form:errors path="name" cssClass="error-messages" />
<br>
<form:label path="email" cssErrorClass="error-label">Email:</form:label>
<form:input path="email" cssErrorClass="error-input" />
<form:errors path="email" cssClass="error-messages" />
<br>
<form:label path="age" cssErrorClass="error-label">Age:</form:label>
<form:input path="age" cssErrorClass="error-input" />
<form:errors path="age" cssClass="error-messages" />
<br>
<form:label path="country" cssErrorClass="error-label">Country:</form:label>
<form:select path="country" cssErrorClass="error-input">
<form:option value="cn">China</form:option>
<form:option value="jp">Japan</form:option>
<form:option value="sg">Singapore</form:option>
</form:select>
<form:errors path="country" cssClass="error-messages" />
<br>

4.1. Input Validation 333


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

<form:button name="confirm">Confirm</form:button>
</form:form>

• Controller class

By giving a group name to @Validated annotation, the rules defined for that group will be applied.

package com.example.sample.app.validation;

import javax.validation.groups.Default;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.sample.app.validation.UserForm.Chinese;
import com.example.sample.app.validation.UserForm.Japanese;
import com.example.sample.app.validation.UserForm.Singaporean;

@Controller
@RequestMapping("user")
public class UserController {

@ModelAttribute
public UserForm setupForm() {
UserForm form = new UserForm();
return form;
}

@RequestMapping(value = "create", method = RequestMethod.GET, params = "form")


public String createForm() {
return "user/createForm";
}

String createConfirm(UserForm form, BindingResult result) {


if (result.hasErrors()) {
return "user/createForm";
}
return "user/createConfirm";
}

@RequestMapping(value = "create", method = RequestMethod.POST, params = {


"confirm", /* (1) */ "country=cn" })
public String createConfirmForChinese(@Validated({ /* (2) */ Chinese.class,
Default.class }) UserForm form, BindingResult result) {
return createConfirm(form, result);
}

334 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@RequestMapping(value = "create", method = RequestMethod.POST, params = {


"confirm", "country=jp" })
public String createConfirmForJapanese(@Validated({ Japanese.class,
Default.class }) UserForm form, BindingResult result) {
return createConfirm(form, result);
}

@RequestMapping(value = "create", method = RequestMethod.POST, params = {


"confirm", "country=sg" })
public String createConfirmForSingaporean(@Validated({ Singaporean.class,
Default.class }) UserForm form, BindingResult result) {
return createConfirm(form, result);
}
}

Sr. No. Description

(1) The parameter which is used as condition to dividing between the groups must be set to
param attribute.

(2) All the annotations, except @Min of age field, belongs to Default group; hence,
specifying Default is mandatory.

In this example, the check result of the combination of each input value is as follows.

4.1. Input Validation 335


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

age value country value Input validation re- Error message


sult

17 cn NG must be greater than or equal to 18

jp NG must be greater than or equal to 20

sg NG must be greater than or equal to 21

18 cn OK

jp NG must be greater than or equal to 20

sg NG must be greater than or equal to 21

20 cn OK

jp OK

sg NG must be greater than or equal to 21

21 cn OK

jp OK

sg OK

336 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Warning: Implementation of this Controller is inadequate; there is no handling when country value is
neither “cn”, “jp” nor “sg”. 400 error is returned when unexpected country value is encountered.

Next, we can think of a condition where the number of countries increase and adult condition of 18 years or more
is be set as a default rule.

Rules are as follows.

Group Adult condition


Japanese 20 years or more
Singaporean 21 years or more
Country other than the above-mentioned(Default) 18 years or more

• Form class

In order to specify a value to Default group (18 years or more), all groups should be specified explicitly
in other annotations as well.

package com.example.sample.app.validation;

import java.io.Serializable;
import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.groups.Default;

import org.hibernate.validator.constraints.Email;

public class UserForm implements Serializable {

private static final long serialVersionUID = 1L;

public static interface Japanese {


};

public static interface Singaporean {


};

@NotNull(groups = { Default.class, Japanese.class, Singaporean.class }) // (1)


@Size(min = 1, max = 20, groups = { Default.class, Japanese.class,
Singaporean.class })
private String name;

@NotNull(groups = { Default.class, Japanese.class, Singaporean.class })


@Size(min = 1, max = 50, groups = { Default.class, Japanese.class,
Singaporean.class })

4.1. Input Validation 337


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@Email(groups = { Default.class, Japanese.class, Singaporean.class })


private String email;

@NotNull(groups = { Default.class, Japanese.class, Singaporean.class })


@Min.List({
@Min(value = 18, groups = Default.class), // (2)
@Min(value = 20, groups = Japanese.class),
@Min(value = 21, groups = Singaporean.class) })
@Max(200)
private Integer age;

@NotNull(groups = { Default.class, Japanese.class, Singaporean.class })


@Size(min = 2, max = 2, groups = { Default.class, Japanese.class,
Singaporean.class })
private String country;

// omitted setter/getter
}

Sr. No. Description

(1) Set all groups to annotations other than @Min of age field as well.

(2) Set the rule for Default group.

• JSP

No change in JSP

• Controller class

package com.example.sample.app.validation;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.example.sample.app.validation.UserForm.Japanese;
import com.example.sample.app.validation.UserForm.Singaporean;

@Controller
@RequestMapping("user")
public class UserController {

338 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@ModelAttribute
public UserForm setupForm() {
UserForm form = new UserForm();
return form;
}

@RequestMapping(value = "create", method = RequestMethod.GET, params = "form")


public String createForm() {
return "user/createForm";
}

String createConfirm(UserForm form, BindingResult result) {


if (result.hasErrors()) {
return "user/createForm";
}
return "user/createConfirm";
}

@RequestMapping(value = "create", method = RequestMethod.POST, params = { "confirm" })


public String createConfirmForDefault(@Validated /* (1) */ UserForm form,
BindingResult result) {
return createConfirm(form, result);
}

@RequestMapping(value = "create", method = RequestMethod.POST, params = {


"confirm", "country=jp" })
public String createConfirmForJapanese(
@Validated(Japanese.class) /* (2) */ UserForm form, BindingResult result) {
return createConfirm(form, result);
}

@RequestMapping(value = "create", method = RequestMethod.POST, params = {


"confirm", "country=sg" })
public String createConfirmForSingaporean(
@Validated(Singaporean.class) UserForm form, BindingResult result) {
return createConfirm(form, result);
}
}

Sr. No. Description

(1) When the field country does not have a value, the request is mapped to a method in which
Default group is specified in @Validated annotation.

(2) When the field country has a value, the request is mapped to a method in which Default
group is not included in @Validated annotation.

4.1. Input Validation 339


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Till now, 2 patterns of using grouped validation have been explained.

In the previous pattern, Default group is used in Controller class and in the later one, Default group is used
in form class.

Pattern Advantages Disadvantages Decision points


Using Default group in group attribute need not be Since all patterns of group Should be used when there
Controller class set for the rules that need not should be defined, it is diffi- are only a limited number
be grouped. cult to define when there are of group patterns (New cre-
many group patterns. ate group, Update group and
Delete group)
Using Default group in Since only the groups that group attribute should be Should be used when there
form class do not belong to the default set for the rules that need not are many group patterns and
group need to be defined, it be grouped making the pro- majority of patterns have a
can be handled even if there cess complicated. common value.
are many patterns.

If none of the above decision points are applicable, then using Bean Validation itself might not be a good
idea.After reviewing the design, usage of Spring Validator or implementation of validation in business logic should
be considered.

Note: In the examples explained so far, the switching of group validation is carried out using request parameter
and parameter that can be specified in @RequestMapping annotation. It is not possible to switch between
groups, if switching is to be performed based on permissions in authentication object or any information which
cannot be handled by @RequestMapping annotation.

In such a case, @Validated annotation must not be used but org.springframework.validation.SmartValidator


must be used. Group validation can be performed inside the handler method of controller.

@Controller
@RequestMapping("user")
public class UserController {

@Inject
SmartValidator smartValidator; // (1)

// omitted

@RequestMapping(value = "create", method = RequestMethod.POST, params = "confirm")


public String createConfirm(/* (2) */ UserForm form, BindingResult result) {
// (3)
Class<?> validationGroup = Default.class;
// logic to determine validation group
// if (xxx) {
// validationGroup = Xxx.class;
// }
smartValidator.validate(form, result, validationGroup); // (4)

340 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

if (result.hasErrors()) {
return "user/createForm";
}
return "user/createConfirm";
}

Sr. No. Description

(1) Inject SmartValidator. Since SmartValidator can be used if


<mvc:annotation-driven> setting is carried out so there is no need to define separately.

(2) Do not use @Validated annotation.

(3) Determine a validation group.


Logic to determine a validation group recommends delegating to Helper class and keeping
logic in Controller in simple state.

(4) Execute grouped validation using validate method of SmartValidator.


Multiple groups can be specified in validate method.

Since logic should not be written in Controller, if switching is possible using request parameters in
@RequestMappingannotation, SmartValidator must not be used.

Correlation item check

For the validation of correlated items, Spring Validator(Validator implementing


org.springframework.validation.Validator interface) or Bean Validation must be used.

Each one of above has been explained below. However, before that, their features and usage have been explained.

4.1. Input Validation 341


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Format Features Usage

Spring Validator It is easy to create input validation for a Input validation implementation of unique
particular class. business requirements depending on specific
It is inconvenient to use in Controller. form

Bean Validation Creation of input validation is not as easy as Common input validation implementation of
Spring Validator. development project not depending on
It is easy to use in Controller. specific form

Correlation item check implementation using Spring Validator

Implementation method is explained with the help of “reset password” process as an example.
Implement the following rules. Following rules are provided in the “reset password” form.

Field name Type Rules Description

password java.lang.String Mandatory input Password


8 or more characters
Must be same as
confirmPassword

confirmPassword java.lang.String Nothing in particular Confirm password

Check rule “Must be same as confirmPassword” is validation of correlated items as password field and
passwordConfirm field should have the same value.

• Form class

other than validation of correlated items, implement using Bean Validation annotation.

package com.example.sample.app.validation;

import java.io.Serializable;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

342 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

public class PasswordResetForm implements Serializable {


private static final long serialVersionUID = 1L;

@NotNull
@Size(min = 8)
private String password;

private String confirmPassword;

// omitted setter/getter
}

Note: Password is normally saved in database after hashing it, hence there is no need to check the maxi-
mum number of characters.

• Validator class

Implement validation of correlated items using org.springframework.validation.Validator


interface.

package com.example.sample.app.validation;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

@Component // (1)
public class PasswordEqualsValidator implements Validator {

@Override
public boolean supports(Class<?> clazz) {
return PasswordResetForm.class.isAssignableFrom(clazz); // (2)
}

@Override
public void validate(Object target, Errors errors) {

if (errors.hasFieldErrors("password")) { // (3)
return;
}

PasswordResetForm form = (PasswordResetForm) target;


String password = form.getPassword();
String confirmPassword = form.getConfirmPassword();

if (!password.equals(confirmPassword)) { // (4)
errors.rejectValue(/* (5) */ "password",
/* (6) */ "PasswordEqualsValidator.passwordResetForm.password",

4.1. Input Validation 343


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

/* (7) */ "password and confirm password must be same.");


}
}
}

Sr. No. Description

(1) Assign @Component to make Validator the target of component scan.

(2) Decide the argument is check target of this validator or not. Here PasswordResetForm
class is the target to be checked.

(3) If an error occurs at the target fields during a single item check, do not perform correlation
check in this Validator.
If it is necessary to perform the correlation check, this determination logic is not required.

(4) Implement check logic.

(5) Specify field name where there is error.

(6) Specify code name of error message. Here, code is


“[validator name].[form attribute name].[property name]”
Refer to Messages to be defined in application-messages.properties for mesaage definition.

(7) Set default message to be used when error message does not get resolved using code.

Note: Spring Validator implementation class should be placed in the same package as the Controller.

• Controller class

package com.example.sample.app.validation;

344 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

import javax.inject.Inject;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("password")
public class PasswordResetController {
@Inject
PasswordEqualsValidator passwordEqualsValidator; // (1)

@ModelAttribute
public PasswordResetForm setupForm() {
return new PasswordResetForm();
}

@InitBinder
public void initBinder(WebDataBinder binder) {
binder.addValidators(passwordEqualsValidator); // (2)
}

@RequestMapping(value = "reset", method = RequestMethod.GET, params = "form")


public String resetForm() {
return "password/resetForm";
}

@RequestMapping(value = "reset", method = RequestMethod.POST)


public String reset(@Validated PasswordResetForm form, BindingResult result) { // (3)
if (result.hasErrors()) {
return "password/resetForm";
}
return "redirect:/password/reset?complete";
}

@RequestMapping(value = "reset", method = RequestMethod.GET, params = "complete")


public String resetComplete() {
return "password/resetComplete";
}
}

4.1. Input Validation 345


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Inject Spring Validator to be used.

(2) In the method having @InitBinder annotation, add Validators using


WebDataBinder.addValidators method.
By this, the added Validator is called when validation is executed with the use of
@Validated annotation.

(3) Implement input validation as per the process performed so far.

• JSP

There are no points to mention for JSP.

<!DOCTYPE html>
<html>
<%-- WEB-INF/views/password/resetForm.jsp --%>
<head>
<style type="text/css">
/* omitted */
</style>
</head>
<body>
<form:form modelAttribute="passwordResetForm" method="post"
class="form-horizontal"
action="${pageContext.request.contextPath}/password/reset">
<form:label path="password" cssErrorClass="error-label">Password:</form:label>
<form:password path="password" cssErrorClass="error-input" />
<form:errors path="password" cssClass="error-messages" />
<br>
<form:label path="confirmPassword" cssErrorClass="error-label">Password (Confirm):</f
<form:password path="confirmPassword"
cssErrorClass="error-input" />
<form:errors path="confirmPassword" cssClass="error-messages" />
<br>
<form:button>Reset</form:button>
</form:form>
</body>
</html>

Error message as shown below is displayed when form is sent by entering different values in password field and
confirmPassword fields.

346 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: When <form:password> tag is used, data gets cleared at the time of redisplay.

Note: Error information can be set for multiple fields for correlation check. However, displaying error messages
and applying style must always be performed in a set and only one part of the tasks cannot not be performed.

When you want to apply style to both the fields wherein correlation check error has occurred however you want to
display only one error message, it can be done by setting a null string in the error message. An example is given
below wherein style is applied to password field and confirmPassword field and error message is displayed
only in password field.

package com.example.sample.app.validation;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

@Component
public class PasswordEqualsValidator implements Validator {

@Override
public boolean supports(Class<?> clazz) {
return PasswordResetForm.class.isAssignableFrom(clazz);
}

@Override
public void validate(Object target, Errors errors) {

// omitted
if (!password.equals(confirmPassword)) {
// register a field error for password
errors.rejectValue("password",
"PasswordEqualsValidator.passwordResetForm.password",
"password and confirm password must be same.");

// register a field error for confirmPassword


errors.rejectValue("confirmPassword", // (1)
"PasswordEqualsValidator.passwordResetForm.confirmPassword", // (2)
""); // (3)
}
}
}

4.1. Input Validation 347


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Register error in confirmPasswordfield.

(2) Specify code name of error message. Specify a null string in the corresponding error message
at that time.
For message definition, refer Messages to be defined in application-messages.properties.

(3) Set a default message to be used when error message could not be resolved in the code.
A null string is set in the example above.

Note: When multiple forms are used in a single controller, model name should be specified in
@InitBinder("xxx") in order to limit the target of Validator.

@Controller
@RequestMapping("xxx")
public class XxxController {
// omitted
@ModelAttribute("aaa")
public AaaForm() {
return new AaaForm();
}

@ModelAttribute("bbb")
public BbbForm() {
return new BbbForm();
}

@InitBinder("aaa")
public void initBinderForAaa(WebDataBinder binder) {
// add validators for AaaForm
binder.addValidators(aaaValidator);
}

@InitBinder("bbb")
public void initBinderForBbb(WebDataBinder binder) {
// add validators for BbbForm
binder.addValidators(bbbValidator);
}
// omitted
}

348 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: To change the check contents of correlated items check rules in accordance with a
validation group (for example: To implement correlated items check only when specific valida-
tion group is specified, etc.), it is better to switch the process within validate method by imple-
menting org.springframework.validation.SmartValidator interface instead of implementing
org.springframework.validation.Validator interface.

package com.example.sample.app.validation;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.SmartValidator;

@Component
public class PasswordEqualsValidator implements SmartValidator { // Implements SmartValidator

@Override
public boolean supports(Class<?> clazz) {
return PasswordResetForm.class.isAssignableFrom(clazz);
}

@Override
public void validate(Object target, Errors errors) {
validate(target, errors, new Object[] {});
}

@Override
public void validate(Object target, Errors errors, Object... validationHints) {
// Check validationHints(groups) and apply validation logic only when 'Update.class'
if (ArrayUtils.contains(validationHints, Update.class)) {
PasswordResetForm form = (PasswordResetForm) target;
String password = form.getPassword();
String confirmPassword = form.getConfirmPassword();

// omitted...
}
}
}

Implementation of input check of correlated items using Bean Validation

Independent validation rules should be added to implement validation of correlated items using Bean Validation.

It is explained in How to extend.

4.1. Input Validation 349


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Definition of error messages

Method to change error messages of input validation is explained.

Error messages of Bean Validation in Spring MVC are resolved in the following order.

1. If there is any message which matches with the rule, among the messages defined in
org.springframework.context.MessageSource, then it is to be used as error message
(Spring rule).
For default rules of Spring, refer to “JavaDoc of DefaultMessageCodesResolver of
DefaultMessageCodesResolver”.

2. If message cannot be found as mentioned in step 1, then error message is acquired from the message
attribute of the annotation. (Bean Validation rule)

1. When the value of message attribute is not in “{message key}” format, use that text as error message.

2. When the value of message attribute is in “{message key}” format, search messages corresponding
to message key from ValidationMessages.properties under classpath.

1. When message corresponding to message key is defined, use that message

2. When message corresponding to message key is not defined, use “{message key}” as error message

Basically, it is recommended to define error messages in properties file.

Messages should be defined at following places.

• properties file read by org.springframework.context.MessageSource

• ValidationMessages.properties under classpath

Considering that the following settings are done in applicationContext.xml, former is called as “application-
messages.properties” and latter is called “ValidationMessages.properties”.

<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>i18n/application-messages</value>
</list>
</property>
</bean>

350 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Warning: Multiple ValidationMessages.properties files should not exist directly under class
path.
If multiple ValidationMessages.properties files exist directly under class path, an appropriate mes-
sage may not be displayed, as either one file of them is read leaving rest of the files unread.
• When adopting multi project structure, please take care so that
ValidationMessages.properties file is not placed in multiple projects.
• When distributing common parts for Bean Validation as jar file, please take care so that
ValidationMessages.properties file is not included in jar file.
Further, when a project is created from Blank project of version 1.0.2.RELEASE or higher,
ValidationMessages.properties is stored directly under xxx-web/src/main/resources.

This guideline classifies the definition as follows.

Properties file name Contents to be defined

ValidationMessages.properties Default error messages of Bean Validation specified by


the system

application-messages.properties Error message of Bean Validation to be overwritten


separately
Error message of input validation implemented in
Spring Validator

When ValidationMessages.properties is not provided, Default messages provided by Hibernate Validator is used.

4.1. Input Validation 351


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Messages to be defined in ValidationMessages.properties

Define messages for message key specified in message attribute of Bean Validation annotation of Validation-
Messages.properties under class path (normal src/main/resources).

It is explained below using the following form used at the beginning of Basic single item check.

• Form class (re-displayed)

public class UserForm implements Serializable {

@NotNull
@Size(min = 1, max = 20)
private String name;

@NotNull
@Size(min = 1, max = 50)
@Email
private String email;

@NotNull
@Min(0)
@Max(200)
private Integer age;

// omitted getter/setter
}

• ValidationMessages.properties

Change error messages of @NotNull, @Size, @Min, @Max, @Email.

javax.validation.constraints.NotNull.message=is required.
# (1)
javax.validation.constraints.Size.message=size is not in the range {min} through {max}.
# (2)
javax.validation.constraints.Min.message=cannot be less than {value}.
javax.validation.constraints.Max.message=cannot be greater than {value}.
org.hibernate.validator.constraints.Email.message=is an invalid e-mail address.

Sr. No. Description

(1) It is possible to embed the value of attributes specified in the annotation using {Attribute
name}.

(2) It is possible to embed the invalid value using {value}.

352 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

When the form is sent with input fields left blank after adding the above settings, changed error messages are
displayed as shown below.

Warning: Since {FQCN of annotation.message} is set in message attribute in Bean Validation


standard annotations and independent Hibernate Validator annotations, messages can be defined in properties
file in the above format. However, since all annotations may not be in this format, Javadoc or source code of
the target annotation should be checked.

FQCN of annotation.message = Message

Add {0} to message as shown below when field name is to be included in error message.

• ValidationMessages.properties

Change error message of @NotNull, @Size, @Min, @Max and @Email.

javax.validation.constraints.NotNull.message="{0}" is required.
javax.validation.constraints.Size.message=The size of "{0}" is not in the range {min} thr
javax.validation.constraints.Min.message="{0}" cannot be less than {value}.
javax.validation.constraints.Max.message="{0}" cannot be greater than {value}.
org.hibernate.validator.constraints.Email.message="{0}" is an invalid e-mail address.

Error message is changed as follows.

In this way, property name of form class gets displayed on the screen and so it is not user friendly. To display an
appropriate field name, it should be defined in application-messages.properties in the following format.

form property name=field name to be displayed

Adding the same to our example.

• application-messages.properties

name=Name
email=Email
age=Age

4.1. Input Validation 353


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Error messages are changed as follows.

Note: Inserting field name in place of {0} is the functionality of Spring and not of Bean
Validation. Therefore, the settings for changing field name should be defined in application-
messages.properties(ResourceBundleMessageSource) which is directly under Spring management.

Tip: In Bean Validation 1.1, it is possible to use Expression Language (hereafter referred to as “EL expression”) in
a message specified in ValidationMessages.properties. Hibernate Validator 5.x supports Expression
Language 2.2 or higher version.

Executable EL expression version differs depending on the version of application server. Therefore when EL
expression is to be used, it should be used after confirming the version of EL expression supported by appli-
cation server.

Following is an example of using EL expression in a message which is defined in


ValidationMessages.properties provided by Hibernate Validator by default.

# ...
# (1)
javax.validation.constraints.DecimalMax.message = must be less than ${inclusive == true ? 'o
# ...

Sr. No. Description


An EL expression is a part of “${inclusive == true ? ’or equal to ’ :
’’} ” in a message.
(1)
From the above mentioned definition of message, 2 patterns of messages are created as given
below.
• must be less than or equal to {value}
• must be less than {value}
(A value specified in value attribute of @DecimalMax annotation is embedded in {value}
part)
Former is created when true is specified (or when not specified) in inclusive attribute of
@DecimalMax annotation, Latter is created when false is specified in inclusive attribute
of @DecimalMax annotation.
For handling of EL expressions in Bean Validation refer to: Hibernate Validator Reference
Guide(Interpolation with message expressions).

354 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Messages to be defined in application-messages.properties

Default messages to be used in system are defined in ValidationMessages.properties however, depending on the
screen, they may have to be changed from the default value.

In this case, define messages in the following format in application-messages.properties.

[annotation name].[form attribute name].[property name] = [target message]

Apply “Messages to be defined in ValidationMessages.properties” and override the message for email and age
field using the below settings.

• application-messages.properties

# override messages
# for email field
Size.userForm.email=The size of "{0}" must be between {2} and {1}.
# for age field
NotNull.userForm.age="{0}" is compulsory.
Min.userForm.age="{0}" must be greater than or equal to {1}.
Max.userForm.age="{0}" must be less than or equal to {1}.

# filed names
name=Name
email=Email
age=Age

Value of attributes of the annotation gets inserted after {1} onwards. Incidentally, index position of attribute
values are alphabetical ordering(ascending order) of attribute names.

For example, index positions of @Size are as follow:

• {0} : property name (physical name or logical name)

• {1} : value of max attribute

• {2} : value of min attribute

For specification details, refer to JavaDoc of SpringValidatorAdapter.

Error messages are changed as follows.

Note: There are other formats as well for the message key format of application-messages.properties; however, if

4.1. Input Validation 355


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

it is used with the purpose of overwriting some default messages, it should be in [annotation name].[form
attribute name].[property name] format.

4.1.3 How to extend

Other than standard check rules, bean validation has a mechanism to develop annotations for independent rules .

The method of creating independent rules can be widely classified into the following two broader criteria.

• Combination of existing rules

• Creation of new rules

Basically, the below template can be used to create annotation for each rule.

package com.example.common.validation;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = {})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface Xxx {
String message() default "{com.example.common.validation.Xxx.message}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })


@Retention(RUNTIME)
@Documented
public @interface List {

356 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Xxx[] value();
}
}

Creation of Bean Validation annotation by combining existing rules

Consider the following restrictions at the system level and domain level respectively.

At the system level,

• String must be single byte alphanumeric characters

• Numbers must be positive

Or at the domain level,

• “User ID” must be between 4 and 20 single byte characters

• “Age” must be between 1 year and 150 years

These can be implemented by combining @Pattern, @Size, @Min, @Max of the existing rules.
However, if the same rules are to be used at multiple places, settings get distributed and maintainability worsens.

One rule can be created by combining multiple rules. There is an advantage to be able to have not only common
regular expression pattern and maximum/minimum values but also error message when an independent annotation
is created. By this, reusability and maintainability increases. Even if multiple rules are not combined, it also proves
beneficial if used only to give specific value to an attribute.

Implementation example is shown below.

• Implementation example of @Alphanumeric annotation which is restricted to single byte alphanumeric


characters

package com.example.common.validation;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

4.1. Input Validation 357


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

import javax.validation.ReportAsSingleViolation;
import javax.validation.constraints.Pattern;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;


import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = {})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@ReportAsSingleViolation // (1)
@Pattern(regexp = "[a-zA-Z0-9]*") // (2)
public @interface AlphaNumeric {
String message() default "{com.example.common.validation.AlphaNumeric.message}"; // (3)

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })


@Retention(RUNTIME)
@Documented
public @interface List {
AlphaNumeric[] value();
}
}

Sr. No. Description

(1) This will consolidate error messages and return only the message of this annotation at the time
of error.

(2) Define rules used by this annotation.

(3) Define default value of error message.

• Implementation example of @NotNegative annotation which is restricted to positive number

package com.example.common.validation;

358 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import javax.validation.constraints.Min;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;


import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = {})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@ReportAsSingleViolation
@Min(value = 0)
public @interface NotNegative {
String message() default "{com.example.common.validation.NotNegative.message}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })


@Retention(RUNTIME)
@Documented
public @interface List {
NotNegative[] value();
}
}

• Implementation example of @UserId annotation which regulates the format of “User ID”.

package com.example.sample.domain.validation;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;


import static java.lang.annotation.ElementType.CONSTRUCTOR;

4.1. Input Validation 359


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

import static java.lang.annotation.ElementType.FIELD;


import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = {})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
@ReportAsSingleViolation
@Size(min = 4, max = 20)
@Pattern(regexp = "[a-z]*")
public @interface UserId {
String message() default "{com.example.sample.domain.validation.UserId.message}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })


@Retention(RUNTIME)
@Documented
public @interface List {
UserId[] value();
}
}

• Implementation example of @Age annotation which regulates the constraints on “Age”

package com.example.sample.domain.validation;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;


import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = {})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)

360 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@ReportAsSingleViolation
@Min(1)
@Max(150)
public @interface Age {
String message() default "{com.example.sample.domain.validation.Age.message}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })


@Retention(RUNTIME)
@Documented
public @interface List {
Age[] value();
}
}

Note: If multiple rules are set in a single annotation, their AND condition forms the composite anno-
tation. In Hibernate Validator, @ConstraintComposition annotation is provided to implement OR
condition. Refer to Hibernate Validator document for details.

Creation of Bean Validation annotation by implementing new rules

Any rule can be created by implementing javax.validation.ConstraintValidator interface and cre-


ating annotation that uses this Validator.

The method of usage is as follows.

• Rules that cannot be implemented by combining the existing rules

• check rule for correlated items

• Business logic check

Rules that cannot be implemented by combining the existing rules

For the rules that cannot be implemented by combining @Pattern, @Size, @Min, @Max, implement
javax.validation.ConstraintValidator.

For example, rules that check ISBN (International Standard Book Number)-13 format are given.

• Annotation

package com.example.common.validation;

import java.lang.annotation.Documented;

4.1. Input Validation 361


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = { ISBN13Validator.class }) // (1)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface ISBN13 {
String message() default "{com.example.common.validation.ISBN13.message}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })


@Retention(RUNTIME)
@Documented
public @interface List {
ISBN13[] value();
}
}

Sr. No. Description

(1) Specify the ConstraintValidator implementation class which will get executed when
this annotation is used. Multiple constraints can also be specified.

• Validator

package com.example.common.validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class ISBN13Validator implements ConstraintValidator<ISBN13, String> { // (1)

@Override
public void initialize(ISBN13 constraintAnnotation) { // (2)
}

@Override

362 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

public boolean isValid(String value, ConstraintValidatorContext context) { // (3)


if (value == null) {
return true; // (4)
}
return isISBN13Valid(value); // (5)
}

// This logic is written in http://en.wikipedia.org/wiki/International_Standard_Book_Numb


static boolean isISBN13Valid(String isbn) {
if (isbn.length() != 13) {
return false;
}
int check = 0;
try {
for (int i = 0; i < 12; i += 2) {
check += Integer.parseInt(isbn.substring(i, i + 1));
}
for (int i = 1; i < 12; i += 2) {
check += Integer.parseInt(isbn.substring(i, i + 1)) * 3;
}
check += Integer.parseInt(isbn.substring(12));
} catch (NumberFormatException e) {
return false;
}
return check % 10 == 0;
}
}

Sr. No. Description

(1) Specify target annotation and field type in generics parameter.

(2) Implement initialization process in initialize method.

(3) Implement input validation in isValid method.

(4) Consider input value as correct in case of null.

(5) Check ISBN-13 format.

4.1. Input Validation 363


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Tip: Example of Bean Validation of file upload is classified in this category. Further, in common library as well,
@ExistInCodeList is implemented in this way.

Check rules for correlated items

Check of correlated items, which span over multiple fields, can be done using Bean Validation as explained in
Correlation item check.
It is recommended to target generalized rules, in case of deciding to use Bean Validation for check of correlated
items.

An example of implementing the rule, “Contents of a field should match with its confirmation field” is given
below.

Set constraint of assigning “confirm” as the prefix of confirmation field.

• Annotation

Define such that annotation for validation of correlated items can be used at class level as well.

package com.example.common.validation;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = { ConfirmValidator.class })
@Target({ TYPE, ANNOTATION_TYPE }) // (1)
@Retention(RUNTIME)
public @interface Confirm {
String message() default "{com.example.common.validation.Confirm.message}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

/**
* Field name
*/
String field(); // (2)

364 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@Target({ TYPE, ANNOTATION_TYPE })


@Retention(RUNTIME)
@Documented
public @interface List {
Confirm[] value();
}
}

Sr. No. Description

(1) Narrow down the target of using this annotation, such that it can be added only to class or
annotation.

(2) Define parameter to pass to annotation.

• Validator

package com.example.common.validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

public class ConfirmValidator implements ConstraintValidator<Confirm, Object> {


private String field;

private String confirmField;

private String message;

public void initialize(Confirm constraintAnnotation) {


field = constraintAnnotation.field();
confirmField = "confirm" + StringUtils.capitalize(field);
message = constraintAnnotation.message();
}

public boolean isValid(Object value, ConstraintValidatorContext context) {


BeanWrapper beanWrapper = new BeanWrapperImpl(value); // (1)
Object fieldValue = beanWrapper.getPropertyValue(field); // (2)
Object confirmFieldValue = beanWrapper.getPropertyValue(confirmField);
boolean matched = ObjectUtils.nullSafeEquals(fieldValue,
confirmFieldValue);

4.1. Input Validation 365


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

if (matched) {
return true;
} else {
context.disableDefaultConstraintViolation(); // (3)
context.buildConstraintViolationWithTemplate(message)
.addPropertyNode(field).addConstraintViolation(); // (4)
return false;
}
}

Sr. No. Description

(1) Use org.springframework.beans.BeanWrapper which is very convenient to access


JavaBean properties.

(2) Acquire property value from the form object through BeanWrapper.

(3) Disable the creation of default ConstraintViolation object.

(4) Create an independent ConstraintViolation object.


Define message to be output in
ConstraintValidatorContext.buildConstraintViolationWithTemplate.
Specify field name to output error message in
ConstraintViolationBuilder.addPropertyNode.
Refer to JavaDoc of ConstraintValidatorContext for details.

Tip: ConstraintViolationBuilder.addPropertyNode method has been added from the


Bean Validation 1.1.

ConstraintViolationBuilder.addNode method had been used in Bean Validation 1.0; however,


it is a deprecated API from Bean Validation 1.1.

For deprecated API of Bean Validation, refer to Bean Validation API Document (Deprecated API).

Note: As introduced in correlation item check using Spring Validator, even in Bean Validation, Set error infor-

366 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

mation for multiple fields for correlation check can be performed.

An example is shown below wherein styles are applied to passwordfield and confirmPasswordfield in Bean
Validation and error message is displayed only for passwordfield.

// omitted
public class ConfirmValidator implements ConstraintValidator<Confirm, Object> {
private String field;

private String confirmField;

private String message;

public void initialize(Confirm constraintAnnotation) {


// omitted
}

public boolean isValid(Object value, ConstraintValidatorContext context) {


// omitted
if (matched) {
return true;
} else {
context.disableDefaultConstraintViolation();

//new ConstraintViolation to be generated for field


context.buildConstraintViolationWithTemplate(message)
.addPropertyNode(field).addConstraintViolation();

//new ConstraintViolation to be generated for confirmField


context.buildConstraintViolationWithTemplate("") // (1)
.addPropertyNode(confirmField).addConstraintViolation();

return false;
}
}

Sr. No. Description

(1) Register error of confirmPasswordfield. A null string is set in error message at that time.

Check below for the changes, if the “Reset password” is re-implemented using @Confirm annotation.

• Form class

package com.example.sample.app.validation;

import java.io.Serializable;

4.1. Input Validation 367


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import com.example.common.validation.Confirm;

@Confirm(field = "password") // (1)


public class PasswordResetForm implements Serializable {
private static final long serialVersionUID = 1L;

@NotNull
@Size(min = 8)
private String password;

private String confirmPassword;

// omitted getter/setter
}

Sr. No. Description

(1) Assign @Confirm annotation at class level.


By this, form object is passed as an argument to ConstraintValidator.isValid.

• Controller class

There is no need to inject Validator and add Validator using @InitBinder.

package com.example.sample.app.validation;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("password")
public class PasswordResetController {

@ModelAttribute
public PasswordResetForm setupForm() {
return new PasswordResetForm();
}

@RequestMapping(value = "reset", method = RequestMethod.GET, params = "form")


public String resetForm() {
return "password/resetForm";

368 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@RequestMapping(value = "reset", method = RequestMethod.POST)


public String reset(@Validated PasswordResetForm form, BindingResult result) {
if (result.hasErrors()) {
return "password/resetForm";
}
return "redirect:/password/reset?complete";
}

@RequestMapping(value = "reset", method = RequestMethod.GET, params = "complete")


public String resetComplete() {
return "password/resetComplete";
}
}

Business logic check

Business logic check should implement Implementation in Service of domain layer and store result message in
ResultMessages object.
Accordingly, it is expected that, they will be normally displayed at the top of the screen.

However, there are cases, where business logic error message (such as, “whether the entered user name is already
registered”) of target input field is to be displayed next to the field. In such a case, service class is injected in
Validator class and business logic check is executed in ConstraintValidator.isValid.

An example of implementing, “whether the entered user name is already registered” in Bean Validation is shown
below.

• Service class

Implementation class (UserServiceImpl) is omitted.

package com.example.sample.domain.service.user;

public interface UserService {

boolean isUnusedUserId(String userId);

// omitted other methods


}

• Annotation

package com.example.sample.domain.validation;

import java.lang.annotation.Documented;

4.1. Input Validation 369


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Documented
@Constraint(validatedBy = { UnusedUserIdValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface UnusedUserId {
String message() default "{com.example.sample.domain.validation.UnusedUserId.message}";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })


@Retention(RUNTIME)
@Documented
public @interface List {
UnusedUserId[] value();
}
}

• Validator class

package com.example.sample.domain.validation;

import javax.inject.Inject;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.springframework.stereotype.Component;

import com.example.sample.domain.service.user.UserService;

@Component // (1)
public class UnusedUserIdValidator implements
ConstraintValidator<UnusedUserId, String> {

@Inject // (2)
UserService userService;

@Override
public void initialize(UnusedUserId constraintAnnotation) {

370 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}

return userService.isUnusedUserId(value); // (3)


}

Sr. No. Description

(1) Settings to enable component scan of the Validator class.


Target package must be included in <context:component-scan
base-package="..." /> of Bean definition file.

(2) Inject the service class to be called.

(3) Return the result of business logic error check. Process should be delegated to service class.
Logic must not be written directly in the isValid method.

Method Validation

A method to check validity of actual argument and return value of method using Bean Validation, is described. In
order to explain, the method is called Method Validation in this chapter. While performing defensive programming
etc, method I/O should be checked in the class other than Controller. If Bean Validation library is used at that time,
constraint annotation of Bean Validation used in Controller can be reused.

Application settings

When Method Validation offered by Spring Framework is used, a bean must be defined for
org.springframework.validation.beanvalidation.MethodValidationPostProcessor
class offered by Spring Framework.

4.1. Input Validation 371


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Bean definition file which defines MethodValidationPostProcessor differs depending on where you use
the Method Validation.

Here, a setup example is given wherein Method Validation is used in the multi-project environment recommended
in this guideline.

Setup for both the projects below must be changed

• Project (projectName-web) for application layer

• Project (projectName-domain) for domain layer

• projectName-domain/src/main/resources/META-INF/spring/projectName-domain.xml

<!-- (1) -->


<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

<!-- (2) -->


<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
<property name="validator" ref="validator" />
</bean>

• projectName-web/src/main/resources/META-INF/spring/spring-mvc.xml

<!-- (3) -->


<mvc:annotation-driven validator="validator">
<!-- ... -->
</mvc:annotation-driven>

<!-- (4) -->


<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
<property name="validator" ref="validator" />
</bean>

372 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description


Define a bean for LocalValidatorFactoryBean.

(1)

Define a bean for MethodValidationPostProcessor and ensure that Method Validation is


executed for a domain layer class method.
(2)
Specify a bean defined in (1), in validator property.

Specify a bean defined in (1), in the validator attribute of <mvc:annotation-driven> ele-


ment.
(3)
A Validator instance is generated that is different from the instance created in (1) in the absence of
this setup.
Define a bean for MethodValidationPostProcessor and ensure that Method Validation is
executed for an application layer class method.
(4)
Specify Bean defined in (1), in validator property.

Tip: LocalValidatorFactoryBean is a class to generate a wrapper Validator object in order to link


Validator class provided by Bean Validation(Hibernate Validator) and Spring Framework.

By using the wrapper Validator generated by this class, message management function (MessageSource)
offered by Spring Framework and DI container can be linked.

Tip: In Spring Framework, Method Validation for calling the method of Bean which is managed by DI container
is executed by using AOP system.

MethodValidationPostProcessor is a class to apply AOP in order to execute Method Validation.

Note: In the example above, an identical Validator object (instance) is set for validator property of each
Bean, but this is not necessarily required. However, it is recommended to set an identical object (instance) unless
there is a reason to do otherwise.

4.1. Input Validation 373


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

How to define for the method for Method Validation target

When Method Validation is applied to the method, annotation which indicates inclusion of target method and the
constraint annotation of Bean Validation should be specified in class level and, method and dummy argument
respectively.

AOP which executes Method Validation is not applicable for “Application settings”. It is necessary to assign
@ org.springframework.validation.annotation.Validated annotation to interface or class in
order to apply AOP which executes Method Validation.

Here, a method to specify an annotation for interface is introduced.

package com.example.domain.service;

import org.springframework.validation.annotation.Validated;

@Validated // (1)
public interface HelloService {
// ...
}

Sr. No. Description


Specify Validated annotation in the interface acting as a target for Method Validation.
In the example above, AOP which executes Method Validation is applied to implementation method of
(1)
HelloService interface.

Tip: By specifying a group interface in value attribute of @Validated annotation, a validation belonging to
a specified group can alone be executed as well.

Further, the validation groups can be changed for each method by assigning Validated annotation in method
level.

Refer “Grouped validation” for validation group.

Next, a method is described wherein constraint annotation of Bean Validation is specified in the method and
dummy argument. Basically,

Specify constraint annotation of Bean Validation for

• Method arguments

• JavaBean field specified in method argument

374 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

and constraint annotation of Bean Validation for

• Return value of method

• JavaBean field returned as return value of method.

A basic specification method is described below. A method to specify annotation in the interface is introduced in
the description hereafter.

First, a method that specifies constraint annotation is described for the method using basic types (primitive type or
primitive wrapper type etc) as a signature of the method

package com.example.domain.service;

import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotNull;

@Validated
public interface HelloService {

// (2)
@NotNull
String hello(@NotNull /* (1) */ String message);

Sr. No. Description


Specify a constraint annotation of Bean Validation as an argument annotation of method.
@NotNull is a constraint that signifies that message argument does not allow Null value. When Null
(1)
value is specified in the argument, javax.validation.ConstraintViolationException
is thrown.
Specify constraint annotation of Bean Validatio as a method annotation.
In the above example, it is shown that the return value is not a Null value, when Null value is returned
(2)
as a return value, javax.validation.ConstraintViolationException is thrown.

Next, a method that specifies constraint annotation of Bean Validation is described for the method using JavaBean
as a signature of method.

Here, a method which species annotation for interface is introduced.

Note: The main point is to specify @javax.validation.Valid annotation. The specification method is

4.1. Input Validation 375


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

described below in detail using sample code.

Service interface

package com.example.domain.service;

import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotNull;

@Validated
public interface HelloService {

@NotNull // (3)
@Valid // (4)
HelloOutput hello(@NotNull /* (1) */ @Valid /* (2) */ HelloInput input);

Sr. No. Description


Specify constraint annotation of Bean Validation as an argument annotation.
It indicates that input argument (JavaBean) does not allow Null value. When Null value is specified
(1)
in the argument, javax.validation.ConstraintViolationException is thrown.

Specify @javax.validation.Valid annotation as an argument annotation of method.


By assigning @Valid annotation, constraint annotation of Bean Validation specified in JavaBean
(2)
field of argument becomes valid. When the constraint specified in JavaBean is not fulfilled,
javax.validation.ConstraintViolationException is thrown.
Specify constraint annotation of Bean Validation as a method annotation.
It indicates that JavaBean of return value is not Null value. When Null value is returned as a return
(3)
value, an exception is thrown.

Specify @Valid annotation as a method annotation.


By assigning @Valid annotation, constraint annotation of Bean Validation specified in JavaBean
(4)
field of return value becomes valid. When constraint specified in JavaBean is not fulfilled,
javax.validation.ConstraintViolationException is thrown.

Implementation sample of JavaBean is introduced below.


Basically, only constraint annotation of Bean Validation is specified, however care must be taken while
performing further nesting of JavaBean in JavaBean.

376 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

JavaBean for Input

package com.example.domain.service;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import java.util.Date;

public class HelloInput {

@NotNull
@Past
private Date visitDate;

@NotNull
private String visitMessage;

private String userId;

// ...

JavaBean for Output

package com.example.domain.service;

import com.example.domain.model.User;

import java.util.Date;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;

public class HelloOutput {

@NotNull
@Past
private Date acceptDate;

@NotNull
private String acceptMessage;

@Valid // (5)
private User user;

// ...

4.1. Input Validation 377


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

JavaBean nested in JavaBean for Output

package com.example.domain.model;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import java.util.Date;

public class User {

@NotNull
private String userId;

@NotNull
private String userName;

@Past
private Date dateOfBirth;

// ...

Sr. No. Description


When constraint annotation of Bean Validation specified in nested JavaBean is to be enabled, specify
@Valid annotation as field annotation.
(5)
By assigning @Valid annotation, constraint annotation of Bean Validation specified in nested
JavaBean field becomes valid. When constraint specified in nested JavaBean is not fulfilled,
javax.validation.ConstraintViolationException is thrown.

Exception handling at the time of violation of constraint

When a constraint violation occurs, javax.validation.ConstraintViolationException is thrown.

When ConstraintViolationException is thrown, the method generated from stack trace can be identi-
fied, however, basic violation details cannot be identified.

An exception handling class should be created which outputs log by handling


ConstraintViolationException exception in order to identify violation details.

An example to show how to create an exception handling class is given below.

package com.example.app;

import javax.validation.ConstraintViolationException;

378 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class ConstraintViolationExceptionHandler {

private static final Logger log = LoggerFactory.getLogger(ConstraintViolationExceptionHandler.

// (1)
@ExceptionHandler
public String handleConstraintViolationException(ConstraintViolationException e){
// (2)
if (log.isErrorEnabled()) {
log.error("ConstraintViolations[\n{}\n]", e.getConstraintViolations());
}
return "common/error/systemError";
}

Sr. No. Description


Create a @ExceptionHandler method to handle ConstraintViolationException.
Receive ConstraintViolationException as an argument of method.
(1)

Output violation details (Set of ConstraintViolation) in a log which are retained by


ConstraintViolationExceptionreceived by method argument.
(2)

Note: Refer to “Implementing “@ControllerAdvice”” for details of @ControllerAdvice annotation.

4.1.4 Appendix

Input validation rules provided by Hibernate Validator

Hibernate Validator provides additional validation annotations, in addition to the annotations defined in Bean
Validation.
Refer to Herefor the annotation list that can be used for validation.

4.1. Input Validation 379


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Bean Validation check rules

Bean Validation standard annotations(javax.validation.*) are shown below.

Refer to Chapter 7 Bean Validation specification for details.

380 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Annotation Target type Description Usage example


@NotNull Arbitrary Validates that the target field is not
@NotNull
null.
private String id;

@Null Arbitrary
@Null(groups={Update.cla
Validates that the target field is private String id;
null.
(Example: usage in group
validation)

@Pattern String
@Pattern(regexp = "[0-9]
Whether the target field matches private String tel;
with the regular expression
(In case of Hibernate Validator
implementation, it is also
possible to use it with arbitrary
implementation class of
CharSequence interface)

@Min Validate whether the value is Refer @Max


greater than the minimum value.
BigDecimal, BigInteger,
byte, short, int, long and
wrapper
(In case of Hibernate Validator
implementation, it is also
possible to use it with arbitrary
implementation class of
CharSequence interface,
Number inherited class.
However, only in cases where
string can be converted to a
number.)

@Max Validate whether the value is less


@Min(1)
than the maximum value.
BigDecimal, BigInteger, @Max(100)
byte, short, int, long and private int quantity;
wrapper
(In case of Hibernate Validator
implementation, it is also
possible to use it with arbitrary
implementation class of
4.1. Input Validation 381
CharSequence interface,
Number inherited class.
However, only in cases where
string can be converted to a
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Tip: inclusive attribute of @DecimalMin and @DecimalMax annotation is, an attribute added from Bean
Validation 1.1.

By specifying true (to allow same value of specified threshold) to the default value of inclusive attribute,
compatibility with Bean Validation 1.0 is maintained.

Warning: In @Size annotation, characters represented by char type 2 (32 bits) called as surrogate pair are
not considered.
When a string consisiting of a surrogate pair is excluded from the check, adequate care must be taken since
number of characters that are counted are likely to be more than the actual number of characters.
For length of the string including surrogate pair, refer Fetching string length.

Hibernate Validator check rules

All the major annotations(org.hibernate.validator.constraints.*) of Hibernate Validator are


shown below.

Refer to Hibernate Validator specifications for details.

382 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Annotation Target type Description Usage example


It is applicable to any implemen-
@CreditCardNumber
@CreditCardNumber
tation class of CharSequence
Validate whether the credit card private String cardNumbe
interface
number is valid as per Luhn
algorithm. It does not necessarily
check whether the credit card
number is available.
By specifying
ignoreNonDigitCharacters
= true, it is possible to validate
by ignoring non-numeric
characters.

@Email It is applicable to any implemen- Validate whether the Email ad-


@Email
tation class of CharSequence dress is complaint with RFC2822.
private String email;
interface

@URL It is applicable to any implemen- Validate whether it is compliant


@URL
tation class of CharSequence with RFC2396.
private String url;
interface

@NotBlank It is applicable to any implemen- Validate that it is not null, empty


@NotBlank
tation class of CharSequence string ("") and space only.
private String userId;
interface

@NotEmpty It is applicable to Collection,


@NotEmpty
Map, Array, and any implementa-
Validate that it is not null or private String password;
tion class of CharSequence in-
empty.
terface
@NotEmpty should be used
when check is to be done in
@NotNull + @Min(1)
combination.

4.1. Input Validation 383


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Warning: When following annotations provided by Hibernate Validator are used, if a default message is used,
a bug that the message is not generated correctly HV-881, HV-949) occurs.
• @CreditCardNumber(message is displayed, but WARN log is output)
• @LuhnCheck
• @Mod10Check
• @Mod11Check
• @ModCheck(deprecated API from 5.1.0.Final)
This bug occurs because of the flaws in message definitions provided by default, and it is possible to avoid
them by overwriting the default messages by an appropriate message.
In case of overwriting the default messages, it is advisable to define an appropriate message by creating
ValidationMessages.properties directly under the class path (normal src/main/resources).
For appropriate message definition, refer to: Modifications for Hibernate Validator 5.2 version (next minor
version upgrade).

Default messages provided by Hibernate Validator

In hibernate-validator-<version>.jar, there is a ValidationMessages.properties file at org/hibernate/validator loca-


tion, which contains the default messages of all Hibernate provided annotations.

javax.validation.constraints.AssertFalse.message = must be false


javax.validation.constraints.AssertTrue.message = must be true
javax.validation.constraints.DecimalMax.message = must be less than ${inclusive == true ? 'or equ
javax.validation.constraints.DecimalMin.message = must be greater than ${inclusive == true ? 'or
javax.validation.constraints.Digits.message = numeric value out of bounds (<{integer} digits>
javax.validation.constraints.Future.message = must be in the future
javax.validation.constraints.Max.message = must be less than or equal to {value}
javax.validation.constraints.Min.message = must be greater than or equal to {value}
javax.validation.constraints.NotNull.message = may not be null
javax.validation.constraints.Null.message = must be null
javax.validation.constraints.Past.message = must be in the past
javax.validation.constraints.Pattern.message = must match "{regexp}"
javax.validation.constraints.Size.message = size must be between {min} and {max}

org.hibernate.validator.constraints.CreditCardNumber.message = invalid credit card number


org.hibernate.validator.constraints.EAN.message = invalid {type} barcode
org.hibernate.validator.constraints.Email.message = not a well-formed email addr
org.hibernate.validator.constraints.Length.message = length must be between {min}
org.hibernate.validator.constraints.LuhnCheck.message = The check digit for ${valida
org.hibernate.validator.constraints.Mod10Check.message = The check digit for ${valida
org.hibernate.validator.constraints.Mod11Check.message = The check digit for ${valida
org.hibernate.validator.constraints.ModCheck.message = The check digit for ${valida
org.hibernate.validator.constraints.NotBlank.message = may not be empty
org.hibernate.validator.constraints.NotEmpty.message = may not be empty
org.hibernate.validator.constraints.ParametersScriptAssert.message = script expression "{script}"
org.hibernate.validator.constraints.Range.message = must be between {min} and {m
org.hibernate.validator.constraints.SafeHtml.message = may have unsafe html content

384 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

org.hibernate.validator.constraints.ScriptAssert.message = script expression "{script}"


org.hibernate.validator.constraints.URL.message = must be a valid URL

org.hibernate.validator.constraints.br.CNPJ.message = invalid Brazilian corporate


org.hibernate.validator.constraints.br.CPF.message = invalid Brazilian individual
org.hibernate.validator.constraints.br.TituloEleitoral.message = invalid Brazilian Voter ID c

Input check rules provided by a common library

A common library provides an independent annotation for verification. Here, how to specify input check rules
which use annotation provided by common library is explained.

terasoluna-gfw-common check rules

Annotation provided by terasoluna-gfw-common (org.terasoluna.gfw.common.codelist.*) is


shown below.

Annotation Target type Description Usage example


@ExistInCodeList Verify whether value is incorpo- Refer @ExistInCodeList
rated in the code list.
Character
Implementation class of
CharSequence
(String,
StringBuilderetc)

terasoluna-gfw-codepoints check rules

Annotation (org.terasoluna.gfw.common.codepoints.*) offered by terasoluna-gfw-codepoints is


shown below. Further, terasoluna-gfw-codepoints can be used in 5.1.0.RELEASE and subsequent ver-
sions.

Annotation Target type Description Usage example


@ConsistOf Verify whether all the character Refer @ConsistOf
strings to be checked are included
Implementation class of
in the specified code point set.
CharSequence
(String, StringBuilder
etc)

4.1. Input Validation 385


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

terasoluna-gfw-validator check rules

Annotation (org.terasoluna.gfw.common.validator.constraints.*) offered by terasoluna-


gfw-validator is shown below. Further, terasoluna-gfw-validatorcan be used in 5.1.0.RELEASE and
subsequent versions.

386 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Annotation Target type Description Usage example


@ByteMin Refer @ByteMax

Implementation class of Verify whether byte length value


CharSequence is greater than or equal to
(String, StringBuilder minimum value.
etc)
[Annotation attributes]
long value - Specify
minimum value of byte length.
String charset - Specify
string character set used while
encoding the value in byte
sequence. Default value is
UTF-8.

@ByteMax
@ByteMin(1)
Implementation class of Verify whether byte length value @ByteMax(value = 100,
CharSequence is less than or equal to maximum charset = "Shift
(String, StringBuilder value. private String id;
etc)
[Annotation attribute]
long value - Specify
maximum value for byte length.
String charset - Specify
string character set used while
encoding the value in byte
sequence. Default value is
UTF-8.

@Compare Check whether the mail ad-


dress matches with the mail
Implementation class of Verify that the magnitude relation
address entered for check-
Comparable interface can be of specified property value is
ing. Implementation is as
applied to any JavaBean with a correct.
below when entire form is
property
to be displayed as an error
[Annotation attribute] message.
String left - Specify the @Compare(left = "email",
property name to be used as a right = "confirm
comparison source in the object. operator = Compa
A message is displayed in the requireBoth = tr
property in case of a validation node = Compare.N
4.1. Input Validation error. 387 UserRegiste
public class
String right - Specify private String email
property name to be used as a private String confi
comparison destination in the }
TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Note: For mandatory input during correlated item check

For unit item check, whether a value is entered in the input field( should not be null) can be checked by
using @NotNull in combination. However, in correlated item check, the check like “if value is entered in one
field, value is entered forcefully in another field” cannot be implemented by using @NotNull alone. Hence,
@Compare provides requireBoth attribute which controls mandatory input for checking which can then be
used for implementing the check whenever required.

Also, when a value is not entered in the input field, requireBoth attribute can be used only when null is
bound. If a form is sent in Spring MVC when a value is not entered in input field of string, it must be noted that
empty string is bound in the form object by default instead of null. When a value is not entered in the string
field, refer Binding null to blank string field to bind null in form object instead of empty string.

Expected check requirements and configuration example are shown below using “checking whether period start
date is earlier than end date” as an example.

388 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Check requirements Configuration example


from and to both are mandatory, compare from Assign @NotNullin from and to and use default
and to. value ( false)in requireBoth attribute.
@Compare(left = "from", right = "to", operato
public class Period {
@NotNull
LocalDate from;
@NotNull
LocalDate to;
}

Only from is mandatory, however carry out compar- Assign @NotNullonly in from and use default
ison check when a value is entered in to as well. value ( false)in requireBoth attribute.
@Compare(left = "from", right = "to", operato
public class Period {
@NotNull
LocalDate from;
LocalDate to;
}

from and to are not both required, carry out com- Do not assign @NotNulland use default value
parison check only when values are entered in both ( false)in requireBoth attribute.
from and to. When the value is entered in only one @Compare(left = "from", right = "to", operato
of the fields, comparison check is not carried out. public class Period {
LocalDate from;
LocalDate to;
}

from and to are not both required, when values are Do not assign @NotNulland specify true in
entered in either of the fromor to, carry out compar- requireBoth attribute.
ison check by always entering values in both fields. @Compare(left = "from", right = "to", operato
public class Period {
LocalDate from;
LocalDate to;
}

4.1. Input Validation 389


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

How to apply check rules of common library

Apply check rules of common library using the procedure below.

Add a dependent library for the rules that are to be used. An example for how to add
terasoluna-gfw-validator is shown below.

<dependencies>
<dependency>
<groupId>org.terasoluna.gfw</groupId>
<artifactId>terasoluna-gfw-validator</artifactId>
</dependency>
</dependencies>

Next, a message definition corresponding to annotation is added to ValidationMessages.properties as


explained in Messages to be defined in ValidationMessages.properties.

# (1)
org.terasoluna.gfw.common.validator.constraints.ByteMin.message = must be greater than or equal to
org.terasoluna.gfw.common.validator.constraints.ByteMax.message = must be less than or equal to {v
org.terasoluna.gfw.common.validator.constraints.Compare.message = not match '{left}' and '{right}'

Sr. No. Description


Add a message definition for each annotation. Annotation attribute value can be incorporated in the
message by using placeholder ({attribute name} format).
(1)

In the end, assign an annotation to JavaBean property as explained in Basic single item check.

Note: When validation cannot be implemented in Bean Validation due to invalid attribute value of annotation,
javax.validation.ValidationException is thrown. Modify the attribute value to a valid value by
referring the reason that is output in stack trace.

Refer Chapter 9 of Bean Validation specification for details.

How to extend check rules of common library

Any rule can be created by using check rules provided by common library.

An example is introduced below wherein @Confirm annotation independently implemented by Check rules for
correlated items is created by using check rules provided by common library.

Create @Confirm annotation by using @Compare as described in Creation of Bean Validation annotation by
combining existing rules.

390 4 Web Application Development Features


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

package com.example.sample.domain.validation;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;


import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.OverridesAttribute;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;

import org.terasoluna.gfw.common.validator.constraints.Compare;

@Documented
@Constraint(validatedBy = {})
@Target({ TYPE, ANNOTATION_TYPE }) // (1)
@Retention(RUNTIME)
@ReportAsSingleViolation // (2)
@Compare(left = "", right = "", operator = Compare.Operator.EQUAL, requireBoth = true) // (3)
public @interface Confirm {

String message() default "{com.example.sample.domain.validation.Confirm.message}"; // (4)

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};

@OverridesAttribute(constraint = Compare.class, name = "left") // (5)


String field();

@OverridesAttribute(constraint = Compare.class, name = "right") // (6)


String confirmField();

@Documented
@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface List {
Confirm[] value();
}
}

4.1. Input Validation 391


TERASOLUNA Server Framework for Java (5.x) Development Guideline Documentation,
Release 5.2.0.RELEASE

Sr. No. Description

(1) Restrict the location where the annotation can be assigned to class or annotation.

(2) Message specified in message attribute of this annotation should be used at the time of error.

(3) Specify Compare.Operator.EQUAL(should be equivalent value) in operator attribute of


@Compare annotation. Specify true in requireBothattribute since an error occurs if a value is
not entered in either of the fields.

(4) Define default value of error message.

(5) Override left attribute of @Compare annotation and change attribute name to field.

(6) Similarly, override right attribute and change attribute name to confirmField.

Use annotation created above instead of annotation implemented in Check rules for correlated items.

package com.example.sample.app.validation;

import java.io.Serializable;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import com.example.common.validation.Confirm;

@Confirm(field = "password", confirmField = "confirmPassword") // (1)


public class PasswordResetForm implements Serializable {
private static final long serialVersionUID = 1L;

@NotNull // (2)
@Size(min = 8)
private String password;

@NotNull // (3)
private String confirmPassword;

392 4 Web Application Development Features


T