際際滷

際際滷Share a Scribd company logo
Intro into MVC 1.0
Maurice de Chateau
June 9, 2016
Agenda
 Why another MVC?
 The specification
 Models, Views and Controllers
 Exception handling
 MVC applications
 Security
 Events
 Current status
Why another MVC?
 We already have JSF
 Component-based MVC (MVC-pull)
 No action-based MVC yet (MVC-push)
 Java EE 8 community survey indicated the need
 Different approach, mental model
 Which one is more suitable, not better
Why another MVC?
Properties of UI component orientation:
 Readily available UI components from various libraries
 Easy-to-use development model with quick results
 Little control over and access to HTML, CSS, JS and
HTTP
 Hard to combine with other technologies
 Difficult to fully understand (e.g. JSF lifecycle)
Why another MVC?
Properties of action orientation:
 Does not hide the HTTP request/response mechanism
 Makes few assumptions (if any) about the UI, does not
dictate HTML/CSS/JS
 Has the developer explicitly deal with events that
originate from the UI
MVC 1.0
 Built on top of JAX-RS
 Integrates with CDI and Bean Validation
 Built-in support for JSP and facelets
 But others template engines may be supported
 Ozark e.g. supports FreeMarker, Thymeleaf and
Handlebars
Models, Views and Controllers

javax.mvc.Models: map between names and
objects
 Optional: CDI-based models (@Named)
@Named@Named("greeting")("greeting")
@RequestScoped@RequestScoped
publicclassGreeting{publicclassGreeting{
privateStringmessage;privateStringmessage;
publicStringgetMessage(){...}publicStringgetMessage(){...}
publicvoidsetMessage(Stringmessage){...}publicvoidsetMessage(Stringmessage){...}
......
}}
@Named@Named("greeting")("greeting")
@RequestScoped@RequestScoped
publicclassGreeting{publicclassGreeting{
privateStringmessage;privateStringmessage;
publicStringgetMessage(){...}publicStringgetMessage(){...}
publicvoidsetMessage(Stringmessage){...}publicvoidsetMessage(Stringmessage){...}
......
}}
@Inject@Inject
privateprivateModelsModelsmodels;models;
@Inject@Inject
privateprivateModelsModelsmodels;models;
models.models.putput("greeting",newGreeting("Hellothere!");("greeting",newGreeting("Hellothere!");models.models.putput("greeting",newGreeting("Hellothere!");("greeting",newGreeting("Hellothere!");
Models, Views and Controllers
 Rendered by a supported view engine
 JSPs and Facelets mandatory
 Located in /WEB足INF/views
The message property is read from the greeting model, whose name was either
specified in a @Named annotation or used as a key in the Models map
<%@pagecontentType="text/html;charset=UTF足8"language="java"%><%@pagecontentType="text/html;charset=UTF足8"language="java"%>
<!DOCTYPEhtml><!DOCTYPEhtml>
<html><html>
<head><head>
<title>Hello</title><title>Hello</title>
</head></head>
<body><body>
<h1>${greeting.message}</h1><h1>${greeting.message}</h1>
</body></body>
</html></html>
<%@pagecontentType="text/html;charset=UTF足8"language="java"%><%@pagecontentType="text/html;charset=UTF足8"language="java"%>
<!DOCTYPEhtml><!DOCTYPEhtml>
<html><html>
<head><head>
<title>Hello</title><title>Hello</title>
</head></head>
<body><body>
<h1>${greeting.message}</h1><h1>${greeting.message}</h1>
</body></body>
</html></html>
Models, Views and Controllers
 An MVC controller is a JAX-RS resource method
decorated by @Controller

@Controller can also be applied at class level:
it then applies to all resource methods in that class
 A controller method may return any of
void (with @View), String, javax.mvc.Viewable, Response,
or any other Java type for which the toString method
returns a view path.
Models, Views and Controllers
 Simple example:
@Path("hello")@Path("hello")
publicclassHelloController{publicclassHelloController{
@Inject@Inject
privateModelsmodels;privateModelsmodels;
@GET@GET
@Controller@Controller
publicStringhello(){publicStringhello(){
models.put("greeting",newGreeting("Hellothere!");models.put("greeting",newGreeting("Hellothere!");
return"hello.jsp";return"hello.jsp";
}}
}}
@Path("hello")@Path("hello")
publicclassHelloController{publicclassHelloController{
@Inject@Inject
privateModelsmodels;privateModelsmodels;
@GET@GET
@Controller@Controller
publicStringhello(){publicStringhello(){
models.put("greeting",newGreeting("Hellothere!");models.put("greeting",newGreeting("Hellothere!");
return"hello.jsp";return"hello.jsp";
}}
}}
Models, Views and Controllers
 Unlike JAX-RS resource classes, classes with MVC
controllers must be CDI-managed beans

@View: for void methods, but also to define the default
view path when null is returned

Viewable: encapsulates info about a view path
 Contains a reference to a Models object (optional)
 Contains a reference to a ViewEngine object (optional)
Models, Views and Controllers
 Support for redirect: prefix (POST-redirect-GET)
can be rewritten as the equivalent:
 New CDI scope for this: @RedirectScoped
 to share the model between the POST and GET
requests
returnResponse.seeOther(URI.create("see/here")).build();returnResponse.seeOther(URI.create("see/here")).build();returnResponse.seeOther(URI.create("see/here")).build();returnResponse.seeOther(URI.create("see/here")).build();
return"redirect:see/here";return"redirect:see/here";return"redirect:see/here";return"redirect:see/here";
Exception Handling
 Based on JAX-RS, with additional support for handling binding and
validation exceptions
 Coarse grained: implement ExceptionMapper for all occurrences of
a specific type
 Finer grained, per @Controller method:
 Inject BindingResult into surrounding class
 Annotate method with @ValidateOnExecution
 BindingResult gives access to detailed information about any violations
Exception Handling
@Controller@Controller
@Path("form")@Path("form")
publicclassFormController{publicclassFormController{
@Inject@Inject
privateprivateBindingResultBindingResultbr;br;
@Inject@Inject
privateErrorDataBeanerror;privateErrorDataBeanerror;
@POST@POST
@ValidateOnExecution(type=ExecutableType.NONE)@ValidateOnExecution(type=ExecutableType.NONE)
publicResponseformPost(@Valid@BeanParamFormDataBeanform){publicResponseformPost(@Valid@BeanParamFormDataBeanform){
if(if(br.isFailed()br.isFailed()){){
//filloutErrorDataBean...//filloutErrorDataBean...
returnResponse.status(BAD_REQUEST).entity("error.jsp").build();returnResponse.status(BAD_REQUEST).entity("error.jsp").build();
}}
returnResponse.status(OK).entity("data.jsp").build();returnResponse.status(OK).entity("data.jsp").build();
}}
}}
@Controller@Controller
@Path("form")@Path("form")
publicclassFormController{publicclassFormController{
@Inject@Inject
privateprivateBindingResultBindingResultbr;br;
@Inject@Inject
privateErrorDataBeanerror;privateErrorDataBeanerror;
@POST@POST
@ValidateOnExecution(type=ExecutableType.NONE)@ValidateOnExecution(type=ExecutableType.NONE)
publicResponseformPost(@Valid@BeanParamFormDataBeanform){publicResponseformPost(@Valid@BeanParamFormDataBeanform){
if(if(br.isFailed()br.isFailed()){){
//filloutErrorDataBean...//filloutErrorDataBean...
returnResponse.status(BAD_REQUEST).entity("error.jsp").build();returnResponse.status(BAD_REQUEST).entity("error.jsp").build();
}}
returnResponse.status(OK).entity("data.jsp").build();returnResponse.status(OK).entity("data.jsp").build();
}}
}}
MVC Applications
 MVC application == JAX-RS application +
one or more @Controllers

MvcContext: provides contextual information
 context and application paths
 access to the JAX-RS application configuration
object
 access to the security-related beans
Security
 Built-in support for CSRF protection
 Using the Csrf object (in the MvcContext) and
an @CsrfValid annotation (and some config)
 Tokens as form fields, or as HTTP headers
<formaction="csrf"method="post"><formaction="csrf"method="post">
<inputtype="submit"value="Clickhere"/><inputtype="submit"value="Clickhere"/>
<inputtype="hidden"name="${<inputtype="hidden"name="${mvc.csrf.namemvc.csrf.name}"}"
value="${value="${mvc.csrf.tokenmvc.csrf.token}"/>}"/>
</form></form>
<formaction="csrf"method="post"><formaction="csrf"method="post">
<inputtype="submit"value="Clickhere"/><inputtype="submit"value="Clickhere"/>
<inputtype="hidden"name="${<inputtype="hidden"name="${mvc.csrf.namemvc.csrf.name}"}"
value="${value="${mvc.csrf.tokenmvc.csrf.token}"/>}"/>
</form></form>
@POST@POST
@CsrfValid@CsrfValid
publicvoidpostForm(...){publicvoidpostForm(...){
......
}}
@POST@POST
@CsrfValid@CsrfValid
publicvoidpostForm(...){publicvoidpostForm(...){
......
}}
Security
 Support for encoding to avoid XSS attacks
 For HTML and Javascript
@Inject@Inject
privateMvcContextmvcCtx;privateMvcContextmvcCtx;
@POST@POST
publicvoidpostForm(@FormParam(input)Stringinput){publicvoidpostForm(@FormParam(input)Stringinput){
Stringescaped=mvcCtx.Stringescaped=mvcCtx.getEncoders()getEncoders().html(input);.html(input);
......
}}
@Inject@Inject
privateMvcContextmvcCtx;privateMvcContextmvcCtx;
@POST@POST
publicvoidpostForm(@FormParam(input)Stringinput){publicvoidpostForm(@FormParam(input)Stringinput){
Stringescaped=mvcCtx.Stringescaped=mvcCtx.getEncoders()getEncoders().html(input);.html(input);
......
}}
Events

CDI events fired by implementations, observable by applications
 Synchronous!

Around a call to a controller:
BeforeControllerEvent, AfterControllerEvent

When a controller returns a redirect (HTTP 3xx) status:
ControllerRedirectEvent

Around the processView call to the view engine:
BeforeProcessViewEvent, AfterProcessViewEvent
Current status
 Released:
 MVC spec: Early Draft Review 2
 Ozark RI: Milestone 2
 Planning:
 Spec: Public Review  Q1 2016 (!)
(currently only 1 of 11 issues has been resolved!)
Proposed Final Draft  Q3 2016
Final Release  H1 2017
 Ozark: Milestone 3  June 30, 2016
(but: currently only 16 of 25 issues have been resolved)
References
 JSR 371: Model-View-Controller (MVC 1.0)
Specification
https://jcp.org/en/jsr/detail?id=371
 Ozark  Reference implementation for MVC 1.0
https://ozark.java.net/
 Why another MVC? By Ed Burns
http://www.oracle.com/technetwork/articles/java/mvc-2280472.html
 MVC 1.0 Users Mailing list
https://java.net/projects/mvc-spec/lists/users/archive
Thank you!
Maurice de Chateau
maurice@jpoint.nl
@mauricedchateau

More Related Content

Intro into MVC 1.0

  • 1. Intro into MVC 1.0 Maurice de Chateau June 9, 2016
  • 2. Agenda Why another MVC? The specification Models, Views and Controllers Exception handling MVC applications Security Events Current status
  • 3. Why another MVC? We already have JSF Component-based MVC (MVC-pull) No action-based MVC yet (MVC-push) Java EE 8 community survey indicated the need Different approach, mental model Which one is more suitable, not better
  • 4. Why another MVC? Properties of UI component orientation: Readily available UI components from various libraries Easy-to-use development model with quick results Little control over and access to HTML, CSS, JS and HTTP Hard to combine with other technologies Difficult to fully understand (e.g. JSF lifecycle)
  • 5. Why another MVC? Properties of action orientation: Does not hide the HTTP request/response mechanism Makes few assumptions (if any) about the UI, does not dictate HTML/CSS/JS Has the developer explicitly deal with events that originate from the UI
  • 6. MVC 1.0 Built on top of JAX-RS Integrates with CDI and Bean Validation Built-in support for JSP and facelets But others template engines may be supported Ozark e.g. supports FreeMarker, Thymeleaf and Handlebars
  • 7. Models, Views and Controllers javax.mvc.Models: map between names and objects Optional: CDI-based models (@Named) @Named@Named("greeting")("greeting") @RequestScoped@RequestScoped publicclassGreeting{publicclassGreeting{ privateStringmessage;privateStringmessage; publicStringgetMessage(){...}publicStringgetMessage(){...} publicvoidsetMessage(Stringmessage){...}publicvoidsetMessage(Stringmessage){...} ...... }} @Named@Named("greeting")("greeting") @RequestScoped@RequestScoped publicclassGreeting{publicclassGreeting{ privateStringmessage;privateStringmessage; publicStringgetMessage(){...}publicStringgetMessage(){...} publicvoidsetMessage(Stringmessage){...}publicvoidsetMessage(Stringmessage){...} ...... }} @Inject@Inject privateprivateModelsModelsmodels;models; @Inject@Inject privateprivateModelsModelsmodels;models; models.models.putput("greeting",newGreeting("Hellothere!");("greeting",newGreeting("Hellothere!");models.models.putput("greeting",newGreeting("Hellothere!");("greeting",newGreeting("Hellothere!");
  • 8. Models, Views and Controllers Rendered by a supported view engine JSPs and Facelets mandatory Located in /WEB足INF/views The message property is read from the greeting model, whose name was either specified in a @Named annotation or used as a key in the Models map <%@pagecontentType="text/html;charset=UTF足8"language="java"%><%@pagecontentType="text/html;charset=UTF足8"language="java"%> <!DOCTYPEhtml><!DOCTYPEhtml> <html><html> <head><head> <title>Hello</title><title>Hello</title> </head></head> <body><body> <h1>${greeting.message}</h1><h1>${greeting.message}</h1> </body></body> </html></html> <%@pagecontentType="text/html;charset=UTF足8"language="java"%><%@pagecontentType="text/html;charset=UTF足8"language="java"%> <!DOCTYPEhtml><!DOCTYPEhtml> <html><html> <head><head> <title>Hello</title><title>Hello</title> </head></head> <body><body> <h1>${greeting.message}</h1><h1>${greeting.message}</h1> </body></body> </html></html>
  • 9. Models, Views and Controllers An MVC controller is a JAX-RS resource method decorated by @Controller @Controller can also be applied at class level: it then applies to all resource methods in that class A controller method may return any of void (with @View), String, javax.mvc.Viewable, Response, or any other Java type for which the toString method returns a view path.
  • 10. Models, Views and Controllers Simple example: @Path("hello")@Path("hello") publicclassHelloController{publicclassHelloController{ @Inject@Inject privateModelsmodels;privateModelsmodels; @GET@GET @Controller@Controller publicStringhello(){publicStringhello(){ models.put("greeting",newGreeting("Hellothere!");models.put("greeting",newGreeting("Hellothere!"); return"hello.jsp";return"hello.jsp"; }} }} @Path("hello")@Path("hello") publicclassHelloController{publicclassHelloController{ @Inject@Inject privateModelsmodels;privateModelsmodels; @GET@GET @Controller@Controller publicStringhello(){publicStringhello(){ models.put("greeting",newGreeting("Hellothere!");models.put("greeting",newGreeting("Hellothere!"); return"hello.jsp";return"hello.jsp"; }} }}
  • 11. Models, Views and Controllers Unlike JAX-RS resource classes, classes with MVC controllers must be CDI-managed beans @View: for void methods, but also to define the default view path when null is returned Viewable: encapsulates info about a view path Contains a reference to a Models object (optional) Contains a reference to a ViewEngine object (optional)
  • 12. Models, Views and Controllers Support for redirect: prefix (POST-redirect-GET) can be rewritten as the equivalent: New CDI scope for this: @RedirectScoped to share the model between the POST and GET requests returnResponse.seeOther(URI.create("see/here")).build();returnResponse.seeOther(URI.create("see/here")).build();returnResponse.seeOther(URI.create("see/here")).build();returnResponse.seeOther(URI.create("see/here")).build(); return"redirect:see/here";return"redirect:see/here";return"redirect:see/here";return"redirect:see/here";
  • 13. Exception Handling Based on JAX-RS, with additional support for handling binding and validation exceptions Coarse grained: implement ExceptionMapper for all occurrences of a specific type Finer grained, per @Controller method: Inject BindingResult into surrounding class Annotate method with @ValidateOnExecution BindingResult gives access to detailed information about any violations
  • 14. Exception Handling @Controller@Controller @Path("form")@Path("form") publicclassFormController{publicclassFormController{ @Inject@Inject privateprivateBindingResultBindingResultbr;br; @Inject@Inject privateErrorDataBeanerror;privateErrorDataBeanerror; @POST@POST @ValidateOnExecution(type=ExecutableType.NONE)@ValidateOnExecution(type=ExecutableType.NONE) publicResponseformPost(@Valid@BeanParamFormDataBeanform){publicResponseformPost(@Valid@BeanParamFormDataBeanform){ if(if(br.isFailed()br.isFailed()){){ //filloutErrorDataBean...//filloutErrorDataBean... returnResponse.status(BAD_REQUEST).entity("error.jsp").build();returnResponse.status(BAD_REQUEST).entity("error.jsp").build(); }} returnResponse.status(OK).entity("data.jsp").build();returnResponse.status(OK).entity("data.jsp").build(); }} }} @Controller@Controller @Path("form")@Path("form") publicclassFormController{publicclassFormController{ @Inject@Inject privateprivateBindingResultBindingResultbr;br; @Inject@Inject privateErrorDataBeanerror;privateErrorDataBeanerror; @POST@POST @ValidateOnExecution(type=ExecutableType.NONE)@ValidateOnExecution(type=ExecutableType.NONE) publicResponseformPost(@Valid@BeanParamFormDataBeanform){publicResponseformPost(@Valid@BeanParamFormDataBeanform){ if(if(br.isFailed()br.isFailed()){){ //filloutErrorDataBean...//filloutErrorDataBean... returnResponse.status(BAD_REQUEST).entity("error.jsp").build();returnResponse.status(BAD_REQUEST).entity("error.jsp").build(); }} returnResponse.status(OK).entity("data.jsp").build();returnResponse.status(OK).entity("data.jsp").build(); }} }}
  • 15. MVC Applications MVC application == JAX-RS application + one or more @Controllers MvcContext: provides contextual information context and application paths access to the JAX-RS application configuration object access to the security-related beans
  • 16. Security Built-in support for CSRF protection Using the Csrf object (in the MvcContext) and an @CsrfValid annotation (and some config) Tokens as form fields, or as HTTP headers <formaction="csrf"method="post"><formaction="csrf"method="post"> <inputtype="submit"value="Clickhere"/><inputtype="submit"value="Clickhere"/> <inputtype="hidden"name="${<inputtype="hidden"name="${mvc.csrf.namemvc.csrf.name}"}" value="${value="${mvc.csrf.tokenmvc.csrf.token}"/>}"/> </form></form> <formaction="csrf"method="post"><formaction="csrf"method="post"> <inputtype="submit"value="Clickhere"/><inputtype="submit"value="Clickhere"/> <inputtype="hidden"name="${<inputtype="hidden"name="${mvc.csrf.namemvc.csrf.name}"}" value="${value="${mvc.csrf.tokenmvc.csrf.token}"/>}"/> </form></form> @POST@POST @CsrfValid@CsrfValid publicvoidpostForm(...){publicvoidpostForm(...){ ...... }} @POST@POST @CsrfValid@CsrfValid publicvoidpostForm(...){publicvoidpostForm(...){ ...... }}
  • 17. Security Support for encoding to avoid XSS attacks For HTML and Javascript @Inject@Inject privateMvcContextmvcCtx;privateMvcContextmvcCtx; @POST@POST publicvoidpostForm(@FormParam(input)Stringinput){publicvoidpostForm(@FormParam(input)Stringinput){ Stringescaped=mvcCtx.Stringescaped=mvcCtx.getEncoders()getEncoders().html(input);.html(input); ...... }} @Inject@Inject privateMvcContextmvcCtx;privateMvcContextmvcCtx; @POST@POST publicvoidpostForm(@FormParam(input)Stringinput){publicvoidpostForm(@FormParam(input)Stringinput){ Stringescaped=mvcCtx.Stringescaped=mvcCtx.getEncoders()getEncoders().html(input);.html(input); ...... }}
  • 18. Events CDI events fired by implementations, observable by applications Synchronous! Around a call to a controller: BeforeControllerEvent, AfterControllerEvent When a controller returns a redirect (HTTP 3xx) status: ControllerRedirectEvent Around the processView call to the view engine: BeforeProcessViewEvent, AfterProcessViewEvent
  • 19. Current status Released: MVC spec: Early Draft Review 2 Ozark RI: Milestone 2 Planning: Spec: Public Review Q1 2016 (!) (currently only 1 of 11 issues has been resolved!) Proposed Final Draft Q3 2016 Final Release H1 2017 Ozark: Milestone 3 June 30, 2016 (but: currently only 16 of 25 issues have been resolved)
  • 20. References JSR 371: Model-View-Controller (MVC 1.0) Specification https://jcp.org/en/jsr/detail?id=371 Ozark Reference implementation for MVC 1.0 https://ozark.java.net/ Why another MVC? By Ed Burns http://www.oracle.com/technetwork/articles/java/mvc-2280472.html MVC 1.0 Users Mailing list https://java.net/projects/mvc-spec/lists/users/archive
  • 21. Thank you! Maurice de Chateau maurice@jpoint.nl @mauricedchateau