Merge branch 'eugenp:master' into master

This commit is contained in:
Kingsley✨ 2023-04-24 05:25:30 +00:00 committed by GitHub
commit f22e99f4a7
24 changed files with 605 additions and 31 deletions

View File

@ -3,9 +3,9 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>lambda</artifactId> <artifactId>lambda-function</artifactId>
<version>0.1.0-SNAPSHOT</version> <version>0.1.0-SNAPSHOT</version>
<name>lambda</name> <name>lambda-function</name>
<packaging>jar</packaging> <packaging>jar</packaging>
<parent> <parent>

View File

@ -0,0 +1,83 @@
package com.baeldung.regex.aftermatch;
import org.junit.jupiter.api.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class GetTextAfterTheRegexMatchUnitTest {
private static final String INPUT1 = "Some text, targetValue=Regex is cool";
private static final String INPUT2 = "Some text. targetValue=Java is cool. some other text";
@Test
void whenUsingSplit_thenGetExpectedString() {
String result1 = INPUT1.split("targetValue=")[1];
assertEquals("Regex is cool", result1);
String afterFirstSplit = INPUT2.split("targetValue=")[1];
assertEquals("Java is cool. some other text", afterFirstSplit);
String result2 = afterFirstSplit.split("[.]")[0];
assertEquals("Java is cool", result2);
// if use the dot as the regex for splitting, the result array is empty
String[] splitByDot = INPUT2.split("targetValue=")[1].split(".");
assertEquals(0, splitByDot.length);
}
@Test
void whenUsingReplaceAll_thenGetExpectedString() {
String result1 = INPUT1.replaceAll(".*targetValue=", "");
assertEquals("Regex is cool", result1);
String afterFirstReplace = INPUT2.replaceAll(".*targetValue=", "");
assertEquals("Java is cool. some other text", afterFirstReplace);
String result2 = afterFirstReplace.replaceAll("[.].*", "");
assertEquals("Java is cool", result2);
}
@Test
void whenUsingRegexGrouping_thenGetExpectedString() {
Pattern p1 = Pattern.compile("targetValue=(.*)");
Matcher m1 = p1.matcher(INPUT1);
assertTrue(m1.find());
String result1 = m1.group(1);
assertEquals("Regex is cool", result1);
Pattern p2 = Pattern.compile("targetValue=([^.]*)");
Matcher m2 = p2.matcher(INPUT2);
assertTrue(m2.find());
String result2 = m2.group(1);
assertEquals("Java is cool", result2);
Pattern p3 = Pattern.compile("targetValue=(.*?)[.]");
Matcher m3 = p3.matcher(INPUT2);
assertTrue(m3.find());
String result3 = m3.group(1);
assertEquals("Java is cool", result3);
}
@Test
void whenUsingLookaround_thenGetExpectedString() {
Pattern p1 = Pattern.compile("(?<=targetValue=).*");
Matcher m1 = p1.matcher(INPUT1);
assertTrue(m1.find());
String result1 = m1.group();
assertEquals("Regex is cool", result1);
Pattern p2 = Pattern.compile("(?<=targetValue=)[^.]*");
Matcher m2 = p2.matcher(INPUT2);
assertTrue(m2.find());
String result2 = m2.group();
assertEquals("Java is cool", result2);
Pattern p3 = Pattern.compile("(?<=targetValue=).*(?=[.])");
Matcher m3 = p3.matcher(INPUT2);
assertTrue(m3.find());
String result3 = m3.group();
assertEquals("Java is cool", result3);
}
}

View File

@ -39,8 +39,8 @@
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version> <version>${maven-compiler-plugin.version}</version>
<configuration> <configuration>
<source>${java.version}</source> <source>${maven.compiler.source}</source>
<target>${java.version}</target> <target>${maven.compiler.target}</target>
<compilerArgument>-parameters</compilerArgument> <compilerArgument>-parameters</compilerArgument>
</configuration> </configuration>
</plugin> </plugin>

View File

@ -0,0 +1,58 @@
package com.baeldung.charfreq;
import static java.util.Map.Entry.comparingByValue;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class CharacterWithHighestFrequency {
public static Character byStream(String input) {
return input.chars()
.mapToObj(x -> (char) x)
.collect(groupingBy(x -> x, counting()))
.entrySet()
.stream()
.max(comparingByValue())
.get()
.getKey();
}
public static Set<Character> byMap(String input) {
Map<Character, Integer> map = new HashMap<>();
for (char c : input.toCharArray()) {
map.compute(c, (character, count) -> count == null ? 1 : ++count);
}
int maxCount = map.values()
.stream()
.mapToInt(Integer::intValue)
.max()
.getAsInt();
return map.keySet()
.stream()
.filter(c -> map.get(c) == maxCount)
.collect(toSet());
}
public static Set<Character> byBucket(String input) {
int[] buckets = new int[128];
int maxCount = 0;
for (char c : input.toCharArray()) {
buckets[c]++;
maxCount = Math.max(buckets[c], maxCount);
}
int finalMaxCount = maxCount;
return IntStream.range(0, 128)
.filter(c -> buckets[c] == finalMaxCount)
.mapToObj(i -> (char) i)
.collect(Collectors.toSet());
}
}

View File

@ -0,0 +1,43 @@
package com.baeldung.charfreq;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Collections;
import java.util.Set;
import org.junit.jupiter.api.Test;
import com.google.common.collect.ImmutableSet;
class CharacterWithHighestFrequencyUnitTest {
private static final String INPUT1 = "aaaaaaaaaa(10) bbbbbbb ccccc dddd eee ff";
private static final Set<Character> EXPECTED1 = Collections.singleton('a');
private static final String INPUT2 = "YYYYYYY(7) bbbbb -------(7) dddd eee kkkkkkk(7) ff";
private static final Set<Character> EXPECTED2 = ImmutableSet.of('Y', '-', 'k');
@Test
void whenGettingSingleCharWithHighestFrequencyByStream_shouldSuccess() {
char result1 = CharacterWithHighestFrequency.byStream(INPUT1);
assertEquals('a', result1);
}
@Test
void whenGettingCharWithHighestFrequencyByMap_shouldSuccess() {
Set<Character> result1 = CharacterWithHighestFrequency.byMap(INPUT1);
assertEquals(EXPECTED1, result1);
Set<Character> result2 = CharacterWithHighestFrequency.byMap(INPUT2);
assertEquals(EXPECTED2, result2);
}
@Test
void whenGettingCharWithHighestFrequencyByBucket_shouldSuccess() {
Set<Character> result1 = CharacterWithHighestFrequency.byBucket(INPUT1);
assertEquals(EXPECTED1, result1);
Set<Character> result2 = CharacterWithHighestFrequency.byBucket(INPUT2);
assertEquals(EXPECTED2, result2);
}
}

View File

@ -0,0 +1,72 @@
package com.baeldung.libraries.h2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
@SpringBootApplication
public class H2InitDemoApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(H2InitDemoApplication.class, args);
initDatabaseUsingPlainJDBCWithURL();
initDatabaseUsingPlainJDBCWithFile();
initDatabaseUsingSpring(ctx.getBean(DataSource.class));
}
/**
* Initialize in-memory database using plain JDBC and SQL
* statements in the URL.
*/
private static void initDatabaseUsingPlainJDBCWithURL() {
try (Connection conn = DriverManager.
getConnection("jdbc:h2:mem:baeldung;INIT=CREATE SCHEMA IF NOT EXISTS baeldung\\;SET SCHEMA baeldung;",
"admin",
"password")) {
conn.createStatement().execute("create table users (name VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL);");
System.out.println("Created table users");
conn.createStatement().execute("insert into users (name, email) values ('Mike', 'mike@baeldung.com')");
System.out.println("Added user mike");
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* Initialize in-memory database using plain JDBC and SQL
* statements in a file.
*/
private static void initDatabaseUsingPlainJDBCWithFile() {
try (Connection conn = DriverManager.
getConnection("jdbc:h2:mem:baeldung;INIT=RUNSCRIPT FROM 'src/main/resources/h2init.sql';",
"admin",
"password")) {
conn.createStatement().execute("insert into users (name, email) values ('Mike', 'mike@baeldung.com')");
System.out.println("Added user mike");
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* Initialize in-memory database using Spring Boot
* properties. See article for full details of required
* properties for this method to work.
*/
private static void initDatabaseUsingSpring(DataSource ds) {
try (Connection conn = ds.getConnection()) {
conn.createStatement().execute("insert into users (name, email) values ('Mike', 'mike@baeldung.com')");
System.out.println("Added user mike");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,3 @@
CREATE SCHEMA IF NOT EXISTS baeldung;
SET SCHEMA baeldung;
CREATE TABLE users (name VARCHAR(100) NOT NULL, email VARCHAR(100) NOT NULL);

View File

@ -44,19 +44,19 @@
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>
<version>4.6.1</version> <version>${mockito-core.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.activemq.tooling</groupId> <groupId>org.apache.activemq.tooling</groupId>
<artifactId>activemq-junit</artifactId> <artifactId>activemq-junit</artifactId>
<version>5.16.5</version> <version>${activemq-junit.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.testcontainers</groupId> <groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId> <artifactId>testcontainers</artifactId>
<version>1.17.3</version> <version>${testcontainers.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@ -83,6 +83,9 @@
<activemq.version>5.14.1</activemq.version> <activemq.version>5.14.1</activemq.version>
<spring-boot-test.version>1.5.10.RELEASE</spring-boot-test.version> <spring-boot-test.version>1.5.10.RELEASE</spring-boot-test.version>
<maven-war-plugin.version>3.3.2</maven-war-plugin.version> <maven-war-plugin.version>3.3.2</maven-war-plugin.version>
<mockito-core.version>4.6.1</mockito-core.version>
<activemq-junit.version>5.16.5</activemq-junit.version>
<testcontainers.version>1.17.3</testcontainers.version>
</properties> </properties>
</project> </project>

View File

@ -23,15 +23,6 @@
<artifactId>rest-express</artifactId> <artifactId>rest-express</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<properties>
<RestExpress.plugin.version>0.3.3</RestExpress.plugin.version>
<metrics-graphite.version>3.1.2</metrics-graphite.version>
<HyperExpressPlugin.version>2.6</HyperExpressPlugin.version>
<RestExpress.version>0.11.3</RestExpress.version>
<Syntaxe.version>1.0</Syntaxe.version>
<repoexpress-mongodb.version>0.4.8</repoexpress-mongodb.version>
<junit4.version>4.11</junit4.version>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
@ -98,7 +89,7 @@
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId> <artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version> <version>${exec-maven-plugin.version}</version>
<configuration> <configuration>
<mainClass>com.baeldung.restexpress.Main</mainClass> <mainClass>com.baeldung.restexpress.Main</mainClass>
</configuration> </configuration>
@ -106,7 +97,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>2.4.1</version> <version>${maven-shade-plugin.version}</version>
<configuration> <configuration>
<createDependencyReducedPom>false</createDependencyReducedPom> <createDependencyReducedPom>false</createDependencyReducedPom>
<filters> <filters>
@ -140,8 +131,22 @@
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId> <artifactId>versions-maven-plugin</artifactId>
<version>2.0</version> <version>${versions-maven-plugin.version}</version>
</plugin> </plugin>
</plugins> </plugins>
</reporting> </reporting>
<properties>
<RestExpress.plugin.version>0.3.3</RestExpress.plugin.version>
<metrics-graphite.version>3.1.2</metrics-graphite.version>
<HyperExpressPlugin.version>2.6</HyperExpressPlugin.version>
<RestExpress.version>0.11.3</RestExpress.version>
<Syntaxe.version>1.0</Syntaxe.version>
<repoexpress-mongodb.version>0.4.8</repoexpress-mongodb.version>
<junit4.version>4.11</junit4.version>
<exec-maven-plugin.version>1.2.1</exec-maven-plugin.version>
<maven-shade-plugin.version>2.4.1</maven-shade-plugin.version>
<versions-maven-plugin.version>2.0</versions-maven-plugin.version>
</properties>
</project> </project>

View File

@ -42,7 +42,7 @@ public class DetachedEntityUnitTest {
assertThatThrownBy(() -> session.persist(detachedPost)) assertThatThrownBy(() -> session.persist(detachedPost))
.isInstanceOf(PersistenceException.class) .isInstanceOf(PersistenceException.class)
.hasMessageContaining("`org.hibernate.PersistentObjectException` to JPA `PersistenceException` : detached entity passed to persist"); .hasMessageContaining("detached entity passed to persist: com.baeldung.hibernate.exception.detachedentity.entity.Post");
} }
@Test @Test
@ -71,13 +71,13 @@ public class DetachedEntityUnitTest {
assertThatThrownBy(() -> session.persist(detachedPost)) assertThatThrownBy(() -> session.persist(detachedPost))
.isInstanceOf(PersistenceException.class) .isInstanceOf(PersistenceException.class)
.hasMessageContaining("`org.hibernate.PersistentObjectException` to JPA `PersistenceException` : detached entity passed to persist"); .hasMessageContaining("detached entity passed to persist: com.baeldung.hibernate.exception.detachedentity.entity.Post");
} }
@Test @Test
public void givenDetachedPost_whenMergeAndPersistComment_thenNoExceptionIsThrown() { public void givenDetachedPost_whenMergeAndPersistComment_thenNoExceptionIsThrown() {
Comment comment = new Comment("nice article!"); Comment comment = new Comment("nice article!");
Post mergedPost = (Post) session.merge(detachedPost); Post mergedPost = session.merge(detachedPost);
comment.setPost(mergedPost); comment.setPost(mergedPost);
session.persist(comment); session.persist(comment);

View File

@ -136,9 +136,6 @@ public class GetReferenceH2IntegrationTest {
}); });
StringBuilder expected = new StringBuilder(); StringBuilder expected = new StringBuilder();
expected.append("Hibernate: select ");
expected.append("p1_0.id,g1_0.id,g1_0.name,p1_0.name ");
expected.append("from Player p1_0 left join Game g1_0 on g1_0.id=p1_0.game_id where p1_0.id=?" + System.lineSeparator());
expected.append("Hibernate: delete from Player where id=?" + System.lineSeparator()); expected.append("Hibernate: delete from Player where id=?" + System.lineSeparator());
assertEquals(expected.toString(), output.toString()); assertEquals(expected.toString(), output.toString());

View File

@ -30,7 +30,7 @@
<module>hibernate-mapping-2</module> <module>hibernate-mapping-2</module>
<!-- <module>hibernate-ogm</module> <!-- <module>hibernate-ogm</module>
<module>hibernate-annotations</module> FAILED --> <module>hibernate-annotations</module> FAILED -->
<!-- <module>hibernate-exceptions</module> FAILED --> <module>hibernate-exceptions</module>
<module>hibernate-libraries</module> <module>hibernate-libraries</module>
<module>hibernate-jpa</module> <module>hibernate-jpa</module>
<!-- <module>hibernate-queries</module> FAILED --> <!-- <module>hibernate-queries</module> FAILED -->

View File

@ -56,10 +56,15 @@
<configuration> <configuration>
<jvmArguments> -agentlib:native-image-agent=config-output-dir=target/native-image <jvmArguments> -agentlib:native-image-agent=config-output-dir=target/native-image
</jvmArguments> </jvmArguments>
<systemPropertyVariables>
<springAot>true</springAot>
</systemPropertyVariables>
</configuration> </configuration>
<executions>
<execution>
<id>process-aot</id>
<goals>
<goal>process-aot</goal>
</goals>
</execution>
</executions>
</plugin> --> </plugin> -->
</plugins> </plugins>
</pluginManagement> </pluginManagement>

View File

@ -11,6 +11,18 @@
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
</parent> </parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-modulith-bom</artifactId>
<version>0.5.1</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -87,6 +99,15 @@
<version>2.34.0</version> <version>2.34.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-modulith-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-modulith-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,21 @@
package com.baeldung.modulith;
import com.baeldung.modulith.product.ProductService;
import com.baeldung.modulith.product.internal.Product;
import org.jobrunr.autoconfigure.JobRunrAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@SpringBootApplication
@EnableAutoConfiguration(exclude = { JobRunrAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args)
.getBean(ProductService.class)
.create(new Product("baeldung", "course", 10));
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.modulith.notification;
import java.util.Date;
public class NotificationDTO {
private Date date;
private String format;
private String productName;
public NotificationDTO(Date date, String format, String productName) {
this.date = date;
this.format = format;
this.productName = productName;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.modulith.notification;
import com.baeldung.modulith.notification.internal.Notification;
import com.baeldung.modulith.notification.internal.NotificationType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.modulith.ApplicationModuleListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class NotificationService {
private static final Logger LOG = LoggerFactory.getLogger(NotificationService.class);
public void createNotification(NotificationDTO notificationDTO) {
Notification notification = toEntity(notificationDTO);
LOG.info("Received notification by module dependency for product {} in date {} by {}.", notification.getProductName()
, notification.getDate(), notification.getFormat());
}
@Async
@ApplicationModuleListener
public void notificationEvent(NotificationDTO event) {
Notification notification = toEntity(event);
LOG.info("Received notification by event for product {} in date {} by {}.", notification.getProductName()
, notification.getDate(), notification.getFormat());
}
private Notification toEntity(NotificationDTO notificationDTO) {
Notification notification = new Notification();
notification.setDate(notificationDTO.getDate());
if (notificationDTO.getFormat().equals("SMS")) {
notification.setFormat(NotificationType.SMS);
}
if (notificationDTO.getFormat().equals("EMAIL")) {
notification.setFormat(NotificationType.EMAIL);
}
notification.setProductName(notificationDTO.getProductName());
return notification;
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.modulith.notification.internal;
import java.util.Date;
public class Notification {
private Date date;
private NotificationType format;
private String productName;
public Notification() {
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public NotificationType getFormat() {
return format;
}
public void setFormat(NotificationType format) {
this.format = format;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.modulith.notification.internal;
public enum NotificationType {
EMAIL, SMS
}

View File

@ -0,0 +1,26 @@
package com.baeldung.modulith.product;
import com.baeldung.modulith.notification.NotificationDTO;
import com.baeldung.modulith.notification.NotificationService;
import com.baeldung.modulith.product.internal.Product;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
public class ProductService {
private final ApplicationEventPublisher events;
private final NotificationService notificationService;
public ProductService(ApplicationEventPublisher events, NotificationService notificationService) {
this.events = events;
this.notificationService = notificationService;
}
public void create(Product product) {
notificationService.createNotification(new NotificationDTO(new Date(), "SMS", product.getName()));
events.publishEvent(new NotificationDTO(new Date(), "SMS", product.getName()));
}
}

View File

@ -0,0 +1,38 @@
package com.baeldung.modulith.product.internal;
public class Product {
private String name;
private String description;
private int price;
public Product(String name, String description, int price) {
this.name = name;
this.description = description;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.modulith;
import org.junit.jupiter.api.Test;
import org.springframework.modulith.core.ApplicationModules;
import org.springframework.modulith.docs.Documenter;
class ApplicationModularityUnitTest {
ApplicationModules modules = ApplicationModules.of(Application.class);
@Test
void verifiesModularStructure() {
modules.verify();
}
@Test
void createModuleDocumentation() {
new Documenter(modules)
.writeDocumentation()
.writeIndividualModulesAsPlantUml();
}
@Test
void createApplicationModuleModel() {
modules.forEach(System.out::println);
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.thymeleaf.attributes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/attributes")
public class AttributeController {
private static final Logger logger = LoggerFactory.getLogger(AttributeController.class);
@GetMapping
public String show(Model model) {
model.addAttribute("title", "Baeldung");
model.addAttribute("email", "default@example.com");
return "attributes/index";
}
@PostMapping
public String submit(String email) {
logger.info("Email: {}", email);
return "redirect:attributes";
}
}

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Difference Between th:text and th:value in Thymeleaf</title>
</head>
<body>
<h1 th:text="${title} ?: 'Default title'"/>
<form th:action="@{/attributes}" method="post">
<label>Email:
<input name="email" type="email" th:value="${email}">
</label>
<input type="submit" value="Submit"/>
</form>
</body>
</html>