This document discusses Java EE action-based MVC frameworks and getting started with the Java EE 8 MVC 1.0 specification. It covers:
1. What is action-based MVC and how it differs from component-based MVC.
2. An overview of getting started with the MVC 1.0 specification, including using Thymeleaf as the view technology.
3. How to use Jersey MVC and RESTEasy HTML in Java EE 7 as alternatives since MVC 1.0 is a Java EE 8 feature.
The 7 Things I Know About Cyber Security After 25 Years | April 2024
Getting start Java EE Action-Based MVC with Thymeleaf
1. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Getting Start
Java EE Action-Based MVC
With Thymeleaf
Masatoshi Tada (Casareal ,Inc)
JJUG CCC 2016 Spring
2016-5-21(Sat)
1
2. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
About This Session
! Answer Your Question "Java EE is Useful
Framework As Next Struts?"
! View is Thymeleaf !
! Code on GitHub
! https://github.com/MasatoshiTada/jjug-action-based-
mvc
! Sorry, comments are written in Japanese
2
3. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
About Me
! Masatoshi Tada
!Casareal, Inc
!GlassFish User Group Japan
!Trainer(Java EE/Spring/Swift)
!Twitter:@suke_masa
3
4. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Agenda
① What’s "Action-Based MVC"?
② Getting Start MVC 1.0(EE 8)
③ Using Jersey MVC & RESTEasy HTML in
EE 7
④ Other Java EE Technologies You Should
Know
⑤ Final Conclusions
4
6. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
What’s Action-Based MVC?
! Web Framework which focuses HTTP
request & response
! Most of framework are Action-Based
! Struts, Spring MVC, …
6
7. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
What’s Action-Based MVC?
7
View
View
Controller Model
request
response
Struts developer friendly
8. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
What’s "Component-Based MVC"?
8
View
Backing
Bean
Model
GUI(VB, Android…) developer friendly
-> Struts developer Un-Friendly
9. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Web Framework of Java EE
! JSF
! Responses HTML
! Component-Based
! JAX-RS
! Responses JSON/XML
! Action-Based
9
There’s no Framework
which is "Action-Based"
and "Responses HTML"
10. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Java EE Standard Action-Based MVC!!
! Model-View-Controller API (MVC 1.0)
! Java EE 8 (2017 H1)
! Based on JAX-RS
10
12. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
MVC 1.0
! MVC 1.0 is Specification
! ≒Set of Interfaces, Annotations, and Exceptions
! Reference Implementation is Ozark
! Set of Implementation Classes of above
interfaces
12
13. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Main Functions of Struts
! Controller
! Validation
! Handling Exception
! View Technology
! Transaction Token
13
14. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
in MVC 1.0?
! Controller → ⭕
! Validation → ⭕
! Handling Exception → ⭕
! View Technology → ❌
! Transaction Token → ❌
14
15. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Why No View Technologies in MVC?
! Non-Goal 1 of MVC specification
"Define a new view (template)
language and processor."
! Instead, MVC provides integration with
many view technologies!
15
16. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
View Technologies
We Can Use in MVC 1.0
! MVC
! JSP, Facelets
! Ozark
! Thymeleaf, Mustache, Freemarker,
Handlerbars, Velocity, AsciiDoc, …
16
If you want to use other View,
Implement ViewEngine interface
17. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Problems of JSP and Facelets
17
! JSP
! Mix of Logic and View
! Sometime Occurs XSS
! Facelets
! Cannot Use All Features in MVC 1.0
! Bad Compatibility with JavaScript
18. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Let’s Use Thymeleaf!
18
! Pure HTML!
! Isolate View and Logic absolutely!
! Good Compatibility with JavaScript!
! Link Expression is very useful!
! Internationalizing message!
! http://www.thymeleaf.org/doc/tutorials/2.1/
usingthymeleaf.html#a-multi-language-welcome
19. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Using Thymeleaf in MVC 1.0
19
<dependency>
<groupId>org.glassfish.ozark.ext</groupId>
<artifactId>ozark-thymeleaf</artifactId>
<version>1.0.0-m02</version>
<scope>compile</scope>
</dependency>
! Just adding dependency like below
20. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Why No Transaction Token Feature?
! In Expert Group’s Mailing-List,
"This is a client side concern"
! https://java.net/projects/mvc-spec/lists/
jsr371-experts/archive/2015-07/message/2
! Spring MVC has no transaction token
feature, too.
20
21. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
How to Avoid Double-Submit-Problem
! See TERASOLUNA Guideline
! http://terasolunaorg.github.io/guideline/
5.1.0.RELEASE/en/ArchitectureInDetail/
DoubleSubmitProtection.html
21
22. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Preparation : Enabling JAX-RS
22
@ApplicationPath("/api")
public class MyApplication extends Application {
}
Inherit Application class
Add Annotation
jjug-mvc10/src/main/java/com/example/rest/MyApllication.java
23. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Basic Controller
23
@Path("/employee")
public class EmployeeController {
@GET @Path("/index")
@Controller
public String index() {
return "employee/index.html";
}
} Path of View
(extention is REQUIRED)
Indicate as controller
method
Mapping to URL &
HTTP method
※Italic is feature of MVC
jjug-mvc10/src/main/java/com/example/rest/controller/EmployeeController.java
24. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Form Class
24
public class EmployeeIdForm {
@QueryParam("id")
@NotBlank
@Pattern(regexp = "[1-9][0-9]*")
private String id;
// setter/getter
}
Mapping to
"id" Query Parameter
Constraint of
Bean Validation
jjug-mvc10/src/main/java/com/example/rest/form/EmployeeIdForm.java
25. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Send Object to View
25
public class EmployeeController {
@Inject private Models models;
@GET @Path("/result") @Controller
@ValidateOnExecution(type=ExecutableType.NONE)
public String result(…) {
models.put("employee", employee);
return "employee/result.html";
}
Box of Object
(Map + Iterator)
Object referred
by View
jjug-mvc10/src/main/java/com/example/rest/controller/EmployeeController.java
※Italic is feature of MVC
26. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Referring Object in View
26
<table th:unless="${employee == null}">
<tr th:object="${employee}">
<td th:text="*{empId}">99999</td>
<td th:text="*{name}">Taro Yamada</td>
<td th:text="*{joinedDate}">2020-01-01</td>
<td th:text="*{department.deptId}">99</td>
<td th:text="*{department.name}">Admin</td>
</tr>
</table> WEB-INF/views is view folder
jjug-mvc10/src/main/webapp/WEB-INF/views/employee/result.html
Name put to Models
27. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Validation
27
public class EmployeeController {
@Inject private BindingResult br;
@GET @Path("/result") @Controller
@ValidateOnExecution(type=ExecutableType.NONE)
public String result( @Valid @BeanParam
EmployeeIdForm form) {
if (br.isFailed()) {
models.put("bindingResult", br);
return "employee/index.html"; // To input view
Box of Messages
Enable
Validation
Error Processing
jjug-mvc10/src/main/java/com/example/rest/controller/EmployeeController.java
※Italic is feature of MVC
28. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Showing Error Messages
28
<ul th:if="${bindingResult != null}">
<li th:each="message
: ${bindingResult.allMessages}"
th:text="${message}">
This is Dummy Message
</li>
</ul>
Get Messages From
BindingResult
jjug-mvc10/src/main/webapp/WEB-INF/views/employee/index.html
29. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Writing Error Messages
! Write messages in
src/main/resources/
ValidationMessages.properties
! Specify Key of Message to "message"
attribute in Annotation
29
30. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Specifying Error Message Key
30
public class EmployeeIdForm {
@QueryParam("id")
@NotBlank(message = "{id.notblank}")
@Pattern(regexp = "[1-9][0-9]*",
message = "{id.pattern}")
private String id;
// setter/getter
Key of Message with "{}"
jjug-mvc10/src/main/java/com/example/rest/form/EmployeeIdForm.java
31. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Caution :
MVC has No "Form-Binding" Feature
! @BeanParam is not "Form-Binding"
! On error, If You want to leave values in
input-components on view, Write view as
Next
31
32. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Implementing Form-Binding
32
<form action="./result" method="get">
<input type="text" name="id" value=""
th:value="${param.id == null} ? ''
: ${param.id[0]}"/>
<input type="submit" value="search"/>
</form>
jjug-mvc10/src/main/webapp/WEB-INF/views/employee/index.html
Maybe Complex with
selectbox …
33. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Handling Exception
! Implement ExceptionMapper interface
! When error occurs, ExceptionMapper
catches Exception
! You can implement multiple
ExceptionMappers
33
34. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
ExceptionMapper class
34
@Provider
public class ExceptionMapper implements
javax.ws.rs.ext.ExceptionMapper<Exception> {
public Response toResponse(
Exception exception) {
// Forward to Error View…
}
}
Don’t Forget @Provider
Catches Exception as
Method Argument
Implement
ExceptionMapper
35. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Other Features of MVC
! Security (XSS, CSRF)
! File Upload, Download
! MvcContext (Easy Specifying URL)
! Hybrid Class (HTML and REST)
! More Details, See GUGJ Slides below
! http://www.slideshare.net/masatoshitada7/java-ee-8mvc-10
35
36. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Conclusions of this chapter
! MVC 1.0 + Thymeleaf covers almost
features of Struts!
! Need to implement Transaction Token
and Form-Binding By Yourself
! Features of MVC are Simple, Reveraging
existing Java EE Features.
36
38. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
What framework should we use
in Java EE 7?
! MVC 1.0 is Java EE 8
! Java EE 8 will be released in 2017 H1
38
Let’s use
Jersey MVC or RESTEasy HTML in EE7!
39. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
What’s Jersey MVC?
! Original Extension of Jersey(JAX-RS RI)
! Similar to MVC 1.0
! GlassFish/Payara inside
! WebLogic not inside
39
40. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
What’s RESTEasy HTML?
! Original Extension of RESTEasy (other
implementation of JAX-RS)
! RESTEasy is inside WildFly/JBoss,
but RESTEasy HTML is not inside
40
41. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Basic Jersey MVC
! Register MvcFeature class to Your Application
sub class (ResourceConfig is Convinient)
41
@ApplicationPath("/api")
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(MvcFeature.class);
property(MvcFeature.TEMPLATE_BASE_PATH,
"/WEB-INF/views/");
packages(true, "com.example.rest");
}
} jjug-jersey-mvc/src/main/java/com/example/rest/MyApplication.java
※Italic is Jersey MVC’s feature
42. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Basic Jersey MVC
! Return Viewable in controller methods
42
@Path("/employee")
public class EmployeeController {
@GET @Path("/index")
public ThymeleafViewable index(…) {
return new ThymeleafViewable(
"employee/index.html");
}
}
My original class
(Viewable’s subclass)
jjug-jersey-mvc/src/main/java/com/example/rest/controller/EmployeeControler.java
※Italic is Jersey MVC’s feature
43. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Basic Jersey MVC
! Add value to Viewable constructor’s 2nd
parameter
43
@Path("/employee")
public class EmployeeController {
@GET @Path("/result")
public ThymeleafViewable result(…) {
Map<String, Object> models = …
return new ThymeleafViewable(
"employee/result.html", models);
}
Put objects to Map
jjug-jersey-mvc/src/main/java/com/example/rest/controller/EmployeeControler.java
※Italic is Jersey MVC’s feature
44. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
How to Use Thymeleaf
with Jersey MVC
! Implment TemplateProcessor interface
(Provided by Jersey)
! AbstractTemplateProcessor class is
useful
! implementation of TemplateProcessor
44
45. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
ThymeleafTemplateProcessor
45
@Provider
public class ThymeleafTemplateProcessor
extends AbstractTemplateProcessor<String> {
private TemplateEngine templateEngine;
@Inject public ThymeleafTemplateProcessor(
Configuration config, ServletContext servletContext) {
super(config, servletContext, "html", "html");
TemplateResolver templateResolver =
new ServletContextTemplateResolver();
templateResolver.setPrefix((String) config.getProperty(
MvcFeature.TEMPLATE_BASE_PATH));
templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
}
// to next slide
jjug-jersey-mvc/src/main/java/com/example/rest
/thymeleaf/ThymeleafTemplateProcessor.java
※Italic is Jersey MVC’s feature
46. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
ThymeleafTemplateProcessor
46
// 続き
@Override public void writeTo(...) {
WebContext webContext = new WebContext(
request, response, servletContext, request.getLocale());
Map<String, Object> map = (Map) viewable.getModel();
webContext.setVariables(map);
templateEngine.process(viewable.getTemplateName(),
webContext, response.getWriter());
}
}
jjug-jersey-mvc/src/main/java/com/example/rest
/thymeleaf/ThymeleafTemplateProcessor.java
Thymeleaf write
the response
※Italic is Jersey MVC’s feature
47. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Validation in Jersey MVC
! Jersey provides @ErrorTemplate annotation
to specify error view, but…
! This annotation is feature for handling
exception (not for validation)
! MVC 1.0 doesn’t have similar feature, so
migration will be difficult
! Cannot use "Validation Group" and "Group
Sequence" (Features of Bean Validation)
47
48. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Validate in Controller Methods
48
@Inject Validator validator;
@GET @Path("/result")
public ThymeleafViewable result(
@BeanParam EmployeeIdForm form) {
Set<ConstraintViolation<EmployeeIdForm>>
violations = validator.validate(form);
if (!violations.isEmpty()) {
Map<String, Object> model = …;
model.put("violations", violations);
return new ThymeleafViewable(
"employee/index.html", model);
}
Execute Bean Validation
No @Valid to arguments
Validate
On error,
return to
input view
49. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Showing Error Message
49
<ul th:if="${violations != null}">
<li th:each="violation : ${violations}"
th:text="${violation.message}">
This is Dummy Message
</li>
</ul>
50. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
About This Method
! Advantage
! Pure JAX-RS code
! Easy MVC 1.0 migration
! Avoid excess framework customization
! Disadvantage
! It takes time and effort
50
I Tried a variety of methods,
this method is best
51. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Handling Exception
! ExceptionMapper
! Same to MVC 1.0 sample code
51
52. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Redirect
! JAX-RSのコードで書けばOK
52
@GET @Path("/redirect")
public Response redirect(
@Context UriInfo uriInfo) throws Exception {
URI location = uriInfo.getBaseUriBuilder()
.path(HelloResource.class)
.path("redirect2")
.build();
return Response.status(Response.Status.FOUND)
.location(location).build();
}
UriInfo has variety of
method to build URI
Specify URI to Location header
Status code 3xx
53. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Basic RESTEasy HTML
! Create Application’s sub class
! No need to register any specific class
! By JAX-RS "Providers"
53
@ApplicationPath("/api")
public class MyApplication extends Application {
}
jjug-resteasy-html/src/main/java/com/example/rest/MyApplication.java
54. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Basic RESTEasy HTML
! Return Renderable in controller method
54
<<interface>>
Renderable
View class
(Forward)
Redirect class
(Redirect)
55. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Using Thymeleaf in RESTEasy HTML
! Create Renderable implementation class
55
<<interface>>
Renderable
View Redirect ThymeleafView
56. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
ThymeleafView
56
public class ThymeleafView implements Renderable {
private String templateName;
private Map<String, Object> models;
private TemplateEngine templateEngine;
public ThymeleafView(String templateName) {
this(templateName, new HashMap<>());
}
public ThymeleafView(String templateName,
Map<String, Object> models) {
this.templateName = templateName;
this.models = models;
}
void setTemplateEngine(TemplateEngine templateEngine) {
this.templateEngine = templateEngine;
}
Implement
Renderable
※Italic is RESTEasy HTML feature
57. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
ThymeleafView
57
// from previous slide
@Override
public void render(HttpServletRequest request,
HttpServletResponse response) throws IOException,
ServletException, WebApplicationException {
response.setCharacterEncoding("UTF-8");
WebContext webContext = new WebContext(
request, response, request.getServletContext(),
request.getLocale());
webContext.setVariables(models);
templateEngine.process(templateName, webContext,
response.getWriter());
}
}
Call TemplateEngine#process() in render()
※Italic is RESTEasy HTML feature
58. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Creating Interceptor
Setting TemplateEngine to ThymeleafView
! Use JAX-RS WriterInterceptor
! Create custom annotation with
NameBinding, to specify which
controller apply interceptor
! There’re many ways(This is not only
way)
58
59. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Creating annotation
59
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,
ElementType.TYPE})
@Documented
public @interface ThymeleafController {
}
Create annotation
with @NameBinding
60. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Creating WriterInterceptor
60
@Provider
@ThymeleafController
public class ThymeleafWriterInterceptor
implements WriterInterceptor {
private TemplateEngine templateEngine;
@PostConstruct
public void init() {
TemplateResolver resolver =
new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/views/");
templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(resolver);
}
Specify annotation you created
Implement WriterInterceptor
61. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Creating WriterInterceptor
61
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {
Object entity = context.getEntity();
if (ThymeleafView.class.isAssignableFrom(entity.getClass())) {
ThymeleafView thymeleafView =
(ThymeleafView) context.getEntity();
thymeleafView.setTemplateEngine(templateEngine);
}
context.proceed();
}
}
Set TemplateEngine
before context.proceed()
62. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Controller
62
@GET @Path("result")
@ThymeleafController
public ThymeleafView result(…) {
Map<String, Object> models = …;
models.put("employee", employee);
return new ThymeleafView(
"employee/result.html", models);
}
Specify annotation
→Applying interceptor
View path and values
※Italic is RESTEasy HTML feature
63. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Validation and Handling Exception
! Same as Jersey MVC sample code
63
64. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Conclusions of this chapter
! In Java EE 7,
Use Jersey MVC or RESTEasy HTML!
! Controller methods, views and handling
exceptions are same as MVC 1.0!
! They have no BindingResult, so validate
in controller methods!
64
66. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
JAX-RS
! Specific features of MVC 1.0/Jersey MVC/
RESTEasy HTML are not many
! To achieve what you want to do, and
trouble-shooting, knowledge of JAX-RS is
very important
66
67. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
JAX-RS Reference
! JSR-339 JAX-RS 2.0 rev.A
! You should learn Processing Pipeline
(Appendix C)
! https://jcp.org/en/jsr/detail?id=339
! Jersey Document
! RESTEasy Document
67
70. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Final Conclusions
! MVC 1.0 + Thymeleaf covers almost
features of Struts!
! In EE 7, Use Jersey MVC or RESTEasy
HTML!
! Understanding JAX-RS is very important!
70
71. #ccc_cd4
(C) CASAREAL, Inc. All rights reserved.
Caution
! Jersey MVC and RESTEasy HTML are
NOT "Java EE 7 standard"
! They will be out of range
of server vendors’ support
! In "Java EE 7 standard",
JSF is the ONLY HTML Framework
71