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

  • JSR 373 - Java EE Management API 1.0
  • JSR 374 - Java API for JSON Processing 1.1
  • JSR 375 - Java EE Security API 1.0
  • JSR 371 - Model-View-Controller 1.0
  • JSR 369 - Java Servlet 4.0

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,425