Merge branch 'masterupstream' into beforeAfterAnnotationsJunit
This commit is contained in:
commit
74e66a8ba9
|
@ -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>
|
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
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
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -0,0 +1,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>RESOURCE NOT FOUND</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>404 RESOURCE NOT FOUND</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -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/"/>
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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…
Reference in New Issue