import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
+@EnableConfigurationProperties(MultipleBeansProperties.class)
public class MultipleBeansApplication {
+
public static void main(String[] args) {
SpringApplication.run(MultipleBeansApplication.class, args);
}
-
}
--- /dev/null
+package de.juplo.demos.multiplebeans;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MultipleBeansBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
+
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
+
+ MultipleBeansProperties properties = factory.getBean(MultipleBeansProperties.class);
+ BeanDefinitionRegistry registry = (BeanDefinitionRegistry)factory;
+
+ for (MultipleBeansProperties.Site site : properties.site) {
+ BeanDefinition beanDefinition =
+ BeanDefinitionBuilder
+ .genericBeanDefinition(SiteController.class)
+ .addConstructorArgValue(site.name)
+ .addConstructorArgValue(site.description)
+ .getBeanDefinition();
+
+ registry.registerBeanDefinition("name", beanDefinition);
+ }
+ }
+}
--- /dev/null
+package de.juplo.demos.multiplebeans;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@ConfigurationProperties("de.juplo")
+@Getter
+@Setter
+public class MultipleBeansProperties {
+
+ Site[] site;
+
+
+ @Getter
+ @Setter
+ public static class Site {
+
+ String name;
+ String description;
+ }
+}
--- /dev/null
+package de.juplo.demos.multiplebeans;
+
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.mvc.Controller;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class SiteController implements Controller {
+
+ private final String name;
+ private final String description;
+
+
+ public SiteController(String name, String description) {
+
+ this.name = name;
+ this.description = description;
+ }
+
+
+ public ModelAndView handleRequest(
+ HttpServletRequest request,
+ HttpServletResponse response) throws Exception {
+
+ ModelAndView mav = new ModelAndView("site");
+ mav.addObject("name", name);
+ mav.addObject("description", description);
+ return mav;
+ }
+}
--- /dev/null
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layout :: pagelayout(~{:: title}, ~{:: h1}, ~{:: div.card-text})}">
+ <head>
+ <title th:text="'400: ' + ${exception.getClass().getSimpleName()}">Testing Exception-Handling - Template for 400</title>
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ </head>
+ <body>
+ <h1 th:text="'400: ' + ${exception.getClass().getSimpleName()}">Template for 400</h1>
+ <div class="card-text table">
+ <p><strong th:text="'Catched exception: ' + ${exception}">EXCEPTION</strong></p>
+ <p><a href="#" th:href="@{/}" class="btn btn-primary">Back to HOME</a></p>
+ </div>
+ </body>
+</html>
--- /dev/null
+de:
+ juplo:
+ site:
+ - name: peter
+ description: This is the Home-Page of PETER
+ - name: ute
+ description: My name is Ute. I like cats!
+ - name: franz
+ description: Franz was here!
+
--- /dev/null
+<!doctype html>
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layout :: pagelayout(~{:: title}, ~{:: h1}, ~{:: table.card-text})}">
+ <head>
+ <title th:text="|${status}: ${error}">XXX: ERROR</title>
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ </head>
+ <body>
+ <h1 th:text="|${status}: ${error}">XXX: ERROR</h1>
+ <table class="card-text table">
+ <tbody>
+ <tr class="border-top-0">
+ <th scope="row">Status</th>
+ <td th:text="${status}">ERROR.STATUS</td>
+ </tr>
+ <tr>
+ <th scope="row">Error</th>
+ <td th:text="${error}">ERROR.ERROR</td>
+ </tr>
+ <tr th:if="!${#strings.isEmpty(message)}">
+ <th scope="row">Message</th>
+ <td th:text="${message}">ERROR.MESSAGE</td>
+ </tr>
+ <tr th:if="!${#strings.isEmpty(requestId)}">
+ <th class="text-nowrap" scope="row">Request-ID</th>
+ <td th:text="${requestId}">ERROR.REQUEST_ID</td>
+ </tr>
+ <tr>
+ <th scope="row">Timstamp</th>
+ <td th:text="${timestamp}">ERROR.TIMESTAMP</td>
+ </tr>
+ <tr th:if="!${#strings.isEmpty(path)}">
+ <th scope="row">Path</th>
+ <td th:text="${path}">ERROR.PATH</td>
+ </tr>
+ <!--/**-->
+ <tr th:if="!${#strings.isEmpty(trace)}">
+ <th scope="row">Trace</th>
+ <td>
+ <div class="overflow-hidden">
+ <pre class="overflow-hidden" th:text="${trace}">ERROR.TRACE</pre>
+ </div>
+ </td>
+ </tr>
+ <!--**/-->
+ </tbody>
+ </table>
+ <p><a href="#" th:href="@{/}" class="btn btn-primary">Back to HOME</a>
+ </div>
+ </body>
+</html>
--- /dev/null
+<!doctype html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org" th:fragment="pagelayout(title,header,body)">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <title th:replace="${title}">TITLE</title>
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" th:href="@{/webjars/bootstrap/4.5.2/css/bootstrap.min.css}">
+ </head>
+ <body>
+ <nav class="navbar navbar-dark bg-primary navbar-expand navbar-dark flex-column">
+ <h2 class="navbar-brand">Demo: Creating Multiple Beans In Spring-Boot Pogrammatically</h2>
+ </nav>
+ <main class="container mt-5">
+ <div id="content" class="card">
+ <div class="card-header"><h1 th:replace="${header}">HEADER</h1></div>
+ <div class="card-body"><div th:replace="${body}">BODY</div></div>
+ </div>
+ </main>
+ </body>
+</html>
--- /dev/null
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{layout :: pagelayout(~{:: title}, ~{:: h1}, ~{:: div.card-text})}">
+ <head>
+ <title th:text="${name}">SITE-TEMPLATE</title>
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ </head>
+ <body>
+ <h1 th:text="${name}">SITE</h1>
+ <div class="card-text">
+ <p th:text="${description}">DESCRIPTION</p>
+ </div>
+ <div class="card-text">
+ <p>
+ <em>
+ Each site is defined in the configuration with name and description inside an array.
+ This demo shows, how to create multiple beans of the same type based on the configuration.
+ </em>
+ </p>
+ </div>
+ </body>
+</html>