Spring MVC An intro to Spring MVC with




































- Slides: 36

Spring MVC An intro to Spring MVC with template engine

A spring application • Controllers • • • Handle the logic Receive HTTP requests Manipulate data/objects and store them (session, cookies, database…) Inject data into a view Returns the view (response) • Views • Html pages • Augmented html: special tags to insert dynamic content (the data injected from the controllers) • Model • The objects used to pass data to the view • Q: similarity with Node. js?

Request / response thymeleaf

Controllers • In Spring’s approach to building web sites, HTTP requests are handled by a controller. You can easily identify these requests by the @Controller annotation package hello; import org. springframework. stereotype. Controller; import org. springframework. ui. Model; import org. springframework. web. bind. annotation. Get. Mapping; import org. springframework. web. bind. annotation. Request. Param; @Controller public class Greeting. Controller { @Get. Mapping("/greeting") public String greeting(@Request. Param(name="name", required=false, default. Value="World") String name, Model model) { model. add. Attribute(”username", name); return "greeting"; } }

Controllers and views • The @Get. Mapping annotation ensures that HTTP GET requests to /greeting are mapped to the greeting() method. • Also @Post. Mapping for POST requests • Equivalent to @Request. Mapping(method = Request. Method. POST) • @Get. Mapping: shortcut for @Request. Mapping(method = Request. Method. GET) • @Request. Param binds the value of the query String parameter name into the name parameter of the greeting() method. • This query String parameter is not required; if it is absent in the request, the default. Value of "World" is used. • The value of the ”name” parameter is added to a Model object, ultimately making it accessible to the view template.

Controller types • Controller may return a view • Response is HTML • Controller may return JSON • Response is intended for Javascript/Ajax client • Controller may forward the request to another controller • URL remains the URL of first controller, forward happens server side • Controller may redirect to another controller • Forward request sent to the browser, Twice as much traffic • Solves the “double submission” problem • Avoiding inflation of URLs: • Some controllers do the logic, then redirect to • controller that return views (and client populates the views with Ajax call) • No data can be passed directly so it is based on states! (session, cookies, application scopes, database)

Views • The implementation of the method body relies on a view technology, that can be • JSP • Thymeleaf • Other… • in this case Thymeleaf, to perform server-side rendering of the HTML. • Thymeleaf is a template engine: • parses the greeting. html template below and evaluates the th: text expression to render the value of the ”username” parameter that was set in the controller. <!DOCTYPE HTML> <html xmlns: th="http: //www. thymeleaf. org"> <head> <title>Getting Started: Serving Web Content</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <p th: text="'Hello, ' + ${username} + '!'" /> </body> </html>

Model • the model can supply attributes used for rendering views • To provide a view with usable data, we simply add this data to its Model object. Additionally, maps with attributes can be merged with Model instances: @Get. Mapping("/show. View. Page") public String pass. Parameters. With. Model(Model model) { Map<String, String> map = new Hash. Map<>(); map. put("spring", "mvc"); model. add. Attribute("message", ”hello"); // simple attribute model. merge. Attributes(map); // map attribute return "view. Page"; }

Model. Map • pass a collection of values and treat these values as if they were within a Map @Get. Mapping("/print. View. Page") public String pass. Parameters. With. Model. Map(Model. Map map) { map. add. Attribute("welcome. Message", "welcome"); map. add. Attribute("message", ”hello"); return "view. Page"; }

Model. And. View • The final interface to pass values to a view @Get. Mapping("/go. To. View. Page") public Model. And. View pass. Parameters. With. Model. And. View() { Model. And. View model. And. View = new Model. And. View("view. Page"); model. And. View. add. Object("message", ”hello"); return model. And. View; }

Other params • A controller method can accept various parameters such as: Session Request Model: hold data for the view Binding. Result: holds the result of a validation and binding and contains errors that may have occurred. • Any type with @Path, @Request. Param • •

Static files • HTML, CSS and JS are static files that need to be served as well from within the views (linked files) • By default Spring Boot serves static content from resources in the classpath at "/static" (or "/public"). • The index. html resource is special because it is used as a "welcome page" if it exists, which means it will be served up as the root resource, i. e. at http: //localhost: 8080/

Make the application executable package hello; import org. springframework. boot. Spring. Application; import org. springframework. boot. autoconfigure. Spring. Boot. Application; @Spring. Boot. Application public class Application { public static void main(String[] args) { Spring. Application. run(Application. class, args); } }

The application annotations • @Spring. Boot. Application is a convenience annotation that adds all of the following: • @Configuration tags the class as a source of bean definitions for the application context. • @Enable. Auto. Configuration tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings. • Normally you would add @Enable. Web. Mvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a Dispatcher. Servlet. • @Component. Scan tells Spring to look for other components, configurations, and services in the hello package, allowing it to find the controllers. • The main() method uses Spring Boot’s Spring. Application. run() method to launch an application. • No web. xml file! This web application is 100% pure Java and you dont’t have to deal with configuring any plumbing or infrastructure.

thymeleaf • Thymeleaf is a Java template engine for processing and creating HTML, XML, Java. Script, CSS, and text. • Automatically configured in Spring. Boot projects under Intelli. J • Can display property values • Define a bean: @Bean @Description("Spring Message Resolver") public Resource. Bundle. Message. Source message. Source() { Resource. Bundle. Message. Source message. Source = new Resource. Bundle. Message. Source(); message. Source. set. Basename("messages"); return message. Source; } • Then use in view: <span th: text="#{welcome. message}" />

thymeleaf : Display model attributes • Use the tag: th: text=”${attributename}” model. add. Attribute("server. Time", date. Format. format(new Date())); Current time is <span th: text="${server. Time}" />

thymeleaf : Conditions • th: if=”${condition}” • is used to display a section of the view if the condition is met. • th: unless=”${condition}” • is used to display a section of the view if the condition is not met. public class Student implements Serializable { private Integer id; Model: private String name; private Character gender; <td> // standard getters and setters <span th: if="${student. gender} == 'M'" th: text="Male" /> } <span th: unless="${student. gender} == 'M'" th: text="Female" /> View: </td>

thymeleaf : Collections • Assume the model is a collection: • The controller adds: public class Student implements Serializable { private Integer id; private String name; // standard getters and setters } List<Student> students = new Array. List<Student>(); // logic to build student data model. add. Attribute("students", students); • We can iterate in the view with: <tbody> <tr th: each="student: ${students}"> <td th: text="${student. id}" /> <td th: text="${student. name}" /> </tr> </tbody>

Examples • Available on course website

More on thymeleaf • Handling user input • displaying Validation Errors • Formatter (converting and displaying) • Readings: • https: //www. thymeleaf. org/doc/articles/springmvcaccessdata. html • https: //www. baeldung. com/thymeleaf-in-spring-mvc

More on annotations • @Component • Spring Component annotation is used to denote a class as Component. It means that it will autodetect these classes for dependency injection when annotation-based configuration and classpath scanning is used. • A simple component is called a Bean (beans are registered in the application context). It has members and getters/setters. • @Service and @Repository are special cases of @Component. • @Service • Beans that hold business logic • @Repository • Database operations

Stateful services • We learned previously that we can store data (for example in Application context, sessions) • Objects to store application data are called “beans” • In spring you have 6 types of scopes • for example to store in application context you use the @Bean annotation and Annotation. Config. Web. Application. Context. get. Bean(”myvariable") • However this may lead to stateful applications: • States are stored on server • Why are stateful services not recommended? • What can we do to avoid stateful services? • Web Browser (has state) <-> Web Server (stateless) <-> Database (has state)

What is a Bean? • A bean is an object that is instantiated, assembled, and managed by a Spring Io. C (inversion of control) container. This is also called “wiring”. • beans are created with the configuration metadata that you supply to the container, using annotations. • You can control not only the various dependencies and configuration values that are to be plugged into an object that is created from a particular bean definition, but also the scope of the objects created from a particular bean definition. • Any class can serve for Beans creation, usually beans contain mostly getter/setters

Beans scopes / @Scope(”…”) • Singleton: • the container creates a single instance of that bean per Application. Context, and all requests for that bean name will return the same object. Not thread safe! • Prototype: • a different instance every time it is requested from the container. • Request • Session • Application (known as Servlet. Context) @Bean @Scope("singleton") public Person person. Singleton() { return new Person(); } • What’s the difference with Singleton? application scoped bean is singleton per Servlet. Context, whereas singleton scoped bean is singleton per Application. Context. There can be multiple application contexts for a single application. • Websocket Note that singleton and application scopes may require you to write thread safe code! (synzhronized sections) Reference: • https: //howtodoinjava. com/spring 5/core/spring-bean-scopes-tutorial/

Example: session bean • The bean // create the bean @Bean @Scope("session") public Todo. List todos() { return new Todo. List(); } • Todo. List is configured as a session-scoped bean • Need to add a param because Bean is created by target class (session scope exists only in controller) @Scope(value = "session", proxy. Mode = Scoped. Proxy. Mode. TARGET_CLASS) • Use it in the controller: • full example: @Controller @Request. Mapping("/mytodos") public class Todo. Controller { @Resource(name = "todos") private Todo. List todos; //. . . } • https: //www. journaldev. com/21039/spring-bean-scopes

Spring sessions • By default Apache Tomcat stores HTTP session objects in memory. • However you can choose among the following implementations: • Spring Session Core - provides core Spring Session functionalities and APIs • Spring Session Data Redis - provides Session. Repository and Reactive. Session. Repository implementation backed by Redis and configuration support • Spring Session JDBC - provides Session. Repository implementation backed by a relational database and configuration support (example on moodle) • Spring Session Hazelcast - provides Session. Repository implementation backed by Hazelcast and configuration support

Typical application (maven based) • ”pom. xml” contains package dependencies (Maven is a build and dependency management tool/ There are other tools available like Gradle) • ”java” is the source code • • “resources” contains html pages • • We usually separate classes into packages: controllers, db stuff, utils etc. . Templates: views of the template engine Application. properties is a config file • • You can put anything you want Spring use it for various packages, for example to define the jdbc url and credentials

Interceptors (previously filters) • Interceptors handle requests before controllers • interceptors handle responses before views • Useful for logging, multilingual apps, etc… • Example available on course website @Configuration public class My. Config implements Web. Mvc. Configurer { @Override public void add. Interceptors(Interceptor. Registry registry){ registry. add. Interceptor(new Logging. Interceptor()). add. Path. Patterns("/*"); }

Listeners (same as before) • Attach handlers to events • you define classes that extend Http. Session. Listener, Servlet. Context. Listener etc… • Then Register the listener classes in your application configuration class • Recent version of Spring simplified with @Event. Listener • Type of listener is defined by the type of param @Event. Listener public void my. Handler(Context. Started. Event ctx. Start. Evt) { System. out. println("Context Start Event received. " + ctx. Start. Evt. to. String()); } • Can also specify the type as: @Event. Listener({ Context. Started. Event. class, Application. Ready. Event. class})

Other libraries • There are many more libraries that extend Spring • For example Lombok is a popular library to inject constructors and lots of boilerplate code • See also logging with Log 4 j 2

References • https: //spring. io/guides • https: //docs. spring. io/spring/docs/current/spring-frameworkreference/index. html • https: //howtodoinjava. com/spring-5 -tutorial/ • REST: https: //www. baeldung. com/rest-with-spring-series

Non related topics • Time to get more into Java… • Do you follow the naming conventions? Essential with Spring! (that generates code by reflection – looking at your method and class names) • Do you document your classes (@param, @return, @exception)? • Do you avoid writing static classes and methods unless there is a reason? • Do you use common design patterns? • And now, here are some topics worth learning…

Java recent features • There a number of features worth knowing in Java • Lambda functions • The compiler infers the types of the parameters if you do not specify the parameter types in a lambda function definition. When you specify the type of parameters, you need to either specify all or none, or else you will get a compiler error. • You can omit the parenthesis if there is only one parameter. But in this case, you cannot provide the type explicitly. You should leave it to the compiler to infer the type of that single parameter. • The return type of the lambda function is inferred from the body. If any of the code in the lambda returns a value, then all the paths should return a value, or else you will get a compiler error. interface Lambda. Function { void call(); } class First. Lambda { public static void main(String []args) { Lambda. Function lambda. Function = () -> System. out. println("Hello world"); lambda. Function. call(); } }

Java recent features • the double colon operator (“: : ”) used for method references • used to call a method by referring to it with the help of its class directly // Java code to print the elements of Stream // using double colon operator import java. util. stream. *; class GFG { public static void main(String[] args) { // Get the stream Stream<String> stream = Stream. of("Geeks", "For", "Geeks", "A", "Computer", "Portal"); // Print the stream // using double colon operator stream. for. Each(System. out: : println); } }

Java recent features • Assertions: the Java assert keyword allows developers to quickly verify certain assumptions or state of a program. • Instead of Connection conn = get. Connection(); if(conn == null) { throw new Runtime. Exception("Connection is null"); } • You write public void setup() { Connection conn = get. Connection(); assert conn != null; }

Java recent features • The Optional library: provide a type-level solution for representing optional values instead of null references. • Readings: • https: //www. oracle. com/technetwork/articles/java 8 -optional 2175753. html • https: //www. baeldung. com/java-optional