updated local repo with upstream
This commit is contained in:
commit
f427e77211
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.automata;
|
package com.baeldung.algorithms.automata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finite state machine.
|
* Finite state machine.
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.automata;
|
package com.baeldung.algorithms.automata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementation of a finite state machine.
|
* Default implementation of a finite state machine.
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.automata;
|
package com.baeldung.algorithms.automata;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.automata;
|
package com.baeldung.algorithms.automata;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.automata;
|
package com.baeldung.algorithms.automata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State. Part of a finite state machine.
|
* State. Part of a finite state machine.
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.automata;
|
package com.baeldung.algorithms.automata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transition in a finite State machine.
|
* Transition in a finite State machine.
|
@ -0,0 +1,109 @@
|
|||||||
|
package com.baeldung.algorithms.mcts.montecarlo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baeldung.algorithms.mcts.tictactoe.Board;
|
||||||
|
import com.baeldung.algorithms.mcts.tree.Node;
|
||||||
|
import com.baeldung.algorithms.mcts.tree.Tree;
|
||||||
|
|
||||||
|
public class MonteCarloTreeSearch {
|
||||||
|
|
||||||
|
private static final int WIN_SCORE = 10;
|
||||||
|
private int level;
|
||||||
|
private int oponent;
|
||||||
|
|
||||||
|
public MonteCarloTreeSearch() {
|
||||||
|
this.level = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevel(int level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMillisForCurrentLevel() {
|
||||||
|
return 2 * (this.level - 1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Board findNextMove(Board board, int playerNo) {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
long end = start + 60 * getMillisForCurrentLevel();
|
||||||
|
|
||||||
|
oponent = 3 - playerNo;
|
||||||
|
Tree tree = new Tree();
|
||||||
|
Node rootNode = tree.getRoot();
|
||||||
|
rootNode.getState().setBoard(board);
|
||||||
|
rootNode.getState().setPlayerNo(oponent);
|
||||||
|
|
||||||
|
while (System.currentTimeMillis() < end) {
|
||||||
|
// Phase 1 - Selection
|
||||||
|
Node promisingNode = selectPromisingNode(rootNode);
|
||||||
|
// Phase 2 - Expansion
|
||||||
|
if (promisingNode.getState().getBoard().checkStatus() == Board.IN_PROGRESS)
|
||||||
|
expandNode(promisingNode);
|
||||||
|
|
||||||
|
// Phase 3 - Simulation
|
||||||
|
Node nodeToExplore = promisingNode;
|
||||||
|
if (promisingNode.getChildArray().size() > 0) {
|
||||||
|
nodeToExplore = promisingNode.getRandomChildNode();
|
||||||
|
}
|
||||||
|
int playoutResult = simulateRandomPlayout(nodeToExplore);
|
||||||
|
// Phase 4 - Update
|
||||||
|
backPropogation(nodeToExplore, playoutResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node winnerNode = rootNode.getChildWithMaxScore();
|
||||||
|
tree.setRoot(winnerNode);
|
||||||
|
return winnerNode.getState().getBoard();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node selectPromisingNode(Node rootNode) {
|
||||||
|
Node node = rootNode;
|
||||||
|
while (node.getChildArray().size() != 0) {
|
||||||
|
node = UCT.findBestNodeWithUCT(node);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expandNode(Node node) {
|
||||||
|
List<State> possibleStates = node.getState().getAllPossibleStates();
|
||||||
|
possibleStates.forEach(state -> {
|
||||||
|
Node newNode = new Node(state);
|
||||||
|
newNode.setParent(node);
|
||||||
|
newNode.getState().setPlayerNo(node.getState().getOpponent());
|
||||||
|
node.getChildArray().add(newNode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void backPropogation(Node nodeToExplore, int playerNo) {
|
||||||
|
Node tempNode = nodeToExplore;
|
||||||
|
while (tempNode != null) {
|
||||||
|
tempNode.getState().incrementVisit();
|
||||||
|
if (tempNode.getState().getPlayerNo() == playerNo)
|
||||||
|
tempNode.getState().addScore(WIN_SCORE);
|
||||||
|
tempNode = tempNode.getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int simulateRandomPlayout(Node node) {
|
||||||
|
Node tempNode = new Node(node);
|
||||||
|
State tempState = tempNode.getState();
|
||||||
|
int boardStatus = tempState.getBoard().checkStatus();
|
||||||
|
|
||||||
|
if (boardStatus == oponent) {
|
||||||
|
tempNode.getParent().getState().setWinScore(Integer.MIN_VALUE);
|
||||||
|
return boardStatus;
|
||||||
|
}
|
||||||
|
while (boardStatus == Board.IN_PROGRESS) {
|
||||||
|
tempState.togglePlayer();
|
||||||
|
tempState.randomPlay();
|
||||||
|
boardStatus = tempState.getBoard().checkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
return boardStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
package com.baeldung.algorithms.mcts.montecarlo;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baeldung.algorithms.mcts.tictactoe.Board;
|
||||||
|
import com.baeldung.algorithms.mcts.tictactoe.Position;
|
||||||
|
|
||||||
|
public class State {
|
||||||
|
private Board board;
|
||||||
|
private int playerNo;
|
||||||
|
private int visitCount;
|
||||||
|
private double winScore;
|
||||||
|
|
||||||
|
public State() {
|
||||||
|
board = new Board();
|
||||||
|
}
|
||||||
|
|
||||||
|
public State(State state) {
|
||||||
|
this.board = new Board(state.getBoard());
|
||||||
|
this.playerNo = state.getPlayerNo();
|
||||||
|
this.visitCount = state.getVisitCount();
|
||||||
|
this.winScore = state.getWinScore();
|
||||||
|
}
|
||||||
|
|
||||||
|
public State(Board board) {
|
||||||
|
this.board = new Board(board);
|
||||||
|
}
|
||||||
|
|
||||||
|
Board getBoard() {
|
||||||
|
return board;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBoard(Board board) {
|
||||||
|
this.board = board;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getPlayerNo() {
|
||||||
|
return playerNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPlayerNo(int playerNo) {
|
||||||
|
this.playerNo = playerNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getOpponent() {
|
||||||
|
return 3 - playerNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVisitCount() {
|
||||||
|
return visitCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVisitCount(int visitCount) {
|
||||||
|
this.visitCount = visitCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
double getWinScore() {
|
||||||
|
return winScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setWinScore(double winScore) {
|
||||||
|
this.winScore = winScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<State> getAllPossibleStates() {
|
||||||
|
List<State> possibleStates = new ArrayList<>();
|
||||||
|
List<Position> availablePositions = this.board.getEmptyPositions();
|
||||||
|
availablePositions.forEach(p -> {
|
||||||
|
State newState = new State(this.board);
|
||||||
|
newState.setPlayerNo(3 - this.playerNo);
|
||||||
|
newState.getBoard().performMove(newState.getPlayerNo(), p);
|
||||||
|
possibleStates.add(newState);
|
||||||
|
});
|
||||||
|
return possibleStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
void incrementVisit() {
|
||||||
|
this.visitCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addScore(double score) {
|
||||||
|
if (this.winScore != Integer.MIN_VALUE)
|
||||||
|
this.winScore += score;
|
||||||
|
}
|
||||||
|
|
||||||
|
void randomPlay() {
|
||||||
|
List<Position> availablePositions = this.board.getEmptyPositions();
|
||||||
|
int totalPossibilities = availablePositions.size();
|
||||||
|
int selectRandom = (int) (Math.random() * ((totalPossibilities - 1) + 1));
|
||||||
|
this.board.performMove(this.playerNo, availablePositions.get(selectRandom));
|
||||||
|
}
|
||||||
|
|
||||||
|
void togglePlayer() {
|
||||||
|
this.playerNo = 3 - this.playerNo;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.baeldung.algorithms.mcts.montecarlo;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baeldung.algorithms.mcts.tree.Node;
|
||||||
|
|
||||||
|
public class UCT {
|
||||||
|
|
||||||
|
public static double uctValue(int totalVisit, double nodeWinScore, int nodeVisit) {
|
||||||
|
if (nodeVisit == 0) {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
return (nodeWinScore / (double) nodeVisit) + 1.41 * Math.sqrt(Math.log(totalVisit) / (double) nodeVisit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Node findBestNodeWithUCT(Node node) {
|
||||||
|
int parentVisit = node.getState().getVisitCount();
|
||||||
|
return Collections.max(
|
||||||
|
node.getChildArray(),
|
||||||
|
Comparator.comparing(c -> uctValue(parentVisit, c.getState().getWinScore(), c.getState().getVisitCount())));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,155 @@
|
|||||||
|
package com.baeldung.algorithms.mcts.tictactoe;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Board {
|
||||||
|
int[][] boardValues;
|
||||||
|
int totalMoves;
|
||||||
|
|
||||||
|
public static final int DEFAULT_BOARD_SIZE = 3;
|
||||||
|
|
||||||
|
public static final int IN_PROGRESS = -1;
|
||||||
|
public static final int DRAW = 0;
|
||||||
|
public static final int P1 = 1;
|
||||||
|
public static final int P2 = 2;
|
||||||
|
|
||||||
|
public Board() {
|
||||||
|
boardValues = new int[DEFAULT_BOARD_SIZE][DEFAULT_BOARD_SIZE];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Board(int boardSize) {
|
||||||
|
boardValues = new int[boardSize][boardSize];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Board(int[][] boardValues) {
|
||||||
|
this.boardValues = boardValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Board(int[][] boardValues, int totalMoves) {
|
||||||
|
this.boardValues = boardValues;
|
||||||
|
this.totalMoves = totalMoves;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Board(Board board) {
|
||||||
|
int boardLength = board.getBoardValues().length;
|
||||||
|
this.boardValues = new int[boardLength][boardLength];
|
||||||
|
int[][] boardValues = board.getBoardValues();
|
||||||
|
int n = boardValues.length;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
int m = boardValues[i].length;
|
||||||
|
for (int j = 0; j < m; j++) {
|
||||||
|
this.boardValues[i][j] = boardValues[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performMove(int player, Position p) {
|
||||||
|
this.totalMoves++;
|
||||||
|
boardValues[p.getX()][p.getY()] = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[][] getBoardValues() {
|
||||||
|
return boardValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBoardValues(int[][] boardValues) {
|
||||||
|
this.boardValues = boardValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int checkStatus() {
|
||||||
|
int boardSize = boardValues.length;
|
||||||
|
int maxIndex = boardSize - 1;
|
||||||
|
int[] diag1 = new int[boardSize];
|
||||||
|
int[] diag2 = new int[boardSize];
|
||||||
|
|
||||||
|
for (int i = 0; i < boardSize; i++) {
|
||||||
|
int[] row = boardValues[i];
|
||||||
|
int[] col = new int[boardSize];
|
||||||
|
for (int j = 0; j < boardSize; j++) {
|
||||||
|
col[j] = boardValues[j][i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkRowForWin = checkForWin(row);
|
||||||
|
if(checkRowForWin!=0)
|
||||||
|
return checkRowForWin;
|
||||||
|
|
||||||
|
int checkColForWin = checkForWin(col);
|
||||||
|
if(checkColForWin!=0)
|
||||||
|
return checkColForWin;
|
||||||
|
|
||||||
|
diag1[i] = boardValues[i][i];
|
||||||
|
diag2[i] = boardValues[maxIndex - i][i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkDia1gForWin = checkForWin(diag1);
|
||||||
|
if(checkDia1gForWin!=0)
|
||||||
|
return checkDia1gForWin;
|
||||||
|
|
||||||
|
int checkDiag2ForWin = checkForWin(diag2);
|
||||||
|
if(checkDiag2ForWin!=0)
|
||||||
|
return checkDiag2ForWin;
|
||||||
|
|
||||||
|
if (getEmptyPositions().size() > 0)
|
||||||
|
return IN_PROGRESS;
|
||||||
|
else
|
||||||
|
return DRAW;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int checkForWin(int[] row) {
|
||||||
|
boolean isEqual = true;
|
||||||
|
int size = row.length;
|
||||||
|
int previous = row[0];
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
if (previous != row[i]) {
|
||||||
|
isEqual = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
previous = row[i];
|
||||||
|
}
|
||||||
|
if(isEqual)
|
||||||
|
return previous;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printBoard() {
|
||||||
|
int size = this.boardValues.length;
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
for (int j = 0; j < size; j++) {
|
||||||
|
System.out.print(boardValues[i][j] + " ");
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Position> getEmptyPositions() {
|
||||||
|
int size = this.boardValues.length;
|
||||||
|
List<Position> emptyPositions = new ArrayList<>();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
for (int j = 0; j < size; j++) {
|
||||||
|
if (boardValues[i][j] == 0)
|
||||||
|
emptyPositions.add(new Position(i, j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return emptyPositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printStatus() {
|
||||||
|
switch (this.checkStatus()) {
|
||||||
|
case P1:
|
||||||
|
System.out.println("Player 1 wins");
|
||||||
|
break;
|
||||||
|
case P2:
|
||||||
|
System.out.println("Player 2 wins");
|
||||||
|
break;
|
||||||
|
case DRAW:
|
||||||
|
System.out.println("Game Draw");
|
||||||
|
break;
|
||||||
|
case IN_PROGRESS:
|
||||||
|
System.out.println("Game In rogress");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.baeldung.algorithms.mcts.tictactoe;
|
||||||
|
|
||||||
|
public class Position {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
public Position() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Position(int x, int y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(int x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(int y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package com.baeldung.algorithms.mcts.tree;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baeldung.algorithms.mcts.montecarlo.State;
|
||||||
|
|
||||||
|
public class Node {
|
||||||
|
State state;
|
||||||
|
Node parent;
|
||||||
|
List<Node> childArray;
|
||||||
|
|
||||||
|
public Node() {
|
||||||
|
this.state = new State();
|
||||||
|
childArray = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node(State state) {
|
||||||
|
this.state = state;
|
||||||
|
childArray = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node(State state, Node parent, List<Node> childArray) {
|
||||||
|
this.state = state;
|
||||||
|
this.parent = parent;
|
||||||
|
this.childArray = childArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node(Node node) {
|
||||||
|
this.childArray = new ArrayList<>();
|
||||||
|
this.state = new State(node.getState());
|
||||||
|
if (node.getParent() != null)
|
||||||
|
this.parent = node.getParent();
|
||||||
|
List<Node> childArray = node.getChildArray();
|
||||||
|
for (Node child : childArray) {
|
||||||
|
this.childArray.add(new Node(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public State getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(State state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParent(Node parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Node> getChildArray() {
|
||||||
|
return childArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChildArray(List<Node> childArray) {
|
||||||
|
this.childArray = childArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getRandomChildNode() {
|
||||||
|
int noOfPossibleMoves = this.childArray.size();
|
||||||
|
int selectRandom = (int) (Math.random() * ((noOfPossibleMoves - 1) + 1));
|
||||||
|
return this.childArray.get(selectRandom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getChildWithMaxScore() {
|
||||||
|
return Collections.max(this.childArray, Comparator.comparing(c -> {
|
||||||
|
return c.getState().getVisitCount();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.baeldung.algorithms.mcts.tree;
|
||||||
|
|
||||||
|
public class Tree {
|
||||||
|
Node root;
|
||||||
|
|
||||||
|
public Tree() {
|
||||||
|
root = new Node();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree(Node root) {
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoot(Node root) {
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChild(Node parent, Node child) {
|
||||||
|
parent.getChildArray().add(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package algorithms;
|
package algorithms;
|
||||||
|
|
||||||
import com.baeldung.automata.*;
|
import com.baeldung.algorithms.automata.*;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
92
algorithms/src/test/java/algorithms/mcts/MCTSTest.java
Normal file
92
algorithms/src/test/java/algorithms/mcts/MCTSTest.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package algorithms.mcts;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.baeldung.algorithms.mcts.montecarlo.MonteCarloTreeSearch;
|
||||||
|
import com.baeldung.algorithms.mcts.montecarlo.State;
|
||||||
|
import com.baeldung.algorithms.mcts.montecarlo.UCT;
|
||||||
|
import com.baeldung.algorithms.mcts.tictactoe.Board;
|
||||||
|
import com.baeldung.algorithms.mcts.tictactoe.Position;
|
||||||
|
import com.baeldung.algorithms.mcts.tree.Tree;
|
||||||
|
|
||||||
|
public class MCTSTest {
|
||||||
|
private Tree gameTree;
|
||||||
|
private MonteCarloTreeSearch mcts;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void initGameTree() {
|
||||||
|
gameTree = new Tree();
|
||||||
|
mcts = new MonteCarloTreeSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStats_whenGetUCTForNode_thenUCTMatchesWithManualData() {
|
||||||
|
double uctValue = 15.79;
|
||||||
|
assertEquals(UCT.uctValue(600, 300, 20), uctValue, 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void giveninitBoardState_whenGetAllPossibleStates_thenNonEmptyList() {
|
||||||
|
State initState = gameTree.getRoot().getState();
|
||||||
|
List<State> possibleStates = initState.getAllPossibleStates();
|
||||||
|
assertTrue(possibleStates.size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyBoard_whenPerformMove_thenLessAvailablePossitions() {
|
||||||
|
Board board = new Board();
|
||||||
|
int initAvailablePositions = board.getEmptyPositions().size();
|
||||||
|
board.performMove(Board.P1, new Position(1, 1));
|
||||||
|
int availablePositions = board.getEmptyPositions().size();
|
||||||
|
assertTrue(initAvailablePositions > availablePositions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyBoard_whenSimulateInterAIPlay_thenGameDraw() {
|
||||||
|
Board board = new Board();
|
||||||
|
|
||||||
|
int player = Board.P1;
|
||||||
|
int totalMoves = Board.DEFAULT_BOARD_SIZE * Board.DEFAULT_BOARD_SIZE;
|
||||||
|
for (int i = 0; i < totalMoves; i++) {
|
||||||
|
board = mcts.findNextMove(board, player);
|
||||||
|
if (board.checkStatus() != -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
player = 3 - player;
|
||||||
|
}
|
||||||
|
int winStatus = board.checkStatus();
|
||||||
|
assertEquals(winStatus, Board.DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyBoard_whenLevel1VsLevel3_thenLevel3WinsOrDraw() {
|
||||||
|
Board board = new Board();
|
||||||
|
MonteCarloTreeSearch mcts1 = new MonteCarloTreeSearch();
|
||||||
|
mcts1.setLevel(1);
|
||||||
|
MonteCarloTreeSearch mcts3 = new MonteCarloTreeSearch();
|
||||||
|
mcts3.setLevel(3);
|
||||||
|
|
||||||
|
int player = Board.P1;
|
||||||
|
int totalMoves = Board.DEFAULT_BOARD_SIZE * Board.DEFAULT_BOARD_SIZE;
|
||||||
|
for (int i = 0; i < totalMoves; i++) {
|
||||||
|
if (player == Board.P1)
|
||||||
|
board = mcts3.findNextMove(board, player);
|
||||||
|
else
|
||||||
|
board = mcts1.findNextMove(board, player);
|
||||||
|
|
||||||
|
if (board.checkStatus() != -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
player = 3 - player;
|
||||||
|
}
|
||||||
|
int winStatus = board.checkStatus();
|
||||||
|
assertTrue(winStatus == Board.DRAW || winStatus == Board.P1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package com.baeldung.javanetworking.url;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class URLDemo {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(URLDemo.class);
|
||||||
|
|
||||||
|
String URLSTRING = "https://wordpress.org:443/support/topic/page-jumps-within-wordpress/?replies=3#post-2278484";
|
||||||
|
// parsed locator
|
||||||
|
String URLPROTOCOL = "https";
|
||||||
|
// final static String URLAUTHORITY = "wordpress.org:443";
|
||||||
|
String URLHOST = "wordpress.org";
|
||||||
|
String URLPATH = "/support/topic/page-jumps-within-wordpress/";
|
||||||
|
// final static String URLFILENAME = "/support/topic/page-jumps-within-wordpress/?replies=3";
|
||||||
|
// final static int URLPORT = 443;
|
||||||
|
int URLDEFAULTPORT = 443;
|
||||||
|
String URLQUERY = "replies=3";
|
||||||
|
String URLREFERENCE = "post-2278484";
|
||||||
|
String URLCOMPOUND = URLPROTOCOL + "://" + URLHOST + ":" + URLDEFAULTPORT + URLPATH + "?" + URLQUERY + "#" + URLREFERENCE;
|
||||||
|
|
||||||
|
URL url;
|
||||||
|
URLConnection urlConnection = null;
|
||||||
|
HttpURLConnection connection = null;
|
||||||
|
BufferedReader in = null;
|
||||||
|
String urlContent = "";
|
||||||
|
|
||||||
|
public String testURL(String urlString) throws IOException, IllegalArgumentException {
|
||||||
|
String urlStringCont = "";
|
||||||
|
// comment the if clause if experiment with URL
|
||||||
|
/*if (!URLSTRING.equals(urlString)) {
|
||||||
|
throw new IllegalArgumentException("URL String argument is not proper: " + urlString);
|
||||||
|
}*/
|
||||||
|
// creating URL object
|
||||||
|
url = new URL(urlString);
|
||||||
|
// get URL connection
|
||||||
|
urlConnection = url.openConnection();
|
||||||
|
connection = null;
|
||||||
|
// we can check, if connection is proper type
|
||||||
|
if (urlConnection instanceof HttpURLConnection) {
|
||||||
|
connection = (HttpURLConnection) urlConnection;
|
||||||
|
} else {
|
||||||
|
log.info("Please enter an HTTP URL");
|
||||||
|
throw new IOException("HTTP URL is not correct");
|
||||||
|
}
|
||||||
|
// we can check response code (200 OK is expected)
|
||||||
|
log.info(connection.getResponseCode() + " " + connection.getResponseMessage());
|
||||||
|
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||||
|
String current;
|
||||||
|
|
||||||
|
while ((current = in.readLine()) != null) {
|
||||||
|
urlStringCont += current;
|
||||||
|
}
|
||||||
|
return urlStringCont;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
URLDemo demo = new URLDemo();
|
||||||
|
String content = demo.testURL(demo.URLCOMPOUND);
|
||||||
|
demo.log.info(content);
|
||||||
|
}
|
||||||
|
}
|
9
core-java/src/main/java/log4j.properties
Normal file
9
core-java/src/main/java/log4j.properties
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Set root logger level to DEBUG and its only appender to A1.
|
||||||
|
log4j.rootLogger=DEBUG, A1
|
||||||
|
|
||||||
|
# A1 is set to be a ConsoleAppender.
|
||||||
|
log4j.appender.A1=org.apache.log4j.ConsoleAppender
|
||||||
|
|
||||||
|
# A1 uses PatternLayout.
|
||||||
|
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
|
@ -0,0 +1,106 @@
|
|||||||
|
package com.baeldung.javanetworking.url.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.FixMethodOrder;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.baeldung.javanetworking.url.URLDemo;
|
||||||
|
|
||||||
|
@FixMethodOrder
|
||||||
|
public class URLDemoTest {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(URLDemo.class);
|
||||||
|
static String URLSTRING = "https://wordpress.org:443/support/topic/page-jumps-within-wordpress/?replies=3#post-2278484";
|
||||||
|
// parsed locator
|
||||||
|
static String URLPROTOCOL = "https";
|
||||||
|
String URLAUTHORITY = "wordpress.org:443";
|
||||||
|
static String URLHOST = "wordpress.org";
|
||||||
|
static String URLPATH = "/support/topic/page-jumps-within-wordpress/";
|
||||||
|
String URLFILENAME = "/support/topic/page-jumps-within-wordpress/?replies=3";
|
||||||
|
int URLPORT = 443;
|
||||||
|
static int URLDEFAULTPORT = 443;
|
||||||
|
static String URLQUERY = "replies=3";
|
||||||
|
static String URLREFERENCE = "post-2278484";
|
||||||
|
static String URLCOMPOUND = URLPROTOCOL + "://" + URLHOST + ":" + URLDEFAULTPORT + URLPATH + "?" + URLQUERY + "#" + URLREFERENCE;
|
||||||
|
|
||||||
|
static URL url;
|
||||||
|
URLConnection urlConnection = null;
|
||||||
|
HttpURLConnection connection = null;
|
||||||
|
BufferedReader in = null;
|
||||||
|
String urlContent = "";
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void givenEmplyURL_whenInitializeURL_thenSuccess() throws MalformedURLException {
|
||||||
|
url = new URL(URLCOMPOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check parsed URL
|
||||||
|
@Test
|
||||||
|
public void givenURL_whenURLIsParsed_thenSuccess() {
|
||||||
|
assertNotNull("URL is null", url);
|
||||||
|
assertEquals("URL string is not equal", url.toString(), URLSTRING);
|
||||||
|
assertEquals("Protocol is not equal", url.getProtocol(), URLPROTOCOL);
|
||||||
|
assertEquals("Authority is not equal", url.getAuthority(), URLAUTHORITY);
|
||||||
|
assertEquals("Host string is not equal", url.getHost(), URLHOST);
|
||||||
|
assertEquals("Path string is not equal", url.getPath(), URLPATH);
|
||||||
|
assertEquals("File string is not equal", url.getFile(), URLFILENAME);
|
||||||
|
assertEquals("Port number is not equal", url.getPort(), URLPORT);
|
||||||
|
assertEquals("Default port number is not equal", url.getDefaultPort(), URLDEFAULTPORT);
|
||||||
|
assertEquals("Query string is not equal", url.getQuery(), URLQUERY);
|
||||||
|
assertEquals("Reference string is not equal", url.getRef(), URLREFERENCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtain the content from location
|
||||||
|
@Test
|
||||||
|
public void givenURL_whenOpenConnectionAndContentIsNotEmpty_thenSuccess() throws IOException {
|
||||||
|
try {
|
||||||
|
urlConnection = url.openConnection();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
urlConnection = null;
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
assertNotNull("URL Connection is null", urlConnection);
|
||||||
|
|
||||||
|
connection = null;
|
||||||
|
assertTrue("URLConnection is not HttpURLConnection", urlConnection instanceof HttpURLConnection);
|
||||||
|
if (urlConnection instanceof HttpURLConnection) {
|
||||||
|
connection = (HttpURLConnection) urlConnection;
|
||||||
|
}
|
||||||
|
assertNotNull("Connection is null", connection);
|
||||||
|
|
||||||
|
log.info(connection.getResponseCode() + " " + connection.getResponseMessage());
|
||||||
|
|
||||||
|
try {
|
||||||
|
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
in = null;
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
assertNotNull("Input stream failed", in);
|
||||||
|
|
||||||
|
String current;
|
||||||
|
try {
|
||||||
|
while ((current = in.readLine()) != null) {
|
||||||
|
urlContent += current;
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
urlContent = null;
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
assertNotNull("Content is null", urlContent);
|
||||||
|
assertTrue("Content is empty", urlContent.length() > 0);
|
||||||
|
}
|
||||||
|
}
|
3
drools/README.MD
Normal file
3
drools/README.MD
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
### Relevant Articles:
|
||||||
|
[Introduction to Drools](http://www.baeldung.com/drools)
|
||||||
|
[Drools Using Rules from Excel Files](http://www.baeldung.com/drools-excel)
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<http-component-version>4.4.6</http-component-version>
|
<http-component-version>4.4.6</http-component-version>
|
||||||
<drools-version>7.0.0.CR1</drools-version>
|
<drools-version>7.1.0.Beta2</drools-version>
|
||||||
<apache-poi-version>3.13</apache-poi-version>
|
<apache-poi-version>3.13</apache-poi-version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
package com.baeldung.drools.config;
|
package com.baeldung.drools.config;
|
||||||
|
|
||||||
|
import org.drools.decisiontable.DecisionTableProviderImpl;
|
||||||
import org.kie.api.KieServices;
|
import org.kie.api.KieServices;
|
||||||
import org.kie.api.builder.*;
|
import org.kie.api.builder.*;
|
||||||
import org.kie.api.io.KieResources;
|
import org.kie.api.io.KieResources;
|
||||||
|
import org.kie.api.io.Resource;
|
||||||
import org.kie.api.runtime.KieContainer;
|
import org.kie.api.runtime.KieContainer;
|
||||||
import org.kie.api.runtime.KieSession;
|
import org.kie.api.runtime.KieSession;
|
||||||
|
import org.kie.internal.builder.DecisionTableConfiguration;
|
||||||
|
import org.kie.internal.builder.DecisionTableInputType;
|
||||||
|
import org.kie.internal.builder.KnowledgeBuilderFactory;
|
||||||
import org.kie.internal.io.ResourceFactory;
|
import org.kie.internal.io.ResourceFactory;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -64,4 +69,39 @@ public class DroolsBeanFactory {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KieSession getKieSession(Resource dt) {
|
||||||
|
KieFileSystem kieFileSystem = kieServices.newKieFileSystem()
|
||||||
|
.write(dt);
|
||||||
|
|
||||||
|
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem)
|
||||||
|
.buildAll();
|
||||||
|
|
||||||
|
KieRepository kieRepository = kieServices.getRepository();
|
||||||
|
|
||||||
|
ReleaseId krDefaultReleaseId = kieRepository.getDefaultReleaseId();
|
||||||
|
|
||||||
|
KieContainer kieContainer = kieServices.newKieContainer(krDefaultReleaseId);
|
||||||
|
|
||||||
|
KieSession ksession = kieContainer.newKieSession();
|
||||||
|
|
||||||
|
return ksession;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Can be used for debugging
|
||||||
|
* Input excelFile example: com/baeldung/drools/rules/Discount.xls
|
||||||
|
*/
|
||||||
|
public String getDrlFromExcel(String excelFile) {
|
||||||
|
DecisionTableConfiguration configuration = KnowledgeBuilderFactory.newDecisionTableConfiguration();
|
||||||
|
configuration.setInputType(DecisionTableInputType.XLS);
|
||||||
|
|
||||||
|
Resource dt = ResourceFactory.newClassPathResource(excelFile, getClass());
|
||||||
|
|
||||||
|
DecisionTableProviderImpl decisionTableProvider = new DecisionTableProviderImpl();
|
||||||
|
|
||||||
|
String drl = decisionTableProvider.loadFromResource(dt, null);
|
||||||
|
|
||||||
|
return drl;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
44
drools/src/main/java/com/baeldung/drools/model/Customer.java
Normal file
44
drools/src/main/java/com/baeldung/drools/model/Customer.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package com.baeldung.drools.model;
|
||||||
|
|
||||||
|
public class Customer {
|
||||||
|
|
||||||
|
private CustomerType type;
|
||||||
|
|
||||||
|
private int years;
|
||||||
|
|
||||||
|
private int discount;
|
||||||
|
|
||||||
|
public Customer(CustomerType type, int numOfYears) {
|
||||||
|
super();
|
||||||
|
this.type = type;
|
||||||
|
this.years = numOfYears;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomerType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(CustomerType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getYears() {
|
||||||
|
return years;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYears(int years) {
|
||||||
|
this.years = years;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDiscount() {
|
||||||
|
return discount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDiscount(int discount) {
|
||||||
|
this.discount = discount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CustomerType {
|
||||||
|
INDIVIDUAL, BUSINESS;
|
||||||
|
}
|
||||||
|
}
|
BIN
drools/src/main/resources/com/baeldung/drools/rules/Discount.xls
Normal file
BIN
drools/src/main/resources/com/baeldung/drools/rules/Discount.xls
Normal file
Binary file not shown.
@ -36,6 +36,7 @@ public class ApplicantServiceIntegrationTest {
|
|||||||
applicantService.suggestARoleForApplicant(applicant, suggestedRole);
|
applicantService.suggestARoleForApplicant(applicant, suggestedRole);
|
||||||
assertEquals("Senior developer", suggestedRole.getRole());
|
assertEquals("Senior developer", suggestedRole.getRole());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenCriteriaMatching_ThenSuggestDeveloperRole() throws IOException {
|
public void whenCriteriaMatching_ThenSuggestDeveloperRole() throws IOException {
|
||||||
Applicant applicant = new Applicant("Davis", 37, 800000.0, 3);
|
Applicant applicant = new Applicant("Davis", 37, 800000.0, 3);
|
||||||
@ -43,6 +44,7 @@ public class ApplicantServiceIntegrationTest {
|
|||||||
applicantService.suggestARoleForApplicant(applicant, suggestedRole);
|
applicantService.suggestARoleForApplicant(applicant, suggestedRole);
|
||||||
assertEquals("Developer", suggestedRole.getRole());
|
assertEquals("Developer", suggestedRole.getRole());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenCriteriaNotMatching_ThenNoRole() throws IOException {
|
public void whenCriteriaNotMatching_ThenNoRole() throws IOException {
|
||||||
Applicant applicant = new Applicant("John", 37, 1200000.0, 5);
|
Applicant applicant = new Applicant("John", 37, 1200000.0, 5);
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.baeldung.drools.service;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.kie.api.io.Resource;
|
||||||
|
import org.kie.api.runtime.KieSession;
|
||||||
|
import org.kie.internal.io.ResourceFactory;
|
||||||
|
|
||||||
|
import com.baeldung.drools.config.DroolsBeanFactory;
|
||||||
|
import com.baeldung.drools.model.Customer;
|
||||||
|
import com.baeldung.drools.model.Customer.CustomerType;
|
||||||
|
|
||||||
|
public class DiscountExcelIntegrationTest {
|
||||||
|
|
||||||
|
private KieSession kSession;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
Resource resource = ResourceFactory.newClassPathResource("com/baeldung/drools/rules/Discount.xls", getClass());
|
||||||
|
kSession = new DroolsBeanFactory().getKieSession(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void giveIndvidualLongStanding_whenFireRule_thenCorrectDiscount() throws Exception {
|
||||||
|
Customer customer = new Customer(CustomerType.INDIVIDUAL, 5);
|
||||||
|
kSession.insert(customer);
|
||||||
|
|
||||||
|
kSession.fireAllRules();
|
||||||
|
|
||||||
|
assertEquals(customer.getDiscount(), 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void giveIndvidualRecent_whenFireRule_thenCorrectDiscount() throws Exception {
|
||||||
|
|
||||||
|
Customer customer = new Customer(CustomerType.INDIVIDUAL, 1);
|
||||||
|
kSession.insert(customer);
|
||||||
|
|
||||||
|
kSession.fireAllRules();
|
||||||
|
|
||||||
|
assertEquals(customer.getDiscount(), 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void giveBusinessAny_whenFireRule_thenCorrectDiscount() throws Exception {
|
||||||
|
Customer customer = new Customer(CustomerType.BUSINESS, 0);
|
||||||
|
kSession.insert(customer);
|
||||||
|
|
||||||
|
kSession.fireAllRules();
|
||||||
|
|
||||||
|
assertEquals(customer.getDiscount(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,6 +3,7 @@ package com.baeldung.drools.service;
|
|||||||
import com.baeldung.drools.model.Product;
|
import com.baeldung.drools.model.Product;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertEquals;
|
import static junit.framework.TestCase.assertEquals;
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Class-Path:
|
||||||
|
|
27
guest/webservices/rest-client/pom.xml
Normal file
27
guest/webservices/rest-client/pom.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<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.stackify</groupId>
|
||||||
|
<artifactId>rest-client</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.5</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
<configuration>
|
||||||
|
<warSourceDirectory>WebContent</warSourceDirectory>
|
||||||
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
57
guest/webservices/rest-client/rest-client/.angular-cli.json
Normal file
57
guest/webservices/rest-client/rest-client/.angular-cli.json
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"project": {
|
||||||
|
"name": "rest-client"
|
||||||
|
},
|
||||||
|
"apps": [
|
||||||
|
{
|
||||||
|
"root": "src",
|
||||||
|
"outDir": "dist",
|
||||||
|
"assets": [
|
||||||
|
"assets",
|
||||||
|
"favicon.ico"
|
||||||
|
],
|
||||||
|
"index": "index.html",
|
||||||
|
"main": "main.ts",
|
||||||
|
"polyfills": "polyfills.ts",
|
||||||
|
"test": "test.ts",
|
||||||
|
"tsconfig": "tsconfig.app.json",
|
||||||
|
"testTsconfig": "tsconfig.spec.json",
|
||||||
|
"prefix": "app",
|
||||||
|
"styles": [
|
||||||
|
"styles.css"
|
||||||
|
],
|
||||||
|
"scripts": [],
|
||||||
|
"environmentSource": "environments/environment.ts",
|
||||||
|
"environments": {
|
||||||
|
"dev": "environments/environment.ts",
|
||||||
|
"prod": "environments/environment.prod.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"e2e": {
|
||||||
|
"protractor": {
|
||||||
|
"config": "./protractor.conf.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": [
|
||||||
|
{
|
||||||
|
"project": "src/tsconfig.app.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"project": "src/tsconfig.spec.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"project": "e2e/tsconfig.e2e.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"test": {
|
||||||
|
"karma": {
|
||||||
|
"config": "./karma.conf.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaults": {
|
||||||
|
"styleExt": "css",
|
||||||
|
"component": {}
|
||||||
|
}
|
||||||
|
}
|
13
guest/webservices/rest-client/rest-client/.editorconfig
Normal file
13
guest/webservices/rest-client/rest-client/.editorconfig
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Editor configuration, see http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
42
guest/webservices/rest-client/rest-client/.gitignore
vendored
Normal file
42
guest/webservices/rest-client/rest-client/.gitignore
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# compiled output
|
||||||
|
/dist
|
||||||
|
/tmp
|
||||||
|
/out-tsc
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IDE - VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# misc
|
||||||
|
/.sass-cache
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
npm-debug.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# e2e
|
||||||
|
/e2e/*.js
|
||||||
|
/e2e/*.map
|
||||||
|
|
||||||
|
# System Files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
28
guest/webservices/rest-client/rest-client/README.md
Normal file
28
guest/webservices/rest-client/rest-client/README.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# RestClient
|
||||||
|
|
||||||
|
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.1.3.
|
||||||
|
|
||||||
|
## Development server
|
||||||
|
|
||||||
|
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||||
|
|
||||||
|
## Code scaffolding
|
||||||
|
|
||||||
|
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|module`.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||||
|
|
||||||
|
## Running end-to-end tests
|
||||||
|
|
||||||
|
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||||
|
Before running the tests make sure you are serving the app via `ng serve`.
|
||||||
|
|
||||||
|
## Further help
|
||||||
|
|
||||||
|
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
@ -0,0 +1,14 @@
|
|||||||
|
import { RestClientPage } from './app.po';
|
||||||
|
|
||||||
|
describe('rest-client App', () => {
|
||||||
|
let page: RestClientPage;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
page = new RestClientPage();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display welcome message', () => {
|
||||||
|
page.navigateTo();
|
||||||
|
expect(page.getParagraphText()).toEqual('Welcome to app!!');
|
||||||
|
});
|
||||||
|
});
|
11
guest/webservices/rest-client/rest-client/e2e/app.po.ts
Normal file
11
guest/webservices/rest-client/rest-client/e2e/app.po.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { browser, by, element } from 'protractor';
|
||||||
|
|
||||||
|
export class RestClientPage {
|
||||||
|
navigateTo() {
|
||||||
|
return browser.get('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
getParagraphText() {
|
||||||
|
return element(by.css('app-root h1')).getText();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../out-tsc/e2e",
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es5",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
33
guest/webservices/rest-client/rest-client/karma.conf.js
Normal file
33
guest/webservices/rest-client/rest-client/karma.conf.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Karma configuration file, see link for more information
|
||||||
|
// https://karma-runner.github.io/0.13/config/configuration-file.html
|
||||||
|
|
||||||
|
module.exports = function (config) {
|
||||||
|
config.set({
|
||||||
|
basePath: '',
|
||||||
|
frameworks: ['jasmine', '@angular/cli'],
|
||||||
|
plugins: [
|
||||||
|
require('karma-jasmine'),
|
||||||
|
require('karma-chrome-launcher'),
|
||||||
|
require('karma-jasmine-html-reporter'),
|
||||||
|
require('karma-coverage-istanbul-reporter'),
|
||||||
|
require('@angular/cli/plugins/karma')
|
||||||
|
],
|
||||||
|
client:{
|
||||||
|
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||||
|
},
|
||||||
|
coverageIstanbulReporter: {
|
||||||
|
reports: [ 'html', 'lcovonly' ],
|
||||||
|
fixWebpackSourcePaths: true
|
||||||
|
},
|
||||||
|
angularCli: {
|
||||||
|
environment: 'dev'
|
||||||
|
},
|
||||||
|
reporters: ['progress', 'kjhtml'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
autoWatch: true,
|
||||||
|
browsers: ['Chrome'],
|
||||||
|
singleRun: false
|
||||||
|
});
|
||||||
|
};
|
48
guest/webservices/rest-client/rest-client/package.json
Normal file
48
guest/webservices/rest-client/rest-client/package.json
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "rest-client",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"ng": "ng",
|
||||||
|
"start": "ng serve",
|
||||||
|
"build": "ng build",
|
||||||
|
"test": "ng test",
|
||||||
|
"lint": "ng lint",
|
||||||
|
"e2e": "ng e2e"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/animations": "^4.0.0",
|
||||||
|
"@angular/common": "^4.0.0",
|
||||||
|
"@angular/compiler": "^4.0.0",
|
||||||
|
"@angular/core": "^4.0.0",
|
||||||
|
"@angular/forms": "^4.0.0",
|
||||||
|
"@angular/http": "^4.0.0",
|
||||||
|
"@angular/platform-browser": "^4.0.0",
|
||||||
|
"@angular/platform-browser-dynamic": "^4.0.0",
|
||||||
|
"@angular/router": "^4.0.0",
|
||||||
|
"core-js": "^2.4.1",
|
||||||
|
"rxjs": "^5.1.0",
|
||||||
|
"zone.js": "^0.8.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular/cli": "1.1.3",
|
||||||
|
"@angular/compiler-cli": "^4.0.0",
|
||||||
|
"@angular/language-service": "^4.0.0",
|
||||||
|
"@types/jasmine": "2.5.45",
|
||||||
|
"@types/node": "~6.0.60",
|
||||||
|
"codelyzer": "~3.0.1",
|
||||||
|
"jasmine-core": "~2.6.2",
|
||||||
|
"jasmine-spec-reporter": "~4.1.0",
|
||||||
|
"karma": "~1.7.0",
|
||||||
|
"karma-chrome-launcher": "~2.1.1",
|
||||||
|
"karma-cli": "~1.0.1",
|
||||||
|
"karma-coverage-istanbul-reporter": "^1.2.1",
|
||||||
|
"karma-jasmine": "~1.1.0",
|
||||||
|
"karma-jasmine-html-reporter": "^0.2.2",
|
||||||
|
"protractor": "~5.1.2",
|
||||||
|
"ts-node": "~3.0.4",
|
||||||
|
"tslint": "~5.3.2",
|
||||||
|
"typescript": "~2.3.3"
|
||||||
|
}
|
||||||
|
}
|
28
guest/webservices/rest-client/rest-client/protractor.conf.js
Normal file
28
guest/webservices/rest-client/rest-client/protractor.conf.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Protractor configuration file, see link for more information
|
||||||
|
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||||
|
|
||||||
|
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||||
|
|
||||||
|
exports.config = {
|
||||||
|
allScriptsTimeout: 11000,
|
||||||
|
specs: [
|
||||||
|
'./e2e/**/*.e2e-spec.ts'
|
||||||
|
],
|
||||||
|
capabilities: {
|
||||||
|
'browserName': 'chrome'
|
||||||
|
},
|
||||||
|
directConnect: true,
|
||||||
|
baseUrl: 'http://localhost:4200/',
|
||||||
|
framework: 'jasmine',
|
||||||
|
jasmineNodeOpts: {
|
||||||
|
showColors: true,
|
||||||
|
defaultTimeoutInterval: 30000,
|
||||||
|
print: function() {}
|
||||||
|
},
|
||||||
|
onPrepare() {
|
||||||
|
require('ts-node').register({
|
||||||
|
project: 'e2e/tsconfig.e2e.json'
|
||||||
|
});
|
||||||
|
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Angular QuickStart</title>
|
||||||
|
<base href="/">
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<users-page>loading users component</users-page>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,32 @@
|
|||||||
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should create the app', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it(`should have as title 'app'`, async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app.title).toEqual('app');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should render title in a h1 tag', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!!');
|
||||||
|
}));
|
||||||
|
});
|
@ -0,0 +1,10 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'app';
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { HttpModule } from '@angular/http';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { UsersComponent } from './users.component';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
UsersComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
HttpModule,
|
||||||
|
FormsModule,
|
||||||
|
RouterModule.forRoot([
|
||||||
|
{ path: '', component: AppComponent },
|
||||||
|
{ path: 'users', component: UsersComponent }])],
|
||||||
|
providers: [],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
@ -0,0 +1,36 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import { Http, Response, Headers, RequestOptions } from '@angular/http';
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
|
||||||
|
export class User {
|
||||||
|
constructor(
|
||||||
|
public email: string,
|
||||||
|
public name: string) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserService {
|
||||||
|
constructor(
|
||||||
|
private _http: Http){}
|
||||||
|
|
||||||
|
url = 'http://localhost:8080/rest-server/users';
|
||||||
|
|
||||||
|
addUser(user){
|
||||||
|
let headers = new Headers({'Content-Type': 'application/json'});
|
||||||
|
let options = new RequestOptions({ headers: headers});
|
||||||
|
|
||||||
|
return this._http.post(this.url, JSON.stringify(user), options)
|
||||||
|
.map(
|
||||||
|
(_response: Response) => {
|
||||||
|
return _response;
|
||||||
|
},
|
||||||
|
err => alert('Error adding user'));
|
||||||
|
}
|
||||||
|
|
||||||
|
getUsers() {
|
||||||
|
return this._http.get(this.url)
|
||||||
|
.map((_response: Response) => {
|
||||||
|
return _response.json();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
<form>
|
||||||
|
Email: <input type="text" [(ngModel)]="user.email" name="email"/><br />
|
||||||
|
Name: <input type="text" [(ngModel)]="user.name" name="name"/><br />
|
||||||
|
<input type="submit" (click)="addUser()" value="Add User"/>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<table>
|
||||||
|
<tr *ngFor="let user of res" >
|
||||||
|
<td>{{user.email}}
|
||||||
|
</td>
|
||||||
|
<td>{{user.name}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import {UserService, User} from './app.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'users-page',
|
||||||
|
providers: [UserService],
|
||||||
|
templateUrl: './users.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class UsersComponent {
|
||||||
|
title = 'Users';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _service:UserService){}
|
||||||
|
|
||||||
|
public user = {email: "", name: ""};
|
||||||
|
public res=[];
|
||||||
|
|
||||||
|
addUser() {
|
||||||
|
this._service.addUser(this.user)
|
||||||
|
.subscribe( () => this.getUsers());
|
||||||
|
}
|
||||||
|
|
||||||
|
getUsers() {
|
||||||
|
this._service.getUsers()
|
||||||
|
.subscribe(
|
||||||
|
users => {
|
||||||
|
this.res=[];
|
||||||
|
users.forEach(usr => {
|
||||||
|
this.res.push(
|
||||||
|
new User(
|
||||||
|
usr.email,
|
||||||
|
usr.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
export const environment = {
|
||||||
|
production: true
|
||||||
|
};
|
@ -0,0 +1,8 @@
|
|||||||
|
// The file contents for the current environment will overwrite these during build.
|
||||||
|
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
|
||||||
|
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
|
||||||
|
// The list of which env maps to which file can be found in `.angular-cli.json`.
|
||||||
|
|
||||||
|
export const environment = {
|
||||||
|
production: false
|
||||||
|
};
|
BIN
guest/webservices/rest-client/rest-client/src/favicon.ico
Normal file
BIN
guest/webservices/rest-client/rest-client/src/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
14
guest/webservices/rest-client/rest-client/src/index.html
Normal file
14
guest/webservices/rest-client/rest-client/src/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>RestClient</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
11
guest/webservices/rest-client/rest-client/src/main.ts
Normal file
11
guest/webservices/rest-client/rest-client/src/main.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { enableProdMode } from '@angular/core';
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
import { environment } from './environments/environment';
|
||||||
|
|
||||||
|
if (environment.production) {
|
||||||
|
enableProdMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
73
guest/webservices/rest-client/rest-client/src/polyfills.ts
Normal file
73
guest/webservices/rest-client/rest-client/src/polyfills.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* This file includes polyfills needed by Angular and is loaded before the app.
|
||||||
|
* You can add your own extra polyfills to this file.
|
||||||
|
*
|
||||||
|
* This file is divided into 2 sections:
|
||||||
|
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
|
||||||
|
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
|
||||||
|
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||||
|
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
||||||
|
*
|
||||||
|
* Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* BROWSER POLYFILLS
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
|
||||||
|
// import 'core-js/es6/symbol';
|
||||||
|
// import 'core-js/es6/object';
|
||||||
|
// import 'core-js/es6/function';
|
||||||
|
// import 'core-js/es6/parse-int';
|
||||||
|
// import 'core-js/es6/parse-float';
|
||||||
|
// import 'core-js/es6/number';
|
||||||
|
// import 'core-js/es6/math';
|
||||||
|
// import 'core-js/es6/string';
|
||||||
|
// import 'core-js/es6/date';
|
||||||
|
// import 'core-js/es6/array';
|
||||||
|
// import 'core-js/es6/regexp';
|
||||||
|
// import 'core-js/es6/map';
|
||||||
|
// import 'core-js/es6/weak-map';
|
||||||
|
// import 'core-js/es6/set';
|
||||||
|
|
||||||
|
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
||||||
|
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||||
|
|
||||||
|
/** IE10 and IE11 requires the following to support `@angular/animation`. */
|
||||||
|
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||||
|
|
||||||
|
|
||||||
|
/** Evergreen browsers require these. **/
|
||||||
|
import 'core-js/es6/reflect';
|
||||||
|
import 'core-js/es7/reflect';
|
||||||
|
|
||||||
|
|
||||||
|
/** ALL Firefox browsers require the following to support `@angular/animation`. **/
|
||||||
|
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* Zone JS is required by Angular itself.
|
||||||
|
*/
|
||||||
|
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* APPLICATION IMPORTS
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Date, currency, decimal and percent pipes.
|
||||||
|
* Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
|
||||||
|
*/
|
||||||
|
// import 'intl'; // Run `npm install --save intl`.
|
||||||
|
/**
|
||||||
|
* Need to import at least one locale-data with intl.
|
||||||
|
*/
|
||||||
|
// import 'intl/locale-data/jsonp/en';
|
1
guest/webservices/rest-client/rest-client/src/styles.css
Normal file
1
guest/webservices/rest-client/rest-client/src/styles.css
Normal file
@ -0,0 +1 @@
|
|||||||
|
/* You can add global styles to this file, and also import other style files */
|
32
guest/webservices/rest-client/rest-client/src/test.ts
Normal file
32
guest/webservices/rest-client/rest-client/src/test.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||||
|
|
||||||
|
import 'zone.js/dist/long-stack-trace-zone';
|
||||||
|
import 'zone.js/dist/proxy.js';
|
||||||
|
import 'zone.js/dist/sync-test';
|
||||||
|
import 'zone.js/dist/jasmine-patch';
|
||||||
|
import 'zone.js/dist/async-test';
|
||||||
|
import 'zone.js/dist/fake-async-test';
|
||||||
|
import { getTestBed } from '@angular/core/testing';
|
||||||
|
import {
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting
|
||||||
|
} from '@angular/platform-browser-dynamic/testing';
|
||||||
|
|
||||||
|
// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
|
||||||
|
declare const __karma__: any;
|
||||||
|
declare const require: any;
|
||||||
|
|
||||||
|
// Prevent Karma from running prematurely.
|
||||||
|
__karma__.loaded = function () {};
|
||||||
|
|
||||||
|
// First, initialize the Angular testing environment.
|
||||||
|
getTestBed().initTestEnvironment(
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting()
|
||||||
|
);
|
||||||
|
// Then we find all the tests.
|
||||||
|
const context = require.context('./', true, /\.spec\.ts$/);
|
||||||
|
// And load the modules.
|
||||||
|
context.keys().map(context);
|
||||||
|
// Finally, start Karma to run the tests.
|
||||||
|
__karma__.start();
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../out-tsc/app",
|
||||||
|
"module": "es2015",
|
||||||
|
"baseUrl": "",
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"test.ts",
|
||||||
|
"**/*.spec.ts"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../out-tsc/spec",
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es5",
|
||||||
|
"baseUrl": "",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"test.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
5
guest/webservices/rest-client/rest-client/src/typings.d.ts
vendored
Normal file
5
guest/webservices/rest-client/rest-client/src/typings.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/* SystemJS module definition */
|
||||||
|
declare var module: NodeModule;
|
||||||
|
interface NodeModule {
|
||||||
|
id: string;
|
||||||
|
}
|
20
guest/webservices/rest-client/rest-client/tsconfig.json
Normal file
20
guest/webservices/rest-client/rest-client/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./dist/out-tsc",
|
||||||
|
"baseUrl": "src",
|
||||||
|
"sourceMap": true,
|
||||||
|
"declaration": false,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"target": "es5",
|
||||||
|
"typeRoots": [
|
||||||
|
"node_modules/@types"
|
||||||
|
],
|
||||||
|
"lib": [
|
||||||
|
"es2016",
|
||||||
|
"dom"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
135
guest/webservices/rest-client/rest-client/tslint.json
Normal file
135
guest/webservices/rest-client/rest-client/tslint.json
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
{
|
||||||
|
"rulesDirectory": [
|
||||||
|
"node_modules/codelyzer"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"arrow-return-shorthand": true,
|
||||||
|
"callable-types": true,
|
||||||
|
"class-name": true,
|
||||||
|
"comment-format": [
|
||||||
|
true,
|
||||||
|
"check-space"
|
||||||
|
],
|
||||||
|
"curly": true,
|
||||||
|
"eofline": true,
|
||||||
|
"forin": true,
|
||||||
|
"import-blacklist": [
|
||||||
|
true,
|
||||||
|
"rxjs"
|
||||||
|
],
|
||||||
|
"import-spacing": true,
|
||||||
|
"indent": [
|
||||||
|
true,
|
||||||
|
"spaces"
|
||||||
|
],
|
||||||
|
"interface-over-type-literal": true,
|
||||||
|
"label-position": true,
|
||||||
|
"max-line-length": [
|
||||||
|
true,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"member-access": false,
|
||||||
|
"member-ordering": [
|
||||||
|
true,
|
||||||
|
"static-before-instance",
|
||||||
|
"variables-before-functions"
|
||||||
|
],
|
||||||
|
"no-arg": true,
|
||||||
|
"no-bitwise": true,
|
||||||
|
"no-console": [
|
||||||
|
true,
|
||||||
|
"debug",
|
||||||
|
"info",
|
||||||
|
"time",
|
||||||
|
"timeEnd",
|
||||||
|
"trace"
|
||||||
|
],
|
||||||
|
"no-construct": true,
|
||||||
|
"no-debugger": true,
|
||||||
|
"no-duplicate-super": true,
|
||||||
|
"no-empty": false,
|
||||||
|
"no-empty-interface": true,
|
||||||
|
"no-eval": true,
|
||||||
|
"no-inferrable-types": [
|
||||||
|
true,
|
||||||
|
"ignore-params"
|
||||||
|
],
|
||||||
|
"no-misused-new": true,
|
||||||
|
"no-non-null-assertion": true,
|
||||||
|
"no-shadowed-variable": true,
|
||||||
|
"no-string-literal": false,
|
||||||
|
"no-string-throw": true,
|
||||||
|
"no-switch-case-fall-through": true,
|
||||||
|
"no-trailing-whitespace": true,
|
||||||
|
"no-unnecessary-initializer": true,
|
||||||
|
"no-unused-expression": true,
|
||||||
|
"no-use-before-declare": true,
|
||||||
|
"no-var-keyword": true,
|
||||||
|
"object-literal-sort-keys": false,
|
||||||
|
"one-line": [
|
||||||
|
true,
|
||||||
|
"check-open-brace",
|
||||||
|
"check-catch",
|
||||||
|
"check-else",
|
||||||
|
"check-whitespace"
|
||||||
|
],
|
||||||
|
"prefer-const": true,
|
||||||
|
"quotemark": [
|
||||||
|
true,
|
||||||
|
"single"
|
||||||
|
],
|
||||||
|
"radix": true,
|
||||||
|
"semicolon": [
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"triple-equals": [
|
||||||
|
true,
|
||||||
|
"allow-null-check"
|
||||||
|
],
|
||||||
|
"typedef-whitespace": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
"call-signature": "nospace",
|
||||||
|
"index-signature": "nospace",
|
||||||
|
"parameter": "nospace",
|
||||||
|
"property-declaration": "nospace",
|
||||||
|
"variable-declaration": "nospace"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"typeof-compare": true,
|
||||||
|
"unified-signatures": true,
|
||||||
|
"variable-name": false,
|
||||||
|
"whitespace": [
|
||||||
|
true,
|
||||||
|
"check-branch",
|
||||||
|
"check-decl",
|
||||||
|
"check-operator",
|
||||||
|
"check-separator",
|
||||||
|
"check-type"
|
||||||
|
],
|
||||||
|
"directive-selector": [
|
||||||
|
true,
|
||||||
|
"attribute",
|
||||||
|
"app",
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
"app",
|
||||||
|
"kebab-case"
|
||||||
|
],
|
||||||
|
"use-input-property-decorator": true,
|
||||||
|
"use-output-property-decorator": true,
|
||||||
|
"use-host-property-decorator": true,
|
||||||
|
"no-input-rename": true,
|
||||||
|
"no-output-rename": true,
|
||||||
|
"use-life-cycle-interface": true,
|
||||||
|
"use-pipe-transform-interface": true,
|
||||||
|
"component-class-suffix": true,
|
||||||
|
"directive-class-suffix": true,
|
||||||
|
"no-access-missing-member": true,
|
||||||
|
"templates-use-public": true,
|
||||||
|
"invoke-injectable": true
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Class-Path:
|
||||||
|
|
20
guest/webservices/rest-server/WebContent/WEB-INF/web.xml
Normal file
20
guest/webservices/rest-server/WebContent/WEB-INF/web.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||||
|
id="WebApp_ID" version="3.1">
|
||||||
|
<display-name>rest-server</display-name>
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>rest-server</servlet-name>
|
||||||
|
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>javax.ws.rs.Application</param-name>
|
||||||
|
<param-value>com.stackify.ApplicationInitializer</param-value>
|
||||||
|
</init-param>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>rest-server</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
</web-app>
|
51
guest/webservices/rest-server/pom.xml
Normal file
51
guest/webservices/rest-server/pom.xml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<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.stackify</groupId>
|
||||||
|
<artifactId>rest-server</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.jersey.containers</groupId>
|
||||||
|
<artifactId>jersey-container-servlet</artifactId>
|
||||||
|
<version>2.25.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.jersey.media</groupId>
|
||||||
|
<artifactId>jersey-media-moxy</artifactId>
|
||||||
|
<version>2.25.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.rest-assured</groupId>
|
||||||
|
<artifactId>rest-assured</artifactId>
|
||||||
|
<version>3.0.3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.5.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
<configuration>
|
||||||
|
<warSourceDirectory>WebContent</warSourceDirectory>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.stackify;
|
||||||
|
|
||||||
|
import org.glassfish.jersey.server.ResourceConfig;
|
||||||
|
|
||||||
|
public class ApplicationInitializer extends ResourceConfig {
|
||||||
|
public ApplicationInitializer() {
|
||||||
|
packages("com.stackify.services");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.stackify.models;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Link;
|
||||||
|
|
||||||
|
public class User {
|
||||||
|
private String email;
|
||||||
|
private String name;
|
||||||
|
private Link link;
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(String email, String name) {
|
||||||
|
super();
|
||||||
|
this.email = email;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Link getLink() {
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLink(Link link) {
|
||||||
|
this.link = link;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.stackify.services;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.ws.rs.container.ContainerRequestContext;
|
||||||
|
import javax.ws.rs.container.ContainerResponseContext;
|
||||||
|
import javax.ws.rs.container.ContainerResponseFilter;
|
||||||
|
import javax.ws.rs.ext.Provider;
|
||||||
|
|
||||||
|
@Provider
|
||||||
|
public class CorsFilter implements ContainerResponseFilter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void filter(final ContainerRequestContext requestContext,
|
||||||
|
final ContainerResponseContext response) throws IOException {
|
||||||
|
response.getHeaders().add("Access-Control-Allow-Origin", "*");
|
||||||
|
response.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.stackify.services;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import com.stackify.models.User;
|
||||||
|
|
||||||
|
@Path("/users")
|
||||||
|
public class UserService {
|
||||||
|
private static List<User> users = new ArrayList<>();
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Response addUser(User user) {
|
||||||
|
users.add(user);
|
||||||
|
return Response.ok()
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public List<User> getUsers() {
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.stackify.services;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import io.restassured.RestAssured;
|
||||||
|
import static io.restassured.RestAssured.*;
|
||||||
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
|
|
||||||
|
public class UserServiceTest {
|
||||||
|
@Test
|
||||||
|
public void whenAddUser_thenGetUserOk() {
|
||||||
|
RestAssured.baseURI = "http://localhost:8080/rest-server";
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
|
||||||
|
String json = "{\"email\":\"john@gmail.com\",\"name\":\"John\"}";
|
||||||
|
given()
|
||||||
|
.contentType("application/json")
|
||||||
|
.body(json)
|
||||||
|
.when()
|
||||||
|
.post("/users")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
|
||||||
|
when()
|
||||||
|
.get("/users")
|
||||||
|
.then()
|
||||||
|
.contentType("application/json")
|
||||||
|
.body("name", hasItem("John"))
|
||||||
|
.body("email", hasItem("john@gmail.com"));
|
||||||
|
|
||||||
|
//@formatter:on
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.stackify;
|
||||||
|
|
||||||
|
import com.stackify.services.DefaultUserImplService;
|
||||||
|
import com.stackify.services.User;
|
||||||
|
import com.stackify.services.UserService;
|
||||||
|
import com.stackify.services.Users;
|
||||||
|
|
||||||
|
public class JAXWSClient {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
DefaultUserImplService service = new DefaultUserImplService();
|
||||||
|
User user = new User();
|
||||||
|
user.setEmail("john@gmail.com");
|
||||||
|
user.setName("John");
|
||||||
|
UserService port = service.getDefaultUserImplPort();
|
||||||
|
port.addUser(user);
|
||||||
|
Users users = port.getUsers();
|
||||||
|
System.out.println(users.getUsers().iterator().next().getName());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
|
||||||
|
package com.stackify.services;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
import javax.xml.ws.Service;
|
||||||
|
import javax.xml.ws.WebEndpoint;
|
||||||
|
import javax.xml.ws.WebServiceClient;
|
||||||
|
import javax.xml.ws.WebServiceException;
|
||||||
|
import javax.xml.ws.WebServiceFeature;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class was generated by the JAX-WS RI.
|
||||||
|
* JAX-WS RI 2.2.9-b130926.1035
|
||||||
|
* Generated source version: 2.2
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@WebServiceClient(name = "DefaultUserImplService", targetNamespace = "http://services.stackify.com/", wsdlLocation = "http://localhost:8080/users?wsdl")
|
||||||
|
public class DefaultUserImplService
|
||||||
|
extends Service
|
||||||
|
{
|
||||||
|
|
||||||
|
private final static URL DEFAULTUSERIMPLSERVICE_WSDL_LOCATION;
|
||||||
|
private final static WebServiceException DEFAULTUSERIMPLSERVICE_EXCEPTION;
|
||||||
|
private final static QName DEFAULTUSERIMPLSERVICE_QNAME = new QName("http://services.stackify.com/", "DefaultUserImplService");
|
||||||
|
|
||||||
|
static {
|
||||||
|
URL url = null;
|
||||||
|
WebServiceException e = null;
|
||||||
|
try {
|
||||||
|
url = new URL("http://localhost:8080/users?wsdl");
|
||||||
|
} catch (MalformedURLException ex) {
|
||||||
|
e = new WebServiceException(ex);
|
||||||
|
}
|
||||||
|
DEFAULTUSERIMPLSERVICE_WSDL_LOCATION = url;
|
||||||
|
DEFAULTUSERIMPLSERVICE_EXCEPTION = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultUserImplService() {
|
||||||
|
super(__getWsdlLocation(), DEFAULTUSERIMPLSERVICE_QNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultUserImplService(WebServiceFeature... features) {
|
||||||
|
super(__getWsdlLocation(), DEFAULTUSERIMPLSERVICE_QNAME, features);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultUserImplService(URL wsdlLocation) {
|
||||||
|
super(wsdlLocation, DEFAULTUSERIMPLSERVICE_QNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultUserImplService(URL wsdlLocation, WebServiceFeature... features) {
|
||||||
|
super(wsdlLocation, DEFAULTUSERIMPLSERVICE_QNAME, features);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultUserImplService(URL wsdlLocation, QName serviceName) {
|
||||||
|
super(wsdlLocation, serviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultUserImplService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
|
||||||
|
super(wsdlLocation, serviceName, features);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* returns UserService
|
||||||
|
*/
|
||||||
|
@WebEndpoint(name = "DefaultUserImplPort")
|
||||||
|
public UserService getDefaultUserImplPort() {
|
||||||
|
return super.getPort(new QName("http://services.stackify.com/", "DefaultUserImplPort"), UserService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param features
|
||||||
|
* A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
|
||||||
|
* @return
|
||||||
|
* returns UserService
|
||||||
|
*/
|
||||||
|
@WebEndpoint(name = "DefaultUserImplPort")
|
||||||
|
public UserService getDefaultUserImplPort(WebServiceFeature... features) {
|
||||||
|
return super.getPort(new QName("http://services.stackify.com/", "DefaultUserImplPort"), UserService.class, features);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static URL __getWsdlLocation() {
|
||||||
|
if (DEFAULTUSERIMPLSERVICE_EXCEPTION!= null) {
|
||||||
|
throw DEFAULTUSERIMPLSERVICE_EXCEPTION;
|
||||||
|
}
|
||||||
|
return DEFAULTUSERIMPLSERVICE_WSDL_LOCATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
package com.stackify.services;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlRegistry;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This object contains factory methods for each
|
||||||
|
* Java content interface and Java element interface
|
||||||
|
* generated in the com.stackify.services package.
|
||||||
|
* <p>An ObjectFactory allows you to programatically
|
||||||
|
* construct new instances of the Java representation
|
||||||
|
* for XML content. The Java representation of XML
|
||||||
|
* content can consist of schema derived interfaces
|
||||||
|
* and classes representing the binding of schema
|
||||||
|
* type definitions, element declarations and model
|
||||||
|
* groups. Factory methods for each of these are
|
||||||
|
* provided in this class.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@XmlRegistry
|
||||||
|
public class ObjectFactory {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.stackify.services
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public ObjectFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of {@link User }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public User createUser() {
|
||||||
|
return new User();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of {@link Users }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public Users createUsers() {
|
||||||
|
return new Users();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
package com.stackify.services;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlType;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Java class for user complex type.
|
||||||
|
*
|
||||||
|
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* <complexType name="user">
|
||||||
|
* <complexContent>
|
||||||
|
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||||
|
* <sequence>
|
||||||
|
* <element name="email" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
|
||||||
|
* <element name="name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
|
||||||
|
* </sequence>
|
||||||
|
* </restriction>
|
||||||
|
* </complexContent>
|
||||||
|
* </complexType>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
@XmlType(name = "user", propOrder = {
|
||||||
|
"email",
|
||||||
|
"name"
|
||||||
|
})
|
||||||
|
public class User {
|
||||||
|
|
||||||
|
protected String email;
|
||||||
|
protected String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the email property.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* possible object is
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of the email property.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* allowed object is
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setEmail(String value) {
|
||||||
|
this.email = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the name property.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* possible object is
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of the name property.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* allowed object is
|
||||||
|
* {@link String }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setName(String value) {
|
||||||
|
this.name = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
package com.stackify.services;
|
||||||
|
|
||||||
|
import javax.jws.WebMethod;
|
||||||
|
import javax.jws.WebParam;
|
||||||
|
import javax.jws.WebResult;
|
||||||
|
import javax.jws.WebService;
|
||||||
|
import javax.jws.soap.SOAPBinding;
|
||||||
|
import javax.xml.bind.annotation.XmlSeeAlso;
|
||||||
|
import javax.xml.ws.Action;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class was generated by the JAX-WS RI.
|
||||||
|
* JAX-WS RI 2.2.9-b130926.1035
|
||||||
|
* Generated source version: 2.2
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@WebService(name = "UserService", targetNamespace = "http://services.stackify.com/")
|
||||||
|
@SOAPBinding(style = SOAPBinding.Style.RPC)
|
||||||
|
@XmlSeeAlso({
|
||||||
|
ObjectFactory.class
|
||||||
|
})
|
||||||
|
public interface UserService {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param arg0
|
||||||
|
*/
|
||||||
|
@WebMethod
|
||||||
|
@Action(input = "http://services.stackify.com/UserService/addUserRequest", output = "http://services.stackify.com/UserService/addUserResponse")
|
||||||
|
public void addUser(
|
||||||
|
@WebParam(name = "arg0", partName = "arg0")
|
||||||
|
User arg0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* returns com.stackify.services.Users
|
||||||
|
*/
|
||||||
|
@WebMethod
|
||||||
|
@WebResult(partName = "return")
|
||||||
|
@Action(input = "http://services.stackify.com/UserService/getUsersRequest", output = "http://services.stackify.com/UserService/getUsersResponse")
|
||||||
|
public Users getUsers();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
package com.stackify.services;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlElement;
|
||||||
|
import javax.xml.bind.annotation.XmlType;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Java class for users complex type.
|
||||||
|
*
|
||||||
|
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* <complexType name="users">
|
||||||
|
* <complexContent>
|
||||||
|
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||||
|
* <sequence>
|
||||||
|
* <element name="users" type="{http://services.stackify.com/}user" maxOccurs="unbounded" minOccurs="0"/>
|
||||||
|
* </sequence>
|
||||||
|
* </restriction>
|
||||||
|
* </complexContent>
|
||||||
|
* </complexType>
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
@XmlType(name = "users", propOrder = {
|
||||||
|
"users"
|
||||||
|
})
|
||||||
|
public class Users {
|
||||||
|
|
||||||
|
@XmlElement(nillable = true)
|
||||||
|
protected List<User> users;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the users property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This accessor method returns a reference to the live list,
|
||||||
|
* not a snapshot. Therefore any modification you make to the
|
||||||
|
* returned list will be present inside the JAXB object.
|
||||||
|
* This is why there is not a <CODE>set</CODE> method for the users property.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* For example, to add a new item, do as follows:
|
||||||
|
* <pre>
|
||||||
|
* getUsers().add(newItem);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Objects of the following type(s) are allowed in the list
|
||||||
|
* {@link User }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public List<User> getUsers() {
|
||||||
|
if (users == null) {
|
||||||
|
users = new ArrayList<User>();
|
||||||
|
}
|
||||||
|
return this.users;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
@javax.xml.bind.annotation.XmlSchema(namespace = "http://services.stackify.com/")
|
||||||
|
package com.stackify.services;
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.stackify;
|
||||||
|
|
||||||
|
import javax.xml.ws.Endpoint;
|
||||||
|
|
||||||
|
import com.stackify.services.DefaultUserImpl;
|
||||||
|
|
||||||
|
public class ServicePublisher {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Endpoint.publish("http://localhost:8080/users", new DefaultUserImpl());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.stackify.models;
|
||||||
|
|
||||||
|
public class User {
|
||||||
|
private String email;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(String email, String name) {
|
||||||
|
super();
|
||||||
|
this.email = email;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.stackify.models;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Users {
|
||||||
|
List<User> users;
|
||||||
|
|
||||||
|
public List<User> getUsers() {
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsers(List<User> users) {
|
||||||
|
this.users = users;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.stackify.services;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import javax.jws.WebService;
|
||||||
|
|
||||||
|
import com.stackify.models.User;
|
||||||
|
import com.stackify.models.Users;
|
||||||
|
|
||||||
|
@WebService(endpointInterface = "com.stackify.services.UserService")
|
||||||
|
public class DefaultUserImpl implements UserService {
|
||||||
|
|
||||||
|
ArrayList<User> usersList = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addUser(User user) {
|
||||||
|
usersList.add(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Users getUsers() {
|
||||||
|
Users users = new Users();
|
||||||
|
users.setUsers(usersList);
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.stackify.services;
|
||||||
|
|
||||||
|
import javax.jws.WebMethod;
|
||||||
|
import javax.jws.WebService;
|
||||||
|
import javax.jws.soap.SOAPBinding;
|
||||||
|
|
||||||
|
import com.stackify.models.User;
|
||||||
|
import com.stackify.models.Users;
|
||||||
|
|
||||||
|
@WebService
|
||||||
|
@SOAPBinding(style = SOAPBinding.Style.RPC)
|
||||||
|
public interface UserService {
|
||||||
|
|
||||||
|
@WebMethod
|
||||||
|
public void addUser(User user);
|
||||||
|
|
||||||
|
@WebMethod
|
||||||
|
public Users getUsers();
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Class-Path:
|
||||||
|
|
48
guest/webservices/spring-rest-service/pom.xml
Normal file
48
guest/webservices/spring-rest-service/pom.xml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<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.stackify</groupId>
|
||||||
|
<artifactId>spring-rest-service</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>1.5.4.RELEASE</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-hateoas</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.springfox</groupId>
|
||||||
|
<artifactId>springfox-swagger2</artifactId>
|
||||||
|
<version>2.7.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.springfox</groupId>
|
||||||
|
<artifactId>springfox-swagger-ui</artifactId>
|
||||||
|
<version>2.7.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.stackify;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.stackify.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import springfox.documentation.builders.PathSelectors;
|
||||||
|
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||||
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableSwagger2
|
||||||
|
public class SwaggerConfig {
|
||||||
|
@Bean
|
||||||
|
public Docket api() {
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2).select()
|
||||||
|
.apis(RequestHandlerSelectors.basePackage("com.stackify.controllers"))
|
||||||
|
.paths(PathSelectors.any())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package com.stackify.controllers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.hateoas.Link;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.stackify.models.User;
|
||||||
|
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
|
||||||
|
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
private static List<User> users = new ArrayList<>();
|
||||||
|
|
||||||
|
@PostMapping(value = "/users", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
@ResponseStatus(HttpStatus.CREATED)
|
||||||
|
public void addUser(@RequestBody User user) {
|
||||||
|
users.add(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/users")
|
||||||
|
public List<User> getUsers() {
|
||||||
|
users.forEach(user -> {
|
||||||
|
Link selfLink = linkTo(methodOn(UserController.class).getUsers()).slash(user.getEmail())
|
||||||
|
.withSelfRel();
|
||||||
|
user.getLinks().clear();
|
||||||
|
user.add(selfLink);
|
||||||
|
});
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/users/{email}")
|
||||||
|
public User getUser(@PathVariable String email) {
|
||||||
|
User us = users.stream()
|
||||||
|
.filter(user -> !user.getEmail()
|
||||||
|
.equals(email))
|
||||||
|
.findAny()
|
||||||
|
.orElse(null);
|
||||||
|
return us;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.stackify.models;
|
||||||
|
|
||||||
|
import org.springframework.hateoas.ResourceSupport;
|
||||||
|
|
||||||
|
public class User extends ResourceSupport {
|
||||||
|
private String email;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(String email, String name) {
|
||||||
|
super();
|
||||||
|
this.email = email;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
52
jmh/pom.xml
Normal file
52
jmh/pom.xml
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>jmh</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<name>jmh</name>
|
||||||
|
<url>http://maven.apache.org</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjdk.jmh</groupId>
|
||||||
|
<artifactId>jmh-core</artifactId>
|
||||||
|
<version>1.19</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjdk.jmh</groupId>
|
||||||
|
<artifactId>jmh-generator-annprocess</artifactId>
|
||||||
|
<version>1.19</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>com.baeldung.Application</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
14
jmh/src/main/java/com/baeldung/Application.java
Normal file
14
jmh/src/main/java/com/baeldung/Application.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.baeldung;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.openjdk.jmh.Main;
|
||||||
|
import org.openjdk.jmh.runner.RunnerException;
|
||||||
|
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws RunnerException, IOException {
|
||||||
|
Main.main(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
jmh/src/main/java/com/baeldung/BenchMark.java
Normal file
12
jmh/src/main/java/com/baeldung/BenchMark.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package com.baeldung;
|
||||||
|
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
|
|
||||||
|
public class BenchMark {
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public void init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
0
jmh/src/main/resources/META-INF/BenchmarkList
Normal file
0
jmh/src/main/resources/META-INF/BenchmarkList
Normal file
38
jmh/src/test/java/com/baeldung/AppTest.java
Normal file
38
jmh/src/test/java/com/baeldung/AppTest.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package com.baeldung;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for simple App.
|
||||||
|
*/
|
||||||
|
public class AppTest
|
||||||
|
extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the test case
|
||||||
|
*
|
||||||
|
* @param testName name of the test case
|
||||||
|
*/
|
||||||
|
public AppTest( String testName )
|
||||||
|
{
|
||||||
|
super( testName );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the suite of tests being tested
|
||||||
|
*/
|
||||||
|
public static Test suite()
|
||||||
|
{
|
||||||
|
return new TestSuite( AppTest.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rigourous Test :-)
|
||||||
|
*/
|
||||||
|
public void testApp()
|
||||||
|
{
|
||||||
|
assertTrue( true );
|
||||||
|
}
|
||||||
|
}
|
8
kotlin-mockito/README.md
Normal file
8
kotlin-mockito/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
## Relevant articles:
|
||||||
|
|
||||||
|
- [Introduction to the Kotlin Language](http://www.baeldung.com/kotlin)
|
||||||
|
- [A guide to the “when{}” block in Kotlin](http://www.baeldung.com/kotlin-when)
|
||||||
|
- [Comprehensive Guide to Null Safety in Kotlin](http://www.baeldung.com/kotlin-null-safety)
|
||||||
|
- [Kotlin Java Interoperability](http://www.baeldung.com/kotlin-java-interoperability)
|
||||||
|
- [Difference Between “==” and “===” in Kotlin](http://www.baeldung.com/kotlin-equality-operators)
|
||||||
|
- [Generics in Kotlin](http://www.baeldung.com/kotlin-generics)
|
121
kotlin-mockito/pom.xml
Normal file
121
kotlin-mockito/pom.xml
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<?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>kotlin-mockito</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<artifactId>kotlin-stdlib</artifactId>
|
||||||
|
<version>${kotlin.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<version>${mockito.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>${junit.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.nhaarman</groupId>
|
||||||
|
<artifactId>mockito-kotlin</artifactId>
|
||||||
|
<version>${mockito-kotlin.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
|
||||||
|
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>kotlin-maven-plugin</artifactId>
|
||||||
|
<groupId>org.jetbrains.kotlin</groupId>
|
||||||
|
<version>${kotlin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>compile</id>
|
||||||
|
<goals>
|
||||||
|
<goal>compile</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<sourceDirs>
|
||||||
|
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
|
||||||
|
<sourceDir>${project.basedir}/src/main/java</sourceDir>
|
||||||
|
</sourceDirs>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>test-compile</id>
|
||||||
|
<goals>
|
||||||
|
<goal>test-compile</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<sourceDirs>
|
||||||
|
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
|
||||||
|
<sourceDir>${project.basedir}/src/test/java</sourceDir>
|
||||||
|
</sourceDirs>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>${maven-compiler.version}</version>
|
||||||
|
<executions>
|
||||||
|
<!-- Replacing default-compile as it is treated specially
|
||||||
|
by maven -->
|
||||||
|
<execution>
|
||||||
|
<id>default-compile</id>
|
||||||
|
<phase>none</phase>
|
||||||
|
</execution>
|
||||||
|
<!-- Replacing default-testCompile as it is treated specially
|
||||||
|
by maven -->
|
||||||
|
<execution>
|
||||||
|
<id>default-testCompile</id>
|
||||||
|
<phase>none</phase>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>java-compile</id>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>compile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>java-test-compile</id>
|
||||||
|
<phase>test-compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>testCompile</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<mockito.version>2.8.9</mockito.version>
|
||||||
|
<junit.version>4.12</junit.version>
|
||||||
|
<kotlin.version>1.1.2-4</kotlin.version>
|
||||||
|
<mockito-kotlin.version>1.5.0</mockito-kotlin.version>
|
||||||
|
<maven-compiler.version>3.5.1</maven-compiler.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.baeldung.java;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ArrayExample {
|
||||||
|
|
||||||
|
public int sumValues(int[] nums) {
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
for (int x:nums) {
|
||||||
|
res += x;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeList() throws IOException {
|
||||||
|
File file = new File("E://file.txt");
|
||||||
|
FileReader fr = new FileReader(file);
|
||||||
|
fr.close();
|
||||||
|
}
|
||||||
|
}
|
24
kotlin-mockito/src/main/java/com/baeldung/java/Customer.java
Normal file
24
kotlin-mockito/src/main/java/com/baeldung/java/Customer.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package com.baeldung.java;
|
||||||
|
|
||||||
|
public class Customer {
|
||||||
|
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.baeldung.java;
|
||||||
|
|
||||||
|
public class StringUtils {
|
||||||
|
public static String toUpperCase(String name) {
|
||||||
|
return name.toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.baeldung.kotlin
|
||||||
|
|
||||||
|
interface BookService {
|
||||||
|
fun inStock(bookId: Int): Boolean
|
||||||
|
fun lend(bookId: Int, memberId: Int)
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.baeldung.kotlin
|
||||||
|
|
||||||
|
class LendBookManager(val bookService:BookService) {
|
||||||
|
fun checkout(bookId: Int, memberId: Int) {
|
||||||
|
if(bookService.inStock(bookId)) {
|
||||||
|
bookService.lend(bookId, memberId)
|
||||||
|
} else {
|
||||||
|
throw IllegalStateException("Book is not available")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.baeldung.kotlin;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class JavaCallToKotlinUnitTest {
|
||||||
|
@Test
|
||||||
|
public void givenKotlinClass_whenCallFromJava_shouldProduceResults() {
|
||||||
|
//when
|
||||||
|
int res = new MathematicsOperations().addTwoNumbers(2, 4);
|
||||||
|
|
||||||
|
//then
|
||||||
|
assertEquals(6, res);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.baeldung.kotlin;
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mockito.Mockito
|
||||||
|
|
||||||
|
class LibraryManagementTest {
|
||||||
|
@Test(expected = IllegalStateException::class)
|
||||||
|
fun whenBookIsNotAvailable_thenAnExceptionIsThrown() {
|
||||||
|
val mockBookService = Mockito.mock(BookService::class.java)
|
||||||
|
|
||||||
|
Mockito.`when`(mockBookService.inStock(100)).thenReturn(false)
|
||||||
|
|
||||||
|
val manager = LendBookManager(mockBookService)
|
||||||
|
|
||||||
|
manager.checkout(100, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenBookIsAvailable_thenLendMethodIsCalled() {
|
||||||
|
val mockBookService = Mockito.mock(BookService::class.java)
|
||||||
|
|
||||||
|
Mockito.`when`(mockBookService.inStock(100)).thenReturn(true)
|
||||||
|
|
||||||
|
val manager = LendBookManager(mockBookService)
|
||||||
|
|
||||||
|
manager.checkout(100, 1)
|
||||||
|
|
||||||
|
Mockito.verify(mockBookService).lend(100, 1)
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user