Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Alessio Stalla 2018-01-29 13:19:55 +01:00
commit b7ab9c3dea
126 changed files with 2726 additions and 712 deletions

View File

@ -2,46 +2,48 @@ package com.baeldung.spliteratorAPI;
import java.util.List;
import java.util.Spliterator;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public class RelatedAuthorSpliterator implements Spliterator<Author> {
private final List<Author> list;
private int current = 0;
private final List<Author> list;
AtomicInteger current = new AtomicInteger();
public RelatedAuthorSpliterator(List<Author> list) {
this.list = list;
}
public RelatedAuthorSpliterator(List<Author> list) {
this.list = list;
}
@Override
public boolean tryAdvance(Consumer<? super Author> action) {
action.accept(list.get(current++));
return current < list.size();
}
@Override
public boolean tryAdvance(Consumer<? super Author> action) {
@Override
public Spliterator<Author> trySplit() {
int currentSize = list.size() - current;
if (currentSize < 10) {
return null;
}
for (int splitPos = currentSize / 2 + current; splitPos < list.size(); splitPos++) {
if (list.get(splitPos)
.getRelatedArticleId() == 0) {
Spliterator<Author> spliterator = new RelatedAuthorSpliterator(list.subList(current, splitPos));
current = splitPos;
return spliterator;
}
}
return null;
}
action.accept(list.get(current.getAndIncrement()));
return current.get() < list.size();
}
@Override
public long estimateSize() {
return list.size() - current;
}
@Override
public Spliterator<Author> trySplit() {
int currentSize = list.size() - current.get();
if (currentSize < 10) {
return null;
}
for (int splitPos = currentSize / 2 + current.intValue(); splitPos < list.size(); splitPos++) {
if (list.get(splitPos).getRelatedArticleId() == 0) {
Spliterator<Author> spliterator = new RelatedAuthorSpliterator(list.subList(current.get(), splitPos));
current.set(splitPos);
return spliterator;
}
}
return null;
}
@Override
public long estimateSize() {
return list.size() - current.get();
}
@Override
public int characteristics() {
return CONCURRENT;
}
@Override
public int characteristics() {
return SIZED + CONCURRENT;
}
}

View File

@ -1,5 +1,7 @@
package com.baeldung.concurrent.waitandnotify;
import org.slf4j.Logger;
public class Data {
private String packet;
@ -11,7 +13,9 @@ public class Data {
while (transfer) {
try {
wait();
} catch (InterruptedException e) {}
} catch (InterruptedException e) {
System.out.println("Thread Interrupted");
}
}
transfer = true;
@ -23,7 +27,9 @@ public class Data {
while (!transfer) {
try {
wait();
} catch (InterruptedException e) {}
} catch (InterruptedException e) {
System.out.println("Thread Interrupted");
}
}
transfer = false;

View File

@ -19,7 +19,9 @@ public class Receiver implements Runnable {
//Thread.sleep() to mimic heavy server-side processing
try {
Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 5000));
} catch (InterruptedException e) {}
} catch (InterruptedException e) {
System.out.println("Thread Interrupted");
}
}
}
}

View File

@ -11,11 +11,11 @@ public class Sender implements Runnable {
public void run() {
String packets[] = {
"First packet",
"Second packet",
"Third packet",
"Fourth packet",
"End"
"First packet",
"Second packet",
"Third packet",
"Fourth packet",
"End"
};
for (String packet : packets) {
@ -24,7 +24,9 @@ public class Sender implements Runnable {
//Thread.sleep() to mimic heavy server-side processing
try {
Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 5000));
} catch (InterruptedException e) {}
} catch (InterruptedException e) {
System.out.println("Thread Interrupted");
}
}
}
}

View File

@ -13,38 +13,38 @@ import org.junit.Test;
public class NetworkIntegrationTest {
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
private String expected;
@Before
public void setUpStreams() {
System.setOut(new PrintStream(outContent));
System.setErr(new PrintStream(errContent));
}
@Before
public void setUpExpectedOutput() {
StringWriter expectedStringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(expectedStringWriter);
printWriter.println("First packet");
printWriter.println("Second packet");
printWriter.println("Third packet");
printWriter.println("Fourth packet");
printWriter.close();
expected = expectedStringWriter.toString();
}
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
private String expected;
@Before
public void setUpStreams() {
System.setOut(new PrintStream(outContent));
System.setErr(new PrintStream(errContent));
}
@Before
public void setUpExpectedOutput() {
StringWriter expectedStringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(expectedStringWriter);
printWriter.println("First packet");
printWriter.println("Second packet");
printWriter.println("Third packet");
printWriter.println("Fourth packet");
printWriter.close();
expected = expectedStringWriter.toString();
}
@After
public void cleanUpStreams() {
System.setOut(null);
System.setErr(null);
}
@Test
public void givenSenderAndReceiver_whenSendingPackets_thenNetworkSynchronized() {
@After
public void cleanUpStreams() {
System.setOut(null);
System.setErr(null);
}
@Test
public void givenSenderAndReceiver_whenSendingPackets_thenNetworkSynchronized() {
Data data = new Data();
Thread sender = new Thread(new Sender(data));
Thread receiver = new Thread(new Receiver(data));
@ -54,12 +54,12 @@ public class NetworkIntegrationTest {
//wait for sender and receiver to finish before we test against expected
try {
sender.join();
receiver.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
assertEquals(expected, outContent.toString());
}
sender.join();
receiver.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
assertEquals(expected, outContent.toString());
}
}

View File

@ -126,3 +126,4 @@
- [A Guide to Inner Interfaces in Java](http://www.baeldung.com/java-inner-interfaces)
- [Polymorphism in Java](http://www.baeldung.com/java-polymorphism)
- [Recursion In Java](http://www.baeldung.com/java-recursion)
- [A Guide to the finalize Method in Java](http://www.baeldung.com/java-finalize)

View File

@ -49,6 +49,11 @@
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>${kotlin-stdlib.version}</version>
</dependency>
<dependency>
<groupId>khttp</groupId>
<artifactId>khttp</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>

View File

@ -0,0 +1,153 @@
package com.baeldung.kotlin.khttp
import khttp.structures.files.FileLike
import org.json.JSONObject
import org.junit.Test
import java.beans.ExceptionListener
import java.beans.XMLEncoder
import java.io.*
import java.lang.Exception
import java.net.ConnectException
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
class KhttpTest {
@Test
fun whenHttpGetRequestIsMade_thenArgsAreReturned() {
val response = khttp.get(
url = "http://httpbin.org/get",
params = mapOf("p1" to "1", "p2" to "2"))
val args = response.jsonObject.getJSONObject("args")
assertEquals("1", args["p1"])
assertEquals("2", args["p2"])
}
@Test
fun whenAlternateHttpGetRequestIsMade_thenArgsAreReturned() {
val response = khttp.request(
method = "GET",
url = "http://httpbin.org/get",
params = mapOf("p1" to "1", "p2" to "2"))
val args = response.jsonObject.getJSONObject("args")
assertEquals("1", args["p1"])
assertEquals("2", args["p2"])
}
@Test
fun whenHeadersAreSet_thenHeadersAreSent() {
val response = khttp.get(
url = "http://httpbin.org/get",
headers = mapOf("header1" to "1", "header2" to "2"))
val headers = response.jsonObject.getJSONObject("headers")
assertEquals("1", headers["Header1"])
assertEquals("2", headers["Header2"])
}
@Test
fun whenHttpPostRequestIsMadeWithJson_thenBodyIsReturned() {
val response = khttp.post(
url = "http://httpbin.org/post",
params = mapOf("p1" to "1", "p2" to "2"),
json = mapOf("pr1" to "1", "pr2" to "2"))
val args = response.jsonObject.getJSONObject("args")
assertEquals("1", args["p1"])
assertEquals("2", args["p2"])
val json = response.jsonObject.getJSONObject("json")
assertEquals("1", json["pr1"])
assertEquals("2", json["pr2"])
}
@Test
fun whenHttpPostRequestIsMadeWithMapData_thenBodyIsReturned() {
val response = khttp.post(
url = "http://httpbin.org/post",
params = mapOf("p1" to "1", "p2" to "2"),
data = mapOf("pr1" to "1", "pr2" to "2"))
val args = response.jsonObject.getJSONObject("args")
assertEquals("1", args["p1"])
assertEquals("2", args["p2"])
val form = response.jsonObject.getJSONObject("form")
assertEquals("1", form["pr1"])
assertEquals("2", form["pr2"])
}
@Test
fun whenHttpPostRequestIsMadeWithFiles_thenBodyIsReturned() {
val response = khttp.post(
url = "http://httpbin.org/post",
params = mapOf("p1" to "1", "p2" to "2"),
files = listOf(
FileLike("file1", "content1"),
FileLike("file2", javaClass.getResource("KhttpTest.class").openStream().readBytes())))
val args = response.jsonObject.getJSONObject("args")
assertEquals("1", args["p1"])
assertEquals("2", args["p2"])
val files = response.jsonObject.getJSONObject("files")
assertEquals("content1", files["file1"])
}
@Test
fun whenHttpPostRequestIsMadeWithInputStream_thenBodyIsReturned() {
val response = khttp.post(
url = "http://httpbin.org/post",
params = mapOf("p1" to "1", "p2" to "2"),
data = ByteArrayInputStream("content!".toByteArray()))
val args = response.jsonObject.getJSONObject("args")
assertEquals("1", args["p1"])
assertEquals("2", args["p2"])
assertEquals("content!", response.jsonObject["data"])
}
@Test
fun whenHttpPostStreamingRequestIsMade_thenBodyIsReturnedInChunks() {
val response = khttp.post(
url = "http://httpbin.org/post",
stream = true,
json = mapOf("pr1" to "1", "pr2" to "2"))
val baos = ByteArrayOutputStream()
response.contentIterator(chunkSize = 10).forEach { arr : ByteArray -> baos.write(arr) }
val json = JSONObject(String(baos.toByteArray())).getJSONObject("json")
assertEquals("1", json["pr1"])
assertEquals("2", json["pr2"])
}
@Test
fun whenHttpRequestFails_thenExceptionIsThrown() {
try {
khttp.get(url = "http://localhost/nothing/to/see/here")
fail("Should have thrown an exception")
} catch (e : ConnectException) {
//Ok
}
}
@Test
fun whenHttpNotFound_thenExceptionIsThrown() {
val response = khttp.get(url = "http://httpbin.org/nothing/to/see/here")
assertEquals(404, response.statusCode)
}
}

View File

@ -0,0 +1,17 @@
package org.baeldung.guava.memoizer;
import java.math.BigInteger;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class CostlySupplier {
public static BigInteger generateBigNumber() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
}
return new BigInteger("12345");
}
}

View File

@ -0,0 +1,22 @@
package org.baeldung.guava.memoizer;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.math.BigInteger;
public class Factorial {
private static LoadingCache<Integer, BigInteger> memo = CacheBuilder.newBuilder()
.build(CacheLoader.from(Factorial::getFactorial));
public static BigInteger getFactorial(int n) {
if (n == 0) {
return BigInteger.ONE;
} else {
return BigInteger.valueOf(n).multiply(memo.getUnchecked(n - 1));
}
}
}

View File

@ -0,0 +1,26 @@
package org.baeldung.guava.memoizer;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.math.BigInteger;
import java.util.concurrent.TimeUnit;
public class FibonacciSequence {
private static LoadingCache<Integer, BigInteger> memo = CacheBuilder.newBuilder()
.maximumSize(100)
.build(CacheLoader.from(FibonacciSequence::getFibonacciNumber));
public static BigInteger getFibonacciNumber(int n) {
if (n == 0) {
return BigInteger.ZERO;
} else if (n == 1) {
return BigInteger.ONE;
} else {
return memo.getUnchecked(n - 1).add(memo.getUnchecked(n - 2));
}
}
}

View File

@ -0,0 +1,98 @@
package org.baeldung.guava;
import com.google.common.base.Suppliers;
import org.baeldung.guava.memoizer.CostlySupplier;
import org.baeldung.guava.memoizer.Factorial;
import org.baeldung.guava.memoizer.FibonacciSequence;
import org.junit.Test;
import java.math.BigInteger;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.number.IsCloseTo.closeTo;
import static org.junit.Assert.assertThat;
public class GuavaMemoizerUnitTest {
@Test
public void givenInteger_whenGetFibonacciNumber_thenShouldCalculateFibonacciNumber() {
// given
int n = 95;
// when
BigInteger fibonacciNumber = FibonacciSequence.getFibonacciNumber(n);
// then
BigInteger expectedFibonacciNumber = new BigInteger("31940434634990099905");
assertThat(fibonacciNumber, is(equalTo(expectedFibonacciNumber)));
}
@Test
public void givenInteger_whenGetFactorial_thenShouldCalculateFactorial() {
// given
int n = 95;
// when
BigInteger factorial = new Factorial().getFactorial(n);
// then
BigInteger expectedFactorial = new BigInteger("10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000");
assertThat(factorial, is(equalTo(expectedFactorial)));
}
@Test
public void givenMemoizedSupplier_whenGet_thenSubsequentGetsAreFast() {
Supplier<BigInteger> memoizedSupplier;
memoizedSupplier = Suppliers.memoize(CostlySupplier::generateBigNumber);
Instant start = Instant.now();
BigInteger bigNumber = memoizedSupplier.get();
Long durationInMs = Duration.between(start, Instant.now()).toMillis();
assertThat(bigNumber, is(equalTo(new BigInteger("12345"))));
assertThat(durationInMs.doubleValue(), is(closeTo(2000D, 100D)));
start = Instant.now();
bigNumber = memoizedSupplier.get().add(BigInteger.ONE);
durationInMs = Duration.between(start, Instant.now()).toMillis();
assertThat(bigNumber, is(equalTo(new BigInteger("12346"))));
assertThat(durationInMs.doubleValue(), is(closeTo(0D, 100D)));
start = Instant.now();
bigNumber = memoizedSupplier.get().add(BigInteger.TEN);
durationInMs = Duration.between(start, Instant.now()).toMillis();
assertThat(bigNumber, is(equalTo(new BigInteger("12355"))));
assertThat(durationInMs.doubleValue(), is(closeTo(0D, 100D)));
}
@Test
public void givenMemoizedSupplierWithExpiration_whenGet_thenSubsequentGetsBeforeExpiredAreFast() throws InterruptedException {
Supplier<BigInteger> memoizedSupplier;
memoizedSupplier = Suppliers.memoizeWithExpiration(CostlySupplier::generateBigNumber, 3, TimeUnit.SECONDS);
Instant start = Instant.now();
BigInteger bigNumber = memoizedSupplier.get();
Long durationInMs = Duration.between(start, Instant.now()).toMillis();
assertThat(bigNumber, is(equalTo(new BigInteger("12345"))));
assertThat(durationInMs.doubleValue(), is(closeTo(2000D, 100D)));
start = Instant.now();
bigNumber = memoizedSupplier.get().add(BigInteger.ONE);
durationInMs = Duration.between(start, Instant.now()).toMillis();
assertThat(bigNumber, is(equalTo(new BigInteger("12346"))));
assertThat(durationInMs.doubleValue(), is(closeTo(0D, 100D)));
TimeUnit.SECONDS.sleep(1);
start = Instant.now();
bigNumber = memoizedSupplier.get().add(BigInteger.TEN);
durationInMs = Duration.between(start, Instant.now()).toMillis();
assertThat(bigNumber, is(equalTo(new BigInteger("12355"))));
assertThat(durationInMs.doubleValue(), is(closeTo(2000D, 100D)));
}
}

20
java-rmi/pom.xml Normal file
View File

@ -0,0 +1,20 @@
<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.rmi</groupId>
<artifactId>java-rmi</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1,36 @@
package com.baeldung.rmi;
import java.io.Serializable;
public class Message implements Serializable {
private String messageText;
private String contentType;
public Message() {
}
public Message(String messageText, String contentType) {
this.messageText = messageText;
this.contentType = contentType;
}
public String getMessageText() {
return messageText;
}
public void setMessageText(String messageText) {
this.messageText = messageText;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
}

View File

@ -0,0 +1,11 @@
package com.baeldung.rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface MessengerService extends Remote {
public String sendMessage(String clientMessage) throws RemoteException;
public Message sendMessage(Message clientMessage) throws RemoteException;
}

View File

@ -0,0 +1,37 @@
package com.baeldung.rmi;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class MessengerServiceImpl implements MessengerService {
public String sendMessage(String clientMessage) {
String serverMessage = null;
if (clientMessage.equals("Client Message")) {
serverMessage = "Server Message";
}
return serverMessage;
}
public void createStubAndBind() throws RemoteException {
MessengerService stub = (MessengerService) UnicastRemoteObject.exportObject((MessengerService) this, 0);
Registry registry = LocateRegistry.createRegistry(1099);
registry.rebind("MessengerService", stub);
}
public Message sendMessage(Message clientMessage) throws RemoteException {
Message serverMessage = null;
if (clientMessage.getMessageText().equals("Client Message")) {
serverMessage = new Message("Server Message", "text/plain");
}
return serverMessage;
}
}

View File

@ -0,0 +1,44 @@
package com.baeldung.rmi;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import org.junit.BeforeClass;
import org.junit.Test;
public class JavaRMIIntegrationTest {
@BeforeClass
public static void whenRunServer_thenServerStarts() {
try {
MessengerServiceImpl server = new MessengerServiceImpl();
server.createStubAndBind();
} catch (RemoteException e) {
fail("Exception Occurred");
}
}
@Test
public void whenClientSendsMessageToServer_thenServerSendsResponseMessage() {
try {
Registry registry = LocateRegistry.getRegistry();
MessengerService server = (MessengerService) registry.lookup("MessengerService");
String responseMessage = server.sendMessage("Client Message");
String expectedMessage = "Server Message";
assertEquals(responseMessage, expectedMessage);
} catch (RemoteException e) {
fail("Exception Occurred");
} catch (NotBoundException nb) {
fail("Exception Occurred");
}
}
}

View File

@ -194,6 +194,11 @@
<artifactId>jetty-servlet</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>rome</groupId>
<artifactId>rome</artifactId>
@ -741,12 +746,11 @@
<assertj.version>3.6.2</assertj.version>
<jsonassert.version>1.5.0</jsonassert.version>
<javers.version>3.1.0</javers.version>
<jetty.version>9.4.3.v20170317</jetty.version>
<httpclient.version>4.5.3</httpclient.version>
<commons.io.version>2.5</commons.io.version>
<commons.dbutils.version>1.6</commons.dbutils.version>
<h2.version>1.4.196</h2.version>
<jetty.version>9.4.2.v20170220</jetty.version>
<jetty.version>9.4.8.v20171121</jetty.version>
<httpclient.version>4.5.3</httpclient.version>
<commons.io.version>2.5</commons.io.version>
<flink.version>1.2.0</flink.version>

View File

@ -0,0 +1,94 @@
package com.baeldung.jetty;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* Simple factory for creating Jetty basic instances.
*
* @author Donato Rimenti
*
*/
public class JettyServerFactory {
/**
* Exposed context of the app.
*/
public final static String APP_PATH = "/myApp";
/**
* The server port.
*/
public final static int SERVER_PORT = 13133;
/**
* Private constructor to avoid instantiation.
*/
private JettyServerFactory() {
}
/**
* Returns a simple server listening on port 80 with a timeout of 30 seconds
* for connections and no handlers.
*
* @return a server
*/
public static Server createBaseServer() {
Server server = new Server();
// Adds a connector for port 80 with a timeout of 30 seconds.
ServerConnector connector = new ServerConnector(server);
connector.setPort(SERVER_PORT);
connector.setHost("127.0.0.1");
connector.setIdleTimeout(30000);
server.addConnector(connector);
return server;
}
/**
* Creates a server which delegates the request handling to a web
* application.
*
* @return a server
*/
public static Server createWebAppServer() {
// Adds an handler to a server and returns it.
Server server = createBaseServer();
String webAppFolderPath = JettyServerFactory.class.getClassLoader().getResource("jetty-embedded-demo-app.war")
.getPath();
Handler webAppHandler = new WebAppContext(webAppFolderPath, APP_PATH);
server.setHandler(webAppHandler);
return server;
}
/**
* Creates a server which delegates the request handling to both a logging
* handler and to a web application, in this order.
*
* @return a server
*/
public static Server createMultiHandlerServer() {
Server server = createBaseServer();
// Creates the handlers and adds them to the server.
HandlerCollection handlers = new HandlerCollection();
String webAppFolderPath = JettyServerFactory.class.getClassLoader().getResource("jetty-embedded-demo-app.war")
.getPath();
Handler customRequestHandler = new WebAppContext(webAppFolderPath, APP_PATH);
handlers.addHandler(customRequestHandler);
Handler loggingRequestHandler = new LoggingRequestHandler();
handlers.addHandler(loggingRequestHandler);
server.setHandler(handlers);
return server;
}
}

View File

@ -0,0 +1,168 @@
package com.baeldung.jetty;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Handler implementation which simply logs that a request has been received.
*
* @author Donato Rimenti
*/
public class LoggingRequestHandler implements Handler {
/**
* Logger.
*/
private final static Logger LOG = LoggerFactory.getLogger(LoggingRequestHandler.class);
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.util.component.LifeCycle#addLifeCycleListener(org.
* eclipse.jetty.util.component.LifeCycle.Listener)
*/
@Override
public void addLifeCycleListener(Listener arg0) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.util.component.LifeCycle#isFailed()
*/
@Override
public boolean isFailed() {
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.util.component.LifeCycle#isRunning()
*/
@Override
public boolean isRunning() {
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.util.component.LifeCycle#isStarted()
*/
@Override
public boolean isStarted() {
return true;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.util.component.LifeCycle#isStarting()
*/
@Override
public boolean isStarting() {
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.util.component.LifeCycle#isStopped()
*/
@Override
public boolean isStopped() {
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.util.component.LifeCycle#isStopping()
*/
@Override
public boolean isStopping() {
return false;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jetty.util.component.LifeCycle#removeLifeCycleListener(org.
* eclipse.jetty.util.component.LifeCycle.Listener)
*/
@Override
public void removeLifeCycleListener(Listener arg0) {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.util.component.LifeCycle#start()
*/
@Override
public void start() throws Exception {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.util.component.LifeCycle#stop()
*/
@Override
public void stop() throws Exception {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.server.Handler#destroy()
*/
@Override
public void destroy() {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.server.Handler#getServer()
*/
@Override
public Server getServer() {
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.server.Handler#handle(java.lang.String,
* org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
@Override
public void handle(String arg0, Request arg1, HttpServletRequest arg2, HttpServletResponse arg3)
throws IOException, ServletException {
LOG.info("Received a new request");
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jetty.server.Handler#setServer(org.eclipse.jetty.server.
* Server)
*/
@Override
public void setServer(Server server) {
}
}

View File

@ -0,0 +1,86 @@
package com.baeldung.jetty;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.eclipse.jetty.server.Server;
import org.junit.Assert;
import org.junit.Test;
/**
* Test for {@link JettyServerFactory}.
*
* @author Donato Rimenti
*
*/
public class JettyServerFactoryUnitTest {
/**
* Tests that when a base server is provided a request returns a status 404.
*
* @throws Exception
*/
@Test
public void givenBaseServer_whenHttpRequest_thenStatus404() throws Exception {
Server server = JettyServerFactory.createBaseServer();
server.start();
int statusCode = sendGetRequest();
Assert.assertEquals(404, statusCode);
server.stop();
}
/**
* Tests that when a web app server is provided a request returns a status
* 200.
*
* @throws Exception
*/
@Test
public void givenWebAppServer_whenHttpRequest_thenStatus200() throws Exception {
Server server = JettyServerFactory.createWebAppServer();
server.start();
int statusCode = sendGetRequest();
Assert.assertEquals(200, statusCode);
server.stop();
}
/**
* Tests that when a multi handler server is provided a request returns a
* status 200.
*
* @throws Exception
*/
@Test
public void givenMultiHandlerServerServer_whenHttpRequest_thenStatus200() throws Exception {
Server server = JettyServerFactory.createMultiHandlerServer();
server.start();
int statusCode = sendGetRequest();
Assert.assertEquals(200, statusCode);
server.stop();
}
/**
* Sends a default HTTP GET request to the server and returns the response
* status code.
*
* @return the status code of the response
* @throws Exception
*/
private int sendGetRequest() throws Exception {
HttpHost target = new HttpHost("localhost", JettyServerFactory.SERVER_PORT);
HttpRequest request = new HttpGet(JettyServerFactory.APP_PATH);
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(target, request);
return response.getStatusLine().getStatusCode();
}
}

View File

@ -32,9 +32,9 @@ public class PactConsumerDrivenContractUnitTest {
headers.put("Content-Type", "application/json");
return builder
.given("test GET ")
.given("test GET")
.uponReceiving("GET REQUEST")
.path("/")
.path("/pact")
.method("GET")
.willRespondWith()
.status(200)
@ -45,11 +45,9 @@ public class PactConsumerDrivenContractUnitTest {
.method("POST")
.headers(headers)
.body("{\"name\": \"Michael\"}")
.path("/create")
.path("/pact")
.willRespondWith()
.status(201)
.headers(headers)
.body("")
.toPact();
}
@ -59,7 +57,7 @@ public class PactConsumerDrivenContractUnitTest {
public void givenGet_whenSendRequest_shouldReturn200WithProperHeaderAndBody() {
//when
ResponseEntity<String> response
= new RestTemplate().getForEntity(mockProvider.getUrl(), String.class);
= new RestTemplate().getForEntity(mockProvider.getUrl() + "/pact", String.class);
//then
assertThat(response.getStatusCode().value()).isEqualTo(200);
@ -73,7 +71,7 @@ public class PactConsumerDrivenContractUnitTest {
//when
ResponseEntity<String> postResponse = new RestTemplate().exchange(
mockProvider.getUrl() + "/create",
mockProvider.getUrl() + "/pact",
HttpMethod.POST,
new HttpEntity<>(jsonBody, httpHeaders),
String.class

View File

@ -87,8 +87,9 @@
<module>jackson</module>
<!-- <module>persistence-modules/java-cassandra</module> -->
<module>vavr</module>
<module>java-lite</module>
<module>java-vavr-stream</module>
<module>java-lite</module>
<module>java-rmi</module>
<module>java-vavr-stream</module>
<module>javax-servlets</module>
<module>javaxval</module>
<module>jaxb</module>

View File

@ -2,22 +2,25 @@ package com.baeldung.reactive.websocket;
import java.net.URI;
import java.time.Duration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient;
import org.springframework.web.reactive.socket.client.WebSocketClient;
import reactor.core.publisher.Mono;
@SpringBootApplication
public class ReactiveJavaClientWebSocket {
public static void main(String[] args) throws InterruptedException {
public static void main(String[] args) throws InterruptedException {
WebSocketClient client = new ReactorNettyWebSocketClient();
client.execute(URI.create("ws://localhost:8080/event-emitter"), session -> session.send(Mono.just(session.textMessage("event-me-from-spring-reactive-client")))
client.execute(
URI.create("ws://localhost:8080/event-emitter"),
session -> session.send(
Mono.just(session.textMessage("event-spring-reactive-client-websocket")))
.thenMany(session.receive()
.map(WebSocketMessage::getPayloadAsText)
.log())
.map(WebSocketMessage::getPayloadAsText)
.log())
.then())
.block(Duration.ofSeconds(10L));
}
}

View File

@ -1,71 +1,41 @@
package com.baeldung.reactive.websocket;
import org.springframework.web.reactive.socket.WebSocketSession;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.WebSocketSession;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.UUID;
import static java.time.LocalDateTime.now;
import static java.util.UUID.randomUUID;
@Component
public class ReactiveWebSocketHandler implements WebSocketHandler {
private Flux<Event> eventFlux;
private Flux<Event> intervalFlux;
private static final ObjectMapper json = new ObjectMapper();
/**
* Here we prepare a Flux that will emit a message every second
*/
@PostConstruct
private void init() throws InterruptedException {
private Flux<String> eventFlux = Flux.generate(sink -> {
Event event = new Event(randomUUID().toString(), now().toString());
try {
sink.next(json.writeValueAsString(event));
} catch (JsonProcessingException e) {
sink.error(e);
}
});
eventFlux = Flux.generate(e -> {
Event event = new Event(UUID.randomUUID()
.toString(),
LocalDateTime.now()
.toString());
e.next(event);
});
private Flux<String> intervalFlux = Flux.interval(Duration.ofMillis(1000L))
.zipWith(eventFlux, (time, event) -> event);
intervalFlux = Flux.interval(Duration.ofMillis(1000L))
.zipWith(eventFlux, (time, event) -> event);
}
/**
* On each new client session, send the message flux to the client.
* Spring subscribes to the flux and send every new flux event to the WebSocketSession object
* @param session
* @return Mono<Void>
*/
@Override
public Mono<Void> handle(WebSocketSession webSocketSession) {
ObjectMapper json = new ObjectMapper();
return webSocketSession.send(intervalFlux.map(event -> {
try {
String jsonEvent = json.writeValueAsString(event);
System.out.println(jsonEvent);
return jsonEvent;
} catch (JsonProcessingException e) {
e.printStackTrace();
return "";
}
})
.map(webSocketSession::textMessage))
.and(webSocketSession.receive()
.map(WebSocketMessage::getPayloadAsText)
.log());
return webSocketSession.send(intervalFlux
.map(webSocketSession::textMessage))
.and(webSocketSession.receive()
.map(WebSocketMessage::getPayloadAsText).log());
}
}

View File

@ -0,0 +1,50 @@
package com.baeldung.loginextrafieldscustom;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public static final String SPRING_SECURITY_FORM_DOMAIN_KEY = "domain";
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
if (!request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: "
+ request.getMethod());
}
CustomAuthenticationToken authRequest = getAuthRequest(request);
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
private CustomAuthenticationToken getAuthRequest(HttpServletRequest request) {
String username = obtainUsername(request);
String password = obtainPassword(request);
String domain = obtainDomain(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
if (domain == null) {
domain = "";
}
return new CustomAuthenticationToken(username, password, domain);
}
private String obtainDomain(HttpServletRequest request) {
return request.getParameter(SPRING_SECURITY_FORM_DOMAIN_KEY);
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.loginextrafieldscustom;
import java.util.Collection;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
public class CustomAuthenticationToken extends UsernamePasswordAuthenticationToken {
private String domain;
public CustomAuthenticationToken(Object principal, Object credentials, String domain) {
super(principal, credentials);
this.domain = domain;
super.setAuthenticated(false);
}
public CustomAuthenticationToken(Object principal, Object credentials, String domain,
Collection<? extends GrantedAuthority> authorities) {
super(principal, credentials, authorities);
this.domain = domain;
super.setAuthenticated(true); // must use super, as we override
}
public String getDomain() {
return this.domain;
}
}

View File

@ -0,0 +1,92 @@
package com.baeldung.loginextrafieldscustom;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;
public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
/**
* The plaintext password used to perform
* PasswordEncoder#matches(CharSequence, String)} on when the user is
* not found to avoid SEC-2056.
*/
private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
private PasswordEncoder passwordEncoder;
private CustomUserDetailsService userDetailsService;
/**
* The password used to perform
* {@link PasswordEncoder#matches(CharSequence, String)} on when the user is
* not found to avoid SEC-2056. This is necessary, because some
* {@link PasswordEncoder} implementations will short circuit if the password is not
* in a valid format.
*/
private String userNotFoundEncodedPassword;
public CustomUserDetailsAuthenticationProvider(PasswordEncoder passwordEncoder, CustomUserDetailsService userDetailsService) {
this.passwordEncoder = passwordEncoder;
this.userDetailsService = userDetailsService;
}
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(
messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
String presentedPassword = authentication.getCredentials()
.toString();
if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(
messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
}
@Override
protected void doAfterPropertiesSet() throws Exception {
Assert.notNull(this.userDetailsService, "A UserDetailsService must be set");
this.userNotFoundEncodedPassword = this.passwordEncoder.encode(USER_NOT_FOUND_PASSWORD);
}
@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
CustomAuthenticationToken auth = (CustomAuthenticationToken) authentication;
UserDetails loadedUser;
try {
loadedUser = this.userDetailsService.loadUserByUsernameAndDomain(auth.getPrincipal()
.toString(), auth.getDomain());
} catch (UsernameNotFoundException notFound) {
if (authentication.getCredentials() != null) {
String presentedPassword = authentication.getCredentials()
.toString();
passwordEncoder.matches(presentedPassword, userNotFoundEncodedPassword);
}
throw notFound;
} catch (Exception repositoryProblem) {
throw new InternalAuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
}
if (loadedUser == null) {
throw new InternalAuthenticationServiceException("UserDetailsService returned null, "
+ "which is an interface contract violation");
}
return loadedUser;
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.loginextrafieldscustom;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
public interface CustomUserDetailsService {
UserDetails loadUserByUsernameAndDomain(String username, String domain) throws UsernameNotFoundException;
}

View File

@ -0,0 +1,30 @@
package com.baeldung.loginextrafieldscustom;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service("userDetailsService")
public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
private UserRepository userRepository;
public CustomUserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsernameAndDomain(String username, String domain) throws UsernameNotFoundException {
if (StringUtils.isAnyBlank(username, domain)) {
throw new UsernameNotFoundException("Username and domain must be provided");
}
User user = userRepository.findUser(username, domain);
if (user == null) {
throw new UsernameNotFoundException(
String.format("Username not found for domain, username=%s, domain=%s",
username, domain));
}
return user;
}
}

View File

@ -1,4 +1,4 @@
package com.baeldung.securityextrafields;
package com.baeldung.loginextrafieldscustom;
import java.util.ArrayList;
import java.util.Collection;

View File

@ -1,13 +1,13 @@
package com.baeldung.securityextrafields;
package com.baeldung.loginextrafieldscustom;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringExtraLoginFieldsApplication {
public class ExtraLoginFieldsApplication {
public static void main(String[] args) {
SpringApplication.run(SpringExtraLoginFieldsApplication.class, args);
SpringApplication.run(ExtraLoginFieldsApplication.class, args);
}
}

View File

@ -0,0 +1,62 @@
package com.baeldung.loginextrafieldscustom;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@EnableWebSecurity
@PropertySource("classpath:/application-extrafields.properties")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/css/**", "/index").permitAll()
.antMatchers("/user/**").authenticated()
.and()
.formLogin().loginPage("/login")
.and()
.logout()
.logoutUrl("/logout");
}
public CustomAuthenticationFilter authenticationFilter() throws Exception {
CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean());
filter.setAuthenticationFailureHandler(failureHandler());
return filter;
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider());
}
public AuthenticationProvider authProvider() {
CustomUserDetailsAuthenticationProvider provider
= new CustomUserDetailsAuthenticationProvider(passwordEncoder(), userDetailsService);
return provider;
}
public SimpleUrlAuthenticationFailureHandler failureHandler() {
return new SimpleUrlAuthenticationFailureHandler("/login?error=true");
}
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@ -1,4 +1,4 @@
package com.baeldung.securityextrafields;
package com.baeldung.loginextrafieldscustom;
import java.util.Collection;
@ -8,7 +8,7 @@ public class User extends org.springframework.security.core.userdetails.User {
private static final long serialVersionUID = 1L;
private final String domain;
private String domain;
public User(String username, String domain, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,

View File

@ -1,4 +1,4 @@
package com.baeldung.securityextrafields;
package com.baeldung.loginextrafieldscustom;
public interface UserRepository {

View File

@ -1,4 +1,4 @@
package com.baeldung.securityextrafields;
package com.baeldung.loginextrafieldscustom;
import java.util.Optional;

View File

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

View File

@ -1,4 +1,4 @@
package com.baeldung.securityextrafields;
package com.baeldung.loginextrafieldssimple;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
@ -36,8 +36,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.logoutUrl("/logout");
}
public CustomAuthenticationFilter authenticationFilter() throws Exception {
CustomAuthenticationFilter filter = new CustomAuthenticationFilter();
public SimpleAuthenticationFilter authenticationFilter() throws Exception {
SimpleAuthenticationFilter filter = new SimpleAuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean());
filter.setAuthenticationFailureHandler(failureHandler());
return filter;

View File

@ -1,4 +1,4 @@
package com.baeldung.securityextrafields;
package com.baeldung.loginextrafieldssimple;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -9,7 +9,7 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public class SimpleAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public static final String SPRING_SECURITY_FORM_DOMAIN_KEY = "domain";

View File

@ -1,4 +1,4 @@
package com.baeldung.securityextrafields;
package com.baeldung.loginextrafieldssimple;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.userdetails.UserDetails;
@ -7,11 +7,11 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
public class SimpleUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
private UserRepository userRepository;
public CustomUserDetailsService(UserRepository userRepository) {
public SimpleUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}

View File

@ -0,0 +1,26 @@
package com.baeldung.loginextrafieldssimple;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Repository;
@Repository("userRepository")
public class SimpleUserRepository implements UserRepository {
@Override
public User findUser(String username, String domain) {
if (StringUtils.isAnyBlank(username, domain)) {
return null;
} else {
Collection<? extends GrantedAuthority> authorities = new ArrayList<>();
User user = new User(username, domain,
"$2a$10$U3GhSMpsMSOE8Kqsbn58/edxDBKlVuYMh7qk/7ErApYFjJzi2VG5K", true,
true, true, true, authorities);
return user;
}
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.loginextrafieldssimple;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
public class User extends org.springframework.security.core.userdetails.User {
private String domain;
public User(String username, String domain, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
this.domain = domain;
}
public String getDomain() {
return domain;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.loginextrafieldssimple;
public interface UserRepository {
public User findUser(String username, String domain);
}

View File

@ -0,0 +1,51 @@
package com.baeldung.loginextrafieldssimple;
import java.util.Optional;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class WebController {
@RequestMapping("/")
public String root() {
return "redirect:/index";
}
@RequestMapping("/index")
public String index(Model model) {
getDomain().ifPresent(d -> {
model.addAttribute("domain", d);
});
return "index";
}
@RequestMapping("/user/index")
public String userIndex(Model model) {
getDomain().ifPresent(d -> {
model.addAttribute("domain", d);
});
return "user/index";
}
@RequestMapping("/login")
public String login() {
return "login";
}
private Optional<String> getDomain() {
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
String domain = null;
if (auth != null && !auth.getClass().equals(AnonymousAuthenticationToken.class)) {
User user = (User) auth.getPrincipal();
domain = user.getDomain();
}
return Optional.ofNullable(domain);
}
}

View File

@ -1,18 +1,8 @@
body {
font-family: sans;
font-size: 1em;
}
p.error {
font-weight: bold;
color: red;
}
div.logout {
float: right;
margin-right: 2em;;
}
.formfield {
margin: 0.5em;
padding: 0.3em;
}

View File

@ -1,24 +1,32 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4" lang="en">
<head>
<title>Spring Security - Login With Extra Fields</title>
<title>Spring Security with Extra Fields</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<div th:fragment="logout" class="logout" sec:authorize="isAuthenticated()">
Logged in user: <span sec:authentication="name"></span> |
domain: <span th:text="${domain}">Some Domain</span>
<div class="container">
<div class="logout float-right" th:fragment="logout" sec:authorize="isAuthenticated()">
<p>Logged in: <span sec:authentication="name"></span> | <span th:text="${domain}">Some Domain</span>
</p>
<div>
<form action="#" th:action="@{/logout}" method="post">
<input type="submit" value="Logout" />
<button class="btn btn-sm btn-primary btn-block" type="submit">Logout</button>
</form>
</div>
</div>
<h1>Hello Spring Security</h1>
<h2>Hello Spring Security</h2>
<p>This is an unsecured page, but you can access the secured pages after authenticating.</p>
<ul>
<li>Go to the <a href="/user/index" th:href="@{/user/index}">secured pages</a></li>
</ul>
</div>
</body>
</html>

View File

@ -1,23 +1,36 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login page</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<h1>Login page</h1>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<title>Login page</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<div class="container">
<form class="form-signin" th:action="@{/login}" method="post">
<h2 class="form-signin-heading">Please sign in</h2>
<p>Example: user / domain / password</p>
<p th:if="${param.error}" class="error">Invalid user, password, or domain</p>
<form th:action="@{/login}" method="post">
<label for="username">Username</label>:
<input class="formfield" type="text" id="username" name="username" autofocus="autofocus" /> <br />
<label for="domain">Domain</label>:
<input class="formfield" type="text" id="domain" name="domain" /> <br />
<label for="password">Password</label>:
<input class="formfield" type="password" id="password" name="password" /> <br />
<input type="submit" value="Log in" />
</form>
<p>
<label for="username" class="sr-only">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required autofocus/>
</p>
<p>
<label for="domain" class="sr-only">Domain</label>
<input type="text" id="domain" name="domain" class="form-control" placeholder="Domain" required autofocus/>
</p>
<p>
<label for="password" class="sr-only">Password</label>
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required autofocus/>
</p>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button><br/>
<p><a href="/index" th:href="@{/index}">Back to home page</a></p>
</body>
</form>
</div>
</body>
</html>

View File

@ -1,13 +1,20 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Security - Login With Extra Fields</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<div th:replace="index::logout"></div>
<h1>This is a secured page!</h1>
<p><a href="/index" th:href="@{/index}">Back to home page</a></p>
</body>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<title>Secured Page</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="http://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet" crossorigin="anonymous"/>
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<div class="container">
<div th:replace="index::logout"></div>
<h2>This is a secured page!</h2>
<p><a href="/index" th:href="@{/index}">Back to home page</a></p>
</div>
</body>
</html>

View File

@ -0,0 +1,46 @@
package com.baeldung.loginextrafields;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrlPattern;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
public abstract class AbstractExtraLoginFieldsTest {
@Autowired
private FilterChainProxy springSecurityFilterChain;
@Autowired
private WebApplicationContext wac;
protected MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac)
.apply(springSecurity(springSecurityFilterChain))
.build();
}
@Test
public void givenRootPathAccess_thenRedirectToIndex() throws Exception {
this.mockMvc.perform(get("/"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern("/index*"));
}
@Test
public void givenSecuredResource_whenAccessUnauthenticated_thenRequiresAuthentication() throws Exception {
this.mockMvc.perform(get("/user/index"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern("**/login"));
}
}

View File

@ -1,8 +1,7 @@
package com.baeldung.securityextrafields;
package com.baeldung.loginextrafields;
import static org.junit.Assert.assertEquals;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
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.redirectedUrlPattern;
@ -11,57 +10,26 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.util.ArrayList;
import java.util.Collection;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.baeldung.loginextrafieldscustom.ExtraLoginFieldsApplication;
import com.baeldung.loginextrafieldscustom.User;
@RunWith(SpringRunner.class)
@SpringJUnitWebConfig
@SpringBootTest(classes = SpringExtraLoginFieldsApplication.class)
public class SecurityExtraFieldsTest {
@Autowired
private FilterChainProxy springSecurityFilterChain;
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac)
.apply(springSecurity(springSecurityFilterChain)).build();
}
@Test
public void givenRootPathAccess_thenRedirectToIndex() throws Exception {
this.mockMvc.perform(get("/"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern("/index*"));
}
@Test
public void givenSecuredResource_whenAccessUnauthenticated_thenRequiresAuthentication() throws Exception {
this.mockMvc.perform(get("/user/index"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern("**/login"));
}
@SpringBootTest(classes = ExtraLoginFieldsApplication.class)
public class LoginFieldsFullTest extends AbstractExtraLoginFieldsTest {
@Test
public void givenAccessSecuredResource_whenAuthenticated_thenAuthHasExtraFields() throws Exception {
@ -100,4 +68,5 @@ public class SecurityExtraFieldsTest {
Collection<? extends GrantedAuthority> authorities = new ArrayList<>();
return new User("myusername", "mydomain", "password", true, true, true, true, authorities);
}
}

View File

@ -0,0 +1,72 @@
package com.baeldung.loginextrafields;
import static org.junit.Assert.assertEquals;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
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.redirectedUrlPattern;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import com.baeldung.loginextrafieldssimple.ExtraLoginFieldsApplication;
import com.baeldung.loginextrafieldssimple.User;
@RunWith(SpringRunner.class)
@SpringJUnitWebConfig
@SpringBootTest(classes = ExtraLoginFieldsApplication.class)
public class LoginFieldsSimpleTest extends AbstractExtraLoginFieldsTest {
@Test
public void givenAccessSecuredResource_whenAuthenticated_thenAuthHasExtraFields() throws Exception {
MockHttpServletRequestBuilder securedResourceAccess = get("/user/index");
MvcResult unauthenticatedResult = mockMvc.perform(securedResourceAccess)
.andExpect(status().is3xxRedirection())
.andReturn();
MockHttpSession session = (MockHttpSession) unauthenticatedResult.getRequest()
.getSession();
String loginUrl = unauthenticatedResult.getResponse()
.getRedirectedUrl();
User user = getUser();
mockMvc.perform(post(loginUrl)
.param("username", user.getUsername())
.param("password", user.getPassword())
.param("domain", user.getDomain())
.session(session)
.with(csrf()))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern("**/user/index"))
.andReturn();
mockMvc.perform(securedResourceAccess.session(session))
.andExpect(status().isOk());
SecurityContext securityContext
= (SecurityContext) session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
Authentication auth = securityContext.getAuthentication();
assertEquals(((User)auth.getPrincipal()).getDomain(), user.getDomain());
}
private User getUser() {
Collection<? extends GrantedAuthority> authorities = new ArrayList<>();
return new User("myusername", "mydomain", "password", true, true, true, true, authorities);
}
}

View File

@ -37,6 +37,7 @@ public class BasicAuthConfigurationIntegrationTest {
@Test
public void whenLoggedUserRequestsHomePage_ThenSuccess() throws IllegalStateException, IOException {
ResponseEntity<String> response = restTemplate.getForEntity(base.toString(), String.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertTrue(response
.getBody()
@ -47,6 +48,7 @@ public class BasicAuthConfigurationIntegrationTest {
public void whenUserWithWrongCredentialsRequestsHomePage_ThenUnauthorizedPage() throws IllegalStateException, IOException {
restTemplate = new TestRestTemplate("user", "wrongpassword");
ResponseEntity<String> response = restTemplate.getForEntity(base.toString(), String.class);
assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
assertTrue(response
.getBody()

View File

@ -2,10 +2,7 @@ package com.baeldung.springbootsecurity.oauth2server;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
@ -13,7 +10,6 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import static java.lang.String.format;
import static java.util.Collections.singletonList;
import static org.junit.Assert.assertNotNull;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@ -21,54 +17,35 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = SpringBootAuthorizationServerApplication.class)
@ActiveProfiles("authz")
public class CustomConfigAuthorizationServerIntegrationTest {
@Value("${local.server.port}") protected int port;
public class CustomConfigAuthorizationServerIntegrationTest extends OAuth2IntegrationTestSupport {
@Test
public void whenAccessTokenIsRequested_ThenAccessTokenValueIsNotNull() {
ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails();
resourceDetails.setClientId("baeldung");
resourceDetails.setClientSecret("baeldung");
resourceDetails.setScope(singletonList("read"));
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter()));
public void givenOAuth2Context_whenAccessTokenIsRequested_ThenAccessTokenValueIsNotNull() {
ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails("baeldung", singletonList("read"));
OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);
OAuth2AccessToken accessToken = restTemplate.getAccessToken();
assertNotNull(accessToken);
}
@Test(expected = OAuth2AccessDeniedException.class)
public void whenAccessTokenIsRequestedWithInvalidException_ThenExceptionIsThrown() {
ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails();
resourceDetails.setClientId("baeldung");
resourceDetails.setClientSecret("baeldung");
resourceDetails.setScope(singletonList("write"));
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter()));
public void givenOAuth2Context_whenAccessTokenIsRequestedWithInvalidException_ThenExceptionIsThrown() {
ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails("baeldung", singletonList("write"));
OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);
restTemplate.getAccessToken();
}
@Test
public void whenAccessTokenIsRequestedByClientWithWriteScope_ThenAccessTokenIsNotNull() {
ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails();
resourceDetails.setClientId("baeldung-admin");
resourceDetails.setClientSecret("baeldung");
resourceDetails.setScope(singletonList("write"));
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter()));
OAuth2AccessToken accessToken = restTemplate.getAccessToken();
assertNotNull(accessToken);
}
public void givenOAuth2Context_whenAccessTokenIsRequestedByClientWithWriteScope_ThenAccessTokenIsNotNull() {
ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails("baeldung-admin", singletonList("write"));
OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);
private ClientCredentialsResourceDetails getClientCredentialsResourceDetails() {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setAccessTokenUri(format("http://localhost:%d/oauth/token", port));
resourceDetails.setGrantType("client_credentials");
return resourceDetails;
OAuth2AccessToken accessToken = restTemplate.getAccessToken();
assertNotNull(accessToken);
}
}

View File

@ -2,40 +2,28 @@ package com.baeldung.springbootsecurity.oauth2server;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.test.context.junit4.SpringRunner;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.junit.Assert.assertNotNull;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = SpringBootAuthorizationServerApplication.class,
properties = { "security.oauth2.client.client-id=client", "security.oauth2.client.client-secret=secret" })
public class DefaultConfigAuthorizationServerIntegrationTest {
@Value("${local.server.port}") protected int port;
properties = { "security.oauth2.client.client-id=client", "security.oauth2.client.client-secret=baeldung" })
public class DefaultConfigAuthorizationServerIntegrationTest extends OAuth2IntegrationTestSupport {
@Test
public void whenAccessTokenIsRequested_ThenAccessTokenValueIsNotNull() {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setAccessTokenUri(format("http://localhost:%d/oauth/token", port));
resourceDetails.setClientId("client");
resourceDetails.setClientSecret("secret");
resourceDetails.setGrantType("client_credentials");
resourceDetails.setScope(asList("read", "write"));
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter()));
public void givenOAuth2Context_whenAccessTokenIsRequested_ThenAccessTokenValueIsNotNull() {
ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails("client", asList("read", "write"));
OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);
OAuth2AccessToken accessToken = restTemplate.getAccessToken();
assertNotNull(accessToken);
}

View File

@ -0,0 +1,34 @@
package com.baeldung.springbootsecurity.oauth2server;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
import java.util.List;
import static java.lang.String.format;
import static java.util.Collections.singletonList;
public class OAuth2IntegrationTestSupport {
@Value("${local.server.port}") protected int port;
protected ClientCredentialsResourceDetails getClientCredentialsResourceDetails(final String clientId, final List<String> scopes) {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setAccessTokenUri(format("http://localhost:%d/oauth/token", port));
resourceDetails.setClientId(clientId);
resourceDetails.setClientSecret("baeldung");
resourceDetails.setScope(scopes);
resourceDetails.setGrantType("client_credentials");
return resourceDetails;
}
protected OAuth2RestTemplate getOAuth2RestTemplate(final ClientCredentialsResourceDetails resourceDetails) {
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter()));
return restTemplate;
}
}

View File

@ -167,6 +167,12 @@
<groupId>org.apache.activemq</groupId>
<artifactId>artemis-server</artifactId>
</dependency>
<dependency>
<groupId>com.rometools</groupId>
<artifactId>rome</artifactId>
<version>${rome.version}</version>
</dependency>
</dependencies>
<build>
@ -276,6 +282,7 @@
<tomee-servlet-api.version>8.5.11</tomee-servlet-api.version>
<h2.version>1.4.194</h2.version>
<togglz.version>2.4.1.Final</togglz.version>
<rome.version>1.9.0</rome.version>
</properties>
</project>

View File

@ -6,14 +6,12 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.baeldung.internationalization.config")
public class MvcConfig extends WebMvcConfigurerAdapter {
@ -33,6 +31,6 @@ public class MvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
registry.addInterceptor(localeChangeInterceptor());
}
}

View File

@ -0,0 +1,54 @@
package com.baeldung.rss;
import com.rometools.rome.feed.rss.Channel;
import com.rometools.rome.feed.rss.Description;
import com.rometools.rome.feed.rss.Item;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.view.feed.AbstractRssFeedView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Service("articleFeedView")
public class ArticleFeedView extends AbstractRssFeedView {
protected Channel newFeed() {
Channel channel = new Channel("rss_2.0");
channel.setLink("http://localhost:8080/rss");
channel.setTitle("Article Feed");
channel.setDescription("Article Feed Description");
channel.setPubDate(new Date());
return channel;
}
@Override
protected List<Item> buildFeedItems(Map<String, Object> map, HttpServletRequest httpStRequest, HttpServletResponse httpStResponse) throws Exception {
List list = new ArrayList<Item>();
Item item1 = new Item();
item1.setLink("http://www.baeldung.com/netty-exception-handling");
item1.setTitle("Exceptions in Netty");
Description description1 = new Description();
description1.setValue("In this quick article, well be looking at exception handling in Netty.");
item1.setDescription(description1);
item1.setPubDate(new Date());
item1.setAuthor("Carlos");
Item item2 = new Item();
item2.setLink("http://www.baeldung.com/cockroachdb-java");
item2.setTitle("Guide to CockroachDB in Java");
Description description2 = new Description();
description2.setValue("This tutorial is an introductory guide to using CockroachDB with Java.");
item2.setDescription(description2);
item2.setPubDate(new Date());
item2.setAuthor("Baeldung");
list.add(item1);
list.add(item2);
return list;
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.rss;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping(value = "/rss", produces = "application/*")
public class ArticleRssController {
@RequestMapping(method = RequestMethod.GET)
public String articleFeed() {
return "articleFeedView";
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.rss;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.stereotype.Component;
@Component
public class CustomContainer implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(8080);
container.setContextPath("");
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.rss;
import com.baeldung.autoconfiguration.MySQLAutoconfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import javax.annotation.security.RolesAllowed;
@SpringBootApplication(exclude = MySQLAutoconfiguration.class)
@ComponentScan(basePackages = "com.baeldung.rss")
public class RssApp {
@RolesAllowed("*")
public static void main(String[] args) {
System.setProperty("security.basic.enabled", "false");
SpringApplication.run(RssApp.class, args);
}
}

View File

@ -4,7 +4,6 @@ import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

View File

@ -2,7 +2,6 @@ package com.baeldung.webjar;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import com.baeldung.autoconfiguration.MySQLAutoconfiguration;

View File

@ -5,7 +5,6 @@ import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Set;
public class GenericBigDecimalConverter implements GenericConverter {

View File

@ -1,7 +1,6 @@
package org.baeldung.boot.converter.controller;
import com.baeldung.toggle.Employee;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

View File

@ -11,7 +11,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

View File

@ -0,0 +1,8 @@
$(document).ready(function() {
$("#locales").change(function () {
var selectedOption = $('#locales').val();
if (selectedOption != ''){
window.location.replace('international?lang=' + selectedOption);
}
});
});

View File

@ -4,16 +4,7 @@
<meta charset="ISO-8859-1" />
<title>Home</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#locales").change(function () {
var selectedOption = $('#locales').val();
if (selectedOption != ''){
window.location.replace('international?lang=' + selectedOption);
}
});
});
</script>
<script src="internationalization.js"></script>
</head>
<body>
<h1 th:text="#{greeting}"></h1>

View File

@ -10,8 +10,6 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.context.WebApplicationContext;
import org.subethamail.wiser.Wiser;
import org.subethamail.wiser.WiserMessage;

View File

@ -12,13 +12,11 @@
Client-side service discovery allows services to find and communicate with each other without hardcoding hostname and port. The only fixed point in such an architecture consists of a service registry with which each service has to register.
### Relevant Articles:
- [Intro to Spring Cloud Netflix - Hystrix](http://www.baeldung.com/spring-cloud-netflix-hystrix)
- [Dockerizing a Spring Boot Application](http://www.baeldung.com/dockerizing-spring-boot-application)
- [Introduction to Spring Cloud Rest Client with Netflix Ribbon](http://www.baeldung.com/spring-cloud-rest-client-with-netflix-ribbon)
- [A Quick Guide to Spring Cloud Consul](http://www.baeldung.com/spring-cloud-consul)
### Relevant Articles:
- [Introduction to Spring Cloud Rest Client with Netflix Ribbon](http://www.baeldung.com/spring-cloud-rest-client-with-netflix-ribbon)
- [An Introduction to Spring Cloud Zookeeper](http://www.baeldung.com/spring-cloud-zookeeper)
- [Using a Spring Cloud App Starter](http://www.baeldung.com/using-a-spring-cloud-app-starter)
- [Spring Cloud Connectors and Heroku](http://www.baeldung.com/spring-cloud-heroku)

View File

@ -19,3 +19,8 @@ to write the following in `application.properties`:
cloud.aws.rds.spring-cloud-test-db
cloud.aws.rds.spring-cloud-test-db.password=se3retpass
```
Multiple application classes are available under this project. To launch InstanceProfileAwsApplication application, replace `start-class` under `pom.xml`:
```
<start-class>com.baeldung.spring.cloud.aws.InstanceProfileAwsApplication</start-class>
```

View File

@ -19,6 +19,7 @@
</parent>
<properties>
<start-class>com.baeldung.spring.cloud.aws.SpringCloudAwsApplication</start-class>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>

View File

@ -0,0 +1,60 @@
package com.baeldung.spring.cloud.aws;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.baeldung.spring.cloud.aws.s3.SpringCloudS3Service;
@Configuration
@EnableAutoConfiguration
@ComponentScan("com.baeldung.spring.cloud.aws.s3")
public class InstanceProfileAwsApplication {
private static final Logger logger = LoggerFactory.getLogger(InstanceProfileAwsApplication.class);
private static final String applicationConfig = "spring.config.name:application-instance-profile";
private static String bucketName;
private static String fileName = "sample-file.txt";
private static void setupResources() {
bucketName = "baeldung-test-" + UUID.randomUUID()
.toString();
try {
Files.write(Paths.get(fileName), "Hello World!".getBytes());
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
public static void main(String[] args) {
setupResources();
if (!new File(fileName).exists()) {
logger.warn("Not able to create {} file. Check your folder permissions.", fileName);
System.exit(1);
}
SpringApplication application = new SpringApplicationBuilder(InstanceProfileAwsApplication.class).properties(applicationConfig)
.build();
ConfigurableApplicationContext context = application.run(args);
SpringCloudS3Service service = context.getBean(SpringCloudS3Service.class);
// S3 bucket operations
service.createBucket(bucketName);
service.uploadObject(bucketName, fileName);
service.downloadObject(bucketName, fileName);
service.deleteBucket(bucketName);
}
}

View File

@ -0,0 +1,64 @@
package com.baeldung.spring.cloud.aws.s3;
import java.io.File;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ListObjectsV2Result;
import com.amazonaws.services.s3.model.S3ObjectSummary;
@Component
public class SpringCloudS3Service {
private static final Logger logger = LoggerFactory.getLogger(SpringCloudS3Service.class);
@Autowired
AmazonS3 amazonS3;
@Autowired
SpringCloudS3 springCloudS3;
public void createBucket(String bucketName) {
logger.debug("Creating S3 bucket: {}", bucketName);
amazonS3.createBucket(bucketName);
logger.info("{} bucket created successfully", bucketName);
}
public void downloadObject(String bucketName, String objectName) {
String s3Url = "s3://" + bucketName + "/" + objectName;
try {
springCloudS3.downloadS3Object(s3Url);
logger.info("{} file download result: {}", objectName, new File(objectName).exists());
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
public void uploadObject(String bucketName, String objectName) {
String s3Url = "s3://" + bucketName + "/" + objectName;
File file = new File(objectName);
try {
springCloudS3.uploadFileToS3(file, s3Url);
logger.info("{} file uploaded to S3", objectName);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
public void deleteBucket(String bucketName) {
logger.trace("Deleting S3 objects under {} bucket...", bucketName);
ListObjectsV2Result listObjectsV2Result = amazonS3.listObjectsV2(bucketName);
for (S3ObjectSummary objectSummary : listObjectsV2Result.getObjectSummaries()) {
logger.info("Deleting S3 object: {}", objectSummary.getKey());
amazonS3.deleteObject(bucketName, objectSummary.getKey());
}
logger.info("Deleting S3 bucket: {}", bucketName);
amazonS3.deleteBucket(bucketName);
}
}

View File

@ -0,0 +1,78 @@
AWSTemplateFormatVersion: 2010-09-09
Metadata:
'AWS::CloudFormation::Designer':
157e7d5f-5cb3-4a23-a50c-97e7f6c57173:
size:
width: 60
height: 60
position:
x: 450
'y': 90
z: 0
embeds: []
9bbaaa55-9cba-4555-a7c6-fb6ac248fd3a:
size:
width: 60
height: 60
position:
x: 260
'y': 90
z: 0
embeds: []
isassociatedwith:
- 157e7d5f-5cb3-4a23-a50c-97e7f6c57173
a7348729-a594-4dca-9b0a-e1c8d777dc3b:
size:
width: 60
height: 60
position:
x: 70
'y': 90
z: 0
embeds: []
Resources:
IAMRoleBaeldung:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AmazonS3FullAccess'
Metadata:
'AWS::CloudFormation::Designer':
id: 157e7d5f-5cb3-4a23-a50c-97e7f6c57173
InstanceProfileBaeldung:
Type: 'AWS::IAM::InstanceProfile'
Properties:
Roles:
- !Ref IAMRoleBaeldung
Metadata:
'AWS::CloudFormation::Designer':
id: 9bbaaa55-9cba-4555-a7c6-fb6ac248fd3a
EC2Instance:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: ami-2581aa40
InstanceType: t2.micro
IamInstanceProfile: !Ref InstanceProfileBaeldung
KeyName: Satish-Ohio
UserData: !Base64
'Fn::Join':
- ''
- - |
#!/bin/bash
- |
apt -y install openjdk-8-jre-headless
Metadata:
'AWS::CloudFormation::Designer':
id: a7348729-a594-4dca-9b0a-e1c8d777dc3b
DependsOn:
- InstanceProfileBaeldung

View File

@ -0,0 +1,14 @@
# Don't try to create DataSouce when running tests which don't need a DataSource
spring.autoconfigure.exclude=\
org.springframework.cloud.aws.autoconfigure.jdbc.AmazonRdsDatabaseAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
cloud.aws.region.auto=true
# Load instance profile credentials
cloud.aws.credentials.instanceProfile=true
# Disable auto cloud formation
cloud.aws.stack.auto=false
# Disable web environment
spring.main.web-environment=false

View File

@ -0,0 +1,46 @@
#!/usr/bin/env bash
# For Ubuntu 14.04
# Inspired from: https://github.com/curran/setupHadoop/blob/master/setupHadoop.sh
# Use from the user directory
# Install Java
sudo apt-get update
sudo add-apt-repository -y ppa:webupd8team/java
sudo apt-get install -y oracle-java8-installer
# Install Hadoop
curl -O http://mirror.cogentco.com/pub/apache/hadoop/common/hadoop-2.8.2/hadoop-2.8.2.tar.gz
tar xfz hadoop-2.8.2.tar.gz
sudo mv hadoop-2.8.2 /usr/local/hadoop
rm hadoop-2.8.2.tar.gz
# Environmental Variables
echo export JAVA_HOME=/usr/lib/jvm/java-8-oracle >> ~/.bashrc
echo export HADOOP_PREFIX=/usr/local/hadoop >> ~/.bashrc
echo export PATH=\$PATH:/usr/local/hadoop/bin >> ~/.bashrc
echo export PATH=\$PATH:/usr/local/hadoop/sbin >> ~/.bashrc
source ~/.bashrc
# Copy configuration files
cp master/* /usr/local/hadoop/etc/hadoop/
# Format HDFS
hdfs namenode -format
# SSH keys for Hadoop to use.
ssh-keygen -t rsa -P 'password' -f ~/.ssh/id_rsa.pub
sudo mv ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
# SSH
ssh localhost
# authenticate with osboxes.org
# Start NameNode daemon and DataNode daemon
start-dfs.sh
# stop-dfs.sh
# Install Maven
sudo apt-get install maven
# Access Hadoop - http://localhost:50070

View File

@ -0,0 +1,3 @@
.idea
*/target/*
*.iml

View File

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<project 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"
xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.twitterhdfs</groupId>
<artifactId>twitterhdfs</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<name>twitterhdfs</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
<dependencies>
<!-- Spring Stream Starter Apps -->
<dependency>
<groupId>org.springframework.cloud.stream.app</groupId>
<artifactId>spring-cloud-starter-stream-source-twitterstream</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud.stream.app</groupId>
<artifactId>spring-cloud-starter-stream-sink-hdfs</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
<!-- JSTL/JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<finalName>twitterhdfs</finalName>
</build>
</project>

View File

@ -0,0 +1,18 @@
package com.baeldung.twitterhdfs.aggregate;
import com.baeldung.twitterhdfs.processor.ProcessorApp;
import com.baeldung.twitterhdfs.source.SourceApp;
import com.baeldung.twitterhdfs.sink.SinkApp;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.aggregate.AggregateApplicationBuilder;
@SpringBootApplication
public class AggregateApp {
public static void main(String[] args) {
new AggregateApplicationBuilder()
.from(SourceApp.class).args("--fixedDelay=5000")
.via(ProcessorApp.class)
.to(SinkApp.class).args("--debug=true")
.run(args);
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.twitterhdfs.processor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Processor;
import org.springframework.integration.annotation.Transformer;
@SpringBootApplication
@EnableBinding(Processor.class)
public class ProcessorApp {
Logger log = LoggerFactory.getLogger(ProcessorApp.class);
@Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
public String processMessage(String payload) {
log.info("Payload received!");
return payload;
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.twitterhdfs.sink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.app.hdfs.sink.HdfsSinkConfiguration;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.context.annotation.Import;
import org.springframework.integration.annotation.ServiceActivator;
@SpringBootApplication
@EnableBinding(Sink.class)
@Import(HdfsSinkConfiguration.class)
public class SinkApp {
Logger log = LoggerFactory.getLogger(SinkApp.class);
@ServiceActivator(inputChannel= Sink.INPUT)
public void loggerSink(Object payload) {
log.info("Received: " + payload);
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.twitterhdfs.source;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.app.twitterstream.source.TwitterstreamSourceConfiguration;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.context.annotation.Import;
import org.springframework.integration.annotation.InboundChannelAdapter;
import java.text.SimpleDateFormat;
import java.util.Date;
@SpringBootApplication
@EnableBinding(Source.class)
@Import(TwitterstreamSourceConfiguration.class)
public class SourceApp {
Logger log = LoggerFactory.getLogger(SourceApp.class);
@InboundChannelAdapter(value = Source.OUTPUT)
public String timerMessageSource() {
return new SimpleDateFormat().format(new Date());
}
}

View File

@ -0,0 +1,6 @@
hdfs.fs-uri=hdfs://127.0.0.1:50010/
twitter.credentials.access-token=
twitter.credentials.access-token-secret=
twitter.credentials.consumer-key=
twitter.credentials.consumer-secret=

View File

@ -0,0 +1 @@
hdfs.fs-uri=hdfs://127.0.0.1:50010/

View File

@ -0,0 +1,11 @@
# Git spring-cloud-stream-app-starters
# https://github.com/spring-cloud-stream-app-starters/hdfs/blob/master/spring-cloud-starter-stream-sink-hdfs/README.adoc
git clone https://github.com/spring-cloud-stream-app-starters/hdfs.git
# Build it
./mvnw clean install -PgenerateApps
# Run it
cd target
# Optionally inject application.properties prior to build
java -jar hdfs-sink.jar --fsUri=hdfs://127.0.0.1:50010/

View File

@ -0,0 +1,4 @@
twitter.credentials.access-token=
twitter.credentials.access-token-secret=
twitter.credentials.consumer-key=
twitter.credentials.consumer-secret=

View File

@ -0,0 +1,12 @@
# Git spring-cloud-stream-app-starters
# https://github.com/spring-cloud-stream-app-starters/hdfs/blob/master/spring-cloud-starter-stream-sink-hdfs/README.adoc
git clone https://github.com/spring-cloud-stream-app-starters/twitter.git
# Build it
./mvnw clean install -PgenerateApps
# Run it
cd target
# Optionally inject application.properties prior to build
java -jar twitter_stream_source.jar --consumerKey=<CONSUMER_KEY> --consumerSecret=<CONSUMER_SECRET> \
--accessToken=<ACCESS_TOKEN> --accessTokenSecret=<ACCESS_TOKEN_SECRET>

View File

@ -1,12 +1,13 @@
package com.baeldung.spring.data.es.repository;
import com.baeldung.spring.data.es.model.Article;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
import com.baeldung.spring.data.es.model.Article;
@Repository
public interface ArticleRepository extends ElasticsearchRepository<Article, String> {
@ -14,4 +15,10 @@ public interface ArticleRepository extends ElasticsearchRepository<Article, Stri
@Query("{\"bool\": {\"must\": [{\"match\": {\"authors.name\": \"?0\"}}]}}")
Page<Article> findByAuthorsNameUsingCustomQuery(String name, Pageable pageable);
@Query("{\"bool\": {\"must\": {\"match_all\": {}}, \"filter\": {\"term\": {\"tags\": \"?0\" }}}}")
Page<Article> findByFilteredTagQuery(String tag, Pageable pageable);
@Query("{\"bool\": {\"must\": {\"match\": {\"authors.name\": \"?0\"}}, \"filter\": {\"term\": {\"tags\": \"?1\" }}}}")
Page<Article> findByAuthorsNameAndFilteredTagQuery(String name, String tag, Pageable pageable);
}

View File

@ -1,9 +1,10 @@
package com.baeldung.spring.data.es.service;
import com.baeldung.spring.data.es.model.Article;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import com.baeldung.spring.data.es.model.Article;
public interface ArticleService {
Article save(Article article);
@ -15,6 +16,10 @@ public interface ArticleService {
Page<Article> findByAuthorNameUsingCustomQuery(String name, Pageable pageable);
Page<Article> findByFilteredTagQuery(String tag, Pageable pageable);
Page<Article> findByAuthorsNameAndFilteredTagQuery(String name, String tag, Pageable pageable);
long count();
void delete(Article article);

View File

@ -1,12 +1,13 @@
package com.baeldung.spring.data.es.service;
import com.baeldung.spring.data.es.repository.ArticleRepository;
import com.baeldung.spring.data.es.model.Article;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import com.baeldung.spring.data.es.model.Article;
import com.baeldung.spring.data.es.repository.ArticleRepository;
@Service
public class ArticleServiceImpl implements ArticleService {
@ -42,6 +43,16 @@ public class ArticleServiceImpl implements ArticleService {
return articleRepository.findByAuthorsNameUsingCustomQuery(name, pageable);
}
@Override
public Page<Article> findByFilteredTagQuery(String tag, Pageable pageable) {
return articleRepository.findByFilteredTagQuery(tag, pageable);
}
@Override
public Page<Article> findByAuthorsNameAndFilteredTagQuery(String name, String tag, Pageable pageable) {
return articleRepository.findByAuthorsNameAndFilteredTagQuery(name, tag, pageable);
}
@Override
public long count() {
return articleRepository.count();

View File

@ -46,14 +46,22 @@ public class ElasticSearchIntegrationTest {
Article article = new Article("Spring Data Elasticsearch");
article.setAuthors(asList(johnSmith, johnDoe));
article.setTags("elasticsearch", "spring data");
articleService.save(article);
article = new Article("Search engines");
article.setAuthors(asList(johnDoe));
article.setTags("search engines", "tutorial");
articleService.save(article);
article = new Article("Second Article About Elasticsearch");
article.setAuthors(asList(johnSmith));
article.setTags("elasticsearch", "spring data");
articleService.save(article);
article = new Article("Elasticsearch Tutorial");
article.setAuthors(asList(johnDoe));
article.setTags("elasticsearch");
articleService.save(article);
}
@ -78,12 +86,22 @@ public class ElasticSearchIntegrationTest {
@Test
public void givenCustomQuery_whenSearchByAuthorsName_thenArticleIsFound() {
final Page<Article> articleByAuthorName = articleService.findByAuthorNameUsingCustomQuery("Smith", new PageRequest(0, 10));
assertEquals(2L, articleByAuthorName.getTotalElements());
}
final Page<Article> articleByAuthorName = articleService
.findByAuthorNameUsingCustomQuery("John Smith", new PageRequest(0, 10));
@Test
public void givenTagFilterQuery_whenSearchByTag_thenArticleIsFound() {
final Page<Article> articleByAuthorName = articleService.findByFilteredTagQuery("elasticsearch", new PageRequest(0, 10));
assertEquals(3L, articleByAuthorName.getTotalElements());
}
@Test
public void givenTagFilterQuery_whenSearchByAuthorsName_thenArticleIsFound() {
final Page<Article> articleByAuthorName = articleService.findByAuthorsNameAndFilteredTagQuery("Doe", "elasticsearch", new PageRequest(0, 10));
assertEquals(2L, articleByAuthorName.getTotalElements());
}
@Test
public void givenPersistedArticles_whenUseRegexQuery_thenRightArticlesFound() {

View File

@ -191,4 +191,16 @@ public class ElasticSearchQueryIntegrationTest {
final List<Article> articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
assertEquals(2, articles.size());
}
@Test
public void givenBoolQuery_whenQueryByAuthorsName_thenFoundArticlesByThatAuthorAndFilteredTag() {
final QueryBuilder builder = boolQuery().must(nestedQuery("authors", boolQuery().must(termQuery("authors.name", "doe"))))
.filter(termQuery("tags", "elasticsearch"));
final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder)
.build();
final List<Article> articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
assertEquals(2, articles.size());
}
}

View File

@ -1 +0,0 @@
/.tern-project

View File

@ -1,91 +0,0 @@
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>spring-mvc-push</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>spring-mvc-push</name>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven-surefire-plugin.version>2.20</maven-surefire-plugin.version>
<maven.compiler.version>3.7.0</maven.compiler.version>
<maven-war-plugin.version>3.2.0</maven-war-plugin.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.jupiter.version>5.0.2</junit.jupiter.version>
<spring.version>5.0.2.RELEASE</spring.version>
<servlet.version>4.0.0</servlet.version>
<jstl.version>1.2</jstl.version>
<jsp-api.version>2.3.2-b02</jsp-api.version>
<junit.jupiter.version>5.0.2</junit.jupiter.version>
<junit.platform.version>1.0.2</junit.platform.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>${jsp-api.version}</version>
</dependency>
<!--Testing -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration>
<warName>spring-mvc-push</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
<outputDirectory>${deploy-path}</outputDirectory>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>${junit.platform.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
<finalName>spring-mvc-push</finalName>
</build>
</project>

View File

@ -1,48 +0,0 @@
package com.baeldung.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.baeldung.controller")
public class PushConfiguration implements WebApplicationInitializer, WebMvcConfigurer {
@Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(PushConfiguration.class);
container.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = container.addServlet("DispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
@Bean
public InternalResourceViewResolver jspViewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setPrefix("/WEB-INF/views/");
bean.setSuffix(".jsp");
return bean;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
}

View File

@ -1,14 +0,0 @@
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>PushBuilder demo</title>
</head>
<body>
<h4>
Go to <a href="demoWithPush">PushBuilder demo</a><br> Go to
<a href="demoWithoutPush">Simple demo</a>
</h4>
</body>
</html>

View File

@ -1 +0,0 @@
console.log('Script')

View File

@ -1,9 +0,0 @@
.single-title {
font-size: 30px;
color: #535353;
font-weight: 200;
letter-spacing: -1.5px;
line-height: 64px;
max-width: 750px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif
}

Some files were not shown because too many files have changed in this diff Show More