Merge branch 'masterupstream' into beforeAfterAnnotationsJunit
This commit is contained in:
commit
74e66a8ba9
32
apache-opennlp/pom.xml
Normal file
32
apache-opennlp/pom.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?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>
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>apache-opennlp</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.opennlp</groupId>
|
||||
<artifactId>opennlp-tools</artifactId>
|
||||
<version>1.8.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.9.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
100
apache-opennlp/src/main/resources/models/DoccatSample.txt
Normal file
100
apache-opennlp/src/main/resources/models/DoccatSample.txt
Normal file
File diff suppressed because one or more lines are too long
BIN
apache-opennlp/src/main/resources/models/en-chunker.bin
Normal file
BIN
apache-opennlp/src/main/resources/models/en-chunker.bin
Normal file
Binary file not shown.
301403
apache-opennlp/src/main/resources/models/en-lemmatizer.dict
Normal file
301403
apache-opennlp/src/main/resources/models/en-lemmatizer.dict
Normal file
File diff suppressed because it is too large
Load Diff
BIN
apache-opennlp/src/main/resources/models/en-ner-person.bin
Normal file
BIN
apache-opennlp/src/main/resources/models/en-ner-person.bin
Normal file
Binary file not shown.
BIN
apache-opennlp/src/main/resources/models/en-pos-maxent.bin
Normal file
BIN
apache-opennlp/src/main/resources/models/en-pos-maxent.bin
Normal file
Binary file not shown.
BIN
apache-opennlp/src/main/resources/models/en-sent.bin
Normal file
BIN
apache-opennlp/src/main/resources/models/en-sent.bin
Normal file
Binary file not shown.
BIN
apache-opennlp/src/main/resources/models/en-token.bin
Normal file
BIN
apache-opennlp/src/main/resources/models/en-token.bin
Normal file
Binary file not shown.
@ -0,0 +1,32 @@
|
||||
package com.baeldung.apache.opennlp;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import opennlp.tools.chunker.ChunkerME;
|
||||
import opennlp.tools.chunker.ChunkerModel;
|
||||
import opennlp.tools.postag.POSModel;
|
||||
import opennlp.tools.postag.POSTaggerME;
|
||||
import opennlp.tools.tokenize.SimpleTokenizer;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ChunkerTest {
|
||||
|
||||
@Test
|
||||
public void givenChunkerModel_whenChunk_thenChunksAreDetected() throws Exception {
|
||||
|
||||
SimpleTokenizer tokenizer = SimpleTokenizer.INSTANCE;
|
||||
String[] tokens = tokenizer.tokenize("He reckons the current account deficit will narrow to only 8 billion.");
|
||||
|
||||
InputStream inputStreamPOSTagger = getClass().getResourceAsStream("/models/en-pos-maxent.bin");
|
||||
POSModel posModel = new POSModel(inputStreamPOSTagger);
|
||||
POSTaggerME posTagger = new POSTaggerME(posModel);
|
||||
String tags[] = posTagger.tag(tokens);
|
||||
|
||||
InputStream inputStreamChunker = new FileInputStream("src/main/resources/models/en-chunker.bin");
|
||||
ChunkerModel chunkerModel = new ChunkerModel(inputStreamChunker);
|
||||
ChunkerME chunker = new ChunkerME(chunkerModel);
|
||||
String[] chunks = chunker.chunk(tokens, tags);
|
||||
assertThat(chunks).contains("B-NP", "B-VP", "B-NP", "I-NP", "I-NP", "I-NP", "B-VP", "I-VP", "B-PP", "B-NP", "I-NP", "I-NP", "O");
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.baeldung.apache.opennlp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import opennlp.tools.langdetect.Language;
|
||||
import opennlp.tools.langdetect.LanguageDetector;
|
||||
import opennlp.tools.langdetect.LanguageDetectorFactory;
|
||||
import opennlp.tools.langdetect.LanguageDetectorME;
|
||||
import opennlp.tools.langdetect.LanguageDetectorModel;
|
||||
import opennlp.tools.langdetect.LanguageDetectorSampleStream;
|
||||
import opennlp.tools.util.InputStreamFactory;
|
||||
import opennlp.tools.util.MarkableFileInputStreamFactory;
|
||||
import opennlp.tools.util.ObjectStream;
|
||||
import opennlp.tools.util.PlainTextByLineStream;
|
||||
import opennlp.tools.util.TrainingParameters;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class LanguageDetectorAndTrainingDataTest {
|
||||
|
||||
@Test
|
||||
public void givenLanguageDictionary_whenLanguageDetect_thenLanguageIsDetected() throws FileNotFoundException, IOException {
|
||||
InputStreamFactory dataIn = new MarkableFileInputStreamFactory(new File("src/main/resources/models/DoccatSample.txt"));
|
||||
ObjectStream lineStream = new PlainTextByLineStream(dataIn, "UTF-8");
|
||||
LanguageDetectorSampleStream sampleStream = new LanguageDetectorSampleStream(lineStream);
|
||||
TrainingParameters params = new TrainingParameters();
|
||||
params.put(TrainingParameters.ITERATIONS_PARAM, 100);
|
||||
params.put(TrainingParameters.CUTOFF_PARAM, 5);
|
||||
params.put("DataIndexer", "TwoPass");
|
||||
params.put(TrainingParameters.ALGORITHM_PARAM, "NAIVEBAYES");
|
||||
|
||||
LanguageDetectorModel model = LanguageDetectorME.train(sampleStream, params, new LanguageDetectorFactory());
|
||||
|
||||
LanguageDetector ld = new LanguageDetectorME(model);
|
||||
Language[] languages = ld.predictLanguages("estava em uma marcenaria na Rua Bruno");
|
||||
assertThat(Arrays.asList(languages).toString()).contains("pob (0.9999999950605625)", "ita (4.939427661577956E-9)", "spa (9.665954064665144E-15)",
|
||||
"fra (8.250349924885834E-25)");
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.baeldung.apache.opennlp;
|
||||
|
||||
import java.io.InputStream;
|
||||
import opennlp.tools.lemmatizer.DictionaryLemmatizer;
|
||||
import opennlp.tools.postag.POSModel;
|
||||
import opennlp.tools.postag.POSTaggerME;
|
||||
import opennlp.tools.tokenize.SimpleTokenizer;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class LemmetizerTest {
|
||||
|
||||
@Test
|
||||
public void givenEnglishDictionary_whenLemmatize_thenLemmasAreDetected() throws Exception {
|
||||
|
||||
SimpleTokenizer tokenizer = SimpleTokenizer.INSTANCE;
|
||||
String[] tokens = tokenizer.tokenize("John has a sister named Penny.");
|
||||
|
||||
InputStream inputStreamPOSTagger = getClass().getResourceAsStream("/models/en-pos-maxent.bin");
|
||||
POSModel posModel = new POSModel(inputStreamPOSTagger);
|
||||
POSTaggerME posTagger = new POSTaggerME(posModel);
|
||||
String tags[] = posTagger.tag(tokens);
|
||||
InputStream dictLemmatizer = getClass().getResourceAsStream("/models/en-lemmatizer.dict");
|
||||
DictionaryLemmatizer lemmatizer = new DictionaryLemmatizer(dictLemmatizer);
|
||||
String[] lemmas = lemmatizer.lemmatize(tokens, tags);
|
||||
|
||||
assertThat(lemmas).contains("O", "have", "a", "sister", "name", "O", "O");
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.baeldung.apache.opennlp;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import opennlp.tools.namefind.NameFinderME;
|
||||
import opennlp.tools.namefind.TokenNameFinderModel;
|
||||
import opennlp.tools.tokenize.SimpleTokenizer;
|
||||
import opennlp.tools.util.Span;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class NamedEntityRecognitionTest {
|
||||
|
||||
@Test
|
||||
public void givenEnglishPersonModel_whenNER_thenPersonsAreDetected() throws Exception {
|
||||
|
||||
SimpleTokenizer tokenizer = SimpleTokenizer.INSTANCE;
|
||||
String[] tokens = tokenizer.tokenize("John is 26 years old. His best friend's name is Leonard. He has a sister named Penny.");
|
||||
|
||||
InputStream inputStreamNameFinder = getClass().getResourceAsStream("/models/en-ner-person.bin");
|
||||
TokenNameFinderModel model = new TokenNameFinderModel(inputStreamNameFinder);
|
||||
NameFinderME nameFinderME = new NameFinderME(model);
|
||||
List<Span> spans = Arrays.asList(nameFinderME.find(tokens));
|
||||
assertThat(spans.toString()).isEqualTo("[[0..1) person, [13..14) person, [20..21) person]");
|
||||
List<String> names = new ArrayList<String>();
|
||||
int k = 0;
|
||||
for (Span s : spans) {
|
||||
names.add("");
|
||||
for (int index = s.getStart(); index < s.getEnd(); index++) {
|
||||
names.set(k, names.get(k) + tokens[index]);
|
||||
}
|
||||
k++;
|
||||
}
|
||||
assertThat(names).contains("John","Leonard","Penny");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.baeldung.apache.opennlp;
|
||||
|
||||
import java.io.InputStream;
|
||||
import opennlp.tools.postag.POSModel;
|
||||
import opennlp.tools.postag.POSTaggerME;
|
||||
import opennlp.tools.tokenize.SimpleTokenizer;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class POSTaggerTest {
|
||||
|
||||
@Test
|
||||
public void givenPOSModel_whenPOSTagging_thenPOSAreDetected() throws Exception {
|
||||
|
||||
SimpleTokenizer tokenizer = SimpleTokenizer.INSTANCE;
|
||||
String[] tokens = tokenizer.tokenize("John has a sister named Penny.");
|
||||
|
||||
InputStream inputStreamPOSTagger = getClass().getResourceAsStream("/models/en-pos-maxent.bin");
|
||||
POSModel posModel = new POSModel(inputStreamPOSTagger);
|
||||
POSTaggerME posTagger = new POSTaggerME(posModel);
|
||||
String tags[] = posTagger.tag(tokens);
|
||||
assertThat(tags).contains("NNP", "VBZ", "DT", "NN", "VBN", "NNP", ".");
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.baeldung.apache.opennlp;
|
||||
|
||||
import java.io.InputStream;
|
||||
import opennlp.tools.sentdetect.SentenceDetectorME;
|
||||
import opennlp.tools.sentdetect.SentenceModel;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SentenceDetectionTest {
|
||||
|
||||
@Test
|
||||
public void givenEnglishModel_whenDetect_thenSentencesAreDetected() throws Exception {
|
||||
|
||||
String paragraph = "This is a statement. This is another statement. Now is an abstract word for time, "
|
||||
+ "that is always flying. And my email address is google@gmail.com.";
|
||||
|
||||
InputStream is = getClass().getResourceAsStream("/models/en-sent.bin");
|
||||
SentenceModel model = new SentenceModel(is);
|
||||
|
||||
SentenceDetectorME sdetector = new SentenceDetectorME(model);
|
||||
|
||||
String sentences[] = sdetector.sentDetect(paragraph);
|
||||
assertThat(sentences).contains("This is a statement.",
|
||||
"This is another statement.",
|
||||
"Now is an abstract word for time, that is always flying.",
|
||||
"And my email address is google@gmail.com.");
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.baeldung.apache.opennlp;
|
||||
|
||||
import java.io.InputStream;
|
||||
import opennlp.tools.tokenize.SimpleTokenizer;
|
||||
import opennlp.tools.tokenize.TokenizerME;
|
||||
import opennlp.tools.tokenize.TokenizerModel;
|
||||
import opennlp.tools.tokenize.WhitespaceTokenizer;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TokenizerTest {
|
||||
|
||||
@Test
|
||||
public void givenEnglishModel_whenTokenize_thenTokensAreDetected() throws Exception {
|
||||
InputStream inputStream = getClass().getResourceAsStream("/models/en-token.bin");
|
||||
TokenizerModel model = new TokenizerModel(inputStream);
|
||||
TokenizerME tokenizer = new TokenizerME(model);
|
||||
String[] tokens = tokenizer.tokenize("Baeldung is a Spring Resource.");
|
||||
assertThat(tokens).contains("Baeldung", "is", "a", "Spring", "Resource", ".");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenWhitespaceTokenizer_whenTokenize_thenTokensAreDetected() throws Exception {
|
||||
WhitespaceTokenizer tokenizer = WhitespaceTokenizer.INSTANCE;
|
||||
String[] tokens = tokenizer.tokenize("Baeldung is a Spring Resource.");
|
||||
assertThat(tokens).contains("Baeldung", "is", "a", "Spring", "Resource.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSimpleTokenizer_whenTokenize_thenTokensAreDetected() throws Exception {
|
||||
SimpleTokenizer tokenizer = SimpleTokenizer.INSTANCE;
|
||||
String[] tokens = tokenizer.tokenize("Baeldung is a Spring Resource.");
|
||||
assertThat(tokens).contains("Baeldung", "is", "a", "Spring", "Resource", ".");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.baeldung.kotlin.objects
|
||||
|
||||
object Counter {
|
||||
private var count: Int = 0
|
||||
|
||||
fun currentCount() = count
|
||||
|
||||
fun increment() {
|
||||
++count
|
||||
}
|
||||
|
||||
fun decrement() {
|
||||
--count
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.baeldung.kotlin.objects
|
||||
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
class ObjectsTest {
|
||||
@Test
|
||||
fun singleton() {
|
||||
|
||||
Assert.assertEquals(42, SimpleSingleton.answer)
|
||||
Assert.assertEquals("Hello, world!", SimpleSingleton.greet("world"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun counter() {
|
||||
Assert.assertEquals(0, Counter.currentCount())
|
||||
Counter.increment()
|
||||
Assert.assertEquals(1, Counter.currentCount())
|
||||
Counter.decrement()
|
||||
Assert.assertEquals(0, Counter.currentCount())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun comparator() {
|
||||
val strings = listOf("Hello", "World")
|
||||
val sortedStrings = strings.sortedWith(ReverseStringComparator)
|
||||
|
||||
Assert.assertEquals(listOf("World", "Hello"), sortedStrings)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun companion() {
|
||||
Assert.assertEquals("You can see me", OuterClass.public)
|
||||
// Assert.assertEquals("You can't see me", OuterClass.secret) // Cannot access 'secret'
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.baeldung.kotlin.objects
|
||||
|
||||
class OuterClass {
|
||||
companion object {
|
||||
private val secret = "You can't see me"
|
||||
val public = "You can see me"
|
||||
}
|
||||
|
||||
fun getSecretValue() = secret
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.baeldung.kotlin.objects
|
||||
|
||||
object ReverseStringComparator : Comparator<String> {
|
||||
override fun compare(o1: String, o2: String) = o1.reversed().compareTo(o2.reversed())
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.baeldung.kotlin.objects
|
||||
|
||||
object SimpleSingleton {
|
||||
val answer = 42;
|
||||
|
||||
fun greet(name: String) = "Hello, $name!"
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.baeldung.kotlin.objects
|
||||
|
||||
class StaticClass {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val staticField = 42
|
||||
}
|
||||
}
|
1
pom.xml
1
pom.xml
@ -42,6 +42,7 @@
|
||||
<module>apache-thrift</module>
|
||||
<module>apache-curator</module>
|
||||
<module>apache-zookeeper</module>
|
||||
<module>apache-opennlp</module>
|
||||
<module>autovalue</module>
|
||||
<module>axon</module>
|
||||
<module>bootique</module>
|
||||
|
@ -0,0 +1,202 @@
|
||||
package com.baeldung.rxjava.filters;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import rx.Observable;
|
||||
import rx.observers.TestSubscriber;
|
||||
|
||||
public class RxJavaFilterOperatorsTest {
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenFilteringItems_thenOddItemsAreFiltered() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.range(1, 10);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.filter(i -> i % 2 != 0);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(5);
|
||||
subscriber.assertValues(1, 3, 5, 7, 9);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenFilteringWithTake_thenOnlyFirstThreeItemsAreEmitted() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.range(1, 10);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.take(3);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(3);
|
||||
subscriber.assertValues(1, 2, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenObservable_whenFilteringWithTakeWhile_thenItemsEmittedUntilConditionIsVerified() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.just(1, 2, 3, 4, 3, 2, 1);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.takeWhile(i -> i < 4);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(3);
|
||||
subscriber.assertValues(1, 2, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenFilteringWithTakeFirst_thenOnlyFirstItemIsEmitted() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.just(1, 2, 3, 4, 5, 7, 6);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.takeFirst(x -> x > 5);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(1);
|
||||
subscriber.assertValue(7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenFilteringWithFirst_thenOnlyFirstThreeItemsAreEmitted() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.range(1, 10);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.first();
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(1);
|
||||
subscriber.assertValue(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmptyObservable_whenFilteringWithFirstOrDefault_thenDefaultValue() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.empty();
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.firstOrDefault(-1);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(1);
|
||||
subscriber.assertValue(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenFilteringWithTakeLast_thenLastThreeItemAreEmitted() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.range(1, 10);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.takeLast(3);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(3);
|
||||
subscriber.assertValues(8, 9, 10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenFilteringWithLast_thenOnlyLastItemIsEmitted() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.range(1, 10);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.last(i -> i % 2 != 0);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(1);
|
||||
subscriber.assertValue(9);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenFilteringWithLastAndDefault_thenOnlyDefaultIsEmitted() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.range(1, 10);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.lastOrDefault(-1, i -> i > 10);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(1);
|
||||
subscriber.assertValue(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenObservable_whenTakingElementAt_thenItemAtSpecifiedIndexIsEmitted() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.just(1, 2, 3, 5, 7, 11);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.elementAt(4);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(1);
|
||||
subscriber.assertValue(7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenObservable_whenTakingElementAtOrDefault_thenDefaultIsReturned() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.just(1, 2, 3, 5, 7, 11);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.elementAtOrDefault(7, -1);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(1);
|
||||
subscriber.assertValue(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMixedTypeObservable_whenFilteringByType_thenOnlyNumbersAreEmitted() {
|
||||
|
||||
Observable sourceObservable = Observable.just(1, "two", 3, "five", 7, 11);
|
||||
TestSubscriber subscriber = new TestSubscriber();
|
||||
|
||||
Observable filteredObservable = sourceObservable.ofType(String.class);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(2);
|
||||
subscriber.assertValues("two", "five");
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package com.baeldung.rxjava.filters;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import rx.Observable;
|
||||
import rx.observers.TestSubscriber;
|
||||
|
||||
public class RxJavaSkipOperatorsTest {
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenSkipping_thenFirstFourItemsAreSkipped() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.range(1, 10);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.skip(4);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(6);
|
||||
subscriber.assertValues(5, 6, 7, 8, 9, 10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenObservable_whenSkippingWhile_thenFirstItemsAreSkipped() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.just(1, 2, 3, 4, 5, 4, 3, 2, 1);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.skipWhile(i -> i < 4);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(6);
|
||||
subscriber.assertValues(4, 5, 4, 3, 2, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenSkippingLast_thenLastFiveItemsAreSkipped() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.range(1, 10);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = sourceObservable.skipLast(5);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(5);
|
||||
subscriber.assertValues(1, 2, 3, 4, 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenObservable_whenFilteringDistinct_thenOnlyDistinctValuesAreEmitted() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.just(1, 1, 2, 2, 1, 3, 3, 1);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> distinctObservable = sourceObservable.distinct();
|
||||
|
||||
distinctObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(3);
|
||||
subscriber.assertValues(1, 2, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenObservable_whenFilteringDistinctUntilChanged_thenOnlyDistinctConsecutiveItemsAreEmitted() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.just(1, 1, 2, 2, 1, 3, 3, 1);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> distinctObservable = sourceObservable.distinctUntilChanged();
|
||||
|
||||
distinctObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(5);
|
||||
subscriber.assertValues(1, 2, 1, 3, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenIgnoringElements_thenOnlyDistinctConsecutiveItemsAreEmitted() {
|
||||
|
||||
Observable<Integer> sourceObservable = Observable.range(1, 10);
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> ignoredObservable = sourceObservable.ignoreElements();
|
||||
|
||||
ignoredObservable.subscribe(subscriber);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValueCount(0);
|
||||
subscriber.assertNoValues();
|
||||
}
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
package com.baeldung.rxjava.filters;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import rx.Observable;
|
||||
import rx.observers.TestSubscriber;
|
||||
import rx.schedulers.TestScheduler;
|
||||
|
||||
public class RxJavaTimeFilteringOperatorsTest {
|
||||
|
||||
@Test
|
||||
public void givenTimedObservable_whenSampling_thenOnlySampleItemsAreEmitted() {
|
||||
|
||||
TestScheduler testScheduler = new TestScheduler();
|
||||
|
||||
Observable<Integer> timedObservable =
|
||||
Observable.just(1, 2, 3, 4, 5, 6)
|
||||
.zipWith(
|
||||
Observable.interval(0, 1, TimeUnit.SECONDS, testScheduler),
|
||||
(item, time) -> item
|
||||
);
|
||||
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> sampledObservable =
|
||||
timedObservable.sample(2500L, TimeUnit.MILLISECONDS, testScheduler);
|
||||
|
||||
sampledObservable.subscribe(subscriber);
|
||||
|
||||
testScheduler.advanceTimeBy(7, TimeUnit.SECONDS);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValues(3, 5, 6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTimedObservable_whenThrottlingLast_thenThrottleLastItemsAreEmitted() {
|
||||
|
||||
TestScheduler testScheduler = new TestScheduler();
|
||||
|
||||
Observable<Integer> timedObservable =
|
||||
Observable.just(1, 2, 3, 4, 5, 6)
|
||||
.zipWith(
|
||||
Observable.interval(0, 1, TimeUnit.SECONDS, testScheduler),
|
||||
(item, time) -> item
|
||||
);
|
||||
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = timedObservable.throttleLast(3100L, TimeUnit.MILLISECONDS, testScheduler);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
testScheduler.advanceTimeBy(7, TimeUnit.SECONDS);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValues(4, 6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRangeObservable_whenThrottlingFirst_thenThrottledFirstItemsAreEmitted() {
|
||||
|
||||
TestScheduler testScheduler = new TestScheduler();
|
||||
|
||||
Observable<Integer> timedObservable =
|
||||
Observable.just(1, 2, 3, 4, 5, 6)
|
||||
.zipWith(
|
||||
Observable.interval(0, 1, TimeUnit.SECONDS, testScheduler),
|
||||
(item, time) -> item
|
||||
);
|
||||
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable =
|
||||
timedObservable.throttleFirst(4100L, TimeUnit.MILLISECONDS, testScheduler);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
testScheduler.advanceTimeBy(7, TimeUnit.SECONDS);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValues(1, 6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTimedObservable_whenThrottlingWithTimeout_thenLastItemIsEmitted() {
|
||||
|
||||
TestScheduler testScheduler = new TestScheduler();
|
||||
|
||||
Observable<Integer> timedObservable =
|
||||
Observable.just(1, 2, 3, 4, 5, 6)
|
||||
.zipWith(
|
||||
Observable.interval(0, 1, TimeUnit.SECONDS, testScheduler),
|
||||
(item, time) -> item
|
||||
);
|
||||
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = timedObservable.throttleWithTimeout(2000L, TimeUnit.MILLISECONDS, testScheduler);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
testScheduler.advanceTimeBy(7, TimeUnit.SECONDS);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValue(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTimedObservable_whenDebounceOperatorIsApplied_thenLastItemIsEmitted() {
|
||||
|
||||
TestScheduler testScheduler = new TestScheduler();
|
||||
|
||||
Observable<Integer> timedObservable =
|
||||
Observable.just(1, 2, 3, 4, 5, 6)
|
||||
.zipWith(
|
||||
Observable.interval(0, 1, TimeUnit.SECONDS, testScheduler),
|
||||
(item, time) -> item
|
||||
);
|
||||
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = timedObservable.debounce(2000L, TimeUnit.MILLISECONDS, testScheduler);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
testScheduler.advanceTimeBy(7, TimeUnit.SECONDS);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValue(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTimedObservable_whenUsingTimeout_thenTimeOutException() {
|
||||
|
||||
TestScheduler testScheduler = new TestScheduler();
|
||||
|
||||
Observable<Integer> timedObservable =
|
||||
Observable.just(1, 2, 3, 4, 5, 6)
|
||||
.zipWith(
|
||||
Observable.interval(0, 1, TimeUnit.SECONDS, testScheduler),
|
||||
(item, time) -> item
|
||||
);
|
||||
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = timedObservable.timeout(500L, TimeUnit.MILLISECONDS, testScheduler);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
testScheduler.advanceTimeBy(7, TimeUnit.SECONDS);
|
||||
|
||||
subscriber.assertError(TimeoutException.class);
|
||||
subscriber.assertValues(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenObservable_whenSkippingUntil_thenItemsAreSkippedUntilSecondObservableEmitsItems() {
|
||||
|
||||
TestScheduler testScheduler = new TestScheduler();
|
||||
|
||||
Observable<Integer> timedObservable =
|
||||
Observable.just(1, 2, 3, 4, 5, 6)
|
||||
.zipWith(
|
||||
Observable.interval(0, 1, TimeUnit.SECONDS, testScheduler),
|
||||
(item, time) -> item
|
||||
);
|
||||
|
||||
|
||||
Observable<Integer> delayedObservable = Observable.just(1)
|
||||
.delay(3000, TimeUnit.MILLISECONDS, testScheduler);
|
||||
|
||||
TestSubscriber<Integer> subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> filteredObservable = timedObservable.skipUntil(delayedObservable);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
testScheduler.advanceTimeBy(7, TimeUnit.SECONDS);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValues(4, 5, 6);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenObservable_whenSkippingWhile_thenItemsAreEmittedUntilSecondObservableEmitsItems() {
|
||||
|
||||
TestScheduler testScheduler = new TestScheduler();
|
||||
|
||||
Observable<Integer> timedObservable =
|
||||
Observable.just(1, 2, 3, 4, 5, 6)
|
||||
.zipWith(
|
||||
Observable.interval(0, 1, TimeUnit.SECONDS, testScheduler),
|
||||
(item, time) -> item
|
||||
);
|
||||
|
||||
TestSubscriber subscriber = new TestSubscriber();
|
||||
|
||||
Observable<Integer> delayedObservable = Observable.just(1)
|
||||
.delay(3000, TimeUnit.MILLISECONDS, testScheduler);
|
||||
|
||||
Observable<Integer> filteredObservable = timedObservable.takeUntil(delayedObservable);
|
||||
|
||||
filteredObservable.subscribe(subscriber);
|
||||
|
||||
testScheduler.advanceTimeBy(7, TimeUnit.SECONDS);
|
||||
|
||||
subscriber.assertCompleted();
|
||||
subscriber.assertNoErrors();
|
||||
subscriber.assertValues(1, 2, 3);
|
||||
}
|
||||
}
|
@ -28,7 +28,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
|
@ -0,0 +1,26 @@
|
||||
package com.baeldung.errorhandling;
|
||||
|
||||
import com.baeldung.autoconfiguration.MySQLAutoconfiguration;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||
|
||||
@SpringBootApplication(exclude = {MySQLAutoconfiguration.class})
|
||||
@ComponentScan(basePackages = "com.baeldung.errorhandling")
|
||||
public class ErrorHandlingApplication {
|
||||
|
||||
public static void main(String [] args) {
|
||||
System.setProperty("spring.profiles.active", "errorhandling");
|
||||
SpringApplication.run(ErrorHandlingApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean(name = "mvcHandlerMappingIntrospector")
|
||||
public HandlerMappingIntrospector mvcHandlerMappingIntrospector(ApplicationContext context) {
|
||||
return new HandlerMappingIntrospector(context);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.baeldung.errorhandling.controllers;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
@Controller
|
||||
public class IndexController {
|
||||
|
||||
@GetMapping(value = {"/", ""})
|
||||
public String index() {
|
||||
return "index";
|
||||
}
|
||||
|
||||
@GetMapping(value = {"/server_error"})
|
||||
public String triggerServerError() {
|
||||
"ser".charAt(30);
|
||||
return "index";
|
||||
}
|
||||
|
||||
@PostMapping(value = {"/general_error"})
|
||||
public String triggerGeneralError() {
|
||||
return "index";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.baeldung.errorhandling.controllers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.ErrorController;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@Controller
|
||||
public class MyErrorController implements ErrorController {
|
||||
|
||||
public MyErrorController() {}
|
||||
|
||||
@RequestMapping(value = "/error")
|
||||
public String handleError(HttpServletRequest request) {
|
||||
|
||||
Integer statusCode =
|
||||
Integer.valueOf(request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE).toString());
|
||||
|
||||
if(statusCode == HttpStatus.NOT_FOUND.value()) {
|
||||
return "error-404";
|
||||
}
|
||||
else if(statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
|
||||
return "error-500";
|
||||
}
|
||||
else {
|
||||
return "error";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorPath() {
|
||||
return "/error";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
#server
|
||||
server.port=9000
|
||||
server.servlet-path=/
|
||||
server.context-path=/
|
||||
#server.error.whitelabel.enabled=false
|
||||
|
||||
#spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration
|
||||
|
||||
#for Spring Boot 2.0+
|
||||
#spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
|
7
spring-boot/src/main/resources/templates/error-404.html
Normal file
7
spring-boot/src/main/resources/templates/error-404.html
Normal file
@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>Sorry we couldn't find the resource you are looking for</h1>
|
||||
<a href="/">Go Home</a>
|
||||
</body>
|
||||
</html>
|
7
spring-boot/src/main/resources/templates/error-500.html
Normal file
7
spring-boot/src/main/resources/templates/error-500.html
Normal file
@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>Oops! We spilled something but we're fixing it</h1>
|
||||
<a href="/">Go Home</a>
|
||||
</body>
|
||||
</html>
|
7
spring-boot/src/main/resources/templates/error.html
Normal file
7
spring-boot/src/main/resources/templates/error.html
Normal file
@ -0,0 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>Something went wrong! Our Engineers are on it temp</h1>
|
||||
<a href="/">Go Home</a>
|
||||
</body>
|
||||
</html>
|
8
spring-boot/src/main/resources/templates/error/404.html
Normal file
8
spring-boot/src/main/resources/templates/error/404.html
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>RESOURCE NOT FOUND</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>404 RESOURCE NOT FOUND</h1>
|
||||
</body>
|
||||
</html>
|
6
spring-boot/src/main/resources/templates/index.ftl
Normal file
6
spring-boot/src/main/resources/templates/index.ftl
Normal file
@ -0,0 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>Welcome Home</h1>
|
||||
</body>
|
||||
</html>
|
@ -4,7 +4,7 @@
|
||||
<link rel="stylesheet" href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Welcome Home</h1>
|
||||
<div class="container"><br/>
|
||||
<div class="alert alert-success">
|
||||
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
|
||||
|
@ -15,3 +15,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||
- [Geolocation by IP in Java](http://www.baeldung.com/geolocation-by-ip-with-maxmind)
|
||||
- [Guide to JavaServer Pages (JSP)](http://www.baeldung.com/jsp)
|
||||
- [Exploring SpringMVC’s Form Tag Library](http://www.baeldung.com/spring-mvc-form-tags)
|
||||
- [Guide to JSTL](http://www.baeldung.com/guide-to-jstl)
|
||||
|
@ -37,6 +37,13 @@
|
||||
|
||||
<!-- web -->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.9.2</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
@ -57,6 +64,13 @@
|
||||
<version>${hibernate-validator.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>6.0.6</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Json conversion -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
@ -108,6 +122,14 @@
|
||||
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>1</id>
|
||||
<name>jstl</name>
|
||||
<url>https://mvnrepository.com/artifact/javax.servlet/jstl</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<!-- Spring -->
|
||||
<org.springframework.version>5.0.2.RELEASE</org.springframework.version>
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.baeldung.jstl.bundles;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public class CustomMessage_en extends ListResourceBundle {
|
||||
@Override
|
||||
protected Object[][] getContents() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
static final Object[][] contents = {
|
||||
{"verb.go", "go"},
|
||||
{"verb.come", "come"},
|
||||
{"verb.sit", "sit"},
|
||||
{"verb.stand", "stand"}
|
||||
};
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.baeldung.jstl.bundles;
|
||||
|
||||
import java.util.ListResourceBundle;
|
||||
|
||||
public class CustomMessage_fr_FR extends ListResourceBundle {
|
||||
@Override
|
||||
protected Object[][] getContents() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
static final Object[][] contents = {
|
||||
{"verb.go", "aller"},
|
||||
{"verb.come", "venir"},
|
||||
{"verb.sit", "siéger"},
|
||||
{"verb.stand", "se lever"}
|
||||
};
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
package com.baeldung.jstl.controllers;
|
||||
|
||||
import com.baeldung.jstl.dbaccess.SQLConnection;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
import java.util.Calendar;
|
||||
|
||||
@Controller
|
||||
public class JSTLController {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JSTLController.class.getName());
|
||||
|
||||
@Autowired
|
||||
ServletContext servletContext;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
PreparedStatement preparedStatement = null;
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = SQLConnection.getConnection();
|
||||
preparedStatement = connection.prepareStatement("create table IF NOT EXISTS USERS " +
|
||||
"( id int not null primary key AUTO_INCREMENT," +
|
||||
" email VARCHAR(255) not null, first_name varchar (255), last_name varchar (255), registered DATE)");
|
||||
int status = preparedStatement.executeUpdate();
|
||||
preparedStatement = connection.prepareStatement("SELECT COUNT(*) AS total FROM USERS;");
|
||||
ResultSet result = preparedStatement.executeQuery();
|
||||
if(result!=null) {
|
||||
result.next();
|
||||
if (result.getInt("total") == 0) {
|
||||
generateDummy(connection);
|
||||
}
|
||||
} else {
|
||||
generateDummy(connection);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
if (preparedStatement != null) {
|
||||
preparedStatement.close();
|
||||
}
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/core_tags", method = RequestMethod.GET)
|
||||
public ModelAndView coreTags(final Model model) {
|
||||
ModelAndView mv = new ModelAndView("core_tags");
|
||||
return mv;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/core_tags_redirect", method = RequestMethod.GET)
|
||||
public ModelAndView coreTagsRedirect(final Model model) {
|
||||
ModelAndView mv = new ModelAndView("core_tags_redirect");
|
||||
return mv;
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping(value = "/formatting_tags", method = RequestMethod.GET)
|
||||
public ModelAndView formattingTags(final Model model) {
|
||||
ModelAndView mv = new ModelAndView("formatting_tags");
|
||||
return mv;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/sql_tags", method = RequestMethod.GET)
|
||||
public ModelAndView sqlTags(final Model model) {
|
||||
ModelAndView mv = new ModelAndView("sql_tags");
|
||||
return mv;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/xml_tags", method = RequestMethod.GET)
|
||||
public ModelAndView xmlTags(final Model model) {
|
||||
ModelAndView mv = new ModelAndView("xml_tags");
|
||||
return mv;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/items_xml", method = RequestMethod.GET)
|
||||
@ResponseBody public FileSystemResource getFile(HttpServletRequest request, HttpServletResponse response) {
|
||||
response.setContentType("application/xml");
|
||||
return new FileSystemResource(new File(servletContext.getRealPath("/WEB-INF/items.xsl")));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/function_tags", method = RequestMethod.GET)
|
||||
public ModelAndView functionTags(final Model model) {
|
||||
ModelAndView mv = new ModelAndView("function_tags");
|
||||
return mv;
|
||||
}
|
||||
|
||||
|
||||
private void generateDummy(Connection connection) throws SQLException {
|
||||
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO USERS " +
|
||||
"(email, first_name, last_name, registered) VALUES (?, ?, ?, ?);");
|
||||
preparedStatement.setString(1, "patrick@baeldung.com");
|
||||
preparedStatement.setString(2, "Patrick");
|
||||
preparedStatement.setString(3, "Frank");
|
||||
preparedStatement.setDate(4, new Date(Calendar.getInstance().getTimeInMillis()));
|
||||
preparedStatement.addBatch();
|
||||
preparedStatement.setString(1, "bfrank@baeldung.com");
|
||||
preparedStatement.setString(2, "Benjamin");
|
||||
preparedStatement.setString(3, "Franklin");
|
||||
preparedStatement.setDate(4, new Date(Calendar.getInstance().getTimeInMillis()));
|
||||
preparedStatement.executeBatch();
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.baeldung.jstl.dbaccess;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
public class SQLConnection {
|
||||
private static String userName = "root";
|
||||
private static String password = "";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SQLConnection.class.getName());
|
||||
|
||||
public static Connection getConnection() throws Exception {
|
||||
LOGGER.error("connecting...");
|
||||
Class.forName("com.mysql.cj.jdbc.Driver");
|
||||
LOGGER.error("class checked...");
|
||||
Connection conn = null;
|
||||
Properties connectionProps = new Properties();
|
||||
connectionProps.put("user", userName);
|
||||
connectionProps.put("password", password);
|
||||
conn = DriverManager.getConnection(
|
||||
"jdbc:mysql://localhost:3306/test?autoReconnect=true&useSSL=false",
|
||||
connectionProps);
|
||||
LOGGER.info("Connected to database");
|
||||
return conn;
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@
|
||||
</mvc:message-converters>
|
||||
</mvc:annotation-driven>
|
||||
|
||||
<context:component-scan base-package="com.baeldung.spring.controller"/>
|
||||
<context:component-scan base-package="com.baeldung.spring.controller, com.baeldung.jstl.controllers"/>
|
||||
|
||||
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||
<property name="prefix" value="/WEB-INF/view/"/>
|
||||
|
27
spring-mvc-xml/src/main/webapp/WEB-INF/items.xsl
Normal file
27
spring-mvc-xml/src/main/webapp/WEB-INF/items.xsl
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version = "1.0"?>
|
||||
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0">
|
||||
|
||||
<xsl:output method = "html" indent = "yes"/>
|
||||
<xsl:param name = "bgColor"/>
|
||||
|
||||
<xsl:template match = "/">
|
||||
<html>
|
||||
<body>
|
||||
<xsl:apply-templates/>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match = "items">
|
||||
<table border = "1" width = "40%" bgColor = "{$bgColor}">
|
||||
<xsl:for-each select = "item">
|
||||
<tr>
|
||||
<td><i><xsl:value-of select = "name"/></i></td>
|
||||
<td><xsl:value-of select = "category"/></td>
|
||||
<td><xsl:value-of select = "price"/></td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
@ -7,7 +7,7 @@
|
||||
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
|
||||
<context:component-scan base-package="com.baeldung.spring.controller"/>
|
||||
<context:component-scan base-package="com.baeldung.spring.controller, com.baeldung.jstl.controllers"/>
|
||||
|
||||
<!-- Start: Mapping by bean name (BeanNameUrlHandlerMapping) -->
|
||||
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
|
||||
@ -40,12 +40,6 @@
|
||||
<bean id="helloController" class="com.baeldung.spring.controller.HelloController"/>
|
||||
<!-- End: Mapping by SimpleUrlHandlerMapping -->
|
||||
|
||||
<!-- Start: Mapping by ControllerClassNameHandlerMapping -->
|
||||
<bean
|
||||
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
|
||||
<property name="caseSensitive" value="true"/>
|
||||
<property name="order" value="0"/>
|
||||
</bean>
|
||||
|
||||
<bean class="com.baeldung.spring.controller.HelloGuestController"/>
|
||||
<!-- End: Mapping by ControllerClassNameHandlerMapping -->
|
||||
|
92
spring-mvc-xml/src/main/webapp/WEB-INF/view/core_tags.jsp
Normal file
92
spring-mvc-xml/src/main/webapp/WEB-INF/view/core_tags.jsp
Normal file
@ -0,0 +1,92 @@
|
||||
<%@ page import="java.util.Random" %>
|
||||
<%@ page import="java.util.Date" %>
|
||||
<%@ page import="java.util.Calendar" %>
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<html>
|
||||
<head>
|
||||
<c:set value="JSTL Core Tags Example" var="pageTitle"/>
|
||||
<title>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</h1>
|
||||
<c:remove var="pageTitle"/>
|
||||
<p><c:out value="${pageTitle}"/></p>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="<c:catch> Example"/>
|
||||
</h3>
|
||||
<c:catch var ="exceptionThrown">
|
||||
<% int x = Integer.valueOf("a");%>
|
||||
</c:catch>
|
||||
|
||||
<c:if test = "${exceptionThrown != null}">
|
||||
<p>The exception is : ${exceptionThrown} <br />
|
||||
There is an exception: ${exceptionThrown.message}</p>
|
||||
</c:if>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<c:choose> Example"/>
|
||||
<c:set value="<%= Calendar.getInstance().get(Calendar.SECOND)%>" var="seconds"/>
|
||||
</h3>
|
||||
<p>
|
||||
<c:choose>
|
||||
<c:when test="${seconds le 30 }">
|
||||
<c:out value="${seconds} is less than 30"/>
|
||||
</c:when>
|
||||
<c:when test="${seconds eq 30 }">
|
||||
<c:out value="${seconds} is equal to 30"/>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<c:out value="${seconds} is greater than 30"/>
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="<c:import> Example"/>
|
||||
</h3>
|
||||
|
||||
<c:import var = "data" url = "http://www.example.com"/>
|
||||
<c:out value = "${data}"/>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<c:forEach> Example"/>
|
||||
</h3>
|
||||
|
||||
<c:forEach var = "i" items="1,4,5,6,7,8,9">
|
||||
Item <c:out value = "No. ${i}"/><p>
|
||||
</c:forEach>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<c:forToken> Example"/>
|
||||
</h3>
|
||||
|
||||
<c:forTokens items = "Patrick:Wilson:Ibrahima:Chris" delims = ":" var = "name">
|
||||
<c:out value = "Name: ${name}"/><p>
|
||||
</c:forTokens>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<c:url> and <c:param> Example"/>
|
||||
</h3>
|
||||
<c:url value = "/core_tags" var = "myURL">
|
||||
<c:param name = "parameter_1" value = "1234"/>
|
||||
<c:param name = "parameter_2" value = "abcd"/>
|
||||
</c:url>
|
||||
<c:out value = "URL: ${myURL}"/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,16 @@
|
||||
<%@ page import="java.util.Random" %>
|
||||
<%@ page import="java.util.Date" %>
|
||||
<%@ page import="java.util.Calendar" %>
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<html>
|
||||
<head>
|
||||
<c:set value="JSTL Core Tags Examples" var="pageTitle"/>
|
||||
<title>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
<c:redirect url="/core_tags"/>
|
||||
</body>
|
||||
</html>
|
213
spring-mvc-xml/src/main/webapp/WEB-INF/view/formatting_tags.jsp
Normal file
213
spring-mvc-xml/src/main/webapp/WEB-INF/view/formatting_tags.jsp
Normal file
@ -0,0 +1,213 @@
|
||||
<%@ page import="java.util.Calendar" %>
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
|
||||
<html>
|
||||
<head>
|
||||
<c:set value="JSTL Formatting Tags Example" var="pageTitle"/>
|
||||
<title>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</h1>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="<fmt:formatNumber> Example"/>
|
||||
</h3>
|
||||
<c:set var="fee" value="35050.1067"/>
|
||||
|
||||
<p>Formatted Number - Currency: <fmt:formatNumber value="${fee}"
|
||||
type="currency"/></p>
|
||||
|
||||
<p>Formatted Number - Maximum Integer Digits: <fmt:formatNumber type="number"
|
||||
maxIntegerDigits="2" value="${fee}"/></p>
|
||||
|
||||
<p>Formatted Number - Maximum Fraction Digits: <fmt:formatNumber type="number"
|
||||
maxFractionDigits="2" value="${fee}"/></p>
|
||||
|
||||
<p>Formatted Number - Grouping: <fmt:formatNumber type="number"
|
||||
groupingUsed="false" value="${fee}"/></p>
|
||||
|
||||
<p>Formatted Number - Percent with Maximum Integer Digits: <fmt:formatNumber type="percent"
|
||||
maxIntegerDigits="3"
|
||||
value="${fee}"/></p>
|
||||
|
||||
<p>Formatted Number - Percent with Minimum Fraction Digits: <fmt:formatNumber type="percent"
|
||||
minFractionDigits="10"
|
||||
value="${fee}"/></p>
|
||||
|
||||
<p>Formatted Number Percent with Minimum Integer Digits: <fmt:formatNumber type="percent"
|
||||
minIntegerDigits="4" value="${fee}"/></p>
|
||||
|
||||
<p>Formatted Number - with Pattern: <fmt:formatNumber type="number"
|
||||
pattern="###.##E0" value="${fee}"/></p>
|
||||
|
||||
<p>Formatted Number - Currency with Internationalization :
|
||||
<fmt:setLocale value="en_US"/>
|
||||
<fmt:formatNumber value="${fee}" type="currency"/>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<fmt:parseNumber> Example"/>
|
||||
</h3>
|
||||
<fmt:parseNumber var="i" type="number" value="${fee}"/>
|
||||
<p>Parsed Number : <c:out value="${i}"/></p>
|
||||
<fmt:parseNumber var="i" integerOnly="true"
|
||||
type="number" value="${fee}"/>
|
||||
<p>Parsed Number - with Integer Only set to True: <c:out value="${i}"/></p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="<fmt:formatDate> Example"/>
|
||||
<c:set var="now" value="<%= new java.util.Date()%>"/>
|
||||
</h3>
|
||||
|
||||
<p>Formatted Date - with type set to time: <fmt:formatDate type="time"
|
||||
value="${now}"/></p>
|
||||
|
||||
<p>Formatted Date - with type set to date: <fmt:formatDate type="date"
|
||||
value="${now}"/></p>
|
||||
|
||||
<p>Formatted Date - with type set to both: <fmt:formatDate type="both"
|
||||
value="${now}"/></p>
|
||||
|
||||
<p>Formatted Date - with short style for both date and time: <fmt:formatDate type="both"
|
||||
dateStyle="short" timeStyle="short"
|
||||
value="${now}"/></p>
|
||||
|
||||
<p>Formatted Date - with medium style for both date and time: <fmt:formatDate type="both"
|
||||
dateStyle="medium" timeStyle="medium"
|
||||
value="${now}"/></p>
|
||||
|
||||
<p>Formatted Date - with long style for both date and time: <fmt:formatDate type="both"
|
||||
dateStyle="long" timeStyle="long"
|
||||
value="${now}"/></p>
|
||||
|
||||
<p>Formatted Date - with pattern: <fmt:formatDate pattern="yyyy-MM-dd"
|
||||
value="${now}"/></p>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<fmt:parseDate> Example"/>
|
||||
</h3>
|
||||
|
||||
<c:set var="today" value="28-03-2018"/>
|
||||
<fmt:parseDate value="${today}" var="parsedDate" pattern="dd-MM-yyyy"/>
|
||||
<p>Parsed Date: <c:out value="${parsedDate}"/></p>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<fmt:bundle> and <fmt:message> Example"/>
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<fmt:bundle basename="com.baeldung.jstl.bundles.CustomMessage" prefix="verb.">
|
||||
<fmt:message key="go"/><br/>
|
||||
<fmt:message key="come"/><br/>
|
||||
<fmt:message key="sit"/><br/>
|
||||
<fmt:message key="stand"/><br/>
|
||||
</fmt:bundle>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<fmt:setLocale> Example"/>
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<fmt:setLocale value="fr_FR"/>
|
||||
<fmt:bundle basename="com.baeldung.jstl.bundles.CustomMessage" prefix="verb.">
|
||||
<fmt:message key="go"/><br/>
|
||||
<fmt:message key="come"/><br/>
|
||||
<fmt:message key="sit"/><br/>
|
||||
<fmt:message key="stand"/><br/>
|
||||
</fmt:bundle>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<fmt:setBundle> Example"/>
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<fmt:setLocale value="En"/>
|
||||
<fmt:setBundle basename="com.baeldung.jstl.bundles.CustomMessage" var="lang"/>
|
||||
<fmt:message key="verb.go" bundle="${lang}"/><br/>
|
||||
<fmt:message key="verb.come" bundle="${lang}"/><br/>
|
||||
<fmt:message key="verb.sit" bundle="${lang}"/><br/>
|
||||
<fmt:message key="verb.stand" bundle="${lang}"/><br/>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<fmt:timeZone> Example"/>
|
||||
</h3>
|
||||
<table border="1" width="40%">
|
||||
<tr>
|
||||
<td width="100%" colspan="2">
|
||||
<p align="center">
|
||||
<b>
|
||||
<font size="4">Time being formatted:
|
||||
<fmt:formatDate value="${now}" type="both"
|
||||
timeStyle="long" dateStyle="long"/>
|
||||
</font>
|
||||
</b>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<c:forEach var="zone"
|
||||
items="<%= java.util.TimeZone.getAvailableIDs()%>" end="4">
|
||||
<tr>
|
||||
<td width="51%">
|
||||
<c:out value="${zone}"/>
|
||||
</td>
|
||||
<td width="49%">
|
||||
<fmt:timeZone value="${zone}">
|
||||
<fmt:formatDate value="${now}" timeZone="${zn}"
|
||||
type="both"/>
|
||||
</fmt:timeZone>
|
||||
</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<fmt:setTimeZone> Example"/>
|
||||
</h3>
|
||||
|
||||
<p>Current Date with Default Time Zone: <fmt:formatDate value="${now}"
|
||||
type="both" timeStyle="long" dateStyle="long"/></p>
|
||||
<p>Change Time Zone to GMT+9</p>
|
||||
<fmt:setTimeZone value="GMT+9"/>
|
||||
<p>Date in Changed Zone: <fmt:formatDate value="${now}"
|
||||
type="both" timeStyle="long" dateStyle="long"/></p>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<fmt:requestEncoding> Example"/>
|
||||
</h3>
|
||||
<fmt:requestEncoding value = "UTF-8" />
|
||||
<fmt:setLocale value = "fr_FR"/>
|
||||
<fmt:setBundle basename = "com.baeldung.jstl.bundles.CustomMessage" var = "lang"/>
|
||||
<fmt:message key="verb.go" bundle="${lang}"/><br/>
|
||||
<fmt:message key="verb.come" bundle="${lang}"/><br/>
|
||||
<fmt:message key="verb.sit" bundle="${lang}"/><br/>
|
||||
<fmt:message key="verb.stand" bundle="${lang}"/><br/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
151
spring-mvc-xml/src/main/webapp/WEB-INF/view/function_tags.jsp
Normal file
151
spring-mvc-xml/src/main/webapp/WEB-INF/view/function_tags.jsp
Normal file
@ -0,0 +1,151 @@
|
||||
<%@ page import="java.util.Random" %>
|
||||
<%@ page import="java.util.Date" %>
|
||||
<%@ page import="java.util.Calendar" %>
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix = "fn"
|
||||
uri = "http://java.sun.com/jsp/jstl/functions" %>
|
||||
<html>
|
||||
<head>
|
||||
<c:set value="JSTL Function Tags Example" var="pageTitle"/>
|
||||
<title>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</h1>
|
||||
<c:set var = "string1" value = "This is first string"/>
|
||||
<c:set var = "string2" value = "This is second string with <tag>test XML</tag>"/>
|
||||
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:contains() Example"/>
|
||||
</h3>
|
||||
<c:if test = "${fn:contains(string1, 'first')}">
|
||||
<p>Found 'first' in string<p>
|
||||
</c:if>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:containsIgnoreCase() Example"/>
|
||||
</h3>
|
||||
<c:if test = "${fn:containsIgnoreCase(string1, 'first')}">
|
||||
<p>Found 'first' string<p>
|
||||
</c:if>
|
||||
|
||||
<c:if test = "${fn:containsIgnoreCase(string1, 'FIRST')}">
|
||||
<p>Found 'FIRST' string<p>
|
||||
</c:if>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:endsWith() Example"/>
|
||||
</h3>
|
||||
<c:if test = "${fn:endsWith(string1, 'string')}">
|
||||
<p>String ends with 'string'<p>
|
||||
</c:if>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:escapeXml() Example"/>
|
||||
</h3>
|
||||
<p>With escapeXml() Function:</p>
|
||||
<p>string (1) : ${fn:escapeXml(string1)}</p>
|
||||
<p>string (2) : ${fn:escapeXml(string2)}</p>
|
||||
|
||||
<p>Without escapeXml() Function:</p>
|
||||
<p>string (1) : ${string1}</p>
|
||||
<p>string (2) : ${string2}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:indexOf() Example"/>
|
||||
</h3>
|
||||
<p>Index (1) : ${fn:indexOf(string1, "first")}</p>
|
||||
<p>Index (2) : ${fn:indexOf(string2, "second")}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:join() and fn:split() Example"/>
|
||||
</h3>
|
||||
<c:set var = "string3" value = "${fn:split(string1, ' ')}" />
|
||||
<c:set var = "string4" value = "${fn:join(string3, '-')}" />
|
||||
<p>Final String : ${string4}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:length() Example"/>
|
||||
</h3>
|
||||
<p>Length of String (1) : ${fn:length(string1)}</p>
|
||||
<p>Length of String (2) : ${fn:length(string2)}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:replace() Example"/>
|
||||
</h3>
|
||||
<c:set var = "string3" value = "${fn:replace(string1, 'first', 'third')}" />
|
||||
<p>Final String : ${string3}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:startsWith() Example"/>
|
||||
</h3>
|
||||
<c:if test = "${fn:startsWith(string1, 'This')}">
|
||||
<p>String starts with 'This'</p>
|
||||
</c:if>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:substring() Example"/>
|
||||
</h3>
|
||||
<c:set var = "string3" value = "${fn:substring(string1, 5, 15)}" />
|
||||
|
||||
<p>Final sub string : ${string3}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:substringAfter() Example"/>
|
||||
</h3>
|
||||
<c:set var = "string3" value = "${fn:substringAfter(string1, 'is')}" />
|
||||
|
||||
<p>Final sub string : ${string3}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:substringBefore() Example"/>
|
||||
</h3>
|
||||
<c:set var = "string3" value = "${fn:substringBefore(string1, 'is')}" />
|
||||
|
||||
<p>Final sub string : ${string3}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:toLowerCase() Example"/>
|
||||
</h3>
|
||||
<c:set var = "string3" value = "${fn:toLowerCase(string1)}" />
|
||||
|
||||
<p>Final string : ${string3}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:toUpperCase() Example"/>
|
||||
</h3>
|
||||
<c:set var = "string3" value = "${fn:toUpperCase(string1)}" />
|
||||
|
||||
<p>Final string : ${string3}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="fn:trim() Example"/>
|
||||
</h3>
|
||||
<c:set var = "string1" value = "This is first String "/>
|
||||
<p>String (1) Length : ${fn:length(string1)}</p>
|
||||
|
||||
<c:set var = "string2" value = "${fn:trim(string1)}" />
|
||||
<p>String (2) Length : ${fn:length(string2)}</p>
|
||||
<p>Final string : "${string2}"</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
198
spring-mvc-xml/src/main/webapp/WEB-INF/view/sql_tags.jsp
Normal file
198
spring-mvc-xml/src/main/webapp/WEB-INF/view/sql_tags.jsp
Normal file
@ -0,0 +1,198 @@
|
||||
<%@ page import="java.util.Random" %>
|
||||
<%@ page import="java.util.Date" %>
|
||||
<%@ page import="java.util.Calendar" %>
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
|
||||
<html>
|
||||
<head>
|
||||
<c:set value="JSTL SQL Tags Example" var="pageTitle"/>
|
||||
<title>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</h1>
|
||||
<!--
|
||||
sql:setDataSource Example
|
||||
-->
|
||||
<sql:setDataSource var="dataSource" driver="com.mysql.cj.jdbc.Driver"
|
||||
url="jdbc:mysql://localhost/test"
|
||||
user="root" password=""/>
|
||||
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<sql:query> Example"/>
|
||||
</h3>
|
||||
<sql:query dataSource="${dataSource}" var="result">
|
||||
SELECT * from USERS;
|
||||
</sql:query>
|
||||
<table border="1" width="50%">
|
||||
<tr>
|
||||
<th>User ID</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Email</th>
|
||||
<th>Registered</th>
|
||||
</tr>
|
||||
|
||||
<c:forEach var="user" items="${result.rows}" varStatus="iterator">
|
||||
<tr>
|
||||
<td><c:out value="${iterator.index + 1}"/></td>
|
||||
<td><c:out value="${user.first_name}"/></td>
|
||||
<td><c:out value="${user.last_name}"/></td>
|
||||
<td><c:out value="${user.email}"/></td>
|
||||
<td><c:out value="${user.registered}"/></td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="<sql:update> Example"/>
|
||||
</h3>
|
||||
|
||||
<sql:update dataSource="${dataSource}" var="count">
|
||||
INSERT INTO USERS(first_name, last_name, email) VALUES ('Grace', 'Adams', 'gracea@domain.com');
|
||||
</sql:update>
|
||||
<sql:query dataSource="${dataSource}" var="result">
|
||||
SELECT * from USERS;
|
||||
</sql:query>
|
||||
<table border="1" width="50%">
|
||||
<tr>
|
||||
<th>User ID</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Email</th>
|
||||
<th>Registered</th>
|
||||
</tr>
|
||||
|
||||
<c:forEach var="user" items="${result.rows}" varStatus="iterator">
|
||||
<tr>
|
||||
<td><c:out value="${iterator.index + 1}"/></td>
|
||||
<td><c:out value="${user.first_name}"/></td>
|
||||
<td><c:out value="${user.last_name}"/></td>
|
||||
<td><c:out value="${user.email}"/></td>
|
||||
<td><c:out value="${user.registered}"/></td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<sql:param> Example"/>
|
||||
</h3>
|
||||
|
||||
<sql:update dataSource = "${dataSource}" var = "count">
|
||||
DELETE FROM USERS WHERE email = ?
|
||||
<sql:param value = "gracea@domain.com" />
|
||||
</sql:update>
|
||||
<sql:query dataSource="${dataSource}" var="result">
|
||||
SELECT * from USERS;
|
||||
</sql:query>
|
||||
<table border="1" width="50%">
|
||||
<tr>
|
||||
<th>User ID</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Email</th>
|
||||
<th>Registered</th>
|
||||
</tr>
|
||||
|
||||
<c:forEach var="user" items="${result.rows}" varStatus="iterator">
|
||||
<tr>
|
||||
<td><c:out value="${iterator.index + 1}"/></td>
|
||||
<td><c:out value="${user.first_name}"/></td>
|
||||
<td><c:out value="${user.last_name}"/></td>
|
||||
<td><c:out value="${user.email}"/></td>
|
||||
<td><c:out value="${user.registered}"/></td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<sql:dateParam> Example"/>
|
||||
</h3>
|
||||
<%
|
||||
Date registered = new Date("2018/03/31");
|
||||
String email = "patrick@baeldung.com";
|
||||
%>
|
||||
|
||||
<sql:update dataSource = "${dataSource}" var = "count">
|
||||
UPDATE Users SET registered = ? WHERE email = ?
|
||||
<sql:dateParam value = "<%=registered%>" type = "DATE" />
|
||||
<sql:param value = "<%=email%>" />
|
||||
</sql:update>
|
||||
<sql:query dataSource="${dataSource}" var="result">
|
||||
SELECT * from USERS;
|
||||
</sql:query>
|
||||
<table border="1" width="50%">
|
||||
<tr>
|
||||
<th>User ID</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Email</th>
|
||||
<th>Registered</th>
|
||||
</tr>
|
||||
|
||||
<c:forEach var="user" items="${result.rows}" varStatus="iterator">
|
||||
<tr>
|
||||
<td><c:out value="${iterator.index + 1}"/></td>
|
||||
<td><c:out value="${user.first_name}"/></td>
|
||||
<td><c:out value="${user.last_name}"/></td>
|
||||
<td><c:out value="${user.email}"/></td>
|
||||
<td><c:out value="${user.registered}"/></td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<sql:transaction> Example"/>
|
||||
</h3>
|
||||
<sql:transaction dataSource = "${dataSource}">
|
||||
<sql:update var = "count">
|
||||
UPDATE Users SET first_name = 'Patrick-Ellis' WHERE email='patrick@baeldung.com'
|
||||
</sql:update>
|
||||
|
||||
<sql:update var = "count">
|
||||
UPDATE Users SET last_name = 'Nelson' WHERE email = 'patrick@baeldung.com'
|
||||
</sql:update>
|
||||
|
||||
<sql:update var = "count">
|
||||
INSERT INTO Users(first_name, last_name, email) VALUES ('Grace', 'Adams', 'gracea@domain.com');
|
||||
</sql:update>
|
||||
</sql:transaction>
|
||||
<sql:query dataSource="${dataSource}" var="result">
|
||||
SELECT * from USERS;
|
||||
</sql:query>
|
||||
<table border="1" width="50%">
|
||||
<tr>
|
||||
<th>User ID</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Email</th>
|
||||
<th>Registered</th>
|
||||
</tr>
|
||||
|
||||
<c:forEach var="user" items="${result.rows}" varStatus="iterator">
|
||||
<tr>
|
||||
<td><c:out value="${iterator.index + 1}"/></td>
|
||||
<td><c:out value="${user.first_name}"/></td>
|
||||
<td><c:out value="${user.last_name}"/></td>
|
||||
<td><c:out value="${user.email}"/></td>
|
||||
<td><c:out value="${user.registered}"/></td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
99
spring-mvc-xml/src/main/webapp/WEB-INF/view/xml_tags.jsp
Normal file
99
spring-mvc-xml/src/main/webapp/WEB-INF/view/xml_tags.jsp
Normal file
@ -0,0 +1,99 @@
|
||||
<%@ page import="java.util.Random" %>
|
||||
<%@ page import="java.util.Date" %>
|
||||
<%@ page import="java.util.Calendar" %>
|
||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
|
||||
<html>
|
||||
<head>
|
||||
<c:set value="JSTL XML Tags Example" var="pageTitle"/>
|
||||
<title>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
<c:out value="${pageTitle}"/>
|
||||
</h1>
|
||||
<c:remove var="pageTitle"/>
|
||||
<p><c:out value="${pageTitle}"/></p>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="<x:transform>, <x::param>, <x:parse>, <x:set>, <x:out>, and <x:if> Examples"/>
|
||||
</h3>
|
||||
<h3>Store Items:</h3>
|
||||
<c:set var="xmltext">
|
||||
<items>
|
||||
<item>
|
||||
<name>Steve Madden</name>
|
||||
<category>Sneakers</category>
|
||||
<price>34</price>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<name>Pearl Izumi</name>
|
||||
<category>Sneakers</category>
|
||||
<price>80</price>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<name>Katy Perry</name>
|
||||
<category>Heels</category>
|
||||
<price>72</price>
|
||||
</item>
|
||||
</items>
|
||||
</c:set>
|
||||
|
||||
<x:parse xml="${xmltext}" var="output"/>
|
||||
<b>The name of the first item listed in the store is</b>:
|
||||
<x:out select="$output/items/item[1]/name"/> with price $<x:out select="$output/items/item[1]/price"/>
|
||||
<br>
|
||||
|
||||
<x:set var="fragment" select="$output//item"/>
|
||||
<b>The second item is </b>:
|
||||
<c:out value="${fragment}"/>
|
||||
|
||||
<x:if select="$output//item">
|
||||
Document has at least one
|
||||
<item> element.
|
||||
</x:if>
|
||||
<br/>
|
||||
|
||||
<c:import url="/items_xml" var="xslt"/>
|
||||
<x:transform xml="${xmltext}" xslt="${xslt}">
|
||||
<x:param name="bgColor" value="blue"/>
|
||||
</x:transform>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
<h3>
|
||||
<c:out value="<x:forEach> Example"/>
|
||||
</h3>
|
||||
<ul class="items">
|
||||
<x:forEach select="$output/items/item/name" var="item">
|
||||
<li>Item Name: <x:out select="$item"/></li>
|
||||
</x:forEach>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3>
|
||||
<c:out value="<x:choose>, <x:when> and <x:otherwise> Example"/>
|
||||
</h3>
|
||||
|
||||
<x:choose>
|
||||
<x:when select="$output//item/category = 'Sneakers'">
|
||||
Item category is Sneakers
|
||||
</x:when>
|
||||
|
||||
<x:when select="$output//item/category = 'Heels'">
|
||||
Item category is Heels
|
||||
</x:when>
|
||||
|
||||
<x:otherwise>
|
||||
Unknown category.
|
||||
</x:otherwise>
|
||||
</x:choose>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -27,3 +27,6 @@ http://localhost:8082/spring-thymeleaf/addStudent/
|
||||
http://localhost:8082/spring-thymeleaf/listStudents/
|
||||
|
||||
The first URL is the home page of the application. The home page has links to the other two pages.
|
||||
|
||||
### Security
|
||||
The user/password required is: user1/user1Pass
|
||||
|
@ -1,210 +1,210 @@
|
||||
<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>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-thymeleaf</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<java-version>1.8</java-version>
|
||||
<!-- spring -->
|
||||
<org.springframework-version>4.3.4.RELEASE</org.springframework-version>
|
||||
<springframework-security.version>4.2.0.RELEASE</springframework-security.version>
|
||||
<javax.servlet-version>3.1.0</javax.servlet-version>
|
||||
<!-- thymeleaf -->
|
||||
<org.thymeleaf-version>3.0.3.RELEASE</org.thymeleaf-version>
|
||||
<org.thymeleaf.extras-version>3.0.0.RELEASE</org.thymeleaf.extras-version>
|
||||
<thymeleaf-layout-dialect.version>2.1.2</thymeleaf-layout-dialect.version>
|
||||
<!-- validation -->
|
||||
<javax.validation-version>1.1.0.Final</javax.validation-version>
|
||||
<hibernate-validator.version>5.3.3.Final</hibernate-validator.version>
|
||||
<org.hibernate-version>5.2.5.Final</org.hibernate-version>
|
||||
|
||||
<!-- Maven plugins -->
|
||||
<maven-war-plugin.version>2.6</maven-war-plugin.version>
|
||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||
<tomcat7-maven-plugin.version>2.2</tomcat7-maven-plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${org.springframework-version}</version>
|
||||
<exclusions>
|
||||
<!-- Exclude Commons Logging in favor of SLF4j -->
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${org.springframework-version}</version>
|
||||
</dependency>
|
||||
<!-- Spring Security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${springframework-security.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>${springframework-security.version}</version>
|
||||
</dependency>
|
||||
<!-- Thymeleaf -->
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf</artifactId>
|
||||
<version>${org.thymeleaf-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-spring4</artifactId>
|
||||
<version>${org.thymeleaf-version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/nz.net.ultraq.thymeleaf/thymeleaf-layout-dialect -->
|
||||
<dependency>
|
||||
<groupId>nz.net.ultraq.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-layout-dialect</artifactId>
|
||||
<version>${thymeleaf-layout-dialect.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf.extras</groupId>
|
||||
<artifactId>thymeleaf-extras-java8time</artifactId>
|
||||
<version>${org.thymeleaf.extras-version}</version>
|
||||
</dependency>
|
||||
<!-- Servlet -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.servlet-version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Validation -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>${javax.validation-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>${hibernate-validator.version}</version>
|
||||
</dependency>
|
||||
<!-- test scoped -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<version>${springframework-security.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.cargo</groupId>
|
||||
<artifactId>cargo-maven2-plugin</artifactId>
|
||||
<version>${cargo-maven2-plugin.version}</version>
|
||||
<configuration>
|
||||
<wait>true</wait>
|
||||
<container>
|
||||
<containerId>jetty8x</containerId>
|
||||
<type>embedded</type>
|
||||
<systemProperties>
|
||||
</systemProperties>
|
||||
</container>
|
||||
<configuration>
|
||||
<properties>
|
||||
<cargo.servlet.port>8082</cargo.servlet.port>
|
||||
</properties>
|
||||
</configuration>
|
||||
</configuration>
|
||||
</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>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>integration</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*IntegrationTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<test.mime>json</test.mime>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<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>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-thymeleaf</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<java-version>1.8</java-version>
|
||||
<!-- spring -->
|
||||
<org.springframework-version>4.3.4.RELEASE</org.springframework-version>
|
||||
<springframework-security.version>4.2.0.RELEASE</springframework-security.version>
|
||||
<javax.servlet-version>3.1.0</javax.servlet-version>
|
||||
<!-- thymeleaf -->
|
||||
<org.thymeleaf-version>3.0.9.RELEASE</org.thymeleaf-version>
|
||||
<org.thymeleaf.extras-version>3.0.0.RELEASE</org.thymeleaf.extras-version>
|
||||
<thymeleaf-layout-dialect.version>2.1.2</thymeleaf-layout-dialect.version>
|
||||
<!-- validation -->
|
||||
<javax.validation-version>1.1.0.Final</javax.validation-version>
|
||||
<hibernate-validator.version>5.3.3.Final</hibernate-validator.version>
|
||||
<org.hibernate-version>5.2.5.Final</org.hibernate-version>
|
||||
|
||||
<!-- Maven plugins -->
|
||||
<maven-war-plugin.version>2.6</maven-war-plugin.version>
|
||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||
<tomcat7-maven-plugin.version>2.2</tomcat7-maven-plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${org.springframework-version}</version>
|
||||
<exclusions>
|
||||
<!-- Exclude Commons Logging in favor of SLF4j -->
|
||||
<exclusion>
|
||||
<groupId>commons-logging</groupId>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${org.springframework-version}</version>
|
||||
</dependency>
|
||||
<!-- Spring Security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${springframework-security.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>${springframework-security.version}</version>
|
||||
</dependency>
|
||||
<!-- Thymeleaf -->
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf</artifactId>
|
||||
<version>${org.thymeleaf-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-spring4</artifactId>
|
||||
<version>${org.thymeleaf-version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/nz.net.ultraq.thymeleaf/thymeleaf-layout-dialect -->
|
||||
<dependency>
|
||||
<groupId>nz.net.ultraq.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf-layout-dialect</artifactId>
|
||||
<version>${thymeleaf-layout-dialect.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf.extras</groupId>
|
||||
<artifactId>thymeleaf-extras-java8time</artifactId>
|
||||
<version>${org.thymeleaf.extras-version}</version>
|
||||
</dependency>
|
||||
<!-- Servlet -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>${javax.servlet-version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Validation -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>${javax.validation-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>${hibernate-validator.version}</version>
|
||||
</dependency>
|
||||
<!-- test scoped -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<version>${springframework-security.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.cargo</groupId>
|
||||
<artifactId>cargo-maven2-plugin</artifactId>
|
||||
<version>${cargo-maven2-plugin.version}</version>
|
||||
<configuration>
|
||||
<wait>true</wait>
|
||||
<container>
|
||||
<containerId>jetty8x</containerId>
|
||||
<type>embedded</type>
|
||||
<systemProperties>
|
||||
</systemProperties>
|
||||
</container>
|
||||
<configuration>
|
||||
<properties>
|
||||
<cargo.servlet.port>8082</cargo.servlet.port>
|
||||
</properties>
|
||||
</configuration>
|
||||
</configuration>
|
||||
</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>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>integration</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*IntegrationTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<test.mime>json</test.mime>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
@ -77,14 +77,14 @@ public class WebMVCConfig extends WebMvcConfigurerAdapter implements Application
|
||||
return resolver;
|
||||
}
|
||||
|
||||
private TemplateEngine templateEngine(ITemplateResolver templateResolver) {
|
||||
SpringTemplateEngine engine = new SpringTemplateEngine();
|
||||
engine.addDialect(new LayoutDialect(new GroupingStrategy()));
|
||||
engine.addDialect(new Java8TimeDialect());
|
||||
engine.setTemplateResolver(templateResolver);
|
||||
engine.setTemplateEngineMessageSource(messageSource());
|
||||
return engine;
|
||||
}
|
||||
private TemplateEngine templateEngine(ITemplateResolver templateResolver) {
|
||||
SpringTemplateEngine engine = new SpringTemplateEngine();
|
||||
engine.addDialect(new LayoutDialect(new GroupingStrategy()));
|
||||
engine.addDialect(new Java8TimeDialect());
|
||||
engine.setTemplateResolver(templateResolver);
|
||||
engine.setTemplateEngineMessageSource(messageSource());
|
||||
return engine;
|
||||
}
|
||||
|
||||
private ITemplateResolver htmlTemplateResolver() {
|
||||
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
|
||||
@ -142,7 +142,8 @@ public class WebMVCConfig extends WebMvcConfigurerAdapter implements Application
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");
|
||||
registry.addResourceHandler("/resources/**", "/css/**")
|
||||
.addResourceLocations("/WEB-INF/resources/", "/WEB-INF/css/");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,33 @@
|
||||
package com.baeldung.thymeleaf.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import com.baeldung.thymeleaf.utils.StudentUtils;
|
||||
|
||||
@Controller
|
||||
public class FragmentsController {
|
||||
|
||||
@GetMapping("/fragments")
|
||||
public String getHome() {
|
||||
return "fragments.html";
|
||||
}
|
||||
|
||||
@GetMapping("/markup")
|
||||
public String markupPage() {
|
||||
return "markup.html";
|
||||
}
|
||||
|
||||
@GetMapping("/params")
|
||||
public String paramsPage() {
|
||||
return "params.html";
|
||||
}
|
||||
|
||||
@GetMapping("/other")
|
||||
public String otherPage(Model model) {
|
||||
model.addAttribute("data", StudentUtils.buildStudents());
|
||||
return "other.html";
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
msg.id=ID
|
||||
msg.name=Name
|
||||
msg.gender=Gender
|
||||
msg.percent=Percentage
|
||||
welcome.message=Welcome Student !!!
|
||||
msg.AddStudent=Add Student
|
||||
msg.ListStudents=List Students
|
||||
msg.Home=Home
|
||||
|
||||
msg.id=ID
|
||||
msg.name=Name
|
||||
msg.gender=Gender
|
||||
msg.percent=Percentage
|
||||
welcome.message=Welcome Student !!!
|
||||
msg.AddStudent=Add Student
|
||||
msg.ListStudents=List Students
|
||||
msg.Home=Home
|
||||
|
||||
|
13
spring-thymeleaf/src/main/webapp/WEB-INF/css/styles.css
Normal file
13
spring-thymeleaf/src/main/webapp/WEB-INF/css/styles.css
Normal file
@ -0,0 +1,13 @@
|
||||
body {
|
||||
background-color: lightGray
|
||||
}
|
||||
|
||||
.dark {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.light {
|
||||
background-color: #f1f1f1;
|
||||
color: #ccc;
|
||||
}
|
@ -1,43 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>Add Student</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Add Student</h1>
|
||||
<form action="#" th:action="@{/saveStudent}" th:object="${student}"
|
||||
method="post">
|
||||
<ul>
|
||||
<li th:errors="*{id}" />
|
||||
<li th:errors="*{name}" />
|
||||
<li th:errors="*{gender}" />
|
||||
<li th:errors="*{percentage}" />
|
||||
</ul>
|
||||
<table border="1">
|
||||
<tr>
|
||||
<td><label th:text="#{msg.id}" /></td>
|
||||
<td><input type="number" th:field="*{id}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label th:text="#{msg.name}" /></td>
|
||||
<td><input type="text" th:field="*{name}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label th:text="#{msg.gender}" /></td>
|
||||
<td><select th:field="*{gender}">
|
||||
<option th:value="'M'" th:text="Male"></option>
|
||||
<option th:value="'F'" th:text="Female"></option>
|
||||
</select></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label th:text="#{msg.percent}" /></td>
|
||||
<td><input type="text" th:field="*{percentage}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="submit" value="Submit" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>Add Student</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Add Student</h1>
|
||||
<form action="#" th:action="@{/saveStudent}" th:object="${student}"
|
||||
method="post">
|
||||
<ul>
|
||||
<li th:errors="*{id}" />
|
||||
<li th:errors="*{name}" />
|
||||
<li th:errors="*{gender}" />
|
||||
<li th:errors="*{percentage}" />
|
||||
</ul>
|
||||
<table border="1">
|
||||
<tr>
|
||||
<td><label th:text="#{msg.id}" /></td>
|
||||
<td><input type="number" th:field="*{id}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label th:text="#{msg.name}" /></td>
|
||||
<td><input type="text" th:field="*{name}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label th:text="#{msg.gender}" /></td>
|
||||
<td><select th:field="*{gender}">
|
||||
<option th:value="'M'" th:text="Male"></option>
|
||||
<option th:value="'F'" th:text="Female"></option>
|
||||
</select></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label th:text="#{msg.percent}" /></td>
|
||||
<td><input type="text" th:field="*{percentage}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="submit" value="Submit" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>Thymeleaf Fragments: home</title>
|
||||
<!--/*/ <th:block th:include="fragments/general.html :: headerfiles"></th:block> /*/-->
|
||||
</head>
|
||||
<body>
|
||||
<header th:insert="fragments/general.html :: header"> </header>
|
||||
<p>Go to the next page to see fragments in action</p>
|
||||
<div th:replace="fragments/general.html :: footer"></div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,12 @@
|
||||
<div th:fragment="formField (field, value, size)">
|
||||
<div>
|
||||
<label th:for="${#strings.toLowerCase(field)}"> <span
|
||||
th:text="${field}">Field</span>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" th:id="${#strings.toLowerCase(field)}"
|
||||
th:name="${#strings.toLowerCase(field)}" th:value="${value}"
|
||||
th:size="${size}">
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head th:fragment="headerfiles">
|
||||
<meta charset="UTF-8" />
|
||||
<link th:href="@{/css/styles.css}" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div th:fragment="header">
|
||||
<h1>Thymeleaf Fragments sample</h1>
|
||||
</div>
|
||||
<p>Go to the next page to see fragments in action</p>
|
||||
<aside>
|
||||
<div>This is a sidebar</div>
|
||||
</aside>
|
||||
<div class="another">This is another sidebar</div>
|
||||
<footer th:fragment="footer">
|
||||
<a th:href="@{/fragments}">Fragments Index</a> |
|
||||
<a th:href="@{/markup}">Markup inclussion</a> |
|
||||
<a th:href="@{/params}">Fragment params</a> |
|
||||
<a th:href="@{/other}">Other</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,2 @@
|
||||
<div th:fragment="dataPresent">Data received</div>
|
||||
<div th:fragment="noData">No data</div>
|
@ -0,0 +1 @@
|
||||
<div><p id="parag">This is a subtitle</p></div>
|
@ -0,0 +1,14 @@
|
||||
<table>
|
||||
<thead th:fragment="fields(theadFields)">
|
||||
<tr th:replace="${theadFields}">
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody th:fragment="tableBody(tableData)">
|
||||
<tr th:each="row: ${tableData}">
|
||||
<td th:text="${row.id}">0</td>
|
||||
<td th:text="${row.name}">Name</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
</tfoot>
|
||||
</table>
|
@ -1,45 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>Student List</title>
|
||||
</head>
|
||||
<script type="text/javascript"
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$.ajax({
|
||||
url : "/spring-thymeleaf/js",
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<body>
|
||||
<h1>Student List</h1>
|
||||
<table border="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th th:text="#{msg.id}" />
|
||||
<th th:text="#{msg.name}" />
|
||||
<th th:text="#{msg.gender}" />
|
||||
<th th:text="#{msg.percent}" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="student: ${students}">
|
||||
<td th:text="${student.id}" />
|
||||
<td th:text="${{student.name}}" />
|
||||
<td th:switch="${student.gender}"><span th:case="'M'"
|
||||
th:text="Male" /> <span th:case="'F'" th:text="Female" /></td>
|
||||
<td th:text="${#conversions.convert(student.percentage, 'Integer')}" />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div>
|
||||
<p>
|
||||
<a th:href="@{/}" th:text="#{msg.Home}" />
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>Student List</title>
|
||||
</head>
|
||||
<script type="text/javascript"
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$.ajax({
|
||||
url : "/spring-thymeleaf/js",
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<body>
|
||||
<h1>Student List</h1>
|
||||
<table border="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th th:text="#{msg.id}" />
|
||||
<th th:text="#{msg.name}" />
|
||||
<th th:text="#{msg.gender}" />
|
||||
<th th:text="#{msg.percent}" />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="student: ${students}">
|
||||
<td th:text="${student.id}" />
|
||||
<td th:text="${{student.name}}" />
|
||||
<td th:switch="${student.gender}"><span th:case="'M'"
|
||||
th:text="Male" /> <span th:case="'F'" th:text="Female" /></td>
|
||||
<td th:text="${#conversions.convert(student.percentage, 'Integer')}" />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div>
|
||||
<p>
|
||||
<a th:href="@{/}" th:text="#{msg.Home}" />
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
13
spring-thymeleaf/src/main/webapp/WEB-INF/views/markup.html
Normal file
13
spring-thymeleaf/src/main/webapp/WEB-INF/views/markup.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Thymeleaf Fragments: markup</title>
|
||||
</head>
|
||||
<body>
|
||||
<header th:insert="fragments/general.html :: header"> </header>
|
||||
<div th:replace="fragments/general.html :: aside"></div>
|
||||
<div th:replace="fragments/general.html :: div.another"></div>
|
||||
<div th:replace="fragments/general.html :: footer"></div>
|
||||
</body>
|
||||
</html>
|
27
spring-thymeleaf/src/main/webapp/WEB-INF/views/other.html
Normal file
27
spring-thymeleaf/src/main/webapp/WEB-INF/views/other.html
Normal file
@ -0,0 +1,27 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title>Thymeleaf Fragments: other</title>
|
||||
</head>
|
||||
<body>
|
||||
<header th:replace="fragments/general.html :: header"> </header>
|
||||
<div
|
||||
th:replace="${#lists.size(data) > 0} ?
|
||||
~{fragments/menus.html :: dataPresent} :
|
||||
~{fragments/menus.html :: noData}">
|
||||
</div>
|
||||
<table>
|
||||
<thead
|
||||
th:replace="fragments/tables.html :: fields(~{ :: .myFields})">
|
||||
<tr class="myFields">
|
||||
|
||||
<th>Id</th>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<div
|
||||
th:replace="fragments/tables.html :: tableBody(tableData=${data})"></div>
|
||||
</table>
|
||||
<div th:replace="fragments/general.html :: footer"></div>
|
||||
</body>
|
||||
</html>
|
14
spring-thymeleaf/src/main/webapp/WEB-INF/views/params.html
Normal file
14
spring-thymeleaf/src/main/webapp/WEB-INF/views/params.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Thymeleaf Fragments: params</title>
|
||||
</head>
|
||||
<body>
|
||||
<header th:insert="fragments/general.html :: header"> </header>
|
||||
<div
|
||||
th:replace="fragments/forms.html :: formField(field='Name', value='John Doe',size='40')">
|
||||
</div>
|
||||
<div th:replace="fragments/general.html :: footer"></div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,90 @@
|
||||
package com.baeldung.thymeleaf.controller;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.RequestPostProcessor;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.baeldung.thymeleaf.config.InitSecurity;
|
||||
import com.baeldung.thymeleaf.config.WebApp;
|
||||
import com.baeldung.thymeleaf.config.WebMVCConfig;
|
||||
import com.baeldung.thymeleaf.config.WebMVCSecurity;
|
||||
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration(classes = { WebApp.class, WebMVCConfig.class, WebMVCSecurity.class, InitSecurity.class })
|
||||
public class FragmentsTest {
|
||||
|
||||
@Autowired
|
||||
WebApplicationContext wac;
|
||||
@Autowired
|
||||
MockHttpSession session;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private Filter springSecurityFilterChain;
|
||||
|
||||
private RequestPostProcessor testUser() {
|
||||
return user("user1").password("user1Pass").roles("USER");
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build();
|
||||
}
|
||||
@Test
|
||||
public void whenAccessingFragmentsRoute_thenViewHasExpectedContent() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/fragments").with(testUser()))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("<title>Thymeleaf Fragments: home</title>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAccessingParamsRoute_thenViewHasExpectedContent() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/params").with(testUser()))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("<span>Name</span>")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAccessingMarkupRoute_thenViewHasExpectedContent() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/markup").with(testUser()))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("<div class=\"another\">This is another sidebar</div>")));
|
||||
}
|
||||
@Test
|
||||
public void whenAccessingOtherRoute_thenViewHasExpectedContent() throws Exception {
|
||||
this.mockMvc
|
||||
.perform(get("/other").with(testUser()))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("<td>John Smith</td>")));
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ public class BaeldungReaderMockDelegationTest {
|
||||
EasyMockSupport easyMockSupport = new EasyMockSupport();
|
||||
|
||||
@Test
|
||||
public void givenBaeldungReader_whenReadAndWrite_thenOperationSupported() {
|
||||
public void givenBaeldungReader_whenReadAndWriteSequencially_thenWorks() {
|
||||
ArticleReader mockArticleReader = easyMockSupport.createMock(ArticleReader.class);
|
||||
IArticleWriter mockArticleWriter = easyMockSupport.createMock(IArticleWriter.class);
|
||||
BaeldungReader baeldungReader = new BaeldungReader(mockArticleReader, mockArticleWriter);
|
||||
|
@ -17,7 +17,7 @@ public class BaeldungReaderMockSupportTest extends EasyMockSupport {
|
||||
@Mock IArticleWriter mockArticleWriter;
|
||||
|
||||
@Test
|
||||
public void givenBaeldungReader_whenReadAndWrite_thenOperationSupported() {
|
||||
public void givenBaeldungReader_whenReadAndWriteSequencially_thenWorks() {
|
||||
expect(mockArticleReader.next())
|
||||
.andReturn(null)
|
||||
.times(2)
|
||||
|
Loading…
x
Reference in New Issue
Block a user