BAEL-3091: The Prototype Pattern in Java (changed code based on valid comments from a reader)

This commit is contained in:
Vivek Balasubramaniam
2019-10-29 22:27:15 +05:30
parent db85c8f275
commit d3d5b060e7
20517 changed files with 1642290 additions and 0 deletions
@@ -0,0 +1,11 @@
package com.baeldung.thymeleaf;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@@ -0,0 +1,23 @@
package com.baeldung.thymeleaf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
@Configuration
public class ThymeleafConfig {
@Bean
public ClassLoaderTemplateResolver secondaryTemplateResolver() {
ClassLoaderTemplateResolver secondaryTemplateResolver = new ClassLoaderTemplateResolver();
secondaryTemplateResolver.setPrefix("templates-2/");
secondaryTemplateResolver.setSuffix(".html");
secondaryTemplateResolver.setTemplateMode(TemplateMode.HTML);
secondaryTemplateResolver.setCharacterEncoding("UTF-8");
secondaryTemplateResolver.setOrder(1);
secondaryTemplateResolver.setCheckExistence(true);
return secondaryTemplateResolver;
}
}
@@ -0,0 +1,28 @@
package com.baeldung.thymeleaf.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
import static java.util.Arrays.asList;
@Controller
public class ParticipantController {
@RequestMapping("/participants")
public String index(
@RequestParam(value = "participant", required = false) String participant,
@RequestParam(value = "country", required = false) String country,
@RequestParam(value = "action", required = false) String action,
@RequestParam(value = "id", required = false) Integer id,
Model model
) {
model.addAttribute("id", id);
List<Integer> userIds = asList(1,2,3,4);
model.addAttribute("userIds", userIds);
return "participants";
}
}
@@ -0,0 +1,22 @@
package com.baeldung.thymeleaf.enums;
public enum Color {
BLACK("Black"),
BLUE("Blue"),
RED("Red"),
YELLOW("Yellow"),
GREEN("Green"),
ORANGE("Orange"),
PURPLE("Purple"),
WHITE("White");
private final String displayValue;
private Color(String displayValue) {
this.displayValue = displayValue;
}
public String getDisplayValue() {
return displayValue;
}
}
@@ -0,0 +1,27 @@
package com.baeldung.thymeleaf.enums;
public class Widget {
private String name;
private Color color;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
@Override
public String toString() {
return "Widget [name=" + name + ", color=" + color + "]";
}
}
@@ -0,0 +1,23 @@
package com.baeldung.thymeleaf.enums;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.ui.Model;
@Controller
public class WidgetController {
@GetMapping("/widget/add")
public String addWidget(@ModelAttribute Widget widget) {
return "enums/new";
}
@PostMapping("/widget/add")
public String saveWidget(@Valid Widget widget, Model model) {
model.addAttribute("widget", widget);
return "enums/view";
}
}
@@ -0,0 +1,64 @@
package com.baeldung.thymeleaf.lists;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/lists")
public class ListsController {
@GetMapping("/toList")
public String usingToList(Model model) {
List<String> colors = getColors();
String[] colorsArray = colors.toArray(new String[0]);
model.addAttribute("myArray", colorsArray);
return "lists/toList";
}
@GetMapping("/contains")
public String usingContains(Model model) {
model.addAttribute("myList", getColors());
model.addAttribute("others", getOtherColors());
return "lists/contains";
}
@GetMapping("/size")
public String usingSize(Model model) {
model.addAttribute("myList", getColors());
return "lists/size";
}
@GetMapping("/isEmpty")
public String usingIsEmpty(Model model) {
model.addAttribute("myList", getColors());
return "lists/isEmpty";
}
@GetMapping("/sort")
public String usingSort(Model model) {
model.addAttribute("myList", getColors());
model.addAttribute("reverse", Comparator.reverseOrder());
return "lists/sort";
}
private List<String> getColors() {
List<String> colors = new ArrayList<>();
colors.add("green");
colors.add("yellow");
colors.add("red");
colors.add("blue");
return colors;
}
private List<String> getOtherColors() {
List<String> colors = new ArrayList<>();
colors.add("green");
colors.add("blue");
return colors;
}
}
@@ -0,0 +1,28 @@
package com.baeldung.thymeleaf.pathvariables;
public class Detail {
private int id;
private String description;
public Detail(int id, String description) {
super();
this.id = id;
this.description = description;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
@@ -0,0 +1,39 @@
package com.baeldung.thymeleaf.pathvariables;
import java.util.List;
public class Item {
private int id;
private String name;
private List<Detail> details;
public Item(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Detail> getDetails() {
return details;
}
public void setDetails(List<Detail> details) {
this.details = details;
}
}
@@ -0,0 +1,62 @@
package com.baeldung.thymeleaf.pathvariables;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@Controller
public class PathVariablesController {
private List<Item> items = new ArrayList<Item>();
public PathVariablesController() {
Item item1 = new Item(1, "First Item");
List<Detail> item1Details = new ArrayList<>();
item1Details.add(new Detail(1, "Green"));
item1Details.add(new Detail(2, "Large"));
item1.setDetails(item1Details);
items.add(item1);
Item item2 = new Item(2, "Second Item");
List<Detail> item2Details = new ArrayList<>();
item2Details.add(new Detail(1, "Red"));
item2Details.add(new Detail(2, "Medium"));
item2.setDetails(item2Details);
items.add(item2);
}
@GetMapping("/pathvars")
public String start(Model model) {
model.addAttribute("items", items);
return "pathvariables/index";
}
@GetMapping("/pathvars/single/{id}")
public String singlePathVariable(@PathVariable("id") int id, Model model) {
if (id == 1) {
model.addAttribute("item", new Item(1, "First Item"));
} else {
model.addAttribute("item", new Item(2, "Second Item"));
}
return "pathvariables/view";
}
@GetMapping("/pathvars/item/{itemId}/detail/{detailId}")
public String multiplePathVariable(@PathVariable("itemId") int itemId, @PathVariable("detailId") int detailId, Model model) {
for (Item item : items) {
if (item.getId() == itemId) {
model.addAttribute("item", item);
for (Detail detail : item.getDetails()) {
if (detail.getId() == detailId) {
model.addAttribute("detail", detail);
}
}
}
}
return "pathvariables/view";
}
}
@@ -0,0 +1,13 @@
package com.baeldung.thymeleaf.templatedir;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
@GetMapping("/hello")
public String sayHello() {
return "hello";
}
}
@@ -0,0 +1 @@
#spring.thymeleaf.prefix=classpath:/templates-2/
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Enums in Thymeleaf</title>
</head>
<body>
<h2>Hello from 'templates/templates-2'</h2>
</body>
</html>
@@ -0,0 +1,32 @@
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<h2>Enter participant</h2>
<form th:action="@{/participants}">
<input type="text" th:name="participant"/>
<select name="country">
<option value="de">Germany</option>
<option value="nl">Netherlands</option>
<option value="pl">Poland</option>
<option value="lv">Latvia</option>
</select>
<button type="submit" th:name="action" th:value="in">check-in</button>
<button type="submit" th:name="action" th:value="out">check-out</button>
</form>
<th:block th:if="${id != null}">
<h2 >User Details</h2>
<p>Details for user [[${id}]] ...</p>
</th:block>
<h2>Users</h2>
<th:block th:each="userId: ${userIds}">
<p>
<a th:href="@{/participants(id=${userId})}"> User [[${userId}]]</a>
</p>
</th:block>
</html>
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Enums in Thymeleaf</title>
</head>
<body>
<form th:action="@{/widget/add}" method="post" th:object="${widget}">
<h3>Add New Widget</h3>
<label for="name">Name: </label>
<input type="text" name="name"/>
<label for="color">Color: </label>
<select name="color">
<option th:each="colorOpt : ${T(com.baeldung.thymeleaf.enums.Color).values()}" th:value="${colorOpt}" th:text="${colorOpt.displayValue}"></option>
</select>
<input type="submit" value="Submit" />
</form>
</body>
</html>
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Enums in Thymeleaf</title>
</head>
<body>
<h3>View Widget</h3>
<div>
<label for="name">Name: </label>
<span th:text="${widget.name}"></span>
</div>
<div>
<label for="color">Color: </label>
<span th:text="${widget.color.displayValue}"></span>
</div>
<div th:if="${widget.color == T(com.baeldung.thymeleaf.enums.Color).RED}">
This color screams danger.
</div>
<div th:if="${widget.color.name() == 'GREEN'}">
Green is for go.
</div>
<div th:switch="${widget.color}">
<span th:case="${T(com.baeldung.thymeleaf.enums.Color).RED}" style="color: red;">Alert</span>
<span th:case="${T(com.baeldung.thymeleaf.enums.Color).ORANGE}" style="color: orange;">Warning</span>
<span th:case="${T(com.baeldung.thymeleaf.enums.Color).YELLOW}" style="color: yellow;">Caution</span>
<span th:case="${T(com.baeldung.thymeleaf.enums.Color).GREEN}" style="color: green;">All Good</span>
</div>
</body>
</html>
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Lists Utility Class in Thymeleaf</title>
</head>
<body>
myList contains red: <span th:text="${#lists.contains(myList, 'red')}"/>
myList contains red and green: <span th:text='${#lists.containsAll(myList, {"red", "green"})}'/>
</body>
</html>
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Lists Utility Class in Thymeleaf</title>
</head>
<body>
isEmpty Check : <span th:text="${#lists.isEmpty(myList)}"/>
<span th:unless="${#lists.isEmpty(myList)}">List is not empty</span>
</body>
</html>
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Lists Utility Class in Thymeleaf</title>
</head>
<body>
size: <span th:text="${#lists.size(myList)}"/>
</body>
</html>
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Lists Utility Class in Thymeleaf</title>
</head>
<body>
sort: <span th:text="${#lists.sort(myList)}"/>
sort with Comparator: <span th:text="${#lists.sort(myList, reverse)}"/>
</body>
</html>
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Lists Utility Class in Thymeleaf</title>
</head>
<body>
<span th:with="convertedList=${#lists.toList(myArray)}">
converted list size: <span th:text="${#lists.size(convertedList)}"/>
</span>
</body>
</html>
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>PathVariables in Thymeleaf</title>
</head>
<body>
<h3>Items</h3>
<div th:each="item : ${items}">
<a th:href="@{/pathvars/single/{id}(id = ${item.id})}">
<span th:text="${item.name}"></span>
</a>
<ul>
<li th:each="detail : ${item.details}">
<a th:href="@{/pathvars/item/{itemId}/detail/{detailId}(itemId = ${item.id}, detailId = ${detail.id})}">
<span th:text="${detail.description}"></span>
</a>
</li>
</ul>
</div>
</body>
</html>
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Pathvariables in Thymeleaf</title>
</head>
<body>
<h3>View Item</h3>
<div>
<label for="name">Name: </label>
<span th:text="${item.name}"></span>
</div>
<h4 th:if="${detail}">Detail</h4>
<div th:if="${detail}">
<label for="description">Description: </label>
<span th:text="${detail.description}"></span>
</div>
</body>
</html>
@@ -0,0 +1,60 @@
package com.baeldung.thymeleaf.lists;
import static org.hamcrest.CoreMatchers.containsString;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc(printOnlyOnFailure = false)
public class ListsControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void whenCalledToList_ThenConvertsToList() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/lists/toList"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("converted list size: <span>4</span>")));
}
@Test
public void whenCalledContains_ThenChecksMembership() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/lists/contains"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("myList contains red: <span>true</span>")))
.andExpect(content().string(containsString("myList contains red and green: <span>true</span>")));
}
@Test
public void whenCalledSize_ThenReturnsSize() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/lists/size"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("size: <span>4</span>")));
}
@Test
public void whenCalledSort_ThenSortsItems() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/lists/sort"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("sort: <span>[blue, green, red, yellow]</span>")))
.andExpect(content().string(containsString("sort with Comparator: <span>[yellow, red, green, blue]</span>")));
}
@Test
public void whenCalledIsEmpty_ThenChecksAnyMembers() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/lists/isEmpty"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("isEmpty Check : <span>false</span>")));
}
}