Merge branch 'master' of github.com:eugenp/tutorials into BAEL-3886

This commit is contained in:
ramkumarvenkat 2020-04-02 07:13:29 +05:30
commit faf46dd544
40 changed files with 808 additions and 13 deletions

View File

@ -8,5 +8,4 @@ This module contains articles about Java 9 core features
- [Introduction to Chronicle Queue](https://www.baeldung.com/java-chronicle-queue)
- [Iterate Through a Range of Dates in Java](https://www.baeldung.com/java-iterate-date-range)
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
- [Immutable Set in Java](https://www.baeldung.com/java-immutable-set)
- [Immutable ArrayList in Java](https://www.baeldung.com/java-immutable-list)

View File

@ -11,3 +11,4 @@ This module contains articles about the Java Set collection
- [Guide to EnumSet](https://www.baeldung.com/java-enumset)
- [Set Operations in Java](https://www.baeldung.com/java-set-operations)
- [Copying Sets in Java](https://www.baeldung.com/java-copy-sets)
- [Immutable Set in Java](https://www.baeldung.com/java-immutable-set)

View File

@ -34,7 +34,23 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<commons-collections4.version>4.3</commons-collections4.version>
<gson.version>2.8.5</gson.version>
</properties>

View File

@ -1,4 +1,4 @@
package com.baeldung.java9.set;
package com.baeldung.set;
import com.google.common.collect.ImmutableSet;

View File

@ -1,9 +1,10 @@
package com.baeldung.java9;
package com.baeldung.set;
import org.junit.Test;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

View File

@ -0,0 +1,26 @@
*.class
0.*
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
.resourceCache
# Packaged files #
*.jar
*.war
*.ear
# Files generated by integration tests
*.txt
backup-pom.xml
/bin/
/temp
#IntelliJ specific
.idea/
*.iml

View File

@ -0,0 +1,7 @@
=========
## Core Java Concurrency Testing Examples
### Relevant Articles:
- [Testing Multi-Threaded Code in Java](https://www.baeldung.com/java-testing-multithreaded)

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-concurrency-testing</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-concurrency-testing</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-java</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-java</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.googlecode.thread-weaver</groupId>
<artifactId>threadweaver</artifactId>
<version>0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.tempus-fugit</groupId>
<artifactId>tempus-fugit</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.googlecode.multithreadedtc</groupId>
<artifactId>multithreadedtc</artifactId>
<version>1.01</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jcstress</groupId>
<artifactId>jcstress-core</artifactId>
<version>0.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<compilerVersion>${javac.target}</compilerVersion>
<source>${javac.target}</source>
<target>${javac.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>main</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>jcstress</finalName>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.openjdk.jcstress.Main</mainClass>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/TestList</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,22 @@
package com.baeldung.concurrent;
public class MyCounter {
private int count;
public void increment() {
int temp = count;
count = temp + 1;
}
public synchronized void incrementWithWait() throws InterruptedException {
int temp = count;
wait(100);
count = temp + 1;
}
public int getCount() {
return count;
}
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -0,0 +1,36 @@
package com.baeldung.concurrent;
import static org.openjdk.jcstress.annotations.Expect.ACCEPTABLE;
import static org.openjdk.jcstress.annotations.Expect.ACCEPTABLE_INTERESTING;
import org.openjdk.jcstress.annotations.Actor;
import org.openjdk.jcstress.annotations.Arbiter;
import org.openjdk.jcstress.annotations.JCStressTest;
import org.openjdk.jcstress.annotations.Outcome;
import org.openjdk.jcstress.annotations.State;
import org.openjdk.jcstress.infra.results.I_Result;
@JCStressTest
@Outcome(id = "1", expect = ACCEPTABLE_INTERESTING, desc = "One update lost.")
@Outcome(id = "2", expect = ACCEPTABLE, desc = "Both updates.")
@State
public class MyCounterJCStressUnitTest {
private MyCounter counter;
@Actor
public void actor1() {
counter.increment();
}
@Actor
public void actor2() {
counter.increment();
}
@Arbiter
public void arbiter(I_Result r) {
r.r1 = counter.getCount();
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.concurrent;
import org.junit.Test;
import edu.umd.cs.mtc.MultithreadedTestCase;
import edu.umd.cs.mtc.TestFramework;
public class MyCounterMultithreadedTCUnitTest extends MultithreadedTestCase {
private MyCounter counter;
@Override
public void initialize() {
counter = new MyCounter();
}
public void thread1() throws InterruptedException {
counter.increment();
}
public void thread2() throws InterruptedException {
counter.increment();
}
@SuppressWarnings("deprecation")
@Override
public void finish() {
assertEquals(2, counter.getCount());
}
@Test
public void testCounter() throws Throwable {
TestFramework.runManyTimes(new MyCounterMultithreadedTCUnitTest(), 1000);
}
}

View File

@ -0,0 +1,57 @@
package com.baeldung.concurrent;
import static org.junit.Assert.assertEquals;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
public class MyCounterSimpleUnitTest {
@Test
public void testCounter() {
MyCounter counter = new MyCounter();
for (int i = 0; i < 500; i++)
counter.increment();
assertEquals(500, counter.getCount());
}
// @Test
public void testCounterWithConcurrency() throws InterruptedException {
int numberOfThreads = 100;
ExecutorService service = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
MyCounter counter = new MyCounter();
for (int i = 0; i < numberOfThreads; i++) {
service.execute(() -> {
counter.increment();
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
// @Test
public void testSummationWithConcurrencyAndWait() throws InterruptedException {
int numberOfThreads = 2;
ExecutorService service = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
MyCounter counter = new MyCounter();
for (int i = 0; i < numberOfThreads; i++) {
service.submit(() -> {
try {
counter.incrementWithWait();
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.concurrent;
import static org.junit.Assert.assertEquals;
import org.junit.AfterClass;
import org.junit.Rule;
import org.junit.Test;
import com.google.code.tempusfugit.concurrency.ConcurrentRule;
import com.google.code.tempusfugit.concurrency.RepeatingRule;
import com.google.code.tempusfugit.concurrency.annotations.Concurrent;
import com.google.code.tempusfugit.concurrency.annotations.Repeating;
public class MyCounterTempusFugitUnitTest {
@Rule
public ConcurrentRule concurrently = new ConcurrentRule();
@Rule
public RepeatingRule rule = new RepeatingRule();
private static MyCounter counter = new MyCounter();
@Test
@Concurrent(count = 2)
@Repeating(repetition = 10)
public void runsMultipleTimes() {
counter.increment();
}
@AfterClass
public static void annotatedTestRunsMultipleTimes() throws InterruptedException {
assertEquals(counter.getCount(), 20);
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.concurrent;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.google.testing.threadtester.AnnotatedTestRunner;
import com.google.testing.threadtester.ThreadedAfter;
import com.google.testing.threadtester.ThreadedBefore;
import com.google.testing.threadtester.ThreadedMain;
import com.google.testing.threadtester.ThreadedSecondary;
public class MyCounterThreadWeaverUnitTest {
private MyCounter counter;
@ThreadedBefore
public void before() {
counter = new MyCounter();
}
@ThreadedMain
public void mainThread() {
counter.increment();
}
@ThreadedSecondary
public void secondThread() {
counter.increment();
}
@ThreadedAfter
public void after() {
assertEquals(2, counter.getCount());
}
@Test
public void testCounter() {
new AnnotatedTestRunner().runTests(this.getClass(), MyCounter.class);
}
}

View File

@ -0,0 +1,13 @@
*.class
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
# Packaged files #
*.jar
*.war
*.ear

View File

@ -38,6 +38,11 @@ public class AddingNewLineToString {
System.out.println("6. Using System.getProperty(\"line.separator\")");
rhyme = line1 + System.getProperty("line.separator") + line2;
System.out.println(rhyme);
//7. Using %n
System.out.println("7. Using %n");
rhyme = "Humpty Dumpty sat on a wall.%nHumpty Dumpty had a great fall.";
System.out.println(rhyme);
System.out.println("***HTML to rendered in a browser***");
//1. Line break for HTML using <br>

View File

@ -42,7 +42,7 @@
<module>core-java-collections-list</module>
<module>core-java-collections-list-2</module>
<module>core-java-collections-list-3</module>
<module>core-java-collections-set</module>
<!-- <module>core-java-collections-set</module> --> <!-- We haven't upgraded to java 11. Fixing in BAEL-10841 -->
<module>core-java-concurrency-2</module>
<module>core-java-concurrency-advanced</module>

View File

@ -10,10 +10,18 @@ import org.junit.Test;
import java.io.IOException;
import static org.junit.Assert.assertNotNull;
/**
* Tests which show issues with JGit that we reported upstream.
*/
public class JGitBugIntegrationTest {
public class JGitBugManualTest {
/**
* This test case expects one git repository to be present in local file system.
* Currently this test uses the Baeldung repository i.e. the current checkout repository.
* It finds the repository by tracking back and scan file system to find .git folder in
* the file system.
*
* Before running the test case ensure that the .git folder is present.
*
* @throws IOException
*/
@Test
public void testRevWalkDisposeClosesReader() throws IOException {
try (Repository repo = Helper.openJGitRepository()) {

View File

@ -5,6 +5,7 @@ spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.datasource.data=data-trans.sql
logging.level.org.hibernate.SQL=INFO
logging.level.org.hibernate.type=TRACE

View File

@ -5,6 +5,7 @@ spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.datasource.data=data-trans.sql
logging.level.org.hibernate.SQL=INFO
logging.level.org.hibernate.type=TRACE

View File

@ -729,6 +729,7 @@
<module>spring-threads</module>
<module>spring-thymeleaf</module>
<module>spring-thymeleaf-2</module>
<module>spring-thymeleaf-3</module>
<module>spring-vault</module>
<module>spring-vertx</module>
@ -1229,6 +1230,7 @@
<module>spring-thymeleaf</module>
<module>spring-thymeleaf-2</module>
<module>spring-thymeleaf-3</module>
<module>spring-vault</module>
<module>spring-vertx</module>

View File

@ -42,6 +42,11 @@
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${byte-buddy.version}</version>
</dependency>
<!--kotlin deps -->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
@ -175,8 +180,8 @@
<jayway-rest-assured.version>2.9.0</jayway-rest-assured.version>
<jackson.version>2.9.9</jackson.version> <!-- Same as spring-boot-dependencies:2.1.7.RELEASE -->
<kotlin.version>1.2.71</kotlin.version> <!-- Same as spring-boot-dependencies:2.1.7.RELEASE -->
<start-class>com.baeldung.Spring5Application</start-class>
<httpclient.version>4.5.8</httpclient.version>
<start-class>com.baeldung.Spring5Application</start-class>
</properties>
</project>

View File

@ -1,6 +1,3 @@
server.port=8081
security.user.name=user
security.user.password=pass
logging.level.root=INFO

View File

@ -0,0 +1,21 @@
package com.baeldung.ioccontainer.bean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private static boolean isBeanFactoryPostProcessorRegistered = false;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){
setBeanFactoryPostProcessorRegistered(true);
}
public static boolean isBeanFactoryPostProcessorRegistered() {
return isBeanFactoryPostProcessorRegistered;
}
public static void setBeanFactoryPostProcessorRegistered(boolean isBeanFactoryPostProcessorRegistered) {
CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered = isBeanFactoryPostProcessorRegistered;
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.ioccontainer.bean;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class CustomBeanPostProcessor implements BeanPostProcessor {
private static boolean isBeanPostProcessorRegistered = false;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName){
setBeanPostProcessorRegistered(true);
return bean;
}
public static boolean isBeanPostProcessorRegistered() {
return isBeanPostProcessorRegistered;
}
public static void setBeanPostProcessorRegistered(boolean isBeanPostProcessorRegistered) {
CustomBeanPostProcessor.isBeanPostProcessorRegistered = isBeanPostProcessorRegistered;
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.ioccontainer.bean;
public class Student {
private static boolean isBeanInstantiated = false;
public void postConstruct() {
setBeanInstantiated(true);
}
public static boolean isBeanInstantiated() {
return isBeanInstantiated;
}
public static void setBeanInstantiated(boolean isBeanInstantiated) {
Student.isBeanInstantiated = isBeanInstantiated;
}
}

View File

@ -0,0 +1,86 @@
package com.baeldung.ioccontainer;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import com.baeldung.ioccontainer.bean.CustomBeanFactoryPostProcessor;
import com.baeldung.ioccontainer.bean.CustomBeanPostProcessor;
import com.baeldung.ioccontainer.bean.Student;
public class IOCContainerAppUnitTest {
@BeforeEach
@AfterEach
public void resetInstantiationFlag() {
Student.setBeanInstantiated(false);
CustomBeanPostProcessor.setBeanPostProcessorRegistered(false);
CustomBeanFactoryPostProcessor.setBeanFactoryPostProcessorRegistered(false);
}
@Test
public void whenBFInitialized_thenStudentNotInitialized() {
Resource res = new ClassPathResource("ioc-container-difference-example.xml");
BeanFactory factory = new XmlBeanFactory(res);
assertFalse(Student.isBeanInstantiated());
}
@Test
public void whenBFInitialized_thenStudentInitialized() {
Resource res = new ClassPathResource("ioc-container-difference-example.xml");
BeanFactory factory = new XmlBeanFactory(res);
Student student = (Student) factory.getBean("student");
assertTrue(Student.isBeanInstantiated());
}
@Test
public void whenAppContInitialized_thenStudentInitialized() {
ApplicationContext context = new ClassPathXmlApplicationContext("ioc-container-difference-example.xml");
assertTrue(Student.isBeanInstantiated());
}
@Test
public void whenBFInitialized_thenBFPProcessorAndBPProcessorNotRegAutomatically() {
Resource res = new ClassPathResource("ioc-container-difference-example.xml");
ConfigurableListableBeanFactory factory = new XmlBeanFactory(res);
assertFalse(CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered());
assertFalse(CustomBeanPostProcessor.isBeanPostProcessorRegistered());
}
@Test
public void whenBFPostProcessorAndBPProcessorRegisteredManually_thenReturnTrue() {
Resource res = new ClassPathResource("ioc-container-difference-example.xml");
ConfigurableListableBeanFactory factory = new XmlBeanFactory(res);
CustomBeanFactoryPostProcessor beanFactoryPostProcessor = new CustomBeanFactoryPostProcessor();
beanFactoryPostProcessor.postProcessBeanFactory(factory);
assertTrue(CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered());
CustomBeanPostProcessor beanPostProcessor = new CustomBeanPostProcessor();
factory.addBeanPostProcessor(beanPostProcessor);
Student student = (Student) factory.getBean("student");
assertTrue(CustomBeanPostProcessor.isBeanPostProcessorRegistered());
}
@Test
public void whenAppContInitialized_thenBFPostProcessorAndBPostProcessorRegisteredAutomatically() {
ApplicationContext context = new ClassPathXmlApplicationContext("ioc-container-difference-example.xml");
assertTrue(CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered());
assertTrue(CustomBeanPostProcessor.isBeanPostProcessorRegistered());
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="student" class="com.baeldung.ioccontainer.bean.Student" init-method="postConstruct"/>
<bean id="customBeanPostProcessor" class="com.baeldung.ioccontainer.bean.CustomBeanPostProcessor" />
<bean id="customBeanFactoryPostProcessor" class="com.baeldung.ioccontainer.bean.CustomBeanFactoryPostProcessor" />
</beans>

View File

@ -0,0 +1,5 @@
## Spring Thymeleaf 3
This module contains articles about Spring with Thymeleaf
## Relevant Articles:

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 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">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-thymeleaf-3</artifactId>
<name>spring-thymeleaf-3</name>
<packaging>war</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-2</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.baeldung.thymeleaf.cssandjs.CssAndJsApplication</mainClass>
<layout>JAR</layout>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>${tomcat7-maven-plugin.version}</version>
<executions>
<execution>
<id>tomcat-run</id>
<goals>
<goal>exec-war-only</goal>
</goals>
<phase>package</phase>
<configuration>
<path>/</path>
<enableNaming>false</enableNaming>
<finalName>webapp.jar</finalName>
<charset>utf-8</charset>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<finalName>spring-thymeleaf-3</finalName>
</build>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<tomcat7-maven-plugin.version>2.2</tomcat7-maven-plugin.version>
</properties>
</project>

View File

@ -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);
}
}

View File

@ -0,0 +1,11 @@
package com.baeldung.thymeleaf.cssandjs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CssAndJsApplication {
public static void main(String[] args) {
SpringApplication.run(CssAndJsApplication.class, args);
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.thymeleaf.cssandjs;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class CssAndJsController {
@GetMapping("/styled-page")
public String getStyledPage(Model model) {
model.addAttribute("name", "Baeldung Reader");
return "cssandjs/styledPage";
}
}

View File

@ -0,0 +1,7 @@
function showAlert() {
alert("The button was clicked!");
}
function showName(name) {
alert("Here's the name: " + name);
}

View File

@ -0,0 +1,18 @@
h2 {
font-family: sans-serif;
font-size: 1.5em;
text-transform: uppercase;
}
strong {
font-weight: 700;
background-color: yellow;
}
p {
font-family: sans-serif;
}
label {
font-weight: 600;
}

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Add CSS and JS to Thymeleaf</title>
<link th:href="@{/styles/cssandjs/main.css}" rel="stylesheet" />
<script th:inline="javascript">
var nameJs = /*[[${name}]]*/;
</script>
<script type="text/javascript" th:src="@{/js/cssandjs/actions.js}"></script>
</head>
<body>
<h2>Carefully Styled Heading</h2>
<p>
This is text on which we want to apply <strong>very special</strong> styling.
</p>
<p><label>Name:</label><span th:text="${name}"></span></p>
<button type="button" th:onclick="showName(nameJs);">Show Name</button>
</body>
</html>

View File

@ -0,0 +1,13 @@
package com.baeldung.thymeleaf;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class ApplicationIntegrationTest {
@Test
public void contextLoads() {
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.thymeleaf.cssandjs;
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 static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = CssAndJsApplication.class)
public class CssAndJsControllerIntegrationTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
@Test
public void whenCalledGetStyledPage_thenReturnContent() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.get("/styled-page"))
.andExpect(status().isOk())
.andExpect(view().name("cssandjs/styledPage"))
.andExpect(content().string(containsString("Carefully Styled Heading")));
}
}