Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Kevin Gilmore 2016-12-17 07:58:33 -06:00
commit 45ab03cc51
54 changed files with 180346 additions and 382 deletions

View File

@ -51,6 +51,18 @@
<artifactId>bcprov-jdk15on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<dependency>
<groupId>org.unix4j</groupId>
<artifactId>unix4j-command</artifactId>
<version>0.4</version>
</dependency>
<dependency>
<groupId>com.googlecode.grep4j</groupId>
<artifactId>grep4j</artifactId>
<version>1.8.7</version>
</dependency>
<!-- web -->
<!-- marshalling -->
@ -85,9 +97,22 @@
<artifactId>log4j-over-slf4j</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.12</version>
<scope>provided</scope>
</dependency>
<!-- test scoped -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@ -236,8 +261,7 @@
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.baeldung.executable.ExecutableMavenJar</mainClass>
</transformer>
</transformers>

View File

@ -0,0 +1,22 @@
package com.baeldung.algorithms;
import lombok.Data;
@Data
public class City {
private int x;
private int y;
public City() {
this.x = (int) (Math.random() * 500);
this.y = (int) (Math.random() * 500);
}
public double distanceToCity(City city) {
int x = Math.abs(getX() - city.getX());
int y = Math.abs(getY() - city.getY());
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}
}

View File

@ -0,0 +1,40 @@
package com.baeldung.algorithms;
public class SimulatedAnnealing {
private static Travel travel = new Travel(10);
public static double simulateAnnealing(double startingTemperature, int numberOfIterations, double coolingRate) {
System.out.println("Starting SA with temperature: " + startingTemperature + ", # of iterations: " + numberOfIterations + " and colling rate: " + coolingRate);
double t = startingTemperature;
travel.generateInitialTravel();
double bestDistance = travel.getDistance();
System.out.println("Initial distance of travel: " + bestDistance);
Travel bestSolution = travel;
Travel currentSolution = bestSolution;
for (int i = 0; i < numberOfIterations; i++) {
if (t > 0.1) {
currentSolution.swapCities();
double currentDistance = currentSolution.getDistance();
if (currentDistance == 0)
continue;
if (currentDistance < bestDistance) {
bestDistance = currentDistance;
} else if (Math.exp((currentDistance - bestDistance) / t) < Math.random()) {
currentSolution.revertSwap();
}
t *= coolingRate;
}
if (i % 100 == 0) {
System.out.println("Iteration #" + i);
}
}
return bestDistance;
}
public static void main(String[] args) {
System.out.println("Optimized distance for travel: " + simulateAnnealing(10, 10000, 0.9));
}
}

View File

@ -0,0 +1,60 @@
package com.baeldung.algorithms;
import java.util.ArrayList;
import java.util.Collections;
import lombok.Data;
@Data
public class Travel {
private ArrayList<City> travel = new ArrayList<>();
private ArrayList<City> previousTravel = new ArrayList<>();
public Travel(int numberOfCities) {
for (int i = 0; i < numberOfCities; i++) {
travel.add(new City());
}
}
public void generateInitialTravel() {
if (travel.isEmpty())
new Travel(10);
Collections.shuffle(travel);
}
public void swapCities() {
int a = generateRandomIndex();
int b = generateRandomIndex();
previousTravel = travel;
travel.set(a, travel.get(b));
}
public void revertSwap() {
travel = previousTravel;
}
private int generateRandomIndex() {
return (int) (Math.random() * travel.size());
}
public City getCity(int index) {
return travel.get(index);
}
public int getDistance() {
int distance = 0;
for (int index = 0; index < travel.size(); index++) {
City starting = getCity(index);
City destination;
if (index + 1 < travel.size()) {
destination = getCity(index + 1);
} else {
destination = getCity(0);
}
distance += starting.distanceToCity(destination);
}
return distance;
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.algorithms;
import org.junit.Assert;
import org.junit.Test;
public class SimulatedAnnealingTest {
@Test
public void testSimulateAnnealing() {
Assert.assertTrue(SimulatedAnnealing.simulateAnnealing(10, 1000, 0.9) > 0);
}
}

View File

@ -22,7 +22,6 @@ public class EncoderDecoderUnitTest {
private static final String testUrl = "http://www.baeldung.com?key1=value+1&key2=value%40%21%242&key3=value%253";
private static final String testUrlWithPath = "http://www.baeldung.com/path+1?key1=value+1&key2=value%40%21%242&key3=value%253";
private String encodeValue(String value) {
String encoded = null;
try {
@ -59,9 +58,7 @@ public class EncoderDecoderUnitTest {
requestParams.put("key2", "value@!$2");
requestParams.put("key3", "value%3");
String encodedURL = requestParams.keySet().stream()
.map(key -> key + "=" + encodeValue(requestParams.get(key)))
.collect(joining("&", "http://www.baeldung.com?", ""));
String encodedURL = requestParams.keySet().stream().map(key -> key + "=" + encodeValue(requestParams.get(key))).collect(joining("&", "http://www.baeldung.com?", ""));
Assert.assertThat(testUrl, is(encodedURL));
}
@ -103,12 +100,9 @@ public class EncoderDecoderUnitTest {
String path = "path+1";
String encodedURL = requestParams.keySet().stream()
.map(key -> key + "=" + encodeValue(requestParams.get(key)))
.collect(joining("&", "http://www.baeldung.com/" + encodePath(path) + "?", ""));
String encodedURL = requestParams.keySet().stream().map(key -> key + "=" + encodeValue(requestParams.get(key))).collect(joining("&", "http://www.baeldung.com/" + encodePath(path) + "?", ""));
Assert.assertThat(testUrlWithPath, is(encodedURL));
}
}

View File

@ -17,9 +17,7 @@ public class Java8CollectionCleanupUnitTest {
@Test
public void givenListContainsNulls_whenFilteringParallel_thenCorrect() {
final List<Integer> list = Lists.newArrayList(null, 1, 2, null, 3, null);
final List<Integer> listWithoutNulls = list.parallelStream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
final List<Integer> listWithoutNulls = list.parallelStream().filter(Objects::nonNull).collect(Collectors.toList());
assertThat(listWithoutNulls, hasSize(3));
}
@ -27,9 +25,7 @@ public class Java8CollectionCleanupUnitTest {
@Test
public void givenListContainsNulls_whenFilteringSerial_thenCorrect() {
final List<Integer> list = Lists.newArrayList(null, 1, 2, null, 3, null);
final List<Integer> listWithoutNulls = list.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
final List<Integer> listWithoutNulls = list.stream().filter(Objects::nonNull).collect(Collectors.toList());
assertThat(listWithoutNulls, hasSize(3));
}
@ -45,9 +41,7 @@ public class Java8CollectionCleanupUnitTest {
@Test
public void givenListContainsDuplicates_whenRemovingDuplicatesWithJava8_thenCorrect() {
final List<Integer> listWithDuplicates = Lists.newArrayList(1, 1, 2, 2, 3, 3);
final List<Integer> listWithoutDuplicates = listWithDuplicates.parallelStream()
.distinct()
.collect(Collectors.toList());
final List<Integer> listWithoutDuplicates = listWithDuplicates.parallelStream().distinct().collect(Collectors.toList());
assertThat(listWithoutDuplicates, hasSize(3));
}

View File

@ -0,0 +1,65 @@
package com.baeldung.java8;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Test;
public class JavaFileSizeUnitTest {
private static final long EXPECTED_FILE_SIZE_IN_BYTES = 11;
private String filePath;
@Before
public void init() {
final String separator = File.separator;
filePath = String.join(separator, new String[] { "src", "test", "resources", "testFolder", "sample_file_1.in" });
}
@Test
public void whenGetFileSize_thenCorrect() {
final File file = new File(filePath);
final long size = getFileSize(file);
assertEquals(EXPECTED_FILE_SIZE_IN_BYTES, size);
}
@Test
public void whenGetFileSizeUsingNioApi_thenCorrect() throws IOException {
final Path path = Paths.get(this.filePath);
final FileChannel fileChannel = FileChannel.open(path);
final long fileSize = fileChannel.size();
assertEquals(EXPECTED_FILE_SIZE_IN_BYTES, fileSize);
}
@Test
public void whenGetFileSizeUsingApacheCommonsIO_thenCorrect() {
final File file = new File(filePath);
final long size = FileUtils.sizeOf(file);
assertEquals(EXPECTED_FILE_SIZE_IN_BYTES, size);
}
@Test
public void whenGetReadableFileSize_thenCorrect() {
final File file = new File(filePath);
final long size = getFileSize(file);
assertEquals(EXPECTED_FILE_SIZE_IN_BYTES + " bytes", FileUtils.byteCountToDisplaySize(size));
}
private long getFileSize(final File file) {
final long length = file.length();
return length;
}
}

View File

@ -93,6 +93,7 @@ public class OptionalTest {
boolean is2017 = yearOptional.filter(y -> y == 2017).isPresent();
assertFalse(is2017);
}
@Test
public void whenFiltersWithoutOptional_thenCorrect() {
assertTrue(priceIsInRange1(new Modem(10.0)));
@ -121,12 +122,9 @@ public class OptionalTest {
}
public boolean priceIsInRange2(Modem modem2) {
return Optional.ofNullable(modem2)
.map(Modem::getPrice)
.filter(p -> p >= 10)
.filter(p -> p <= 15)
.isPresent();
return Optional.ofNullable(modem2).map(Modem::getPrice).filter(p -> p >= 10).filter(p -> p <= 15).isPresent();
}
// Transforming Value With map()
@Test
public void givenOptional_whenMapWorks_thenCorrect() {

View File

@ -0,0 +1,55 @@
package com.baeldung.java8.unix.grep;
import java.io.File;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.unix4j.Unix4j;
import static org.unix4j.Unix4j.*;
import static org.junit.Assert.assertEquals;
import org.unix4j.line.Line;
import static org.unix4j.unix.Grep.*;
import static org.unix4j.unix.cut.CutOption.*;
public class GrepWithUnix4JTest {
private File fileToGrep;
@Before
public void init() {
final String separator = File.separator;
final String filePath = String.join(separator, new String[] { "src", "test", "resources", "dictionary.in" });
fileToGrep = new File(filePath);
}
@Test
public void whenGrepWithSimpleString_thenCorrect() {
int expectedLineCount = 4;
// grep "NINETEEN" dictionary.txt
List<Line> lines = Unix4j.grep("NINETEEN", fileToGrep).toLineList();
assertEquals(expectedLineCount, lines.size());
}
@Test
public void whenInverseGrepWithSimpleString_thenCorrect() {
int expectedLineCount = 178687;
// grep -v "NINETEEN" dictionary.txt
List<Line> lines = grep(Options.v, "NINETEEN", fileToGrep).toLineList();
assertEquals(expectedLineCount, lines.size());
}
@Test
public void whenGrepWithRegex_thenCorrect() {
int expectedLineCount = 151;
// grep -c ".*?NINE.*?" dictionary.txt
String patternCount = grep(Options.c, ".*?NINE.*?", fileToGrep).cut(fields, ":", 1).toStringResult();
assertEquals(expectedLineCount, Integer.parseInt(patternCount));
}
}

View File

@ -15,8 +15,7 @@ public class JoinSplitCollectionsUnitTest {
public void whenJoiningTwoArrays_thenJoined() {
String[] animals1 = new String[] { "Dog", "Cat" };
String[] animals2 = new String[] { "Bird", "Cow" };
String[] result = Stream.concat(
Arrays.stream(animals1), Arrays.stream(animals2)).toArray(String[]::new);
String[] result = Stream.concat(Arrays.stream(animals1), Arrays.stream(animals2)).toArray(String[]::new);
assertArrayEquals(result, new String[] { "Dog", "Cat", "Bird", "Cow" });
}
@ -25,9 +24,7 @@ public class JoinSplitCollectionsUnitTest {
public void whenJoiningTwoCollections_thenJoined() {
Collection<String> collection1 = Arrays.asList("Dog", "Cat");
Collection<String> collection2 = Arrays.asList("Bird", "Cow", "Moose");
Collection<String> result = Stream.concat(
collection1.stream(), collection2.stream())
.collect(Collectors.toList());
Collection<String> result = Stream.concat(collection1.stream(), collection2.stream()).collect(Collectors.toList());
assertTrue(result.equals(Arrays.asList("Dog", "Cat", "Bird", "Cow", "Moose")));
}
@ -36,10 +33,7 @@ public class JoinSplitCollectionsUnitTest {
public void whenJoiningTwoCollectionsWithFilter_thenJoined() {
Collection<String> collection1 = Arrays.asList("Dog", "Cat");
Collection<String> collection2 = Arrays.asList("Bird", "Cow", "Moose");
Collection<String> result = Stream.concat(
collection1.stream(), collection2.stream())
.filter(e -> e.length() == 3)
.collect(Collectors.toList());
Collection<String> result = Stream.concat(collection1.stream(), collection2.stream()).filter(e -> e.length() == 3).collect(Collectors.toList());
assertTrue(result.equals(Arrays.asList("Dog", "Cat", "Cow")));
}
@ -67,9 +61,7 @@ public class JoinSplitCollectionsUnitTest {
animals.put(2, "Cat");
animals.put(3, "Cow");
String result = animals.entrySet().stream()
.map(entry -> entry.getKey() + " = " + entry.getValue())
.collect(Collectors.joining(", "));
String result = animals.entrySet().stream().map(entry -> entry.getKey() + " = " + entry.getValue()).collect(Collectors.joining(", "));
assertEquals(result, "1 = Dog, 2 = Cat, 3 = Cow");
}
@ -80,10 +72,7 @@ public class JoinSplitCollectionsUnitTest {
nested.add(Arrays.asList("Dog", "Cat"));
nested.add(Arrays.asList("Cow", "Pig"));
String result = nested.stream().map(
nextList -> nextList.stream()
.collect(Collectors.joining("-")))
.collect(Collectors.joining("; "));
String result = nested.stream().map(nextList -> nextList.stream().collect(Collectors.joining("-"))).collect(Collectors.joining("; "));
assertEquals(result, "Dog-Cat; Cow-Pig");
}
@ -91,17 +80,14 @@ public class JoinSplitCollectionsUnitTest {
@Test
public void whenConvertCollectionToStringAndSkipNull_thenConverted() {
Collection<String> animals = Arrays.asList("Dog", "Cat", null, "Moose");
String result = animals.stream()
.filter(Objects::nonNull)
.collect(Collectors.joining(", "));
String result = animals.stream().filter(Objects::nonNull).collect(Collectors.joining(", "));
assertEquals(result, "Dog, Cat, Moose");
}
@Test
public void whenSplitCollectionHalf_thenConverted() {
Collection<String> animals = Arrays.asList(
"Dog", "Cat", "Cow", "Bird", "Moose", "Pig");
Collection<String> animals = Arrays.asList("Dog", "Cat", "Cow", "Bird", "Moose", "Pig");
Collection<String> result1 = new ArrayList<>();
Collection<String> result2 = new ArrayList<>();
AtomicInteger count = new AtomicInteger();
@ -123,8 +109,7 @@ public class JoinSplitCollectionsUnitTest {
@Test
public void whenSplitArrayByWordLength_thenConverted() {
String[] animals = new String[] { "Dog", "Cat", "Bird", "Cow", "Pig", "Moose" };
Map<Integer, List<String>> result = Arrays.stream(animals)
.collect(Collectors.groupingBy(String::length));
Map<Integer, List<String>> result = Arrays.stream(animals).collect(Collectors.groupingBy(String::length));
assertTrue(result.get(3).equals(Arrays.asList("Dog", "Cat", "Cow", "Pig")));
assertTrue(result.get(4).equals(Arrays.asList("Bird")));
@ -151,9 +136,7 @@ public class JoinSplitCollectionsUnitTest {
public void whenConvertStringToMap_thenConverted() {
String animals = "1 = Dog, 2 = Cat, 3 = Bird";
Map<Integer, String> result = Arrays.stream(
animals.split(", ")).map(next -> next.split(" = "))
.collect(Collectors.toMap(entry -> Integer.parseInt(entry[0]), entry -> entry[1]));
Map<Integer, String> result = Arrays.stream(animals.split(", ")).map(next -> next.split(" = ")).collect(Collectors.toMap(entry -> Integer.parseInt(entry[0]), entry -> entry[1]));
assertEquals(result.get(1), "Dog");
assertEquals(result.get(2), "Cat");
@ -164,10 +147,7 @@ public class JoinSplitCollectionsUnitTest {
public void whenConvertCollectionToStringMultipleSeparators_thenConverted() {
String animals = "Dog. , Cat, Bird. Cow";
Collection<String> result = Arrays.stream(animals.split("[,|.]"))
.map(String::trim)
.filter(next -> !next.isEmpty())
.collect(Collectors.toList());
Collection<String> result = Arrays.stream(animals.split("[,|.]")).map(String::trim).filter(next -> !next.isEmpty()).collect(Collectors.toList());
assertTrue(result.equals(Arrays.asList("Dog", "Cat", "Bird", "Cow")));
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
<code_scheme name="updated-formatter">
<option name="RIGHT_MARGIN" value="260" />
<option name="ENABLE_JAVADOC_FORMATTING" value="false" />
<option name="FORMATTER_TAGS_ENABLED" value="true" />
<JavaCodeStyleSettings>
<option name="SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENT" value="true" />
<option name="DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION" value="true" />
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
</JavaCodeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
<option name="INDENT_CASE_FROM_SWITCH" value="false" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_RESOURCES" value="false" />
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true" />
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="RESOURCE_LIST_WRAP" value="5" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="1" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="1" />
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="8" />
</indentOptions>
</codeStyleSettings>
</code_scheme>

View File

@ -5,13 +5,19 @@
<artifactId>logmdc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>logmdc</name>
<description>tutorial on logging with MDC</description>
<packaging>war</packaging>
<description>tutorial on logging with MDC and NDC</description>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
@ -19,6 +25,17 @@
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.library}</version>
</dependency>
<!--log4j dependencies -->
<dependency>
@ -31,12 +48,12 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j-api.version}</version>
<version>${log4j2.version}</version>
</dependency>
<!--disruptor for log4j2 async logging -->
@ -53,21 +70,64 @@
<version>${logback.version}</version>
</dependency>
<!-- JBoss Logging (bridge) dependencies -->
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>${jbosslogging.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${springframework.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<springframework.version>4.3.4.RELEASE</springframework.version>
<log4j.version>1.2.17</log4j.version>
<log4j-api.version>2.7</log4j-api.version>
<log4j2.version>2.7</log4j2.version>
<disruptor.version>3.3.6</disruptor.version>
<logback.version>1.1.7</logback.version>
<jbosslogging.version>3.3.0.Final</jbosslogging.version>
<javax.servlet.version>3.1.0</javax.servlet.version>
<jackson.library>2.8.5</jackson.library>
<junit.version>4.12</junit.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
<warName>logging-service</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<finalName>logging-service</finalName>
</build>
</project>

View File

@ -0,0 +1,19 @@
package com.baeldung.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.baeldung")
public class AppConfiguration extends WebMvcConfigurerAdapter {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
}
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfiguration.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.ndc;
public class Investment {
private String transactionId;
private String owner;
private Long amount;
public Investment() {
}
public Investment(String transactionId, String owner, Long amount) {
this.transactionId = transactionId;
this.owner = owner;
this.amount = amount;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public Long getAmount() {
return amount;
}
public void setAmount(Long amount) {
this.amount = amount;
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.ndc.controller;
import org.jboss.logging.NDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.ndc.Investment;
import com.baeldung.ndc.service.InvestmentService;
@RestController
public class JBossLoggingController {
@Autowired
@Qualifier("JBossLoggingInvestmentService")
private InvestmentService jbossLoggingBusinessService;
@RequestMapping(value = "/ndc/jboss-logging", method = RequestMethod.POST)
public ResponseEntity<Investment> postPayment(@RequestBody Investment investment) {
// Add transactionId and owner to NDC
NDC.push("tx.id=" + investment.getTransactionId());
NDC.push("tx.owner=" + investment.getOwner());
try {
jbossLoggingBusinessService.transfer(investment.getAmount());
} finally {
// take out owner from the NDC stack
NDC.pop();
// take out transactionId from the NDC stack
NDC.pop();
NDC.clear();
}
return new ResponseEntity<Investment>(investment, HttpStatus.OK);
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.ndc.controller;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.ndc.Investment;
import com.baeldung.ndc.service.InvestmentService;
@RestController
public class Log4J2Controller {
@Autowired
@Qualifier("log4j2InvestmentService")
private InvestmentService log4j2BusinessService;
@RequestMapping(value = "/ndc/log4j2", method = RequestMethod.POST)
public ResponseEntity<Investment> postPayment(@RequestBody Investment investment) {
// Add transactionId and owner to NDC
ThreadContext.push("tx.id=" + investment.getTransactionId());
ThreadContext.push("tx.owner=" + investment.getOwner());
try {
log4j2BusinessService.transfer(investment.getAmount());
} finally {
// take out owner from the NDC stack
ThreadContext.pop();
// take out transactionId from the NDC stack
ThreadContext.pop();
ThreadContext.clearAll();
}
return new ResponseEntity<Investment>(investment, HttpStatus.OK);
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.ndc.controller;
import org.apache.log4j.NDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.ndc.Investment;
import com.baeldung.ndc.service.InvestmentService;
@RestController
public class Log4JController {
@Autowired
@Qualifier("log4jInvestmentService")
private InvestmentService log4jBusinessService;
@RequestMapping(value = "/ndc/log4j", method = RequestMethod.POST)
public ResponseEntity<Investment> postPayment(@RequestBody Investment investment) {
// Add transactionId and owner to NDC
NDC.push("tx.id=" + investment.getTransactionId());
NDC.push("tx.owner=" + investment.getOwner());
try {
log4jBusinessService.transfer(investment.getAmount());
} finally {
// take out owner from the NDC stack
NDC.pop();
// take out transactionId from the NDC stack
NDC.pop();
NDC.remove();
}
return new ResponseEntity<Investment>(investment, HttpStatus.OK);
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.ndc.service;
/**
* A fake investment service.
*/
public interface InvestmentService {
/**
* Sample service transferring a given amount of money.
* @param amount
* @return {@code true} when the transfer complete successfully, {@code false} otherwise.
*/
default public boolean transfer(long amount) {
beforeTransfer(amount);
// exchange messages with a remote system to transfer the money
try {
// let's pause randomly to properly simulate an actual system.
Thread.sleep((long) (500 + Math.random() * 500));
} catch (InterruptedException e) {
// should never happen
}
// let's simulate both failing and successful transfers
boolean outcome = Math.random() >= 0.25;
afterTransfer(amount, outcome);
return outcome;
}
void beforeTransfer(long amount);
void afterTransfer(long amount, boolean outcome);
}

View File

@ -0,0 +1,21 @@
package com.baeldung.ndc.service;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
@Qualifier("JBossLoggingInvestmentService")
public class JBossLoggingInvestmentService implements InvestmentService {
private static final Logger logger = Logger.getLogger(JBossLoggingInvestmentService.class);
@Override
public void beforeTransfer(long amount) {
logger.infov("Preparing to transfer {0}$.", amount);
}
@Override
public void afterTransfer(long amount, boolean outcome) {
logger.infov("Has transfer of {0}$ completed successfully ? {1}.", amount, outcome);
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.ndc.service;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
@Qualifier("log4j2InvestmentService")
public class Log4J2InvestmentService implements InvestmentService {
private static final Logger logger = LogManager.getLogger();
@Override
public void beforeTransfer(long amount) {
logger.info("Preparing to transfer {}$.", amount);
}
@Override
public void afterTransfer(long amount, boolean outcome) {
logger.info("Has transfer of {}$ completed successfully ? {}.", amount, outcome);
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.ndc.service;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
@Qualifier("log4jInvestmentService")
public class Log4JInvestmentService implements InvestmentService {
private Logger logger = Logger.getLogger(Log4JInvestmentService.class);
@Override
public void beforeTransfer(long amount) {
logger.info("Preparing to transfer " + amount + "$.");
}
@Override
public void afterTransfer(long amount, boolean outcome) {
logger.info("Has transfer of " + amount + "$ completed successfully ? " + outcome + ".");
}
}

View File

@ -3,6 +3,10 @@ log4j.appender.consoleAppender.layout=org.apache.log4j.PatternLayout
#note the %X{userName} - this is how you fetch data from Mapped Diagnostic Context (MDC)
#log4j.appender.consoleAppender.layout.ConversionPattern=%-4r [%t] %5p %c{1} %x - %m%n
# %x is used to fetch data from NDC. So below setting uses both MDC and NDC
log4j.appender.consoleAppender.layout.ConversionPattern=%-4r [%t] %5p %c{1} %x - %m - tx.id=%X{transaction.id} tx.owner=%X{transaction.owner}%n
log4j.rootLogger = TRACE, consoleAppender
# NDC only setting - %x is used to fetch data from NDC
#log4j.appender.consoleAppender.layout.ConversionPattern=%-4r [%t] %5p %c{1} - %m - [%x]%n
log4j.rootLogger = INFO, consoleAppender

View File

@ -2,8 +2,15 @@
<Configuration status="INFO">
<Appenders>
<Console name="stdout" target="SYSTEM_OUT">
<!-- MDC and NDC -->
<PatternLayout
pattern="%-4r [%t] %5p %c{1} - %m - tx.id=%X{transaction.id} tx.owner=%X{transaction.owner}%n" />
pattern="%-4r [%t] %5p %c{1} - %m - %x - tx.id=%X{transaction.id} tx.owner=%X{transaction.owner}%n" />
<!-- MDC Only -->
<!-- <PatternLayout
pattern="%-4r [%t] %5p %c{1} - %m - tx.id=%X{transaction.id} tx.owner=%X{transaction.owner}%n" /> -->
<!-- NDC Only -->
<!-- <PatternLayout
pattern="%-4r [%t] %5p %c{1} - %m - %x%n" /> -->
</Console>
</Appenders>

View File

@ -0,0 +1,61 @@
package com.baeldung.ndc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.baeldung.config.AppConfiguration;
import com.fasterxml.jackson.databind.ObjectMapper;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfiguration.class)
@WebAppConfiguration
public class NDCLogTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
private Investment investment;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
investment = new Investment();
investment.setTransactionId("123");
investment.setOwner("Mark");
investment.setAmount(1000L);
}
@Test
public void givenLog4jLogger_whenNDCAdded_thenResponseOkAndNDCInLog() throws Exception {
mockMvc.perform(post("/ndc/log4j", investment).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(investment))).andExpect(status().is2xxSuccessful());
}
@Test
public void givenLog4j2Logger_whenNDCAdded_thenResponseOkAndNDCInLog() throws Exception {
mockMvc.perform(post("/ndc/log4j2", investment).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(investment))).andExpect(status().is2xxSuccessful());
}
@Test
public void givenJBossLoggerBridge_whenNDCAdded_thenResponseOkAndNDCInLog() throws Exception {
mockMvc.perform(post("/ndc/jboss-logging", investment).contentType(MediaType.APPLICATION_JSON).content(new ObjectMapper().writeValueAsString(investment))).andExpect(status().is2xxSuccessful());
}
}

View File

@ -117,6 +117,7 @@
<module>spring-mvc-velocity</module>
<module>spring-mvc-web-vs-initializer</module>
<module>spring-mvc-xml</module>
<module>spring-mvc-simple</module>
<module>spring-openid</module>
<module>spring-protobuf</module>
<module>spring-quartz</module>

View File

@ -2,10 +2,10 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>SpringMVCHandlers</artifactId>
<artifactId>spring-mvc-simple</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>SpringMVCHandlers Maven Webapp</name>
<name>Spring MVC simple Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
@ -59,12 +59,12 @@
<version>${maven-war-plugin.version}</version>
<configuration>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
<warName>springMVCHandlers</warName>
<warName>springMvcSimple</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<finalName>springMVCHandlers</finalName>
<finalName>springMvcSimple</finalName>
</build>
</project>

13
spring-security-core/.gitignore vendored Normal file
View File

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

View File

@ -0,0 +1,7 @@
## @PreFilter and @PostFilter annotations
### Build the Project ###
```
mvn clean install
```

View File

@ -0,0 +1,168 @@
<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-security-core</artifactId>
<version>0.1-SNAPSHOT</version>
<name>spring-security-core</name>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
</dependencies>
<build>
<finalName>spring-security-core</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<debug>true</debug>
<debuglevel>source</debuglevel>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*LiveTest.java</exclude>
<exclude>**/*ManualTest.java</exclude>
</excludes>
<systemPropertyVariables>
<!-- <provPersistenceTarget>h2</provPersistenceTarget> -->
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>live</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>none</exclude>
</excludes>
<includes>
<include>**/*LiveTest.java</include>
</includes>
<systemPropertyVariables>
<webTarget>cargo</webTarget>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<!-- Spring -->
<org.springframework.version>4.3.4.RELEASE</org.springframework.version>
<org.springframework.security.version>4.2.0.RELEASE</org.springframework.security.version>
<!-- http -->
<httpcore.version>4.4.5</httpcore.version>
<httpclient.version>4.5.2</httpclient.version>
<!-- logging -->
<org.slf4j.version>1.7.21</org.slf4j.version>
<logback.version>1.1.7</logback.version> <!-- do not upgrade - see http://jira.qos.ch/browse/LOGBACK-851 -->
<!-- various -->
<hibernate-validator.version>5.3.3.Final</hibernate-validator.version>
<jstl.version>1.2</jstl.version>
<javax.servlet.version>3.1.0</javax.servlet.version>
<jackson.version>2.8.5</jackson.version>
<!-- util -->
<guava.version>19.0</guava.version>
<commons-lang3.version>3.5</commons-lang3.version>
<!-- testing -->
<org.hamcrest.version>1.3</org.hamcrest.version>
<junit.version>4.12</junit.version>
<mockito.version>1.10.19</mockito.version>
<rest-assured.version>2.9.0</rest-assured.version>
<!-- Maven plugins -->
<maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>
<maven-war-plugin.version>2.6</maven-war-plugin.version>
<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
</properties>
</project>

View File

@ -0,0 +1,17 @@
package org.baeldung.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
@EnableJpaRepositories("org.baeldung.repository")
@ComponentScan("org.baeldung")
@EntityScan("org.baeldung.entity")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}

View File

@ -0,0 +1,23 @@
package org.baeldung.config;
import org.baeldung.entity.Task;
import org.baeldung.repository.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class DatabaseLoader implements CommandLineRunner {
@Autowired
private TaskRepository taskRepository;
@Override
public void run(String... strings) throws Exception {
this.taskRepository.save(new Task("Send a fax", "pam"));
this.taskRepository.save(new Task("Print a document", "pam"));
this.taskRepository.save(new Task("Answer the phone", "pam"));
this.taskRepository.save(new Task("Call a client", "jim"));
this.taskRepository.save(new Task("Organize a meeting", "michael"));
}
}

View File

@ -0,0 +1,39 @@
package org.baeldung.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/loggedout").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.logout().disable()
.csrf().disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("jim").password("jim").roles("USER")
.and()
.withUser("pam").password("pam").roles("USER")
.and()
.withUser("michael").password("michael").roles("MANAGER");
}
}

View File

@ -0,0 +1,32 @@
package org.baeldung.controller;
import org.baeldung.entity.Task;
import org.baeldung.service.TaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("api/tasks")
public class TaskController {
@Autowired
private TaskService taskService;
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Iterable<Task>> findAllTasks() {
Iterable<Task> tasks = taskService.findAll();
return ResponseEntity.ok().body(tasks);
}
@RequestMapping(method = RequestMethod.POST, consumes = "application/json")
public ResponseEntity<Iterable<Task>> addTasks(@RequestBody Iterable<Task> newTasks) {
Iterable<Task> tasks = taskService.save(newTasks);
return ResponseEntity.ok().body(tasks);
}
}

View File

@ -0,0 +1,46 @@
package org.baeldung.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Task {
private @Id @GeneratedValue Long id;
private String description;
private String assignee;
public Task() {
}
public Task(String description, String assignee) {
this.description = description;
this.assignee = assignee;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getAssignee() {
return assignee;
}
public void setAssignee(String assignee) {
this.assignee = assignee;
}
}

View File

@ -0,0 +1,8 @@
package org.baeldung.repository;
import org.baeldung.entity.Task;
import org.springframework.data.repository.CrudRepository;
public interface TaskRepository extends CrudRepository<Task, Long> {
}

View File

@ -0,0 +1,26 @@
package org.baeldung.service;
import org.baeldung.entity.Task;
import org.baeldung.repository.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreFilter;
import org.springframework.stereotype.Service;
@Service
public class TaskService {
@Autowired
private TaskRepository taskRepository;
@PostFilter("hasRole('MANAGER') or filterObject.assignee == authentication.name")
public Iterable<Task> findAll() {
return taskRepository.findAll();
}
@PreFilter("hasRole('MANAGER') or filterObject.assignee == authentication.name")
public Iterable<Task> save(Iterable<Task> entities) {
return taskRepository.save(entities);
}
}

View File

@ -0,0 +1,75 @@
package org.baeldung.test;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.baeldung.app.App;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = App.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class LiveTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).dispatchOptions(true).build();
}
@Test
@WithMockUser(roles = "MANAGER")
public void givenUserIsManager_whenGetTasks_thenAllTasks() throws Exception {
String allTasks = "[{'id':1,'description':'Send a fax','assignee':'pam'}," +
"{'id':2,'description':'Print a document','assignee':'pam'}," +
"{'id':3,'description':'Answer the phone','assignee':'pam'}," +
"{'id':4,'description':'Call a client','assignee':'jim'}," +
"{'id':5,'description':'Organize a meeting','assignee':'michael'}]";
mockMvc.perform(get("/api/tasks")).andExpect(status().isOk()).andExpect(content().json(allTasks));
}
@Test
@WithMockUser(username = "jim")
public void givenUserNotManager_whenGetTasks_thenReturnAssignedToMe() throws Exception {
String myTasks = "[{'id':4,'description':'Call a client','assignee':'jim'}]";
mockMvc.perform(get("/api/tasks")).andExpect(status().isOk()).andExpect(content().json(myTasks));
}
@Test
@WithMockUser(roles = "MANAGER")
public void givenUserIsManager_whenPostTasks_thenIncludeAllTasks() throws Exception {
String newTasks = "[{\"description\":\"New to Michael\",\"assignee\":\"michael\"}," +
"{\"description\":\"New to Pam\",\"assignee\":\"pam\"}]";
mockMvc.perform(post("/api/tasks").contentType(MediaType.APPLICATION_JSON).content(newTasks)).andExpect(status().isOk()).andExpect(content().json("[{'id': 6,'description':'New to Michael','assignee':'michael'}, {'id': 7,'description':'New to Pam','assignee':'pam'}]"));
}
@Test
@WithMockUser(username = "jim")
public void givenUserNotManager_whenPostTasks_thenIncludeOnlyAssignedToMe() throws Exception {
String newTasks = "[{\"description\":\"New to Jim\",\"assignee\":\"jim\"}," +
"{\"description\":\"New to Pam\",\"assignee\":\"pam\"}]";
mockMvc.perform(post("/api/tasks").contentType(MediaType.APPLICATION_JSON).content(newTasks)).andExpect(status().isOk()).andExpect(content().json("[{'id': 8,'description':'New to Jim','assignee':'jim'}]"));
}
}

View File

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

View File

@ -1,8 +1,7 @@
package org.baeldung.spring;
import org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler;
import org.baeldung.security.RestAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ -10,6 +9,7 @@ import org.springframework.security.config.annotation.authentication.builders.Au
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
@Configuration
@ -17,11 +17,11 @@ import org.springframework.security.web.authentication.SimpleUrlAuthenticationFa
@ComponentScan("org.baeldung.security")
public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
// @Autowired
// private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired
private MySavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler;
// @Autowired
// private MySavedRequestAwareAuthenticationSuccessHandler authenticationSuccessHandler;
public SecurityJavaConfig() {
super();
@ -38,17 +38,21 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {
protected void configure(final HttpSecurity http) throws Exception {// @formatter:off
http
.csrf().disable()
.authorizeRequests()
.and()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
// .authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/api/csrfAttacker*").permitAll()
.antMatchers("/api/customer/**").permitAll()
.antMatchers("/api/foos/**").authenticated()
.antMatchers("/api/async/**").authenticated()
.and()
.formLogin()
.successHandler(authenticationSuccessHandler)
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.httpBasic()
// .and()
// .successHandler(authenticationSuccessHandler)
// .failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout();
} // @formatter:on
@ -63,4 +67,13 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter {
return new SimpleUrlAuthenticationFailureHandler();
}
@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
methodInvokingFactoryBean.setTargetMethod("setStrategyName");
methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
return methodInvokingFactoryBean;
}
}

View File

@ -2,14 +2,21 @@ package org.baeldung.web.controller;
import java.util.concurrent.Callable;
import org.baeldung.web.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
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.multipart.MultipartFile;
@Controller
public class AsyncController {
@Autowired
private AsyncService asyncService;
@RequestMapping(method = RequestMethod.POST, value = "/upload")
public Callable<Boolean> processUpload(final MultipartFile file) {
@ -21,4 +28,10 @@ public class AsyncController {
};
}
@RequestMapping(method = RequestMethod.GET, value = "/async")
@ResponseBody
public Boolean checkIfContextPropagated() throws Exception{
return asyncService.checkIfPrincipalPropagated().call() && asyncService.checkIfContextPropagated(SecurityContextHolder.getContext());
}
}

View File

@ -0,0 +1,11 @@
package org.baeldung.web.service;
import java.util.concurrent.Callable;
public interface AsyncService {
Callable<Boolean> checkIfPrincipalPropagated();
Boolean checkIfContextPropagated(Object context);
}

View File

@ -0,0 +1,36 @@
package org.baeldung.web.service;
import java.util.concurrent.Callable;
import org.apache.log4j.Logger;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@Service
public class AsyncServiceImpl implements AsyncService {
private static final Logger log = Logger.getLogger(AsyncService.class);
@Override
public Callable<Boolean> checkIfPrincipalPropagated() {
Object before = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("Before new thread: " + before);
return new Callable<Boolean>() {
public Boolean call() throws Exception {
Object after = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
log.info("New thread: " + after);
return before == after;
}
};
}
@Async
@Override
public Boolean checkIfContextPropagated(Object context) {
log.info("Before @Async: " + context);
log.info("Inside @Async: " + SecurityContextHolder.getContext());
return context == SecurityContextHolder.getContext();
}
}

View File

@ -1,25 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"
>
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<http use-expressions="true" entry-point-ref="restAuthenticationEntryPoint">
<intercept-url pattern="/api/**" access="isAuthenticated()" />
<csrf disabled="true" />
<form-login authentication-success-handler-ref="mySuccessHandler" authentication-failure-handler-ref="myFailureHandler"/>
<form-login authentication-success-handler-ref="mySuccessHandler"
authentication-failure-handler-ref="myFailureHandler" />
<logout />
</http>
<beans:bean id="mySuccessHandler" class="org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler"/>
<beans:bean id="myFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"/>
<beans:bean id="mySuccessHandler"
class="org.baeldung.security.MySavedRequestAwareAuthenticationSuccessHandler" />
<beans:bean id="myFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler" />
<authentication-manager alias="authenticationManager">
<authentication-provider>
@ -30,4 +34,9 @@
</authentication-provider>
</authentication-manager>
<beans:bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
p:targetClass="org.springframework.security.core.context.SecurityContextHolder"
p:targetMethod="setStrategyName" p:arguments="MODE_INHERITABLETHREADLOCAL" />
</beans:beans>