Merged latest code and resolved conflicts
This commit is contained in:
commit
0f909270af
|
@ -3,25 +3,25 @@ package com.baeldung.algorithms.sudoku;
|
|||
import java.util.stream.IntStream;
|
||||
|
||||
public class BacktrackingAlgorithm {
|
||||
|
||||
private static int BOARD_SIZE = 9;
|
||||
private static int SUBSECTION_SIZE = 3;
|
||||
private static int BOARD_START_INDEX = 0;
|
||||
|
||||
private static int NO_VALUE = 0;
|
||||
private static int MIN_VALUE = 1;
|
||||
private static int MAX_VALUE = 9;
|
||||
|
||||
public static int[][] board = {
|
||||
{ 8, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 3, 6, 0, 0, 0, 0, 0 },
|
||||
{ 0, 7, 0, 0, 9, 0, 2, 0, 0 },
|
||||
{ 0, 5, 0, 0, 0, 7, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 4, 5, 7, 0, 0 },
|
||||
{ 0, 0, 0, 1, 0, 0, 0, 3, 0 },
|
||||
{ 0, 0, 1, 0, 0, 0, 0, 6, 8 },
|
||||
{ 0, 0, 8, 5, 0, 0, 0, 1, 0 },
|
||||
{ 0, 9, 0, 0, 0, 0, 4, 0, 0 }
|
||||
private static final int BOARD_SIZE = 9;
|
||||
private static final int SUBSECTION_SIZE = 3;
|
||||
private static final int BOARD_START_INDEX = 0;
|
||||
|
||||
private static final int NO_VALUE = 0;
|
||||
private static final int MIN_VALUE = 1;
|
||||
private static final int MAX_VALUE = 9;
|
||||
|
||||
private static int[][] board = {
|
||||
{8, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 3, 6, 0, 0, 0, 0, 0},
|
||||
{0, 7, 0, 0, 9, 0, 2, 0, 0},
|
||||
{0, 5, 0, 0, 0, 7, 0, 0, 0},
|
||||
{0, 0, 0, 0, 4, 5, 7, 0, 0},
|
||||
{0, 0, 0, 1, 0, 0, 0, 3, 0},
|
||||
{0, 0, 1, 0, 0, 0, 0, 6, 8},
|
||||
{0, 0, 8, 5, 0, 0, 0, 1, 0},
|
||||
{0, 9, 0, 0, 0, 0, 4, 0, 0}
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
@ -30,7 +30,7 @@ public class BacktrackingAlgorithm {
|
|||
solver.printBoard();
|
||||
}
|
||||
|
||||
public void printBoard() {
|
||||
private void printBoard() {
|
||||
for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) {
|
||||
for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) {
|
||||
System.out.print(board[row][column] + " ");
|
||||
|
@ -39,7 +39,7 @@ public class BacktrackingAlgorithm {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean solve(int[][] board) {
|
||||
private boolean solve(int[][] board) {
|
||||
for (int r = BOARD_START_INDEX; r < BOARD_SIZE; r++) {
|
||||
for (int c = BOARD_START_INDEX; c < BOARD_SIZE; c++) {
|
||||
if (board[r][c] == NO_VALUE) {
|
||||
|
@ -47,9 +47,8 @@ public class BacktrackingAlgorithm {
|
|||
board[r][c] = k;
|
||||
if (isValid(board, r, c) && solve(board)) {
|
||||
return true;
|
||||
} else {
|
||||
board[r][c] = NO_VALUE;
|
||||
}
|
||||
board[r][c] = NO_VALUE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -58,16 +57,22 @@ public class BacktrackingAlgorithm {
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean isValid(int[][] board, int r, int c) {
|
||||
return (rowConstraint(board, r) &&
|
||||
columnConstraint(board, c) &&
|
||||
subsectionConstraint(board, r, c));
|
||||
private boolean isValid(int[][] board, int r, int c) {
|
||||
return rowConstraint(board, r) &&
|
||||
columnConstraint(board, c) &&
|
||||
subsectionConstraint(board, r, c);
|
||||
}
|
||||
|
||||
private boolean subsectionConstraint(int[][] board, int r, int c) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
for (int i = (r / SUBSECTION_SIZE) * SUBSECTION_SIZE; i < (r / SUBSECTION_SIZE) * SUBSECTION_SIZE + SUBSECTION_SIZE; i++) {
|
||||
for (int j = (c / SUBSECTION_SIZE) * SUBSECTION_SIZE; j < (c / SUBSECTION_SIZE) * SUBSECTION_SIZE + SUBSECTION_SIZE; j++) {
|
||||
int subsectionRowStart = (r / SUBSECTION_SIZE) * SUBSECTION_SIZE;
|
||||
int subsectionRowEnd = subsectionRowStart + SUBSECTION_SIZE;
|
||||
|
||||
int subsectionColumnStart = (c / SUBSECTION_SIZE) * SUBSECTION_SIZE;
|
||||
int subsectionColumnEnd = subsectionColumnStart + SUBSECTION_SIZE;
|
||||
|
||||
for (int i = subsectionRowStart; i < subsectionRowEnd; i++) {
|
||||
for (int j = subsectionColumnStart; j < subsectionColumnEnd; j++) {
|
||||
if (!checkConstraint(board, i, constraint, j)) return false;
|
||||
}
|
||||
}
|
||||
|
@ -76,23 +81,19 @@ public class BacktrackingAlgorithm {
|
|||
|
||||
private boolean columnConstraint(int[][] board, int c) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
for (int i = BOARD_START_INDEX; i < BOARD_SIZE; i++) {
|
||||
if (!checkConstraint(board, i, constraint, c)) return false;
|
||||
}
|
||||
return true;
|
||||
return IntStream.range(BOARD_START_INDEX, BOARD_SIZE)
|
||||
.allMatch(i -> checkConstraint(board, i, constraint, c));
|
||||
}
|
||||
|
||||
private boolean rowConstraint(int[][] board, int r) {
|
||||
boolean[] constraint = new boolean[BOARD_SIZE];
|
||||
for (int i = BOARD_START_INDEX; i < BOARD_SIZE; i++) {
|
||||
if (!checkConstraint(board, r, constraint, i)) return false;
|
||||
}
|
||||
return true;
|
||||
return IntStream.range(BOARD_START_INDEX, BOARD_SIZE)
|
||||
.allMatch(i -> checkConstraint(board, r, constraint, i));
|
||||
}
|
||||
|
||||
private boolean checkConstraint(int[][] board, int r, boolean[] constraint, int c) {
|
||||
if (board[r][c] >= MIN_VALUE && board[r][c] <= MAX_VALUE) {
|
||||
if (constraint[board[r][c] - 1] == false) {
|
||||
if (board[r][c] != NO_VALUE) {
|
||||
if (!constraint[board[r][c] - 1]) {
|
||||
constraint[board[r][c] - 1] = true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -4,7 +4,7 @@ class ColumnNode extends DancingNode {
|
|||
int size;
|
||||
String name;
|
||||
|
||||
public ColumnNode(String n) {
|
||||
ColumnNode(String n) {
|
||||
super();
|
||||
size = 0;
|
||||
name = n;
|
||||
|
|
|
@ -50,10 +50,9 @@ public class DancingLinks {
|
|||
|
||||
private ColumnNode makeDLXBoard(boolean[][] grid) {
|
||||
final int COLS = grid[0].length;
|
||||
final int ROWS = grid.length;
|
||||
|
||||
ColumnNode headerNode = new ColumnNode("header");
|
||||
ArrayList<ColumnNode> columnNodes = new ArrayList<ColumnNode>();
|
||||
List<ColumnNode> columnNodes = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < COLS; i++) {
|
||||
ColumnNode n = new ColumnNode(Integer.toString(i));
|
||||
|
@ -62,10 +61,10 @@ public class DancingLinks {
|
|||
}
|
||||
headerNode = headerNode.R.C;
|
||||
|
||||
for (int i = 0; i < ROWS; i++) {
|
||||
for (boolean[] aGrid : grid) {
|
||||
DancingNode prev = null;
|
||||
for (int j = 0; j < COLS; j++) {
|
||||
if (grid[i][j] == true) {
|
||||
if (aGrid[j]) {
|
||||
ColumnNode col = columnNodes.get(j);
|
||||
DancingNode newNode = new DancingNode(col);
|
||||
if (prev == null)
|
||||
|
@ -82,21 +81,21 @@ public class DancingLinks {
|
|||
return headerNode;
|
||||
}
|
||||
|
||||
public DancingLinks(boolean[][] cover) {
|
||||
DancingLinks(boolean[][] cover) {
|
||||
header = makeDLXBoard(cover);
|
||||
}
|
||||
|
||||
public void runSolver() {
|
||||
answer = new LinkedList<DancingNode>();
|
||||
answer = new LinkedList<>();
|
||||
search(0);
|
||||
}
|
||||
|
||||
public void handleSolution(List<DancingNode> answer) {
|
||||
private void handleSolution(List<DancingNode> answer) {
|
||||
int[][] result = parseBoard(answer);
|
||||
printSolution(result);
|
||||
}
|
||||
|
||||
int size = 9;
|
||||
private int size = 9;
|
||||
|
||||
private int[][] parseBoard(List<DancingNode> answer) {
|
||||
int[][] result = new int[size][size];
|
||||
|
@ -120,12 +119,12 @@ public class DancingLinks {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static void printSolution(int[][] result) {
|
||||
private static void printSolution(int[][] result) {
|
||||
int N = result.length;
|
||||
for (int i = 0; i < N; i++) {
|
||||
String ret = "";
|
||||
for (int[] aResult : result) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
for (int j = 0; j < N; j++) {
|
||||
ret += result[i][j] + " ";
|
||||
ret.append(aResult[j]).append(" ");
|
||||
}
|
||||
System.out.println(ret);
|
||||
}
|
||||
|
|
|
@ -1,39 +1,37 @@
|
|||
package com.baeldung.algorithms.sudoku;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class DancingLinksAlgorithm {
|
||||
private static int BOARD_SIZE = 9;
|
||||
private static int SUBSECTION_SIZE = 3;
|
||||
private static int NO_VALUE = 0;
|
||||
private static int CONSTRAINTS = 4;
|
||||
private static int MIN_VALUE = 1;
|
||||
private static int MAX_VALUE = 9;
|
||||
private static int COVER_START_INDEX = 1;
|
||||
private static final int BOARD_SIZE = 9;
|
||||
private static final int SUBSECTION_SIZE = 3;
|
||||
private static final int NO_VALUE = 0;
|
||||
private static final int CONSTRAINTS = 4;
|
||||
private static final int MIN_VALUE = 1;
|
||||
private static final int MAX_VALUE = 9;
|
||||
private static final int COVER_START_INDEX = 1;
|
||||
|
||||
public static int[][] board = {
|
||||
{ 8, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 3, 6, 0, 0, 0, 0, 0 },
|
||||
{ 0, 7, 0, 0, 9, 0, 2, 0, 0 },
|
||||
{ 0, 5, 0, 0, 0, 7, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 4, 5, 7, 0, 0 },
|
||||
{ 0, 0, 0, 1, 0, 0, 0, 3, 0 },
|
||||
{ 0, 0, 1, 0, 0, 0, 0, 6, 8 },
|
||||
{ 0, 0, 8, 5, 0, 0, 0, 1, 0 },
|
||||
{ 0, 9, 0, 0, 0, 0, 4, 0, 0 }
|
||||
};
|
||||
private static int[][] board = {
|
||||
{8, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
{0, 0, 3, 6, 0, 0, 0, 0, 0},
|
||||
{0, 7, 0, 0, 9, 0, 2, 0, 0},
|
||||
{0, 5, 0, 0, 0, 7, 0, 0, 0},
|
||||
{0, 0, 0, 0, 4, 5, 7, 0, 0},
|
||||
{0, 0, 0, 1, 0, 0, 0, 3, 0},
|
||||
{0, 0, 1, 0, 0, 0, 0, 6, 8},
|
||||
{0, 0, 8, 5, 0, 0, 0, 1, 0},
|
||||
{0, 9, 0, 0, 0, 0, 4, 0, 0}
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
DancingLinksAlgorithm solver = new DancingLinksAlgorithm();
|
||||
solver.solve(board);
|
||||
}
|
||||
|
||||
public boolean solve(int[][] board) {
|
||||
private void solve(int[][] board) {
|
||||
boolean[][] cover = initializeExactCoverBoard(board);
|
||||
DancingLinks dlx = new DancingLinks(cover);
|
||||
dlx.runSolver();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getIndex(int row, int col, int num) {
|
||||
|
@ -54,7 +52,7 @@ public class DancingLinksAlgorithm {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Row constrain.
|
||||
for (int r = COVER_START_INDEX; r <= BOARD_SIZE; r++) {
|
||||
for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) {
|
||||
|
|
|
@ -39,11 +39,11 @@ class DancingNode {
|
|||
this.U.D = this.D.U = this;
|
||||
}
|
||||
|
||||
public DancingNode() {
|
||||
DancingNode() {
|
||||
L = R = U = D = this;
|
||||
}
|
||||
|
||||
public DancingNode(ColumnNode c) {
|
||||
DancingNode(ColumnNode c) {
|
||||
this();
|
||||
C = c;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
package com.baeldung.java9.httpclient;
|
||||
|
||||
import jdk.incubator.http.HttpClient;
|
||||
import jdk.incubator.http.HttpRequest;
|
||||
import jdk.incubator.http.HttpResponse;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.collection.IsEmptyCollection.empty;
|
||||
import static org.hamcrest.core.IsNot.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Created by adam.
|
||||
*/
|
||||
public class HttpClientTest {
|
||||
|
||||
@Test
|
||||
public void shouldReturnSampleDataContentWhenConnectViaSystemProxy() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/post"))
|
||||
.headers("Content-Type", "text/plain;charset=UTF-8")
|
||||
.POST(HttpRequest.BodyProcessor.fromString("Sample body"))
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newBuilder()
|
||||
.proxy(ProxySelector.getDefault())
|
||||
.build()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
assertThat(response.body(), containsString("Sample body"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotFollowRedirectWhenSetToDefaultNever() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("http://stackoverflow.com"))
|
||||
.version(HttpClient.Version.HTTP_1_1)
|
||||
.GET()
|
||||
.build();
|
||||
HttpResponse<String> response = HttpClient.newBuilder()
|
||||
.build()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_MOVED_PERM));
|
||||
assertThat(response.body(), containsString("https://stackoverflow.com/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFollowRedirectWhenSetToAlways() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("http://stackoverflow.com"))
|
||||
.version(HttpClient.Version.HTTP_1_1)
|
||||
.GET()
|
||||
.build();
|
||||
HttpResponse<String> response = HttpClient.newBuilder()
|
||||
.followRedirects(HttpClient.Redirect.ALWAYS)
|
||||
.build()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
assertThat(response.finalRequest()
|
||||
.uri()
|
||||
.toString(), equalTo("https://stackoverflow.com/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnOKStatusForAuthenticatedAccess() throws URISyntaxException, IOException, InterruptedException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/basic-auth"))
|
||||
.GET()
|
||||
.build();
|
||||
HttpResponse<String> response = HttpClient.newBuilder()
|
||||
.authenticator(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication("postman", "password".toCharArray());
|
||||
}
|
||||
})
|
||||
.build()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSendRequestAsync() throws URISyntaxException, InterruptedException, ExecutionException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/post"))
|
||||
.headers("Content-Type", "text/plain;charset=UTF-8")
|
||||
.POST(HttpRequest.BodyProcessor.fromString("Sample body"))
|
||||
.build();
|
||||
CompletableFuture<HttpResponse<String>> response = HttpClient.newBuilder()
|
||||
.build()
|
||||
.sendAsync(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.get()
|
||||
.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUseJustTwoThreadWhenProcessingSendAsyncRequest() throws URISyntaxException, InterruptedException, ExecutionException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/get"))
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
CompletableFuture<HttpResponse<String>> response1 = HttpClient.newBuilder()
|
||||
.executor(Executors.newFixedThreadPool(2))
|
||||
.build()
|
||||
.sendAsync(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
CompletableFuture<HttpResponse<String>> response2 = HttpClient.newBuilder()
|
||||
.executor(Executors.newFixedThreadPool(2))
|
||||
.build()
|
||||
.sendAsync(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
CompletableFuture<HttpResponse<String>> response3 = HttpClient.newBuilder()
|
||||
.executor(Executors.newFixedThreadPool(2))
|
||||
.build()
|
||||
.sendAsync(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
CompletableFuture.allOf(response1, response2, response3)
|
||||
.join();
|
||||
|
||||
assertThat(response1.get()
|
||||
.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
assertThat(response2.get()
|
||||
.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
assertThat(response3.get()
|
||||
.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotStoreCookieWhenPolicyAcceptNone() throws URISyntaxException, IOException, InterruptedException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/get"))
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
HttpClient httpClient = HttpClient.newBuilder()
|
||||
.cookieManager(new CookieManager(null, CookiePolicy.ACCEPT_NONE))
|
||||
.build();
|
||||
|
||||
httpClient.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(httpClient.cookieManager()
|
||||
.get()
|
||||
.getCookieStore()
|
||||
.getCookies(), empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldStoreCookieWhenPolicyAcceptAll() throws URISyntaxException, IOException, InterruptedException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/get"))
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
HttpClient httpClient = HttpClient.newBuilder()
|
||||
.cookieManager(new CookieManager(null, CookiePolicy.ACCEPT_ALL))
|
||||
.build();
|
||||
|
||||
httpClient.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(httpClient.cookieManager()
|
||||
.get()
|
||||
.getCookieStore()
|
||||
.getCookies(), not(empty()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldProcessMultipleRequestViaStream() throws URISyntaxException, ExecutionException, InterruptedException {
|
||||
List<URI> targets = Arrays.asList(new URI("https://postman-echo.com/get?foo1=bar1"), new URI("https://postman-echo.com/get?foo2=bar2"));
|
||||
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
|
||||
List<CompletableFuture<String>> futures = targets.stream()
|
||||
.map(target -> client.sendAsync(HttpRequest.newBuilder(target)
|
||||
.GET()
|
||||
.build(), HttpResponse.BodyHandler.asString())
|
||||
.thenApply(response -> response.body()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
|
||||
.join();
|
||||
|
||||
if (futures.get(0)
|
||||
.get()
|
||||
.contains("foo1")) {
|
||||
assertThat(futures.get(0)
|
||||
.get(), containsString("bar1"));
|
||||
assertThat(futures.get(1)
|
||||
.get(), containsString("bar2"));
|
||||
} else {
|
||||
assertThat(futures.get(1)
|
||||
.get(), containsString("bar2"));
|
||||
assertThat(futures.get(1)
|
||||
.get(), containsString("bar1"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
package com.baeldung.java9.httpclient;
|
||||
|
||||
import jdk.incubator.http.HttpClient;
|
||||
import jdk.incubator.http.HttpRequest;
|
||||
import jdk.incubator.http.HttpResponse;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.Duration;
|
||||
|
||||
import static java.time.temporal.ChronoUnit.SECONDS;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Created by adam.
|
||||
*/
|
||||
public class HttpRequestTest {
|
||||
|
||||
@Test
|
||||
public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/get"))
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUseHttp2WhenWebsiteUsesHttp2() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://stackoverflow.com"))
|
||||
.version(HttpClient.Version.HTTP_2)
|
||||
.GET()
|
||||
.build();
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
assertThat(response.version(), equalTo(HttpClient.Version.HTTP_2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFallbackToHttp1_1WhenWebsiteDoesNotUseHttp2() throws IOException, InterruptedException, URISyntaxException, NoSuchAlgorithmException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/get"))
|
||||
.version(HttpClient.Version.HTTP_2)
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.version(), equalTo(HttpClient.Version.HTTP_1_1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnStatusOKWhenSendGetRequestWithDummyHeaders() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/get"))
|
||||
.headers("key1", "value1", "key2", "value2")
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnStatusOKWhenSendGetRequestTimeoutSet() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/get"))
|
||||
.timeout(Duration.of(10, SECONDS))
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnNoContentWhenPostWithNoBody() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/post"))
|
||||
.POST(HttpRequest.noBody())
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnSampleDataContentWhenPostWithBodyText() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/post"))
|
||||
.headers("Content-Type", "text/plain;charset=UTF-8")
|
||||
.POST(HttpRequest.BodyProcessor.fromString("Sample request body"))
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
assertThat(response.body(), containsString("Sample request body"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnSampleDataContentWhenPostWithInputStream() throws IOException, InterruptedException, URISyntaxException {
|
||||
byte[] sampleData = "Sample request body".getBytes();
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/post"))
|
||||
.headers("Content-Type", "text/plain;charset=UTF-8")
|
||||
.POST(HttpRequest.BodyProcessor.fromInputStream(() -> new ByteArrayInputStream(sampleData)))
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
assertThat(response.body(), containsString("Sample request body"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnSampleDataContentWhenPostWithByteArrayProcessorStream() throws IOException, InterruptedException, URISyntaxException {
|
||||
byte[] sampleData = "Sample request body".getBytes();
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/post"))
|
||||
.headers("Content-Type", "text/plain;charset=UTF-8")
|
||||
.POST(HttpRequest.BodyProcessor.fromByteArray(sampleData))
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
assertThat(response.body(), containsString("Sample request body"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnSampleDataContentWhenPostWithFileProcessorStream() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/post"))
|
||||
.headers("Content-Type", "text/plain;charset=UTF-8")
|
||||
.POST(HttpRequest.BodyProcessor.fromFile(Paths.get("src/test/resources/sample.txt")))
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
assertThat(response.body(), containsString("Sample file content"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.baeldung.java9.httpclient;
|
||||
|
||||
import jdk.incubator.http.HttpClient;
|
||||
import jdk.incubator.http.HttpRequest;
|
||||
import jdk.incubator.http.HttpResponse;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.Matchers.isEmptyString;
|
||||
import static org.hamcrest.core.IsNot.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Created by adam.
|
||||
*/
|
||||
public class HttpResponseTest {
|
||||
|
||||
@Test
|
||||
public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("https://postman-echo.com/get"))
|
||||
.GET()
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = HttpClient.newHttpClient()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK));
|
||||
assertThat(response.body(), not(isEmptyString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldResponseURIDifferentThanRequestUIRWhenRedirect() throws IOException, InterruptedException, URISyntaxException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(new URI("http://stackoverflow.com"))
|
||||
.version(HttpClient.Version.HTTP_1_1)
|
||||
.GET()
|
||||
.build();
|
||||
HttpResponse<String> response = HttpClient.newBuilder()
|
||||
.followRedirects(HttpClient.Redirect.ALWAYS)
|
||||
.build()
|
||||
.send(request, HttpResponse.BodyHandler.asString());
|
||||
|
||||
assertThat(request.uri()
|
||||
.toString(), equalTo("http://stackoverflow.com"));
|
||||
assertThat(response.uri()
|
||||
.toString(), equalTo("https://stackoverflow.com/"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.baeldung.concurrent.prioritytaskexecution;
|
||||
|
||||
public class Job implements Runnable {
|
||||
private String jobName;
|
||||
private JobPriority jobPriority;
|
||||
|
||||
public Job(String jobName, JobPriority jobPriority) {
|
||||
this.jobName = jobName;
|
||||
this.jobPriority = jobPriority != null ? jobPriority : JobPriority.MEDIUM;
|
||||
}
|
||||
|
||||
public JobPriority getJobPriority() {
|
||||
return jobPriority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
System.out.println("Job:" + jobName + " Priority:" + jobPriority);
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.baeldung.concurrent.prioritytaskexecution;
|
||||
|
||||
public enum JobPriority {
|
||||
HIGH,
|
||||
MEDIUM,
|
||||
LOW
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.baeldung.concurrent.prioritytaskexecution;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PriorityJobScheduler {
|
||||
|
||||
private ExecutorService priorityJobPoolExecutor;
|
||||
private ExecutorService priorityJobScheduler;
|
||||
private PriorityBlockingQueue<Runnable> priorityQueue;
|
||||
|
||||
public PriorityJobScheduler(Integer poolSize, Integer queueSize) {
|
||||
priorityJobPoolExecutor = Executors.newFixedThreadPool(poolSize);
|
||||
Comparator<? super Job> jobComparator = Comparator.comparing(Job::getJobPriority);
|
||||
priorityQueue = new PriorityBlockingQueue<Runnable>(queueSize,
|
||||
(Comparator<? super Runnable>) jobComparator);
|
||||
|
||||
priorityJobScheduler = Executors.newSingleThreadExecutor();
|
||||
priorityJobScheduler.execute(()->{
|
||||
while (true) {
|
||||
try {
|
||||
priorityJobPoolExecutor.execute(priorityQueue.take());
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void scheduleJob(Job job) {
|
||||
priorityQueue.add(job);
|
||||
}
|
||||
|
||||
public int getQueuedTaskCount() {
|
||||
return priorityQueue.size();
|
||||
}
|
||||
|
||||
protected void close(ExecutorService scheduler) {
|
||||
scheduler.shutdown();
|
||||
try {
|
||||
if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
scheduler.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
scheduler.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
public void closeScheduler() {
|
||||
close(priorityJobPoolExecutor);
|
||||
close(priorityJobScheduler);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
package com.baeldung.concurrent.waitandnotify;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class Data {
|
||||
private String packet;
|
||||
|
||||
|
@ -14,6 +12,7 @@ public class Data {
|
|||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.out.println("Thread Interrupted");
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +27,7 @@ public class Data {
|
|||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.out.println("Thread Interrupted");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ public class Receiver implements Runnable {
|
|||
try {
|
||||
Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 5000));
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.out.println("Thread Interrupted");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ public class Sender implements Runnable {
|
|||
try {
|
||||
Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 5000));
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.out.println("Thread Interrupted");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package com.baeldung.concurrent.prioritytaskexecution;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class PriorityJobSchedulerUnitTest {
|
||||
private static int POOL_SIZE = 1;
|
||||
private static int QUEUE_SIZE = 10;
|
||||
|
||||
@Test
|
||||
public void whenMultiplePriorityJobsQueued_thenHighestPriorityJobIsPicked() {
|
||||
Job job1 = new Job("Job1", JobPriority.LOW);
|
||||
Job job2 = new Job("Job2", JobPriority.MEDIUM);
|
||||
Job job3 = new Job("Job3", JobPriority.HIGH);
|
||||
Job job4 = new Job("Job4", JobPriority.MEDIUM);
|
||||
Job job5 = new Job("Job5", JobPriority.LOW);
|
||||
Job job6 = new Job("Job6", JobPriority.HIGH);
|
||||
|
||||
PriorityJobScheduler pjs = new PriorityJobScheduler(POOL_SIZE, QUEUE_SIZE);
|
||||
|
||||
pjs.scheduleJob(job1);
|
||||
pjs.scheduleJob(job2);
|
||||
pjs.scheduleJob(job3);
|
||||
pjs.scheduleJob(job4);
|
||||
pjs.scheduleJob(job5);
|
||||
pjs.scheduleJob(job6);
|
||||
|
||||
// ensure no tasks is pending before closing the scheduler
|
||||
while (pjs.getQueuedTaskCount() != 0);
|
||||
|
||||
// delay to avoid job sleep (added for demo) being interrupted
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
|
||||
pjs.closeScheduler();
|
||||
}
|
||||
}
|
|
@ -57,7 +57,8 @@ public class NetworkIntegrationTest {
|
|||
sender.join();
|
||||
receiver.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
Thread.currentThread().interrupt();
|
||||
System.out.println("Thread Interrupted");
|
||||
}
|
||||
|
||||
assertEquals(expected, outContent.toString());
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package com.baeldung.designpatterns.observer;
|
||||
|
||||
public interface Channel {
|
||||
public void update(Object o);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.baeldung.designpatterns.observer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NewsAgency {
|
||||
private String news;
|
||||
private List<Channel> channels = new ArrayList<>();
|
||||
|
||||
public void addObserver(Channel channel) {
|
||||
this.channels.add(channel);
|
||||
}
|
||||
|
||||
public void removeObserver(Channel channel) {
|
||||
this.channels.remove(channel);
|
||||
}
|
||||
|
||||
public void setNews(String news) {
|
||||
this.news = news;
|
||||
for (Channel channel : this.channels) {
|
||||
channel.update(this.news);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.baeldung.designpatterns.observer;
|
||||
|
||||
public class NewsChannel implements Channel {
|
||||
|
||||
private String news;
|
||||
|
||||
@Override
|
||||
public void update(Object news) {
|
||||
this.setNews((String) news);
|
||||
}
|
||||
|
||||
public String getNews() {
|
||||
return news;
|
||||
}
|
||||
|
||||
public void setNews(String news) {
|
||||
this.news = news;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.designpatterns.observer;
|
||||
|
||||
import java.util.Observable;
|
||||
|
||||
public class ONewsAgency extends Observable {
|
||||
private String news;
|
||||
|
||||
public void setNews(String news) {
|
||||
this.news = news;
|
||||
setChanged();
|
||||
notifyObservers(news);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.baeldung.designpatterns.observer;
|
||||
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
public class ONewsChannel implements Observer {
|
||||
|
||||
private String news;
|
||||
|
||||
@Override
|
||||
public void update(Observable o, Object news) {
|
||||
this.setNews((String) news);
|
||||
}
|
||||
|
||||
public String getNews() {
|
||||
return news;
|
||||
}
|
||||
|
||||
public void setNews(String news) {
|
||||
this.news = news;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.designpatterns.observer;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
|
||||
public class PCLNewsAgency {
|
||||
private String news;
|
||||
|
||||
private PropertyChangeSupport support;
|
||||
|
||||
public PCLNewsAgency() {
|
||||
support = new PropertyChangeSupport(this);
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener pcl) {
|
||||
support.addPropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener pcl) {
|
||||
support.removePropertyChangeListener(pcl);
|
||||
}
|
||||
|
||||
public void setNews(String value) {
|
||||
support.firePropertyChange("news", this.news, value);
|
||||
this.news = value;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.baeldung.designpatterns.observer;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
|
||||
public class PCLNewsChannel implements PropertyChangeListener {
|
||||
|
||||
private String news;
|
||||
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
this.setNews((String) evt.getNewValue());
|
||||
}
|
||||
|
||||
public String getNews() {
|
||||
return news;
|
||||
}
|
||||
|
||||
public void setNews(String news) {
|
||||
this.news = news;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.javac;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Data {
|
||||
List<String> textList = new ArrayList();
|
||||
|
||||
public void addText(String text) {
|
||||
textList.add(text);
|
||||
}
|
||||
|
||||
public List getTextList() {
|
||||
return this.textList;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
-d javac-target -verbose
|
||||
com/baeldung/javac/Data.java
|
|
@ -0,0 +1,2 @@
|
|||
-d javac-target
|
||||
-verbose
|
|
@ -0,0 +1 @@
|
|||
com/baeldung/javac/Data.java
|
|
@ -0,0 +1,3 @@
|
|||
-d javac-target
|
||||
-Xlint:rawtypes,unchecked,static,cast,serial,fallthrough
|
||||
com/baeldung/javac/Data.java
|
|
@ -0,0 +1,47 @@
|
|||
package com.baeldung.designpatterns.observer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.designpatterns.observer.NewsAgency;
|
||||
import com.baeldung.designpatterns.observer.NewsChannel;
|
||||
|
||||
public class ObserverIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void whenChangingNewsAgencyState_thenNewsChannelNotified() {
|
||||
|
||||
NewsAgency observable = new NewsAgency();
|
||||
NewsChannel observer = new NewsChannel();
|
||||
|
||||
observable.addObserver(observer);
|
||||
|
||||
observable.setNews("news");
|
||||
assertEquals(observer.getNews(), "news");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenChangingONewsAgencyState_thenONewsChannelNotified() {
|
||||
|
||||
ONewsAgency observable = new ONewsAgency();
|
||||
ONewsChannel observer = new ONewsChannel();
|
||||
|
||||
observable.addObserver(observer);
|
||||
|
||||
observable.setNews("news");
|
||||
assertEquals(observer.getNews(), "news");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenChangingPCLNewsAgencyState_thenONewsChannelNotified() {
|
||||
|
||||
PCLNewsAgency observable = new PCLNewsAgency();
|
||||
PCLNewsChannel observer = new PCLNewsChannel();
|
||||
|
||||
observable.addPropertyChangeListener(observer);
|
||||
|
||||
observable.setNews("news");
|
||||
assertEquals(observer.getNews(), "news");
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
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 = Factorial.getFactorial(n);
|
||||
|
||||
// then
|
||||
BigInteger expectedFactorial = new BigInteger("10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000");
|
||||
assertThat(factorial, is(equalTo(expectedFactorial)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMemoizedSupplier_whenGet_thenSubsequentGetsAreFast() {
|
||||
// given
|
||||
Supplier<BigInteger> memoizedSupplier;
|
||||
memoizedSupplier = Suppliers.memoize(CostlySupplier::generateBigNumber);
|
||||
|
||||
// when
|
||||
BigInteger expectedValue = new BigInteger("12345");
|
||||
assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 2000D);
|
||||
|
||||
// then
|
||||
assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 0D);
|
||||
assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 0D);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMemoizedSupplierWithExpiration_whenGet_thenSubsequentGetsBeforeExpiredAreFast() throws InterruptedException {
|
||||
// given
|
||||
Supplier<BigInteger> memoizedSupplier;
|
||||
memoizedSupplier = Suppliers.memoizeWithExpiration(CostlySupplier::generateBigNumber, 3, TimeUnit.SECONDS);
|
||||
|
||||
// when
|
||||
BigInteger expectedValue = new BigInteger("12345");
|
||||
assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 2000D);
|
||||
|
||||
// then
|
||||
assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 0D);
|
||||
// add one more second until memoized Supplier is evicted from memory
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 2000D);
|
||||
}
|
||||
|
||||
private <T> void assertSupplierGetExecutionResultAndDuration(Supplier<T> supplier,
|
||||
T expectedValue,
|
||||
double expectedDurationInMs) {
|
||||
Instant start = Instant.now();
|
||||
T value = supplier.get();
|
||||
Long durationInMs = Duration.between(start, Instant.now()).toMillis();
|
||||
double marginOfErrorInMs = 100D;
|
||||
|
||||
assertThat(value, is(equalTo(expectedValue)));
|
||||
assertThat(durationInMs.doubleValue(), is(closeTo(expectedDurationInMs, marginOfErrorInMs)));
|
||||
}
|
||||
|
||||
}
|
|
@ -9,7 +9,7 @@ import org.hibernate.Interceptor;
|
|||
import org.hibernate.Transaction;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
public class CustomInterceptorImpl implements Interceptor {
|
||||
public class CustomInterceptorImpl implements Interceptor, Serializable {
|
||||
|
||||
@Override
|
||||
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
### Relevant Article:
|
||||
- [Introduction to using InfluxDB with Java](http://www.baeldung.com/using-influxdb-with-java/)
|
||||
- [Using InfluxDB with Java](http://www.baeldung.com/java-influxdb)
|
||||
|
||||
### Overview
|
||||
This Maven project contains the Java code for the article linked above.
|
||||
|
|
|
@ -8,7 +8,6 @@ import org.influxdb.dto.*;
|
|||
import org.influxdb.impl.InfluxDBResultMapper;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -103,7 +102,7 @@ public class InfluxDBConnectionLiveTest {
|
|||
// another brief pause.
|
||||
Thread.sleep(10);
|
||||
|
||||
List<MemoryPoint> memoryPointList = getPoints(connection, "Select * from memory", "baeldung");
|
||||
List<com.baeldung.influxdb.MemoryPoint> memoryPointList = getPoints(connection, "Select * from memory", "baeldung");
|
||||
|
||||
assertEquals(10, memoryPointList.size());
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
## Reliable Messaging with JGroups Tutorial Project
|
||||
|
||||
### Relevant Article:
|
||||
- [Reliable Messaging with JGroups](http://www.baeldung.com/reliable-messaging-with-jgroups/)
|
||||
|
||||
### Overview
|
||||
This Maven project contains the Java code for the article linked above.
|
||||
|
||||
### Package Organization
|
||||
Java classes for the intro tutorial are in the org.baeldung.jgroups package.
|
||||
|
||||
|
||||
### Running the tests
|
||||
|
||||
```
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>jgroups</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>jgroups</name>
|
||||
<description>Reliable Messaging with JGroups Tutorial</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jgroups</groupId>
|
||||
<artifactId>jgroups</artifactId>
|
||||
<version>4.0.10.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,222 @@
|
|||
package com.baeldung.jgroups;
|
||||
|
||||
import org.apache.commons.cli.*;
|
||||
import org.jgroups.*;
|
||||
import org.jgroups.util.Util;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class JGroupsMessenger extends ReceiverAdapter {
|
||||
|
||||
private JChannel channel;
|
||||
private String userName;
|
||||
private String clusterName;
|
||||
private View lastView;
|
||||
private boolean running = true;
|
||||
|
||||
// Our shared state
|
||||
private Integer messageCount = 0;
|
||||
|
||||
/**
|
||||
* Connect to a JGroups cluster using command line options
|
||||
* @param args command line arguments
|
||||
* @throws Exception
|
||||
*/
|
||||
private void start(String[] args) throws Exception {
|
||||
processCommandline(args);
|
||||
|
||||
// Create the channel
|
||||
// This file could be moved, or made a command line option.
|
||||
channel = new JChannel("src/main/resources/udp.xml");
|
||||
|
||||
// Set a name
|
||||
channel.name(userName);
|
||||
|
||||
// Register for callbacks
|
||||
channel.setReceiver(this);
|
||||
|
||||
// Ignore our messages
|
||||
channel.setDiscardOwnMessages(true);
|
||||
|
||||
// Connect
|
||||
channel.connect(clusterName);
|
||||
|
||||
// Start state transfer
|
||||
channel.getState(null, 0);
|
||||
|
||||
// Do the things
|
||||
processInput();
|
||||
|
||||
// Clean up
|
||||
channel.close();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick and dirty implementaton of commons cli for command line args
|
||||
* @param args the command line args
|
||||
* @throws ParseException
|
||||
*/
|
||||
private void processCommandline(String[] args) throws ParseException {
|
||||
|
||||
// Options, parser, friendly help
|
||||
Options options = new Options();
|
||||
CommandLineParser parser = new DefaultParser();
|
||||
HelpFormatter formatter = new HelpFormatter();
|
||||
|
||||
options.addOption("u", "user", true, "User name")
|
||||
.addOption("c", "cluster", true, "Cluster name");
|
||||
|
||||
CommandLine line = parser.parse(options, args);
|
||||
|
||||
if (line.hasOption("user")) {
|
||||
userName = line.getOptionValue("user");
|
||||
} else {
|
||||
formatter.printHelp("JGroupsMessenger: need a user name.\n", options);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
if (line.hasOption("cluster")) {
|
||||
clusterName = line.getOptionValue("cluster");
|
||||
} else {
|
||||
formatter.printHelp("JGroupsMessenger: need a cluster name.\n", options);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// Start it up
|
||||
public static void main(String[] args) throws Exception {
|
||||
new JGroupsMessenger().start(args);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void viewAccepted(View newView) {
|
||||
|
||||
// Save view if this is the first
|
||||
if (lastView == null) {
|
||||
System.out.println("Received initial view:");
|
||||
newView.forEach(System.out::println);
|
||||
} else {
|
||||
|
||||
// Compare to last view
|
||||
System.out.println("Received new view.");
|
||||
|
||||
List<Address> newMembers = View.newMembers(lastView, newView);
|
||||
if (newMembers.size() > 0) {
|
||||
System.out.println("New members: ");
|
||||
newMembers.forEach(System.out::println);
|
||||
}
|
||||
|
||||
List<Address> exMembers = View.leftMembers(lastView, newView);
|
||||
if (exMembers.size() > 0) {
|
||||
System.out.println("Exited members:");
|
||||
exMembers.forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
lastView = newView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop on console input until we see 'x' to exit
|
||||
*/
|
||||
private void processInput() {
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||
while (running) {
|
||||
try {
|
||||
|
||||
// Get a destination, <enter> means broadcast
|
||||
Address destination = null;
|
||||
System.out.print("Enter a destination: ");
|
||||
System.out.flush();
|
||||
String destinationName = in.readLine().toLowerCase();
|
||||
|
||||
if (destinationName.equals("x")) {
|
||||
running = false;
|
||||
continue;
|
||||
} else if (!destinationName.isEmpty()) {
|
||||
Optional<Address> optDestination = getAddress(destinationName);
|
||||
if (optDestination.isPresent()) {
|
||||
destination = optDestination.get();
|
||||
} else {
|
||||
System.out.println("Destination not found, try again.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Accept a string to send
|
||||
System.out.print("Enter a message: ");
|
||||
System.out.flush();
|
||||
String line = in.readLine().toLowerCase();
|
||||
sendMessage(destination, line);
|
||||
} catch (IOException ioe) {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
System.out.println("Exiting.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message from here
|
||||
* @param destination the destination
|
||||
* @param messageString the message
|
||||
*/
|
||||
private void sendMessage(Address destination, String messageString) {
|
||||
try {
|
||||
System.out.println("Sending " + messageString + " to " + destination);
|
||||
Message message = new Message(destination, messageString);
|
||||
channel.send(message);
|
||||
} catch (Exception exception) {
|
||||
System.err.println("Exception sending message: " + exception.getMessage());
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(Message message) {
|
||||
// Print source and dest with message
|
||||
String line = "Message received from: " + message.getSrc() + " to: " + message.getDest() + " -> " + message.getObject();
|
||||
|
||||
// Only track the count of broadcast messages
|
||||
// Tracking direct message would make for a pointless state
|
||||
if (message.getDest() == null) {
|
||||
messageCount++;
|
||||
System.out.println("Message count: " + messageCount);
|
||||
}
|
||||
|
||||
System.out.println(line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getState(OutputStream output) throws Exception {
|
||||
// Serialize into the stream
|
||||
Util.objectToStream(messageCount, new DataOutputStream(output));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(InputStream input) {
|
||||
|
||||
// NOTE: since we know that incrementing the count and transferring the state
|
||||
// is done inside the JChannel's thread, we don't have to worry about synchronizing
|
||||
// messageCount. For production code it should be synchronized!
|
||||
try {
|
||||
// Deserialize
|
||||
messageCount = Util.objectFromStream(new DataInputStream(input));
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error deserialing state!");
|
||||
}
|
||||
System.out.println(messageCount + " is the current messagecount.");
|
||||
}
|
||||
|
||||
|
||||
private Optional<Address> getAddress(String name) {
|
||||
View view = channel.view();
|
||||
return view.getMembers().stream().filter(address -> name.equals(address.toString())).findFirst();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<config xmlns="urn:org:jgroups"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/jgroups.xsd">
|
||||
<UDP
|
||||
mcast_port="${jgroups.udp.mcast_port:45588}"
|
||||
ip_ttl="4"
|
||||
tos="8"
|
||||
ucast_recv_buf_size="5M"
|
||||
ucast_send_buf_size="5M"
|
||||
mcast_recv_buf_size="5M"
|
||||
mcast_send_buf_size="5M"
|
||||
max_bundle_size="64K"
|
||||
enable_diagnostics="true"
|
||||
thread_naming_pattern="cl"
|
||||
|
||||
thread_pool.min_threads="0"
|
||||
thread_pool.max_threads="20"
|
||||
thread_pool.keep_alive_time="30000"/>
|
||||
|
||||
<PING />
|
||||
<MERGE3 max_interval="30000"
|
||||
min_interval="10000"/>
|
||||
<FD_SOCK/>
|
||||
<FD_ALL/>
|
||||
<VERIFY_SUSPECT timeout="1500" />
|
||||
<BARRIER />
|
||||
<pbcast.NAKACK2 xmit_interval="500"
|
||||
xmit_table_num_rows="100"
|
||||
xmit_table_msgs_per_row="2000"
|
||||
xmit_table_max_compaction_time="30000"
|
||||
use_mcast_xmit="false"
|
||||
discard_delivered_msgs="true"/>
|
||||
<UNICAST3 xmit_interval="500"
|
||||
xmit_table_num_rows="100"
|
||||
xmit_table_msgs_per_row="2000"
|
||||
xmit_table_max_compaction_time="60000"
|
||||
conn_expiry_timeout="0"/>
|
||||
<pbcast.STABLE desired_avg_gossip="50000"
|
||||
max_bytes="4M"/>
|
||||
<pbcast.GMS print_local_addr="true" join_timeout="2000"/>
|
||||
<UFC max_credits="2M"
|
||||
min_threshold="0.4"/>
|
||||
<MFC max_credits="2M"
|
||||
min_threshold="0.4"/>
|
||||
<FRAG2 frag_size="60K" />
|
||||
<RSVP resend_interval="2000" timeout="10000"/>
|
||||
<pbcast.STATE_TRANSFER />
|
||||
</config>
|
|
@ -31,6 +31,11 @@
|
|||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20171018</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import org.json.CDL;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONTokener;
|
||||
|
||||
public class CDLDemo {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("7.1. Producing JSONArray Directly from Comma Delimited Text: ");
|
||||
jsonArrayFromCDT();
|
||||
|
||||
System.out.println("\n7.2. Producing Comma Delimited Text from JSONArray: ");
|
||||
cDTfromJSONArray();
|
||||
|
||||
System.out.println("\n7.3.1. Producing JSONArray of JSONObjects Using Comma Delimited Text: ");
|
||||
jaOfJOFromCDT2();
|
||||
|
||||
System.out.println("\n7.3.2. Producing JSONArray of JSONObjects Using Comma Delimited Text: ");
|
||||
jaOfJOFromCDT2();
|
||||
}
|
||||
|
||||
public static void jsonArrayFromCDT() {
|
||||
JSONArray ja = CDL.rowToJSONArray(new JSONTokener("England, USA, Canada"));
|
||||
System.out.println(ja);
|
||||
}
|
||||
|
||||
public static void cDTfromJSONArray() {
|
||||
JSONArray ja = new JSONArray("[\"England\",\"USA\",\"Canada\"]");
|
||||
String cdt = CDL.rowToString(ja);
|
||||
System.out.println(cdt);
|
||||
}
|
||||
|
||||
public static void jaOfJOFromCDT() {
|
||||
String string =
|
||||
"name, city, age \n" +
|
||||
"john, chicago, 22 \n" +
|
||||
"gary, florida, 35 \n" +
|
||||
"sal, vegas, 18";
|
||||
|
||||
JSONArray result = CDL.toJSONArray(string);
|
||||
System.out.println(result.toString());
|
||||
}
|
||||
|
||||
public static void jaOfJOFromCDT2() {
|
||||
JSONArray ja = new JSONArray();
|
||||
ja.put("name");
|
||||
ja.put("city");
|
||||
ja.put("age");
|
||||
|
||||
String string =
|
||||
"john, chicago, 22 \n" +
|
||||
"gary, florida, 35 \n" +
|
||||
"sal, vegas, 18";
|
||||
|
||||
JSONArray result = CDL.toJSONArray(ja, string);
|
||||
System.out.println(result.toString());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import org.json.Cookie;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class CookieDemo {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("8.1. Converting a Cookie String into a JSONObject");
|
||||
cookieStringToJSONObject();
|
||||
|
||||
System.out.println("\n8.2. Converting a JSONObject into Cookie String");
|
||||
jSONObjectToCookieString();
|
||||
}
|
||||
|
||||
public static void cookieStringToJSONObject() {
|
||||
String cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/";
|
||||
JSONObject cookieJO = Cookie.toJSONObject(cookie);
|
||||
System.out.println(cookieJO);
|
||||
}
|
||||
|
||||
public static void jSONObjectToCookieString() {
|
||||
JSONObject cookieJO = new JSONObject();
|
||||
cookieJO.put("name", "username");
|
||||
cookieJO.put("value", "John Doe");
|
||||
cookieJO.put("expires", "Thu, 18 Dec 2013 12:00:00 UTC");
|
||||
cookieJO.put("path", "/");
|
||||
String cookie = Cookie.toString(cookieJO);
|
||||
System.out.println(cookie);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
public class DemoBean {
|
||||
private int id;
|
||||
private String name;
|
||||
private boolean active;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import org.json.HTTP;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class HTTPDemo {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("9.1. Converting JSONObject to HTTP Header: ");
|
||||
jSONObjectToHTTPHeader();
|
||||
|
||||
System.out.println("\n9.2. Converting HTTP Header String Back to JSONObject: ");
|
||||
hTTPHeaderToJSONObject();
|
||||
}
|
||||
|
||||
public static void jSONObjectToHTTPHeader() {
|
||||
JSONObject jo = new JSONObject();
|
||||
jo.put("Method", "POST");
|
||||
jo.put("Request-URI", "http://www.example.com/");
|
||||
jo.put("HTTP-Version", "HTTP/1.1");
|
||||
System.out.println(HTTP.toString(jo));
|
||||
}
|
||||
|
||||
public static void hTTPHeaderToJSONObject() {
|
||||
JSONObject obj = HTTP.toJSONObject("POST \"http://www.example.com/\" HTTP/1.1");
|
||||
System.out.println(obj);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class JSONArrayDemo {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("5.1. Creating JSON Array: ");
|
||||
creatingJSONArray();
|
||||
|
||||
System.out.println("\n5.2. Creating JSON Array from JSON string: ");
|
||||
jsonArrayFromJSONString();
|
||||
|
||||
System.out.println("\n5.3. Creating JSON Array from Collection Object: ");
|
||||
jsonArrayFromCollectionObj();
|
||||
}
|
||||
|
||||
public static void creatingJSONArray() {
|
||||
JSONArray ja = new JSONArray();
|
||||
ja.put(Boolean.TRUE);
|
||||
ja.put("lorem ipsum");
|
||||
|
||||
// We can also put a JSONObject in JSONArray
|
||||
JSONObject jo = new JSONObject();
|
||||
jo.put("name", "jon doe");
|
||||
jo.put("age", "22");
|
||||
jo.put("city", "chicago");
|
||||
|
||||
ja.put(jo);
|
||||
|
||||
System.out.println(ja.toString());
|
||||
}
|
||||
|
||||
public static void jsonArrayFromJSONString() {
|
||||
JSONArray ja = new JSONArray("[true, \"lorem ipsum\", 215]");
|
||||
System.out.println(ja);
|
||||
}
|
||||
|
||||
public static void jsonArrayFromCollectionObj() {
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("California");
|
||||
list.add("Texas");
|
||||
list.add("Hawaii");
|
||||
list.add("Alaska");
|
||||
|
||||
JSONArray ja = new JSONArray(list);
|
||||
System.out.println(ja);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class JSONObjectDemo {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("4.1. Creating JSONObject: ");
|
||||
jsonFromJSONObject();
|
||||
|
||||
System.out.println("\n4.2. Creating JSONObject from Map: ");
|
||||
jsonFromMap();
|
||||
|
||||
System.out.println("\n4.3. Creating JSONObject from JSON string: ");
|
||||
jsonFromJSONString();
|
||||
|
||||
System.out.println("\n4.4. Creating JSONObject from Java Bean: ");
|
||||
jsonFromDemoBean();
|
||||
}
|
||||
|
||||
public static void jsonFromJSONObject() {
|
||||
JSONObject jo = new JSONObject();
|
||||
jo.put("name", "jon doe");
|
||||
jo.put("age", "22");
|
||||
jo.put("city", "chicago");
|
||||
|
||||
System.out.println(jo.toString());
|
||||
}
|
||||
|
||||
public static void jsonFromMap() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("name", "jon doe");
|
||||
map.put("age", "22");
|
||||
map.put("city", "chicago");
|
||||
JSONObject jo = new JSONObject(map);
|
||||
|
||||
System.out.println(jo.toString());
|
||||
}
|
||||
|
||||
public static void jsonFromJSONString() {
|
||||
JSONObject jo = new JSONObject(
|
||||
"{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}"
|
||||
);
|
||||
|
||||
System.out.println(jo.toString());
|
||||
}
|
||||
|
||||
public static void jsonFromDemoBean() {
|
||||
DemoBean demo = new DemoBean();
|
||||
demo.setId(1);
|
||||
demo.setName("lorem ipsum");
|
||||
demo.setActive(true);
|
||||
|
||||
JSONObject jo = new JSONObject(demo);
|
||||
System.out.println(jo);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import org.json.JSONTokener;
|
||||
|
||||
public class JSONTokenerDemo {
|
||||
public static void main(String[] args) {
|
||||
JSONTokener jt = new JSONTokener("Sample String");
|
||||
|
||||
while(jt.more()) {
|
||||
System.out.println(jt.next());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.json.CDL;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONTokener;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CDLIntegrationTest {
|
||||
@Test
|
||||
public void givenCommaDelimitedText_thenConvertToJSONArray() {
|
||||
JSONArray ja = CDL.rowToJSONArray(new JSONTokener("England, USA, Canada"));
|
||||
assertEquals("[\"England\",\"USA\",\"Canada\"]", ja.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJSONArray_thenConvertToCommaDelimitedText() {
|
||||
JSONArray ja = new JSONArray("[\"England\",\"USA\",\"Canada\"]");
|
||||
String cdt = CDL.rowToString(ja);
|
||||
assertEquals("England,USA,Canada", cdt.toString().trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCommaDelimitedText_thenGetJSONArrayOfJSONObjects() {
|
||||
String string =
|
||||
"name, city, age \n" +
|
||||
"john, chicago, 22 \n" +
|
||||
"gary, florida, 35 \n" +
|
||||
"sal, vegas, 18";
|
||||
|
||||
JSONArray result = CDL.toJSONArray(string);
|
||||
assertEquals("[{\"name\":\"john\",\"city\":\"chicago\",\"age\":\"22\"},{\"name\":\"gary\",\"city\":\"florida\",\"age\":\"35\"},{\"name\":\"sal\",\"city\":\"vegas\",\"age\":\"18\"}]", result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCommaDelimitedText_thenGetJSONArrayOfJSONObjects2() {
|
||||
JSONArray ja = new JSONArray();
|
||||
ja.put("name");
|
||||
ja.put("city");
|
||||
ja.put("age");
|
||||
|
||||
String string =
|
||||
"john, chicago, 22 \n" +
|
||||
"gary, florida, 35 \n" +
|
||||
"sal, vegas, 18";
|
||||
|
||||
JSONArray result = CDL.toJSONArray(ja, string);
|
||||
assertEquals("[{\"name\":\"john\",\"city\":\"chicago\",\"age\":\"22\"},{\"name\":\"gary\",\"city\":\"florida\",\"age\":\"35\"},{\"name\":\"sal\",\"city\":\"vegas\",\"age\":\"18\"}]", result.toString());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.json.Cookie;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
|
||||
public class CookieIntegrationTest {
|
||||
@Test
|
||||
public void givenCookieString_thenConvertToJSONObject() {
|
||||
String cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/";
|
||||
JSONObject cookieJO = Cookie.toJSONObject(cookie);
|
||||
|
||||
assertEquals("{\"path\":\"/\",\"expires\":\"Thu, 18 Dec 2013 12:00:00 UTC\",\"name\":\"username\",\"value\":\"John Doe\"}", cookieJO.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJSONObject_thenConvertToCookieString() {
|
||||
JSONObject cookieJO = new JSONObject();
|
||||
cookieJO.put("name", "username");
|
||||
cookieJO.put("value", "John Doe");
|
||||
cookieJO.put("expires", "Thu, 18 Dec 2013 12:00:00 UTC");
|
||||
cookieJO.put("path", "/");
|
||||
String cookie = Cookie.toString(cookieJO);
|
||||
|
||||
assertEquals("username=John Doe;expires=Thu, 18 Dec 2013 12:00:00 UTC;path=/", cookie.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.json.HTTP;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HTTPIntegrationTest {
|
||||
@Test
|
||||
public void givenJSONObject_thenConvertToHTTPHeader() {
|
||||
JSONObject jo = new JSONObject();
|
||||
jo.put("Method", "POST");
|
||||
jo.put("Request-URI", "http://www.example.com/");
|
||||
jo.put("HTTP-Version", "HTTP/1.1");
|
||||
|
||||
assertEquals("POST \"http://www.example.com/\" HTTP/1.1"+HTTP.CRLF+HTTP.CRLF, HTTP.toString(jo));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHTTPHeader_thenConvertToJSONObject() {
|
||||
JSONObject obj = HTTP.toJSONObject("POST \"http://www.example.com/\" HTTP/1.1");
|
||||
|
||||
assertEquals("{\"Request-URI\":\"http://www.example.com/\",\"Method\":\"POST\",\"HTTP-Version\":\"HTTP/1.1\"}", obj.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JSONArrayIntegrationTest {
|
||||
@Test
|
||||
public void givenJSONJava_thenCreateNewJSONArrayFromScratch() {
|
||||
JSONArray ja = new JSONArray();
|
||||
ja.put(Boolean.TRUE);
|
||||
ja.put("lorem ipsum");
|
||||
|
||||
// We can also put a JSONObject in JSONArray
|
||||
JSONObject jo = new JSONObject();
|
||||
jo.put("name", "jon doe");
|
||||
jo.put("age", "22");
|
||||
jo.put("city", "chicago");
|
||||
|
||||
ja.put(jo);
|
||||
|
||||
assertEquals("[true,\"lorem ipsum\",{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}]", ja.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJsonString_thenCreateNewJSONArray() {
|
||||
JSONArray ja = new JSONArray("[true, \"lorem ipsum\", 215]");
|
||||
assertEquals("[true,\"lorem ipsum\",215]", ja.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenListObject_thenConvertItToJSONArray() {
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add("California");
|
||||
list.add("Texas");
|
||||
list.add("Hawaii");
|
||||
list.add("Alaska");
|
||||
|
||||
JSONArray ja = new JSONArray(list);
|
||||
assertEquals("[\"California\",\"Texas\",\"Hawaii\",\"Alaska\"]", ja.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JSONObjectIntegrationTest {
|
||||
@Test
|
||||
public void givenJSONJava_thenCreateNewJSONObject() {
|
||||
JSONObject jo = new JSONObject();
|
||||
jo.put("name", "jon doe");
|
||||
jo.put("age", "22");
|
||||
jo.put("city", "chicago");
|
||||
|
||||
assertEquals("{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}", jo.toString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMapObject_thenCreateJSONObject() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("name", "jon doe");
|
||||
map.put("age", "22");
|
||||
map.put("city", "chicago");
|
||||
JSONObject jo = new JSONObject(map);
|
||||
|
||||
assertEquals("{\"name\":\"jon doe\",\"city\":\"chicago\",\"age\":\"22\"}", jo.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenJsonString_thenCreateJSONObject() {
|
||||
JSONObject jo = new JSONObject(
|
||||
"{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}"
|
||||
);
|
||||
|
||||
assertEquals("{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}", jo.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenDemoBean_thenCreateJSONObject() {
|
||||
DemoBean demo = new DemoBean();
|
||||
demo.setId(1);
|
||||
demo.setName("lorem ipsum");
|
||||
demo.setActive(true);
|
||||
|
||||
JSONObject jo = new JSONObject(demo);
|
||||
assertEquals("{\"name\":\"lorem ipsum\",\"active\":true,\"id\":1}", jo.toString());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.baeldung.jsonjava;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.json.JSONTokener;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JSONTokenerIntegrationTest {
|
||||
@Test
|
||||
public void givenString_convertItToJSONTokens() {
|
||||
String str = "Sample String";
|
||||
JSONTokener jt = new JSONTokener(str);
|
||||
|
||||
char[] expectedTokens = str.toCharArray();
|
||||
int index = 0;
|
||||
|
||||
while(jt.more()) {
|
||||
assertEquals(expectedTokens[index++], jt.next());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -116,6 +116,12 @@
|
|||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/org.asynchttpclient/async-http-client -->
|
||||
<dependency>
|
||||
<groupId>org.asynchttpclient</groupId>
|
||||
<artifactId>async-http-client</artifactId>
|
||||
<version>${async.http.client.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.beykery/neuroph/2.92 -->
|
||||
<dependency>
|
||||
<groupId>org.beykery</groupId>
|
||||
|
@ -710,6 +716,11 @@
|
|||
<classifier>test</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.milyn</groupId>
|
||||
<artifactId>milyn-smooks-all</artifactId>
|
||||
<version>${smooks.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<repository>
|
||||
|
@ -761,7 +772,7 @@
|
|||
<serenity.jira.version>1.1.3-rc.5</serenity.jira.version>
|
||||
<serenity.plugin.version>1.4.0</serenity.plugin.version>
|
||||
<jUnitParams.version>1.1.0</jUnitParams.version>
|
||||
<netty.version>4.1.15.Final</netty.version>
|
||||
<netty.version>4.1.20.Final</netty.version>
|
||||
<commons.collections.version>4.1</commons.collections.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
<java-lsh.version>0.10</java-lsh.version>
|
||||
|
@ -789,6 +800,8 @@
|
|||
<google-api.version>1.23.0</google-api.version>
|
||||
<google-sheets.version>v4-rev493-1.21.0</google-sheets.version>
|
||||
<kafka.version>1.0.0</kafka.version>
|
||||
<smooks.version>1.7.0</smooks.version>
|
||||
<docker.version>3.0.14</docker.version>
|
||||
<async.http.client.version>2.2.0</async.http.client.version>
|
||||
</properties>
|
||||
</project>
|
|
@ -0,0 +1,45 @@
|
|||
package com.baeldung.smooks.converter;
|
||||
|
||||
import com.baeldung.smooks.model.Order;
|
||||
import org.milyn.Smooks;
|
||||
import org.milyn.payload.JavaResult;
|
||||
import org.milyn.payload.StringResult;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.IOException;
|
||||
|
||||
public class OrderConverter {
|
||||
|
||||
public Order convertOrderXMLToOrderObject(String path) throws IOException, SAXException {
|
||||
Smooks smooks = new Smooks(OrderConverter.class.getResourceAsStream("/smooks/smooks-mapping.xml"));
|
||||
try {
|
||||
JavaResult javaResult = new JavaResult();
|
||||
smooks.filterSource(new StreamSource(OrderConverter.class.getResourceAsStream(path)), javaResult);
|
||||
return (Order) javaResult.getBean("order");
|
||||
} finally {
|
||||
smooks.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String convertOrderXMLtoEDIFACT(String path) throws IOException, SAXException {
|
||||
return convertDocumentWithTempalte(path, "/smooks/smooks-transform-edi.xml");
|
||||
}
|
||||
|
||||
public String convertOrderXMLtoEmailMessage(String path) throws IOException, SAXException {
|
||||
return convertDocumentWithTempalte(path, "/smooks/smooks-transform-email.xml");
|
||||
}
|
||||
|
||||
private String convertDocumentWithTempalte(String path, String config) throws IOException, SAXException {
|
||||
Smooks smooks = new Smooks(config);
|
||||
|
||||
try {
|
||||
StringResult stringResult = new StringResult();
|
||||
smooks.filterSource(new StreamSource(OrderConverter.class.getResourceAsStream(path)), stringResult);
|
||||
return stringResult.toString();
|
||||
} finally {
|
||||
smooks.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.baeldung.smooks.converter;
|
||||
|
||||
import org.milyn.Smooks;
|
||||
import org.milyn.payload.JavaResult;
|
||||
import org.milyn.payload.StringResult;
|
||||
import org.milyn.validation.ValidationResult;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.IOException;
|
||||
|
||||
public class OrderValidator {
|
||||
|
||||
public ValidationResult validate(String path) throws IOException, SAXException {
|
||||
Smooks smooks = new Smooks(OrderValidator.class.getResourceAsStream("/smooks/smooks-validation.xml"));
|
||||
|
||||
try {
|
||||
StringResult xmlResult = new StringResult();
|
||||
JavaResult javaResult = new JavaResult();
|
||||
ValidationResult validationResult = new ValidationResult();
|
||||
smooks.filterSource(new StreamSource(OrderValidator.class.getResourceAsStream(path)), xmlResult, javaResult, validationResult);
|
||||
return validationResult;
|
||||
} finally {
|
||||
smooks.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.baeldung.smooks.model;
|
||||
|
||||
public class Item {
|
||||
|
||||
public Item() {
|
||||
}
|
||||
|
||||
public Item(String code, Double price, Integer quantity) {
|
||||
this.code = code;
|
||||
this.price = price;
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
private String code;
|
||||
private Double price;
|
||||
private Integer quantity;
|
||||
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(Double price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public Integer getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(Integer quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Item item = (Item) o;
|
||||
|
||||
if (code != null ? !code.equals(item.code) : item.code != null) return false;
|
||||
if (price != null ? !price.equals(item.price) : item.price != null) return false;
|
||||
return quantity != null ? quantity.equals(item.quantity) : item.quantity == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = code != null ? code.hashCode() : 0;
|
||||
result = 31 * result + (price != null ? price.hashCode() : 0);
|
||||
result = 31 * result + (quantity != null ? quantity.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Item{" +
|
||||
"code='" + code + '\'' +
|
||||
", price=" + price +
|
||||
", quantity=" + quantity +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.baeldung.smooks.model;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class Order {
|
||||
private Date creationDate;
|
||||
private Long number;
|
||||
private Status status;
|
||||
private Supplier supplier;
|
||||
private List<Item> items;
|
||||
|
||||
public Date getCreationDate() {
|
||||
return creationDate;
|
||||
}
|
||||
|
||||
public void setCreationDate(Date creationDate) {
|
||||
this.creationDate = creationDate;
|
||||
}
|
||||
|
||||
public Long getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(Long number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Supplier getSupplier() {
|
||||
return supplier;
|
||||
}
|
||||
|
||||
public void setSupplier(Supplier supplier) {
|
||||
this.supplier = supplier;
|
||||
}
|
||||
|
||||
public List<Item> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void setItems(List<Item> items) {
|
||||
this.items = items;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.baeldung.smooks.model;
|
||||
|
||||
public enum Status {
|
||||
NEW, IN_PROGRESS, FINISHED
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.baeldung.smooks.model;
|
||||
|
||||
public class Supplier {
|
||||
|
||||
private String name;
|
||||
private String phoneNumber;
|
||||
|
||||
public Supplier() {
|
||||
}
|
||||
|
||||
public Supplier(String name, String phoneNumber) {
|
||||
this.name = name;
|
||||
this.phoneNumber = phoneNumber;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPhoneNumber() {
|
||||
return phoneNumber;
|
||||
}
|
||||
|
||||
public void setPhoneNumber(String phoneNumber) {
|
||||
this.phoneNumber = phoneNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Supplier supplier = (Supplier) o;
|
||||
|
||||
if (name != null ? !name.equals(supplier.name) : supplier.name != null) return false;
|
||||
return phoneNumber != null ? phoneNumber.equals(supplier.phoneNumber) : supplier.phoneNumber == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name != null ? name.hashCode() : 0;
|
||||
result = 31 * result + (phoneNumber != null ? phoneNumber.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
<#setting locale="en_US">
|
||||
Hi,
|
||||
Order number #${order.number} created on ${order.creationDate?string["yyyy-MM-dd"]} is currently in ${order.status} status.
|
||||
Consider contact supplier "${supplier.name}" with phone number: "${supplier.phoneNumber}".
|
||||
Order items:
|
||||
<#list items as item>
|
||||
${item.quantity} X ${item.code} (total price ${item.price * item.quantity})
|
||||
</#list>
|
|
@ -0,0 +1 @@
|
|||
"max_total","item.quantity * item.price < 300.00"
|
|
|
@ -0,0 +1,7 @@
|
|||
<#setting locale="en_US">
|
||||
UNA:+.? '
|
||||
UNH+${order.number}+${order.status}+${order.creationDate?string["yyyy-MM-dd"]}'
|
||||
CTA+${supplier.name}+${supplier.phoneNumber}'
|
||||
<#list items as item>
|
||||
LIN+${item.quantity}+${item.code}+${item.price}'
|
||||
</#list>
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"creationDate":"2018-01-14",
|
||||
"orderNumber":771,
|
||||
"orderStatus":"IN_PROGRESS",
|
||||
"supplier":{
|
||||
"name":"CompanyX",
|
||||
"phone":"1234567"
|
||||
},
|
||||
"orderItems":[
|
||||
{
|
||||
"quantity":1,
|
||||
"code":"PX1234",
|
||||
"price":9.99
|
||||
},
|
||||
{
|
||||
"quantity":2,
|
||||
"code":"RX1990",
|
||||
"price":120.32
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<order creation-date="2018-01-14">
|
||||
<order-number>771</order-number>
|
||||
<order-status>IN_PROGRESS</order-status>
|
||||
<supplier>
|
||||
<name>CompanyX</name>
|
||||
<phone>1234567</phone>
|
||||
</supplier>
|
||||
<order-items>
|
||||
<item>
|
||||
<quantity>1</quantity>
|
||||
<code>PX1234</code>
|
||||
<price>9.99</price>
|
||||
</item>
|
||||
<item>
|
||||
<quantity>2</quantity>
|
||||
<code>RX990</code>
|
||||
<price>120.32</price>
|
||||
</item>
|
||||
</order-items>
|
||||
</order>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0"?>
|
||||
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
|
||||
xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.2.xsd">
|
||||
|
||||
<jb:bean beanId="order" class="com.baeldung.smooks.model.Order" createOnElement="order">
|
||||
<jb:value property="number" data="order/order-number" />
|
||||
<jb:value property="status" data="order/order-status" />
|
||||
<jb:value property="creationDate" data="order/@creation-date" decoder="Date">
|
||||
<jb:decodeParam name="format">yyyy-MM-dd</jb:decodeParam>
|
||||
</jb:value>
|
||||
<jb:wiring property="supplier" beanIdRef="supplier" />
|
||||
<jb:wiring property="items" beanIdRef="items" />
|
||||
</jb:bean>
|
||||
|
||||
<jb:bean beanId="supplier" class="com.baeldung.smooks.model.Supplier" createOnElement="supplier">
|
||||
<jb:value property="name" data="name" />
|
||||
<jb:value property="phoneNumber" data="phone" />
|
||||
</jb:bean>
|
||||
|
||||
<jb:bean beanId="items" class="java.util.ArrayList" createOnElement="order">
|
||||
<jb:wiring beanIdRef="item" />
|
||||
</jb:bean>
|
||||
<jb:bean beanId="item" class="com.baeldung.smooks.model.Item" createOnElement="item">
|
||||
<jb:value property="code" data="item/code" />
|
||||
<jb:value property="price" decoder="Double" data="item/price" />
|
||||
<jb:value property="quantity" decoder="Integer" data="item/quantity" />
|
||||
</jb:bean>
|
||||
|
||||
</smooks-resource-list>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0"?>
|
||||
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
|
||||
xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
|
||||
|
||||
<import file="smooks-validation.xml" />
|
||||
|
||||
<ftl:freemarker applyOnElement="#document">
|
||||
<ftl:template>/smooks/order.ftl</ftl:template>
|
||||
</ftl:freemarker>
|
||||
|
||||
</smooks-resource-list>
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0"?>
|
||||
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
|
||||
xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
|
||||
|
||||
|
||||
<import file="smooks-validation.xml" />
|
||||
|
||||
<ftl:freemarker applyOnElement="#document">
|
||||
<ftl:template>/smooks/email.ftl</ftl:template>
|
||||
</ftl:freemarker>
|
||||
|
||||
</smooks-resource-list>
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0"?>
|
||||
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
|
||||
xmlns:rules="http://www.milyn.org/xsd/smooks/rules-1.0.xsd"
|
||||
xmlns:validation="http://www.milyn.org/xsd/smooks/validation-1.0.xsd">
|
||||
|
||||
<import file="/smooks/smooks-mapping.xml" />
|
||||
|
||||
<rules:ruleBases>
|
||||
<rules:ruleBase name="supplierValidation" src="/smooks/supplier.properties" provider="org.milyn.rules.regex.RegexProvider"/>
|
||||
<rules:ruleBase name="itemsValidation" src="/smooks/item-rules.csv" provider="org.milyn.rules.mvel.MVELProvider"/>
|
||||
</rules:ruleBases>
|
||||
|
||||
<validation:rule executeOn="supplier/name" name="supplierValidation.supplierName" onFail="ERROR"/>
|
||||
<validation:rule executeOn="supplier/phone" name="supplierValidation.supplierPhone" onFail="ERROR"/>
|
||||
<validation:rule executeOn="order-items/item" name="itemsValidation.max_total" onFail="ERROR"/>
|
||||
|
||||
</smooks-resource-list>
|
|
@ -0,0 +1,2 @@
|
|||
supplierName=[A-Za-z0-9]*
|
||||
supplierPhone=^[0-9\\-\\+]{9,15}$
|
|
@ -0,0 +1,209 @@
|
|||
package com.baeldung.asynchttpclient;
|
||||
|
||||
import io.netty.handler.codec.http.HttpHeaders;
|
||||
import org.asynchttpclient.AsyncCompletionHandler;
|
||||
import org.asynchttpclient.AsyncHandler;
|
||||
import org.asynchttpclient.AsyncHttpClient;
|
||||
import org.asynchttpclient.AsyncHttpClientConfig;
|
||||
import org.asynchttpclient.BoundRequestBuilder;
|
||||
import org.asynchttpclient.Dsl;
|
||||
import org.asynchttpclient.HttpResponseBodyPart;
|
||||
import org.asynchttpclient.HttpResponseStatus;
|
||||
import org.asynchttpclient.ListenableFuture;
|
||||
import org.asynchttpclient.Request;
|
||||
import org.asynchttpclient.Response;
|
||||
import org.asynchttpclient.ws.WebSocket;
|
||||
import org.asynchttpclient.ws.WebSocketListener;
|
||||
import org.asynchttpclient.ws.WebSocketUpgradeHandler;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class AsyncHttpClientTestCase {
|
||||
|
||||
private static AsyncHttpClient HTTP_CLIENT;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
AsyncHttpClientConfig clientConfig = Dsl.config().setConnectTimeout(15000).setRequestTimeout(15000).build();
|
||||
HTTP_CLIENT = Dsl.asyncHttpClient(clientConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHttpClient_executeSyncGetRequest() {
|
||||
|
||||
BoundRequestBuilder boundGetRequest = HTTP_CLIENT.prepareGet("http://www.baeldung.com");
|
||||
|
||||
Future<Response> responseFuture = boundGetRequest.execute();
|
||||
try {
|
||||
Response response = responseFuture.get(5000, TimeUnit.MILLISECONDS);
|
||||
assertNotNull(response);
|
||||
assertEquals(200, response.getStatusCode());
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHttpClient_executeAsyncGetRequest() {
|
||||
|
||||
// execute an unbound GET request
|
||||
Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build();
|
||||
|
||||
HTTP_CLIENT.executeRequest(unboundGetRequest, new AsyncCompletionHandler<Integer>() {
|
||||
@Override
|
||||
public Integer onCompleted(Response response) {
|
||||
|
||||
int resposeStatusCode = response.getStatusCode();
|
||||
assertEquals(200, resposeStatusCode);
|
||||
return resposeStatusCode;
|
||||
}
|
||||
});
|
||||
|
||||
// execute a bound GET request
|
||||
BoundRequestBuilder boundGetRequest = HTTP_CLIENT.prepareGet("http://www.baeldung.com");
|
||||
|
||||
boundGetRequest.execute(new AsyncCompletionHandler<Integer>() {
|
||||
@Override
|
||||
public Integer onCompleted(Response response) {
|
||||
int resposeStatusCode = response.getStatusCode();
|
||||
assertEquals(200, resposeStatusCode);
|
||||
return resposeStatusCode;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHttpClient_executeAsyncGetRequestWithAsyncHandler() {
|
||||
|
||||
// execute an unbound GET request
|
||||
Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build();
|
||||
|
||||
HTTP_CLIENT.executeRequest(unboundGetRequest, new AsyncHandler<Integer>() {
|
||||
|
||||
int responseStatusCode = -1;
|
||||
|
||||
@Override
|
||||
public State onStatusReceived(HttpResponseStatus responseStatus) {
|
||||
responseStatusCode = responseStatus.getStatusCode();
|
||||
return State.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State onHeadersReceived(HttpHeaders headers) {
|
||||
return State.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State onBodyPartReceived(HttpResponseBodyPart bodyPart) {
|
||||
return State.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onThrowable(Throwable t) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer onCompleted() {
|
||||
assertEquals(200, responseStatusCode);
|
||||
return responseStatusCode;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHttpClient_executeAsyncGetRequestWithListanableFuture() {
|
||||
// execute an unbound GET request
|
||||
Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build();
|
||||
|
||||
ListenableFuture<Response> listenableFuture = HTTP_CLIENT.executeRequest(unboundGetRequest);
|
||||
listenableFuture.addListener(() -> {
|
||||
Response response;
|
||||
try {
|
||||
response = listenableFuture.get(5000, TimeUnit.MILLISECONDS);
|
||||
assertEquals(200, response.getStatusCode());
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, Executors.newCachedThreadPool());
|
||||
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenWebSocketClient_tryToConnect() {
|
||||
|
||||
WebSocketUpgradeHandler.Builder upgradeHandlerBuilder = new WebSocketUpgradeHandler.Builder();
|
||||
WebSocketUpgradeHandler wsHandler = upgradeHandlerBuilder.addWebSocketListener(new WebSocketListener() {
|
||||
@Override
|
||||
public void onOpen(WebSocket websocket) {
|
||||
// WebSocket connection opened
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(WebSocket websocket, int code, String reason) {
|
||||
// WebSocket connection closed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable t) {
|
||||
// WebSocket connection error
|
||||
assertTrue(t.getMessage().contains("Request timeout"));
|
||||
}
|
||||
}).build();
|
||||
|
||||
WebSocket WEBSOCKET_CLIENT = null;
|
||||
try {
|
||||
WEBSOCKET_CLIENT = Dsl.asyncHttpClient()
|
||||
.prepareGet("ws://localhost:5590/websocket")
|
||||
.addHeader("header_name", "header_value")
|
||||
.addQueryParam("key", "value")
|
||||
.setRequestTimeout(5000)
|
||||
.execute(wsHandler).get();
|
||||
|
||||
if (WEBSOCKET_CLIENT.isOpen()) {
|
||||
WEBSOCKET_CLIENT.sendPingFrame();
|
||||
WEBSOCKET_CLIENT.sendTextFrame("test message");
|
||||
WEBSOCKET_CLIENT.sendBinaryFrame(new byte[]{'t', 'e', 's', 't'});
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (WEBSOCKET_CLIENT != null && WEBSOCKET_CLIENT.isOpen()) {
|
||||
WEBSOCKET_CLIENT.sendCloseFrame(200, "OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.baeldung.smooks.converter;
|
||||
|
||||
import com.baeldung.smooks.model.Item;
|
||||
import com.baeldung.smooks.model.Order;
|
||||
import com.baeldung.smooks.model.Status;
|
||||
import com.baeldung.smooks.model.Supplier;
|
||||
import org.junit.Test;
|
||||
import org.milyn.validation.ValidationResult;
|
||||
import java.text.SimpleDateFormat;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
public class SmooksIntegrationTest {
|
||||
|
||||
private static final String EDIFACT_MESSAGE =
|
||||
"UNA:+.? '\r\n" +
|
||||
"UNH+771+IN_PROGRESS+2018-01-14'\r\n" +
|
||||
"CTA+CompanyX+1234567'\r\n" +
|
||||
"LIN+1+PX1234+9.99'\r\n" +
|
||||
"LIN+2+RX990+120.32'\r\n";
|
||||
private static final String EMAIL_MESSAGE =
|
||||
"Hi,\r\n" +
|
||||
"Order number #771 created on 2018-01-14 is currently in IN_PROGRESS status.\r\n" +
|
||||
"Consider contact supplier \"CompanyX\" with phone number: \"1234567\".\r\n" +
|
||||
"Order items:\r\n" +
|
||||
"1 X PX1234 (total price 9.99)\r\n" +
|
||||
"2 X RX990 (total price 240.64)\r\n";
|
||||
|
||||
@Test
|
||||
public void givenOrderXML_whenConvert_thenPOJOsConstructedCorrectly() throws Exception {
|
||||
|
||||
OrderConverter xmlToJavaOrderConverter = new OrderConverter();
|
||||
Order order = xmlToJavaOrderConverter.convertOrderXMLToOrderObject("/smooks/order.xml");
|
||||
|
||||
assertThat(order.getNumber(),is(771L));
|
||||
assertThat(order.getStatus(),is(Status.IN_PROGRESS));
|
||||
assertThat(order.getCreationDate(),is(new SimpleDateFormat("yyyy-MM-dd").parse("2018-01-14")));
|
||||
assertThat(order.getSupplier(),is(new Supplier("CompanyX","1234567")));
|
||||
assertThat(order.getItems(),containsInAnyOrder(
|
||||
new Item("PX1234",9.99,1),
|
||||
new Item("RX990",120.32,2))
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenIncorrectOrderXML_whenValidate_thenExpectValidationErrors() throws Exception {
|
||||
OrderValidator orderValidator = new OrderValidator();
|
||||
ValidationResult validationResult = orderValidator.validate("/smooks/order.xml");
|
||||
|
||||
assertThat(validationResult.getErrors(), hasSize(1));
|
||||
// 1234567 didn't match ^[0-9\\-\\+]{9,15}$
|
||||
assertThat(validationResult.getErrors().get(0).getFailRuleResult().getRuleName(),is("supplierPhone"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOrderXML_whenApplyEDITemplate_thenConvertedToEDIFACT() throws Exception {
|
||||
OrderConverter orderConverter = new OrderConverter();
|
||||
String edifact = orderConverter.convertOrderXMLtoEDIFACT("/smooks/order.xml");
|
||||
assertThat(edifact,is(EDIFACT_MESSAGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOrderXML_whenApplyEmailTemplate_thenConvertedToEmailMessage() throws Exception {
|
||||
OrderConverter orderConverter = new OrderConverter();
|
||||
String emailMessage = orderConverter.convertOrderXMLtoEmailMessage("/smooks/order.xml");
|
||||
assertThat(emailMessage,is(EMAIL_MESSAGE));
|
||||
}
|
||||
}
|
|
@ -8,11 +8,16 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.annotation.Commit;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
import org.springframework.test.context.transaction.TestTransaction;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = { HibernateConf.class })
|
||||
@Transactional
|
||||
|
@ -35,4 +40,146 @@ public class HibernateBootstrapIntegrationTest {
|
|||
Assert.assertNotNull(searchEntity);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenProgrammaticTransactionCommit_thenEntityIsInDatabase() {
|
||||
assertTrue(TestTransaction.isActive());
|
||||
|
||||
//Save an entity and commit.
|
||||
Session session = sessionFactory.getCurrentSession();
|
||||
|
||||
TestEntity newEntity = new TestEntity();
|
||||
newEntity.setId(1);
|
||||
session.save(newEntity);
|
||||
|
||||
TestEntity searchEntity = session.find(TestEntity.class, 1);
|
||||
|
||||
Assert.assertNotNull(searchEntity);
|
||||
assertTrue(TestTransaction.isFlaggedForRollback());
|
||||
|
||||
TestTransaction.flagForCommit();
|
||||
TestTransaction.end();
|
||||
|
||||
assertFalse(TestTransaction.isFlaggedForRollback());
|
||||
assertFalse(TestTransaction.isActive());
|
||||
|
||||
//Check that the entity is still there in a new transaction,
|
||||
//then delete it, but don't commit.
|
||||
TestTransaction.start();
|
||||
|
||||
assertTrue(TestTransaction.isFlaggedForRollback());
|
||||
assertTrue(TestTransaction.isActive());
|
||||
|
||||
session = sessionFactory.getCurrentSession();
|
||||
searchEntity = session.find(TestEntity.class, 1);
|
||||
|
||||
Assert.assertNotNull(searchEntity);
|
||||
|
||||
session.delete(searchEntity);
|
||||
session.flush();
|
||||
|
||||
TestTransaction.end();
|
||||
|
||||
assertFalse(TestTransaction.isActive());
|
||||
|
||||
//Check that the entity is still there in a new transaction,
|
||||
//then delete it and commit.
|
||||
TestTransaction.start();
|
||||
|
||||
session = sessionFactory.getCurrentSession();
|
||||
searchEntity = session.find(TestEntity.class, 1);
|
||||
|
||||
Assert.assertNotNull(searchEntity);
|
||||
|
||||
session.delete(searchEntity);
|
||||
session.flush();
|
||||
|
||||
assertTrue(TestTransaction.isActive());
|
||||
|
||||
TestTransaction.flagForCommit();
|
||||
TestTransaction.end();
|
||||
|
||||
assertFalse(TestTransaction.isActive());
|
||||
|
||||
//Check that the entity is no longer there in a new transaction.
|
||||
TestTransaction.start();
|
||||
|
||||
assertTrue(TestTransaction.isActive());
|
||||
|
||||
session = sessionFactory.getCurrentSession();
|
||||
searchEntity = session.find(TestEntity.class, 1);
|
||||
|
||||
Assert.assertNull(searchEntity);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Commit
|
||||
public void givenTransactionCommitDefault_whenProgrammaticTransactionCommit_thenEntityIsInDatabase() {
|
||||
assertTrue(TestTransaction.isActive());
|
||||
|
||||
//Save an entity and commit.
|
||||
Session session = sessionFactory.getCurrentSession();
|
||||
|
||||
TestEntity newEntity = new TestEntity();
|
||||
newEntity.setId(1);
|
||||
session.save(newEntity);
|
||||
|
||||
TestEntity searchEntity = session.find(TestEntity.class, 1);
|
||||
|
||||
Assert.assertNotNull(searchEntity);
|
||||
assertFalse(TestTransaction.isFlaggedForRollback());
|
||||
|
||||
TestTransaction.end();
|
||||
|
||||
assertFalse(TestTransaction.isFlaggedForRollback());
|
||||
assertFalse(TestTransaction.isActive());
|
||||
|
||||
//Check that the entity is still there in a new transaction,
|
||||
//then delete it, but don't commit.
|
||||
TestTransaction.start();
|
||||
|
||||
assertFalse(TestTransaction.isFlaggedForRollback());
|
||||
assertTrue(TestTransaction.isActive());
|
||||
|
||||
session = sessionFactory.getCurrentSession();
|
||||
searchEntity = session.find(TestEntity.class, 1);
|
||||
|
||||
Assert.assertNotNull(searchEntity);
|
||||
|
||||
session.delete(searchEntity);
|
||||
session.flush();
|
||||
|
||||
TestTransaction.flagForRollback();
|
||||
TestTransaction.end();
|
||||
|
||||
assertFalse(TestTransaction.isActive());
|
||||
|
||||
//Check that the entity is still there in a new transaction,
|
||||
//then delete it and commit.
|
||||
TestTransaction.start();
|
||||
|
||||
session = sessionFactory.getCurrentSession();
|
||||
searchEntity = session.find(TestEntity.class, 1);
|
||||
|
||||
Assert.assertNotNull(searchEntity);
|
||||
|
||||
session.delete(searchEntity);
|
||||
session.flush();
|
||||
|
||||
assertTrue(TestTransaction.isActive());
|
||||
|
||||
TestTransaction.end();
|
||||
|
||||
assertFalse(TestTransaction.isActive());
|
||||
|
||||
//Check that the entity is no longer there in a new transaction.
|
||||
TestTransaction.start();
|
||||
|
||||
assertTrue(TestTransaction.isActive());
|
||||
|
||||
session = sessionFactory.getCurrentSession();
|
||||
searchEntity = session.find(TestEntity.class, 1);
|
||||
|
||||
Assert.assertNull(searchEntity);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -93,6 +93,7 @@
|
|||
<module>javax-servlets</module>
|
||||
<module>javaxval</module>
|
||||
<module>jaxb</module>
|
||||
<module>jgroups</module>
|
||||
<module>jee-7</module>
|
||||
<!-- <module>jhipster/jhipster-monolithic</module> -->
|
||||
<module>jjwt</module>
|
||||
|
@ -246,6 +247,7 @@
|
|||
<module>spring-zuul</module>
|
||||
<module>spring-reactor</module>
|
||||
<module>spring-vertx</module>
|
||||
<module>spring-jinq</module>
|
||||
|
||||
<module>spring-rest-embedded-tomcat</module>
|
||||
|
||||
|
|
|
@ -1,48 +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 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 = Flux.generate(e -> {
|
||||
Event event = new Event(UUID.randomUUID().toString(), LocalDateTime.now().toString());
|
||||
e.next(event);
|
||||
private static final ObjectMapper json = new ObjectMapper();
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
private Flux<Event> intervalFlux = Flux.interval(Duration.ofMillis(1000L)).zipWith(eventFlux, (time, event) -> event);
|
||||
|
||||
private ObjectMapper json = new ObjectMapper();
|
||||
private Flux<String> intervalFlux = Flux.interval(Duration.ofMillis(1000L))
|
||||
.zipWith(eventFlux, (time, event) -> event);
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(WebSocketSession webSocketSession) {
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
# About this project
|
||||
This project contains examples from the [Spring Data with Spring Security](http://www.baeldung.com/spring-data-with-spring-security) article from Baeldung.
|
||||
|
||||
# Running the project
|
||||
The application uses [Spring Boot](http://projects.spring.io/spring-boot/), so it is easy to run. You can start it any of a few ways:
|
||||
* Run the `main` method from `SpringDataRestApplication`
|
||||
* Use the Maven Spring Boot plugin: `mvn spring-boot:run`
|
||||
* Package the application as a JAR and run it using `java -jar spring-data-spring-security.jar`
|
||||
|
||||
# Viewing the running application
|
||||
To view the running application, visit [http://localhost:8080](http://localhost:8080) in your browser
|
||||
|
||||
###Relevant Articles:
|
||||
- [Spring Data with Spring Security](http://www.baeldung.com/spring-data-with-spring-security)
|
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-data-spring-security</artifactId>
|
||||
<version>1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>intro-spring-data-spring-security</name>
|
||||
<description>Spring Data with Spring Security</description>
|
||||
|
||||
<parent>
|
||||
<artifactId>parent-boot-5</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-5</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-data</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-jasper</artifactId>
|
||||
<!-- <scope>provided</scope> -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
|
@ -0,0 +1,64 @@
|
|||
package com.baeldung;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
@SpringBootApplication
|
||||
@PropertySource("classpath:persistence-h2.properties")
|
||||
@EnableJpaRepositories(basePackages = { "com.baeldung.data.repositories" })
|
||||
@EnableWebMvc
|
||||
@Import(SpringSecurityConfig.class)
|
||||
public class AppConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private Environment env;
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||
dataSource.setDriverClassName(env.getProperty("driverClassName"));
|
||||
dataSource.setUrl(env.getProperty("url"));
|
||||
dataSource.setUsername(env.getProperty("user"));
|
||||
dataSource.setPassword(env.getProperty("password"));
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||
em.setDataSource(dataSource());
|
||||
em.setPackagesToScan(new String[] { "com.baeldung.models" });
|
||||
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
|
||||
em.setJpaProperties(additionalProperties());
|
||||
return em;
|
||||
}
|
||||
|
||||
final Properties additionalProperties() {
|
||||
final Properties hibernateProperties = new Properties();
|
||||
if (env.getProperty("hibernate.hbm2ddl.auto") != null) {
|
||||
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
|
||||
}
|
||||
if (env.getProperty("hibernate.dialect") != null) {
|
||||
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
|
||||
}
|
||||
if (env.getProperty("hibernate.show_sql") != null) {
|
||||
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
|
||||
}
|
||||
return hibernateProperties;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package com.baeldung;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
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.builders.WebSecurity;
|
||||
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.data.repository.query.SecurityEvaluationContextExtension;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.baeldung.security.AuthenticationSuccessHandlerImpl;
|
||||
import com.baeldung.security.CustomUserDetailsService;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@ComponentScan("com.baeldung.security")
|
||||
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext applicationContext;
|
||||
private CustomUserDetailsService userDetailsService;
|
||||
@Autowired
|
||||
private AuthenticationSuccessHandlerImpl successHandler;
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
@PostConstruct
|
||||
public void completeSetup() {
|
||||
userDetailsService = applicationContext.getBean(CustomUserDetailsService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userDetailsService)
|
||||
.passwordEncoder(encoder())
|
||||
.and()
|
||||
.authenticationProvider(authenticationProvider())
|
||||
.jdbcAuthentication()
|
||||
.dataSource(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring()
|
||||
.antMatchers("/resources/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests()
|
||||
.antMatchers("/login")
|
||||
.permitAll()
|
||||
.and()
|
||||
.formLogin()
|
||||
.permitAll()
|
||||
.successHandler(successHandler)
|
||||
.and()
|
||||
.csrf()
|
||||
.disable();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DaoAuthenticationProvider authenticationProvider() {
|
||||
final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
||||
authProvider.setUserDetailsService(userDetailsService);
|
||||
authProvider.setPasswordEncoder(encoder());
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder encoder() {
|
||||
return new BCryptPasswordEncoder(11);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
|
||||
return new SecurityEvaluationContextExtension();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.data.repositories;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
import com.baeldung.models.Tweet;
|
||||
|
||||
public interface TweetRepository extends PagingAndSortingRepository<Tweet, Long> {
|
||||
|
||||
@Query("select twt from Tweet twt JOIN twt.likes as lk where lk = ?#{ principal?.username } or twt.owner = ?#{ principal?.username }")
|
||||
Page<Tweet> getMyTweetsAndTheOnesILiked(Pageable pageable);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.baeldung.data.repositories;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.baeldung.models.AppUser;
|
||||
import com.baeldung.models.Tweet;
|
||||
|
||||
public interface UserRepository extends CrudRepository<AppUser, Long> {
|
||||
AppUser findByUsername(String username);
|
||||
|
||||
List<AppUser> findByName(String name);
|
||||
|
||||
@Query("UPDATE AppUser u SET u.lastLogin=:lastLogin WHERE u.username = ?#{ principal?.username }")
|
||||
@Modifying
|
||||
@Transactional
|
||||
public void updateLastLogin(@Param("lastLogin") Date lastLogin);
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package com.baeldung.models;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
public class AppUser {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
private long id;
|
||||
|
||||
private String name;
|
||||
@Column(unique = true)
|
||||
private String username;
|
||||
private String password;
|
||||
private boolean enabled = true;
|
||||
private Date lastLogin;
|
||||
|
||||
private AppUser() {
|
||||
}
|
||||
|
||||
public AppUser(String name, String email, String password) {
|
||||
this.username = email;
|
||||
this.name = name;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Date getLastLogin() {
|
||||
return lastLogin;
|
||||
}
|
||||
|
||||
public void setLastLogin(Date lastLogin) {
|
||||
this.lastLogin = lastLogin;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.baeldung.models;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Tweet {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
private long id;
|
||||
private String tweet;
|
||||
private String owner;
|
||||
@ElementCollection(targetClass = String.class, fetch = FetchType.EAGER)
|
||||
private Set<String> likes = new HashSet();
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
private Tweet() {
|
||||
}
|
||||
|
||||
public Tweet(String tweet, String owner) {
|
||||
this.tweet = tweet;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public String getTweet() {
|
||||
return tweet;
|
||||
}
|
||||
|
||||
public void setTweet(String tweet) {
|
||||
this.tweet = tweet;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Set<String> getLikes() {
|
||||
return likes;
|
||||
}
|
||||
|
||||
public void setLikes(Set<String> likes) {
|
||||
this.likes = likes;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.baeldung.security;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import com.baeldung.models.AppUser;
|
||||
|
||||
public class AppUserPrincipal implements UserDetails {
|
||||
|
||||
private final AppUser user;
|
||||
|
||||
//
|
||||
|
||||
public AppUserPrincipal(AppUser user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return user.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return user.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
final List<GrantedAuthority> authorities = Collections.singletonList(new SimpleGrantedAuthority("User"));
|
||||
return authorities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public AppUser getAppUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.baeldung.data.repositories.UserRepository;
|
||||
|
||||
@Component
|
||||
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest arg0, HttpServletResponse arg1, Authentication arg2) throws IOException, ServletException {
|
||||
userRepository.updateLastLogin(new Date());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.baeldung.security;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.baeldung.data.repositories.UserRepository;
|
||||
import com.baeldung.models.AppUser;
|
||||
|
||||
@Service
|
||||
public class CustomUserDetailsService implements UserDetailsService {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext applicationContext;
|
||||
private UserRepository userRepository;
|
||||
|
||||
public CustomUserDetailsService() {
|
||||
super();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void completeSetup() {
|
||||
userRepository = applicationContext.getBean(UserRepository.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(final String username) {
|
||||
final AppUser appUser = userRepository.findByUsername(username);
|
||||
if (appUser == null) {
|
||||
throw new UsernameNotFoundException(username);
|
||||
}
|
||||
return new AppUserPrincipal(appUser);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.baeldung.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
import com.baeldung.models.AppUser;
|
||||
import com.baeldung.models.Tweet;
|
||||
|
||||
public class DummyContentUtil {
|
||||
|
||||
public static final List<AppUser> generateDummyUsers() {
|
||||
List<AppUser> appUsers = new ArrayList<>();
|
||||
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
appUsers.add(new AppUser("Lionel Messi", "lionel@messi.com", passwordEncoder.encode("li1234")));
|
||||
appUsers.add(new AppUser("Cristiano Ronaldo", "cristiano@ronaldo.com", passwordEncoder.encode("c1234")));
|
||||
appUsers.add(new AppUser("Neymar Dos Santos", "neymar@neymar.com", passwordEncoder.encode("n1234")));
|
||||
appUsers.add(new AppUser("Luiz Suarez", "luiz@suarez.com", passwordEncoder.encode("lu1234")));
|
||||
appUsers.add(new AppUser("Andres Iniesta", "andres@iniesta.com", passwordEncoder.encode("a1234")));
|
||||
appUsers.add(new AppUser("Ivan Rakitic", "ivan@rakitic.com", passwordEncoder.encode("i1234")));
|
||||
appUsers.add(new AppUser("Ousman Dembele", "ousman@dembele.com", passwordEncoder.encode("o1234")));
|
||||
appUsers.add(new AppUser("Sergio Busquet", "sergio@busquet.com", passwordEncoder.encode("s1234")));
|
||||
appUsers.add(new AppUser("Gerard Pique", "gerard@pique.com", passwordEncoder.encode("g1234")));
|
||||
appUsers.add(new AppUser("Ter Stergen", "ter@stergen.com", passwordEncoder.encode("t1234")));
|
||||
return appUsers;
|
||||
}
|
||||
|
||||
public static final List<Tweet> generateDummyTweets(List<AppUser> users) {
|
||||
List<Tweet> tweets = new ArrayList<>();
|
||||
Random random = new Random();
|
||||
IntStream.range(0, 9)
|
||||
.sequential()
|
||||
.forEach(i -> {
|
||||
Tweet twt = new Tweet(String.format("Tweet %d", i), users.get(random.nextInt(users.size()))
|
||||
.getUsername());
|
||||
twt.getLikes()
|
||||
.addAll(users.subList(0, random.nextInt(users.size()))
|
||||
.stream()
|
||||
.map(AppUser::getUsername)
|
||||
.collect(Collectors.toSet()));
|
||||
tweets.add(twt);
|
||||
});
|
||||
return tweets;
|
||||
}
|
||||
|
||||
public static Collection<GrantedAuthority> getAuthorities() {
|
||||
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
|
||||
GrantedAuthority grantedAuthority = new GrantedAuthority() {
|
||||
public String getAuthority() {
|
||||
return "ROLE_USER";
|
||||
}
|
||||
};
|
||||
grantedAuthorities.add(grantedAuthority);
|
||||
return grantedAuthorities;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
driverClassName=org.h2.Driver
|
||||
url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1
|
||||
username=sa
|
||||
password=
|
||||
|
||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||
hibernate.show_sql=false
|
||||
hibernate.hbm2ddl.auto=create-drop
|
|
@ -0,0 +1,100 @@
|
|||
package com.baeldung.relationships;
|
||||
|
||||
import static org.springframework.util.Assert.isTrue;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
import com.baeldung.AppConfig;
|
||||
import com.baeldung.data.repositories.TweetRepository;
|
||||
import com.baeldung.data.repositories.UserRepository;
|
||||
import com.baeldung.models.AppUser;
|
||||
import com.baeldung.models.Tweet;
|
||||
import com.baeldung.security.AppUserPrincipal;
|
||||
import com.baeldung.util.DummyContentUtil;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
@DirtiesContext
|
||||
public class SpringDataWithSecurityTest {
|
||||
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
|
||||
@Autowired
|
||||
private ServletContext servletContext;
|
||||
private static UserRepository userRepository;
|
||||
private static TweetRepository tweetRepository;
|
||||
|
||||
@Before
|
||||
public void testInit() {
|
||||
ctx.register(AppConfig.class);
|
||||
ctx.setServletContext(servletContext);
|
||||
ctx.refresh();
|
||||
userRepository = ctx.getBean(UserRepository.class);
|
||||
tweetRepository = ctx.getBean(TweetRepository.class);
|
||||
List<AppUser> appUsers = (List<AppUser>) userRepository.save(DummyContentUtil.generateDummyUsers());
|
||||
tweetRepository.save(DummyContentUtil.generateDummyTweets(appUsers));
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
tweetRepository.deleteAll();
|
||||
userRepository.deleteAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAppUser_whenLoginSuccessful_shouldUpdateLastLogin() {
|
||||
AppUser appUser = userRepository.findByUsername("lionel@messi.com");
|
||||
Authentication auth = new UsernamePasswordAuthenticationToken(new AppUserPrincipal(appUser), null, DummyContentUtil.getAuthorities());
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(auth);
|
||||
userRepository.updateLastLogin(new Date());
|
||||
}
|
||||
|
||||
@Test(expected = InvalidDataAccessApiUsageException.class)
|
||||
public void givenNoAppUserInSecurityContext_whenUpdateLastLoginAttempted_shouldFail() {
|
||||
userRepository.updateLastLogin(new Date());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAppUser_whenLoginSuccessful_shouldReadMyPagedTweets() {
|
||||
AppUser appUser = userRepository.findByUsername("lionel@messi.com");
|
||||
Authentication auth = new UsernamePasswordAuthenticationToken(new AppUserPrincipal(appUser), null, DummyContentUtil.getAuthorities());
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(auth);
|
||||
Page<Tweet> page = null;
|
||||
do {
|
||||
page = tweetRepository.getMyTweetsAndTheOnesILiked(new PageRequest(page != null ? page.getNumber() + 1 : 0, 5));
|
||||
for (Tweet twt : page.getContent()) {
|
||||
isTrue((twt.getOwner() == appUser.getUsername()) || (twt.getLikes()
|
||||
.contains(appUser.getUsername())), "I do not have any Tweets");
|
||||
}
|
||||
} while (page.hasNext());
|
||||
}
|
||||
|
||||
@Test(expected = InvalidDataAccessApiUsageException.class)
|
||||
public void givenNoAppUser_whenPaginatedResultsRetrievalAttempted_shouldFail() {
|
||||
Page<Tweet> page = null;
|
||||
do {
|
||||
page = tweetRepository.getMyTweetsAndTheOnesILiked(new PageRequest(page != null ? page.getNumber() + 1 : 0, 5));
|
||||
} while (page != null && page.hasNext());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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">
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-jinq</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
|
||||
<name>spring-jinq</name>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
|
||||
<jinq.version>1.8.22</jinq.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>1.5.9.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jinq</groupId>
|
||||
<artifactId>jinq-jpa</artifactId>
|
||||
<version>${jinq.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Database Access -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
<useIncrementalCompilation>false</useIncrementalCompilation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,12 @@
|
|||
package com.baeldung.spring.jinq;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class JinqApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(JinqApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.baeldung.spring.jinq.config;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.jinq.jpa.JinqJPAStreamProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class JinqProviderConfiguration {
|
||||
|
||||
@Bean
|
||||
@Autowired
|
||||
JinqJPAStreamProvider jinqProvider(EntityManagerFactory emf) {
|
||||
return new JinqJPAStreamProvider(emf);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package com.baeldung.spring.jinq.entities;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
@Entity(name = "CAR")
|
||||
public class Car {
|
||||
private String model;
|
||||
private String description;
|
||||
private int year;
|
||||
private String engine;
|
||||
private Manufacturer manufacturer;
|
||||
|
||||
@Id
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public void setYear(int year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public String getEngine() {
|
||||
return engine;
|
||||
}
|
||||
|
||||
public void setEngine(String engine) {
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "name")
|
||||
public Manufacturer getManufacturer() {
|
||||
return manufacturer;
|
||||
}
|
||||
|
||||
public void setManufacturer(Manufacturer manufacturer) {
|
||||
this.manufacturer = manufacturer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.baeldung.spring.jinq.entities;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
@Entity(name = "MANUFACTURER")
|
||||
public class Manufacturer {
|
||||
|
||||
private String name;
|
||||
private String city;
|
||||
private List<Car> cars;
|
||||
|
||||
@Id
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
@OneToMany(mappedBy = "model")
|
||||
public List<Car> getCars() {
|
||||
return cars;
|
||||
}
|
||||
|
||||
public void setCars(List<Car> cars) {
|
||||
this.cars = cars;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue