MVC 1.0 for JAVA EE 8
Bogdan Posa
Java developer @ING
BJUG - 12.12.2015
https://bjug.ro/
JAVA EE 8
release date: first half of 2017
JCP & JSR -> https://www.jcp.org/en/home/index
Motivation


CONTEXT
Java EE 8 Community Survey - Java.net
OVERVIEW
MVC 1.0 Specification
https://jcp.org/en/jsr/detail?id=371 - JSR 371
https://java.net/projects/mvc-spec/
https://java.net/jira/browse/MVC_SPEC/
https://ozark.java.net/ - RI
- on top of JAX-RS
- integrates with existing EE technologies like CDI and Bean Validation.
Controllers
@Path("hello")
public class HelloController {
@GET
@Controller
public String hello() {
return "hello.jsp";
}
}
@Controller -> class or method
Controllers
@Controller
@Path("hello")
public class HelloController {
@GET
@Path("void")
@View("hello.jsp")
public void helloVoid() {
}
@GET
@Path("string")
public String helloString() {
return "hello.jsp";
}
@GET
@Path("viewable")
public Viewable helloViewable() {
return new Viewable("hello.jsp");
}
@GET
@Path("response")
public Response helloResponse() {
return Response.status(Response.Status.OK)
.entity("hello.jsp").build();
}
@GET
@Path("myview")
public MyView helloMyView() {
return new MyView("hello.jsp"); // toString() -> "hello.jsp"
}
}
Controllers
Viewable: template + model
Response: more access to the http response
@GET
@Controller
public Response getById(@PathParam("id") String id) {
if (id.length() == 0) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("error.jsp").build();
}
...
}
PRG pattern
@GET
@Controller
public String redirect() {
return "redirect:see/here";
}
@GET
@Controller
public Response redirect() {
return Response.seeOther(URI.create("see/here")).build();
}
PRG pattern
@Controller
@Path("submit")
public class MyController {
@Inject
private MyBean myBean;
@POST
public String post() {
myBean.setValue("Redirect about to happen");
myBean.setValue("Redirect about to happen");
return "redirect:/submit";
}
@GET
public String get() {
return "mybean.jsp"; // mybean.value accessed in JSP
}
}
@RedirectScoped - scope that spans at most two requests and thus fits between a request and a session scope
Models
1. @Named beans
@Named("greeting")
@RequestScoped
public class Greeting {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
@Path("hello")
public class HelloController {
@Inject
private Greeting greeting;
@GET
@Controller
public String hello() {
greeting.setMessage("Hello there!");
return "hello.jsp";
}
}
Models
2. Models map
@Path("hello")
public class HelloController {
@Inject
private Models models;
@GET
@Controller
public String hello() {
models.put("greeting", new Greeting("Hello there!");
return "hello.jsp";
}
}
Models
"Support for the Models interface is mandatory for all view engines; support for CDI @Named beans is OPTIONAL but highly RECOMMENDED. Application developers are encouraged to use CDI-based models whenever supported."
Views
<html>
<head>
<title>Hello</title>
</head>
<body>
<h1>${greeting.message}</h1>
</body>
</html>
Exception handling
@Controller
@Path("form")
public class FormController {
@Inject
private BindingResult br;
@Inject
private ErrorDataBean error;
@POST
@ValidateOnExecution(type = ExecutableType.NONE)
public Response formPost(@Valid @BeanParam FormDataBean form) {
if (br.isFailed()) {
// fill out ErrorDataBean ...
return Response.status(BAD_REQUEST).entity("error.jsp").build();
}
return Response.status(OK).entity("data.jsp").build();
}
}
Security
<html>
<head>
<title>CSRF Protected Form</title>
</head>
<body>
<form action="csrf" method="post" accept-charset="utf-8">
<input type="submit" value="Click here"/>
<input type="hidden" name="${mvc.csrf.name}"
value="${mvc.csrf.token}"/>
</form>
</html>
CSRF:
<img src="http://yourbank.com/transfer?from=yours&to=mine&sum=1000000">
Security
@Path("csrf")
@Controller
public class CsrfController {
@GET
public String getForm() {
return "csrf.jsp"; // Injects CSRF token
}
@POST
@CsrfValid // Required for CsrfOptions.EXPLICIT
public void postForm(@FormParam("greeting") String greeting) {
}
}
Solution 2:
javax.mvc.security.CsrfProtection property
View Engines
public class JUGViewEngine implements ViewEngine {
public JUGViewEngine() {
}
public boolean supports(String view) {
return view.endsWith(".bjug");
}
public void processView(ViewEngineContext context) throws ViewEngineException {
Models models = context.getModels();
try (PrintWriter writer = context.getResponse().getWriter()) {
writer.write("Processing result here");
} catch (IOException e) {
throw new ViewEngineException(e);
}
}
}
easy to extend the view processing mechanism
THANK YOU
LET'S PLAY !!!
Q & A

MVC 1.0
By Bogdan Posa
MVC 1.0
- 2,471