This commit is contained in:
Jonathan Cook 2020-03-01 08:34:45 +01:00
commit 08506092e8
489 changed files with 5750 additions and 10643 deletions

View File

@ -0,0 +1,57 @@
package com.baeldung.algorithms.suffixtree;
import java.util.ArrayList;
import java.util.List;
public class Node {
private String text;
private List<Node> children;
private int position;
public Node(String word, int position) {
this.text = word;
this.position = position;
this.children = new ArrayList<>();
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public List<Node> getChildren() {
return children;
}
public void setChildren(List<Node> children) {
this.children = children;
}
public String printTree(String depthIndicator) {
String str = "";
String positionStr = position > -1 ? "[" + String.valueOf(position) + "]" : "";
str += depthIndicator + text + positionStr + "\n";
for (int i = 0; i < children.size(); i++) {
str += children.get(i)
.printTree(depthIndicator + "\t");
}
return str;
}
@Override
public String toString() {
return printTree("");
}
}

View File

@ -0,0 +1,175 @@
package com.baeldung.algorithms.suffixtree;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SuffixTree {
private static final Logger LOGGER = LoggerFactory.getLogger(SuffixTree.class);
private static final String WORD_TERMINATION = "$";
private static final int POSITION_UNDEFINED = -1;
private Node root;
private String fullText;
public SuffixTree(String text) {
root = new Node("", POSITION_UNDEFINED);
for (int i = 0; i < text.length(); i++) {
addSuffix(text.substring(i) + WORD_TERMINATION, i);
}
fullText = text;
}
public List<String> searchText(String pattern) {
LOGGER.info("Searching for pattern \"{}\"", pattern);
List<String> result = new ArrayList<>();
List<Node> nodes = getAllNodesInTraversePath(pattern, root, false);
if (nodes.size() > 0) {
Node lastNode = nodes.get(nodes.size() - 1);
if (lastNode != null) {
List<Integer> positions = getPositions(lastNode);
positions = positions.stream()
.sorted()
.collect(Collectors.toList());
positions.forEach(m -> result.add((markPatternInText(m, pattern))));
}
}
return result;
}
private void addSuffix(String suffix, int position) {
LOGGER.info(">>>>>>>>>>>> Adding new suffix {}", suffix);
List<Node> nodes = getAllNodesInTraversePath(suffix, root, true);
if (nodes.size() == 0) {
addChildNode(root, suffix, position);
LOGGER.info("{}", printTree());
} else {
Node lastNode = nodes.remove(nodes.size() - 1);
String newText = suffix;
if (nodes.size() > 0) {
String existingSuffixUptoLastNode = nodes.stream()
.map(a -> a.getText())
.reduce("", String::concat);
// Remove prefix from newText already included in parent
newText = newText.substring(existingSuffixUptoLastNode.length());
}
extendNode(lastNode, newText, position);
LOGGER.info("{}", printTree());
}
}
private List<Integer> getPositions(Node node) {
List<Integer> positions = new ArrayList<>();
if (node.getText()
.endsWith(WORD_TERMINATION)) {
positions.add(node.getPosition());
}
for (int i = 0; i < node.getChildren()
.size(); i++) {
positions.addAll(getPositions(node.getChildren()
.get(i)));
}
return positions;
}
private String markPatternInText(Integer startPosition, String pattern) {
String matchingTextLHS = fullText.substring(0, startPosition);
String matchingText = fullText.substring(startPosition, startPosition + pattern.length());
String matchingTextRHS = fullText.substring(startPosition + pattern.length());
return matchingTextLHS + "[" + matchingText + "]" + matchingTextRHS;
}
private void addChildNode(Node parentNode, String text, int position) {
parentNode.getChildren()
.add(new Node(text, position));
}
private void extendNode(Node node, String newText, int position) {
String currentText = node.getText();
String commonPrefix = getLongestCommonPrefix(currentText, newText);
if (commonPrefix != currentText) {
String parentText = currentText.substring(0, commonPrefix.length());
String childText = currentText.substring(commonPrefix.length());
splitNodeToParentAndChild(node, parentText, childText);
}
String remainingText = newText.substring(commonPrefix.length());
addChildNode(node, remainingText, position);
}
private void splitNodeToParentAndChild(Node parentNode, String parentNewText, String childNewText) {
Node childNode = new Node(childNewText, parentNode.getPosition());
if (parentNode.getChildren()
.size() > 0) {
while (parentNode.getChildren()
.size() > 0) {
childNode.getChildren()
.add(parentNode.getChildren()
.remove(0));
}
}
parentNode.getChildren()
.add(childNode);
parentNode.setText(parentNewText);
parentNode.setPosition(POSITION_UNDEFINED);
}
private String getLongestCommonPrefix(String str1, String str2) {
int compareLength = Math.min(str1.length(), str2.length());
for (int i = 0; i < compareLength; i++) {
if (str1.charAt(i) != str2.charAt(i)) {
return str1.substring(0, i);
}
}
return str1.substring(0, compareLength);
}
private List<Node> getAllNodesInTraversePath(String pattern, Node startNode, boolean isAllowPartialMatch) {
List<Node> nodes = new ArrayList<>();
for (int i = 0; i < startNode.getChildren()
.size(); i++) {
Node currentNode = startNode.getChildren()
.get(i);
String nodeText = currentNode.getText();
if (pattern.charAt(0) == nodeText.charAt(0)) {
if (isAllowPartialMatch && pattern.length() <= nodeText.length()) {
nodes.add(currentNode);
return nodes;
}
int compareLength = Math.min(nodeText.length(), pattern.length());
for (int j = 1; j < compareLength; j++) {
if (pattern.charAt(j) != nodeText.charAt(j)) {
if (isAllowPartialMatch) {
nodes.add(currentNode);
}
return nodes;
}
}
nodes.add(currentNode);
if (pattern.length() > compareLength) {
List<Node> nodes2 = getAllNodesInTraversePath(pattern.substring(compareLength), currentNode, isAllowPartialMatch);
if (nodes2.size() > 0) {
nodes.addAll(nodes2);
} else if (!isAllowPartialMatch) {
nodes.add(null);
}
}
return nodes;
}
}
return nodes;
}
public String printTree() {
return root.printTree("");
}
}

View File

@ -0,0 +1,77 @@
package com.baeldung.algorithms.suffixtree;
import java.util.List;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SuffixTreeUnitTest {
private static final Logger LOGGER = LoggerFactory.getLogger(SuffixTreeUnitTest.class);
private static SuffixTree suffixTree;
@BeforeClass
public static void setUp() {
suffixTree = new SuffixTree("havanabanana");
printTree();
}
@Test
public void givenSuffixTree_whenSearchingForA_thenReturn6Matches() {
List<String> matches = suffixTree.searchText("a");
matches.stream()
.forEach(m -> LOGGER.info(m));
Assert.assertArrayEquals(new String[] { "h[a]vanabanana", "hav[a]nabanana", "havan[a]banana", "havanab[a]nana", "havanaban[a]na", "havanabanan[a]" }, matches.toArray());
}
@Test
public void givenSuffixTree_whenSearchingForNab_thenReturn1Match() {
List<String> matches = suffixTree.searchText("nab");
matches.stream()
.forEach(m -> LOGGER.info(m));
Assert.assertArrayEquals(new String[] { "hava[nab]anana" }, matches.toArray());
}
@Test
public void givenSuffixTree_whenSearchingForNag_thenReturnNoMatches() {
List<String> matches = suffixTree.searchText("nag");
matches.stream()
.forEach(m -> LOGGER.info(m));
Assert.assertArrayEquals(new String[] {}, matches.toArray());
}
@Test
public void givenSuffixTree_whenSearchingForBanana_thenReturn2Matches() {
List<String> matches = suffixTree.searchText("ana");
matches.stream()
.forEach(m -> LOGGER.info(m));
Assert.assertArrayEquals(new String[] { "hav[ana]banana", "havanab[ana]na", "havanaban[ana]" }, matches.toArray());
}
@Test
public void givenSuffixTree_whenSearchingForNa_thenReturn4Matches() {
List<String> matches = suffixTree.searchText("na");
matches.stream()
.forEach(m -> LOGGER.info(m));
Assert.assertArrayEquals(new String[] { "hava[na]banana", "havanaba[na]na", "havanabana[na]" }, matches.toArray());
}
@Test
public void givenSuffixTree_whenSearchingForX_thenReturnNoMatches() {
List<String> matches = suffixTree.searchText("x");
matches.stream()
.forEach(m -> LOGGER.info(m));
Assert.assertArrayEquals(new String[] {}, matches.toArray());
}
private static void printTree() {
suffixTree.printTree();
LOGGER.info("\n" + suffixTree.printTree());
LOGGER.info("==============================================");
}
}

View File

@ -11,5 +11,5 @@ This module contains articles about core Java input and output (IO)
- [List Files in a Directory in Java](https://www.baeldung.com/java-list-directory-files)
- [Java Append Data to a File](https://www.baeldung.com/java-append-to-file)
- [How to Copy a File with Java](https://www.baeldung.com/java-copy-file)
- [Create a Directory in Java](https://www.baeldung.com/java-create-directory)
- [Create a Directory in Java](https://www.baeldung.com/java-create-directory)
- [[<-- Prev]](/core-java-modules/core-java-io)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,148 @@
package com.baeldung.lock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.NonReadableChannelException;
import java.nio.channels.NonWritableChannelException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class FileLocks {
private static final Logger LOG = LoggerFactory.getLogger(FileLocks.class);
// Write locks
/**
* Trying to get an exclusive lock on a read-only FileChannel won't work.
*/
static void getExclusiveLockFromInputStream() throws IOException {
Path path = Files.createTempFile("foo", "txt");
try (FileInputStream fis = new FileInputStream(path.toFile());
FileLock lock = fis.getChannel()
.lock()) {
LOG.debug("This won't happen");
} catch (NonWritableChannelException e) {
LOG.error("The channel obtained through a FileInputStream isn't writable. You can't obtain an exclusive lock on it!");
throw e;
}
}
/**
* Gets an exclusive lock from a RandomAccessFile. Works because the file is writable.
* @param from beginning of the locked region
* @param size how many bytes to lock
* @return A lock object representing the newly-acquired lock
* @throws IOException if there is a problem creating the temporary file
*/
static FileLock getExclusiveLockFromRandomAccessFile(long from, long size) throws IOException {
Path path = Files.createTempFile("foo", "txt");
try (RandomAccessFile file = new RandomAccessFile(path.toFile(), "rw");
FileLock lock = file.getChannel()
.lock(from, size, false)) {
if (lock.isValid()) {
LOG.debug("This is a valid exclusive lock");
return lock;
}
return null;
} catch (Exception e) {
LOG.error(e.getMessage());
}
return null;
}
/**
* Acquires an exclusive lock on a file region.
* @param from beginning of the locked region
* @param size how many bytes to lock
* @return A lock object representing the newly-acquired lock
* @throws IOException if there is a problem creating the temporary file
*/
static FileLock getExclusiveLockFromFileChannelOpen(long from, long size) throws IOException {
Path path = Files.createTempFile("foo", "txt");
try (FileChannel channel = FileChannel.open(path, StandardOpenOption.APPEND); FileLock lock = channel.lock(from, size, false)) {
String text = "Hello, world.";
ByteBuffer buffer = ByteBuffer.allocate(text.length() + System.lineSeparator()
.length());
buffer.put((text + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
buffer.flip();
while (buffer.hasRemaining()) {
channel.write(buffer, channel.size());
}
LOG.debug("This was written to the file");
Files.lines(path)
.forEach(LOG::debug);
return lock;
}
}
// Read locks
/**
* Trying to get a shared lock on a write-only FileChannel won't work.
*/
static void getReadLockFromOutputStream() throws IOException {
Path path = Files.createTempFile("foo", "txt");
try (FileOutputStream fis = new FileOutputStream(path.toFile());
FileLock lock = fis.getChannel()
.lock(0, Long.MAX_VALUE, true)) {
LOG.debug("This won't happen");
} catch (NonReadableChannelException e) {
LOG.error("The channel obtained through a FileOutputStream isn't readable. " + "You can't obtain an shared lock on it!");
throw e;
}
}
/**
* Gets a lock from an <tt>InputStream</tt>.
* @param from beginning of the locked region
* @param size how many bytes to lock
* @return A lock object representing the newly-acquired lock
* @throws IOException if there is a problem creating the temporary file
*/
static FileLock getReadLockFromInputStream(long from, long size) throws IOException {
Path path = Files.createTempFile("foo", "txt");
try (FileInputStream fis = new FileInputStream(path.toFile());
FileLock lock = fis.getChannel()
.lock(from, size, true)) {
if (lock.isValid()) {
LOG.debug("This is a valid shared lock");
return lock;
}
return null;
}
}
/**
* Gets an exclusive lock from a RandomAccessFile. Works because the file is readable.
* @param from beginning of the locked region
* @param size how many bytes to lock
* @return A lock object representing the newly-acquired lock
* @throws IOException if there is a problem creating the temporary file
*/
static FileLock getReadLockFromRandomAccessFile(long from, long size) throws IOException {
Path path = Files.createTempFile("foo", "txt");
try (RandomAccessFile file = new RandomAccessFile(path.toFile(), "r"); // could also be "rw", but "r" is sufficient for reading
FileLock lock = file.getChannel()
.lock(from, size, true)) {
if (lock.isValid()) {
LOG.debug("This is a valid shared lock");
return lock;
}
} catch (Exception e) {
LOG.error(e.getMessage());
}
return null;
}
}

View File

@ -0,0 +1,54 @@
package com.baeldung.lock;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.nio.channels.FileLock;
import java.nio.channels.NonReadableChannelException;
import java.nio.channels.NonWritableChannelException;
import org.junit.jupiter.api.Test;
class FileLocksUnitTest {
@Test
void givenAnInputStream_whenGetWriteLock_thenThrowNonWritableChannelException() {
assertThrows(NonWritableChannelException.class, () -> FileLocks.getExclusiveLockFromInputStream());
}
@Test
void givenARandomAccessFileWithReadWriteAccess_whenGetWriteLock_thenLock() throws IOException {
FileLock lock = FileLocks.getExclusiveLockFromRandomAccessFile(0, 10);
assertNotNull(lock);
assertFalse(lock.isShared());
}
@Test
void givenAPath_whenGetExclusiveLock_thenLock() throws IOException {
FileLock lock = FileLocks.getExclusiveLockFromFileChannelOpen(0, 10);
assertNotNull(lock);
assertFalse(lock.isShared());
}
@Test
void givenAFileOutputStream_whenGetSharedLock_thenThrowNonReadableChannelException() {
assertThrows(NonReadableChannelException.class, FileLocks::getReadLockFromOutputStream);
}
@Test
void givenAnInputStream_whenGetSharedLock_thenLock() throws IOException {
FileLock lock = FileLocks.getReadLockFromInputStream(0, 10);
assertNotNull(lock);
assertTrue(lock.isShared());
}
@Test
void givenARandomAccessFile_whenGetSharedLock_thenLock() throws IOException {
FileLock lock = FileLocks.getReadLockFromRandomAccessFile(0, 10);
assertNotNull(lock);
assertTrue(lock.isShared());
}
}

View File

@ -11,7 +11,7 @@
- [Introduction to Java Serialization](http://www.baeldung.com/java-serialization)
- [Guide to UUID in Java](http://www.baeldung.com/java-uuid)
- [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin)
- [Quick Guide to Java Stack](http://www.baeldung.com/java-stack)
- [Quick Guide to the Java Stack](http://www.baeldung.com/java-stack)
- [Compiling Java *.class Files with javac](http://www.baeldung.com/javac)
- [Introduction to Javadoc](http://www.baeldung.com/javadoc)
- [Guide to the Externalizable Interface in Java](http://www.baeldung.com/java-externalizable)

View File

@ -1,4 +1,4 @@
package com.baeldung;
package com.baeldung.timer;
import org.junit.Test;
import org.slf4j.Logger;

View File

@ -5,4 +5,5 @@ This module contains articles about Kotlin core features.
### Relevant articles:
- [Working with Dates in Kotlin](https://www.baeldung.com/kotlin-dates)
- [Kotlin Ternary Conditional Operator](https://www.baeldung.com/kotlin-ternary-operator)
- [Sequences in Kotlin](https://www.baeldung.com/kotlin/sequences)
- [[<-- Prev]](/core-kotlin-modules/core-kotlin)

View File

@ -13,4 +13,7 @@ This module contains articles about Kotlin core features.
- [Implementing a Binary Tree in Kotlin](https://www.baeldung.com/kotlin-binary-tree)
- [JUnit 5 for Kotlin Developers](https://www.baeldung.com/junit-5-kotlin)
- [Converting Kotlin Data Class from JSON using GSON](https://www.baeldung.com/kotlin-json-convert-data-class)
- [Fuel HTTP Library with Kotlin](https://www.baeldung.com/kotlin-fuel)
- [Introduction to Kovenant Library for Kotlin](https://www.baeldung.com/kotlin-kovenant)
- [Dependency Injection for Kotlin with Injekt](https://www.baeldung.com/kotlin-dependency-injection-with-injekt)
- [[More --> ]](/core-kotlin-modules/core-kotlin-2)

View File

@ -5,3 +5,4 @@ This module contains articles about Scala's core features
### Relevant Articles:
- [Introduction to Scala](https://www.baeldung.com/scala-intro)
- [Regular Expressions in Scala](https://www.baeldung.com/scala/regular-expressions)

View File

@ -0,0 +1,82 @@
package com.baeldung.scala
import org.junit.Assert.assertEquals
import org.junit.Test
class HigherOrderFunctionsExamplesUnitTest {
@Test
def whenCallingMapWithAnonymousFunction_thenTransformationIsApplied() = {
val expected = Seq("sir Alex Ferguson", "sir Bobby Charlton", "sir Frank Lampard")
val names = Seq("Alex Ferguson", "Bobby Charlton", "Frank Lampard")
val sirNames = names.map(name => "sir " + name)
assertEquals(expected, sirNames)
}
@Test
def whenCallingMapWithDefined_thenTransformationIsApplied() = {
val expected = Seq("sir Alex Ferguson", "sir Bobby Charlton", "sir Frank Lampard")
val names = Seq("Alex Ferguson", "Bobby Charlton", "Frank Lampard")
def prefixWithSir(name: String) = "sir " + name
val sirNames = names.map(prefixWithSir)
assertEquals(expected, sirNames)
}
@Test
def whenCallingFilter_thenUnecessaryElementsAreRemoved() = {
val expected = Seq("John O'Shea", "John Hartson")
val names = Seq("John O'Shea", "Aiden McGeady", "John Hartson")
val johns = names.filter(name => name.matches("^John .*"))
assertEquals(expected, johns)
}
@Test
def whenCallingReduce_thenProperSumIsCalculated() = {
val expected = 2750
val earnings = Seq(1000, 1300, 450)
val sumEarnings = earnings.reduce((acc, x) => acc + x)
assertEquals(expected, sumEarnings)
}
@Test
def whenCallingFold_thenNumberOfWordsShouldBeCalculated() = {
val expected = 6
val strings = Seq("bunch of words", "just me", "it")
val sumEarnings = strings.foldLeft(0)((acc, x) => acc + x.split(" ").size)
assertEquals(expected, sumEarnings)
}
@Test
def whenCallingOwnHigherOrderFunction_thenProperFunctionIsReturned() = {
def mathOperation(name: String): (Int, Int) => Int = (x: Int, y: Int) => {
name match {
case "addition" => x + y
case "multiplication" => x * y
case "division" => x/y
case "subtraction" => x - y
}
}
def add: (Int, Int) => Int = mathOperation("addition")
def mul: (Int, Int) => Int = mathOperation("multiplication")
def div: (Int, Int) => Int = mathOperation("division")
def sub: (Int, Int) => Int = mathOperation("subtraction")
assertEquals(15, add(10, 5))
assertEquals(50, mul(10, 5))
assertEquals(2, div(10, 5))
assertEquals(5, sub(10, 5))
}
}

View File

@ -1,4 +1,4 @@
package com.baeldung.scala
package com.baeldung.scala.regex
import org.junit.Test
import org.junit.Assert.assertEquals

1
ddd-modules/README.md Normal file
View File

@ -0,0 +1 @@
## Relevant Articles

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.dddmodules.infrastructure</groupId>
<artifactId>infrastructure</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.dddmodules</groupId>
<artifactId>dddmodules</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>com.baeldung.dddmodules.shippingcontext</groupId>
<artifactId>shippingcontext</artifactId>
<version>${appmodules.version}</version>
</dependency>
<dependency>
<groupId>com.baeldung.dddmodules.ordercontext</groupId>
<artifactId>ordercontext</artifactId>
<version>${appmodules.version}</version>
</dependency>
<dependency>
<groupId>com.baeldung.dddmodules.sharedkernel</groupId>
<artifactId>sharedkernel</artifactId>
<version>${appmodules.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${source.version}</source>
<target>${target.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<source.version>9</source.version>
<target.version>9</target.version>
</properties>
</project>

View File

@ -0,0 +1,79 @@
package com.baeldung.dddmodules.infrastructure.db;
import com.baeldung.dddmodules.ordercontext.model.CustomerOrder;
import com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository;
import com.baeldung.dddmodules.shippingcontext.model.PackageItem;
import com.baeldung.dddmodules.shippingcontext.model.ShippableOrder;
import com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
public class InMemoryOrderStore implements CustomerOrderRepository, ShippingOrderRepository {
private Map<Integer, PersistenceOrder> ordersDb = new HashMap<>();
private volatile static InMemoryOrderStore instance = new InMemoryOrderStore();
@Override
public void saveCustomerOrder(CustomerOrder order) {
this.ordersDb.put(order.getOrderId(), new PersistenceOrder(order.getOrderId(),
order.getPaymentMethod(),
order.getAddress(),
order
.getOrderItems()
.stream()
.map(orderItem ->
new PersistenceOrder.OrderItem(orderItem.getProductId(),
orderItem.getQuantity(),
orderItem.getUnitWeight(),
orderItem.getUnitPrice()))
.collect(Collectors.toList())
));
}
@Override
public Optional<ShippableOrder> findShippableOrder(int orderId) {
if (!this.ordersDb.containsKey(orderId)) return Optional.empty();
PersistenceOrder orderRecord = this.ordersDb.get(orderId);
return Optional.of(
new ShippableOrder(orderRecord.orderId, orderRecord.orderItems
.stream().map(orderItem -> new PackageItem(orderItem.productId,
orderItem.itemWeight,
orderItem.quantity * orderItem.unitPrice)
).collect(Collectors.toList())));
}
public static InMemoryOrderStore provider() {
return instance;
}
public static class PersistenceOrder {
public int orderId;
public String paymentMethod;
public String address;
public List<OrderItem> orderItems;
public PersistenceOrder(int orderId, String paymentMethod, String address, List<OrderItem> orderItems) {
this.orderId = orderId;
this.paymentMethod = paymentMethod;
this.address = address;
this.orderItems = orderItems;
}
public static class OrderItem {
public int productId;
public float unitPrice;
public float itemWeight;
public int quantity;
public OrderItem(int productId, int quantity, float unitWeight, float unitPrice) {
this.itemWeight = unitWeight;
this.quantity = quantity;
this.unitPrice = unitPrice;
this.productId = productId;
}
}
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.dddmodules.infrastructure.events;
import com.baeldung.dddmodules.sharedkernel.events.ApplicationEvent;
import com.baeldung.dddmodules.sharedkernel.events.EventBus;
import com.baeldung.dddmodules.sharedkernel.events.EventSubscriber;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
public class SimpleEventBus implements EventBus {
private final Map<String, Set<EventSubscriber>> subscribers = new ConcurrentHashMap<>();
@Override
public <E extends ApplicationEvent> void publish(E event) {
if (subscribers.containsKey(event.getType())) {
subscribers.get(event.getType())
.forEach(subscriber -> subscriber.onEvent(event));
}
}
@Override
public <E extends ApplicationEvent> void subscribe(String eventType, EventSubscriber subscriber) {
Set<EventSubscriber> eventSubscribers = subscribers.get(eventType);
if (eventSubscribers == null) {
eventSubscribers = new CopyOnWriteArraySet<>();
subscribers.put(eventType, eventSubscribers);
}
eventSubscribers.add(subscriber);
}
@Override
public <E extends ApplicationEvent> void unsubscribe(String eventType, EventSubscriber subscriber) {
if (subscribers.containsKey(eventType)) {
subscribers.get(eventType).remove(subscriber);
}
}
}

View File

@ -0,0 +1,11 @@
module com.baeldung.dddmodules.infrastructure {
requires transitive com.baeldung.dddmodules.sharedkernel;
requires transitive com.baeldung.dddmodules.ordercontext;
requires transitive com.baeldung.dddmodules.shippingcontext;
provides com.baeldung.dddmodules.sharedkernel.events.EventBus
with com.baeldung.dddmodules.infrastructure.events.SimpleEventBus;
provides com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository
with com.baeldung.dddmodules.infrastructure.db.InMemoryOrderStore;
provides com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository
with com.baeldung.dddmodules.infrastructure.db.InMemoryOrderStore;
}

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.dddmodules.mainapp</groupId>
<artifactId>mainapp</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.dddmodules</groupId>
<artifactId>dddmodules</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>com.baeldung.dddmodules.infrastructure</groupId>
<artifactId>infrastructure</artifactId>
<version>${appmodules.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<enableAssertions>true</enableAssertions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler.plugin.version}</version>
<configuration>
<source>${source.version}</source>
<target>${target.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<source.version>9</source.version>
<target.version>9</target.version>
</properties>
</project>

View File

@ -0,0 +1,54 @@
package com.baeldung.dddmodules.mainapp;
import com.baeldung.dddmodules.ordercontext.model.CustomerOrder;
import com.baeldung.dddmodules.ordercontext.model.OrderItem;
import com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository;
import com.baeldung.dddmodules.ordercontext.service.OrderService;
import com.baeldung.dddmodules.sharedkernel.events.EventBus;
import com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository;
import com.baeldung.dddmodules.shippingcontext.service.ShippingService;
import java.util.*;
public class Application {
public static void main(String args[]) {
Map<Class<?>, Object> container = createContainer();
OrderService orderService = (OrderService) container.get(OrderService.class);
ShippingService shippingService = (ShippingService) container.get(ShippingService.class);
shippingService.listenToOrderEvents();
CustomerOrder customerOrder = new CustomerOrder();
int orderId = 1;
customerOrder.setOrderId(orderId);
List<OrderItem> orderItems = new ArrayList<OrderItem>();
orderItems.add(new OrderItem(1, 2, 3, 1));
orderItems.add(new OrderItem(2, 1, 1, 1));
orderItems.add(new OrderItem(3, 4, 11, 21));
customerOrder.setOrderItems(orderItems);
customerOrder.setPaymentMethod("PayPal");
customerOrder.setAddress("Full address here");
orderService.placeOrder(customerOrder);
if (orderId == shippingService.getParcelByOrderId(orderId).get().getOrderId()) {
System.out.println("Order has been processed and shipped successfully");
}
}
public static Map<Class<?>, Object> createContainer() {
EventBus eventBus = ServiceLoader.load(EventBus.class).findFirst().get();
CustomerOrderRepository customerOrderRepository = ServiceLoader.load(CustomerOrderRepository.class).findFirst().get();
ShippingOrderRepository shippingOrderRepository = ServiceLoader.load(ShippingOrderRepository.class).findFirst().get();
ShippingService shippingService = ServiceLoader.load(ShippingService.class).findFirst().get();
shippingService.setEventBus(eventBus);
shippingService.setOrderRepository(shippingOrderRepository);
OrderService orderService = ServiceLoader.load(OrderService.class).findFirst().get();
orderService.setEventBus(eventBus);
orderService.setOrderRepository(customerOrderRepository);
HashMap<Class<?>, Object> container = new HashMap<>();
container.put(OrderService.class, orderService);
container.put(ShippingService.class, shippingService);
return container;
}
}

View File

@ -0,0 +1,8 @@
module com.baeldung.dddmodules.mainapp {
uses com.baeldung.dddmodules.sharedkernel.events.EventBus;
uses com.baeldung.dddmodules.ordercontext.service.OrderService;
uses com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository;
uses com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository;
uses com.baeldung.dddmodules.shippingcontext.service.ShippingService;
requires transitive com.baeldung.dddmodules.infrastructure;
}

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.dddmodules.ordercontext</groupId>
<artifactId>ordercontext</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.dddmodules</groupId>
<artifactId>dddmodules</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>com.baeldung.dddmodules.sharedkernel</groupId>
<artifactId>sharedkernel</artifactId>
<version>${appmodules.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${source.version}</source>
<target>${target.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<source.version>9</source.version>
<target.version>9</target.version>
<entitymodule.version>1.0</entitymodule.version>
<daomodule.version>1.0</daomodule.version>
</properties>
</project>

View File

@ -0,0 +1,51 @@
package com.baeldung.dddmodules.ordercontext.model;
import java.util.List;
public class CustomerOrder {
private int orderId;
private String paymentMethod;
private String address;
private List<OrderItem> orderItems;
public CustomerOrder() {
}
public float calculateTotalPrice() {
return orderItems.stream().map(OrderItem::getTotalPrice)
.reduce(0F, Float::sum);
}
public void setOrderItems(List<OrderItem> orderItems) {
this.orderItems = orderItems;
}
public int getOrderId() {
return orderId;
}
public List<OrderItem> getOrderItems() {
return orderItems;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getPaymentMethod() {
return paymentMethod;
}
public void setPaymentMethod(String paymentMethod) {
this.paymentMethod = paymentMethod;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}

View File

@ -0,0 +1,51 @@
package com.baeldung.dddmodules.ordercontext.model;
public class OrderItem {
private int productId;
private int quantity;
private float unitPrice;
private float unitWeight;
public OrderItem(int productId, int quantity, float unitPrice, float unitWeight) {
this.productId = productId;
this.quantity = quantity;
this.unitPrice = unitPrice;
this.unitWeight = unitWeight;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public float getTotalPrice() {
return this.quantity * this.unitPrice;
}
public void setUnitPrice(float unitPrice) {
this.unitPrice = unitPrice;
}
public float getUnitWeight() {
return unitWeight;
}
public float getUnitPrice() {
return unitPrice;
}
public void setUnitWeight(float unitWeight) {
this.unitWeight = unitWeight;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.dddmodules.ordercontext.repository;
import com.baeldung.dddmodules.ordercontext.model.CustomerOrder;
public interface CustomerOrderRepository {
void saveCustomerOrder(CustomerOrder order);
}

View File

@ -0,0 +1,44 @@
package com.baeldung.dddmodules.ordercontext.service;
import com.baeldung.dddmodules.ordercontext.model.CustomerOrder;
import com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository;
import com.baeldung.dddmodules.sharedkernel.events.ApplicationEvent;
import com.baeldung.dddmodules.sharedkernel.events.EventBus;
import java.util.HashMap;
import java.util.Map;
public class CustomerOrderService implements OrderService {
public static final String EVENT_ORDER_READY_FOR_SHIPMENT = "OrderReadyForShipmentEvent";
private CustomerOrderRepository orderRepository;
private EventBus eventBus;
@Override
public void placeOrder(CustomerOrder order) {
this.orderRepository.saveCustomerOrder(order);
Map<String, String> payload = new HashMap<>();
payload.put("order_id", String.valueOf(order.getOrderId()));
ApplicationEvent event = new ApplicationEvent(payload) {
@Override
public String getType() {
return EVENT_ORDER_READY_FOR_SHIPMENT;
}
};
this.eventBus.publish(event);
}
@Override
public EventBus getEventBus() {
return eventBus;
}
public void setOrderRepository(CustomerOrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@Override
public void setEventBus(EventBus eventBus) {
this.eventBus = eventBus;
}
}

View File

@ -0,0 +1,11 @@
package com.baeldung.dddmodules.ordercontext.service;
import com.baeldung.dddmodules.ordercontext.model.CustomerOrder;
import com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository;
import com.baeldung.dddmodules.sharedkernel.service.ApplicationService;
public interface OrderService extends ApplicationService {
void placeOrder(CustomerOrder order);
void setOrderRepository(CustomerOrderRepository orderRepository);
}

View File

@ -0,0 +1,8 @@
module com.baeldung.dddmodules.ordercontext {
requires com.baeldung.dddmodules.sharedkernel;
exports com.baeldung.dddmodules.ordercontext.service;
exports com.baeldung.dddmodules.ordercontext.model;
exports com.baeldung.dddmodules.ordercontext.repository;
provides com.baeldung.dddmodules.ordercontext.service.OrderService
with com.baeldung.dddmodules.ordercontext.service.CustomerOrderService;
}

68
ddd-modules/pom.xml Normal file
View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.dddmodules</groupId>
<artifactId>dddmodules</artifactId>
<version>1.0</version>
<name>ddd-modules</name>
<packaging>pom</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modules>
<module>sharedkernel</module>
<module>infrastructure</module>
<module>shippingcontext</module>
<module>ordercontext</module>
<module>mainapp</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${compiler.plugin.version}</version>
<configuration>
<source>${source.version}</source>
<target>${target.version}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<properties>
<compiler.plugin.version>3.8.1</compiler.plugin.version>
<source.version>9</source.version>
<target.version>9</target.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<assertj-core.version>3.12.2</assertj-core.version>
<appmodules.version>1.0</appmodules.version>
</properties>
</project>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.dddmodules.sharedkernel</groupId>
<artifactId>sharedkernel</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.dddmodules</groupId>
<artifactId>dddmodules</artifactId>
<version>1.0</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${source.version}</source>
<target>${target.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<source.version>9</source.version>
<target.version>9</target.version>
</properties>
</project>

View File

@ -0,0 +1,21 @@
package com.baeldung.dddmodules.sharedkernel.events;
import java.util.Map;
public abstract class ApplicationEvent {
protected Map<String, String> payload;
public abstract String getType();
public String getPayloadValue(String key) {
if (this.payload.containsKey(key)) {
return this.payload.get(key);
}
return "";
}
public ApplicationEvent(Map<String, String> payload) {
this.payload = payload;
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.dddmodules.sharedkernel.events;
public interface EventBus {
<E extends ApplicationEvent> void publish(E event);
<E extends ApplicationEvent> void subscribe(String eventType, EventSubscriber subscriber);
<E extends ApplicationEvent> void unsubscribe(String eventType, EventSubscriber subscriber);
}

View File

@ -0,0 +1,5 @@
package com.baeldung.dddmodules.sharedkernel.events;
public interface EventSubscriber {
<E extends ApplicationEvent> void onEvent(E event);
}

View File

@ -0,0 +1,33 @@
package com.baeldung.dddmodules.sharedkernel.service;
import com.baeldung.dddmodules.sharedkernel.events.ApplicationEvent;
import com.baeldung.dddmodules.sharedkernel.events.EventBus;
import com.baeldung.dddmodules.sharedkernel.events.EventSubscriber;
public interface ApplicationService {
default <E extends ApplicationEvent> void publishEvent(E event) {
EventBus eventBus = getEventBus();
if (eventBus != null) {
eventBus.publish(event);
}
}
default <E extends ApplicationEvent> void subscribe(String eventType, EventSubscriber subscriber) {
EventBus eventBus = getEventBus();
if (eventBus != null) {
eventBus.subscribe(eventType, subscriber);
}
}
default <E extends ApplicationEvent> void unsubscribe(String eventType, EventSubscriber subscriber) {
EventBus eventBus = getEventBus();
if (eventBus != null) {
eventBus.unsubscribe(eventType, subscriber);
}
}
EventBus getEventBus();
void setEventBus(EventBus eventBus);
}

View File

@ -0,0 +1,4 @@
module com.baeldung.dddmodules.sharedkernel {
exports com.baeldung.dddmodules.sharedkernel.events;
exports com.baeldung.dddmodules.sharedkernel.service;
}

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.dddmodules.shippingcontext</groupId>
<artifactId>shippingcontext</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.dddmodules</groupId>
<artifactId>dddmodules</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>com.baeldung.dddmodules.sharedkernel</groupId>
<artifactId>sharedkernel</artifactId>
<version>${appmodules.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${source.version}</source>
<target>${target.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<source.version>9</source.version>
<target.version>9</target.version>
</properties>
</project>

View File

@ -0,0 +1,37 @@
package com.baeldung.dddmodules.shippingcontext.model;
public class PackageItem {
private int productId;
private float weight;
private float estimatedValue;
public PackageItem(int productId, float weight, float estimatedValue) {
this.productId = productId;
this.weight = weight;
this.estimatedValue = estimatedValue;
}
public int getProductId() {
return productId;
}
public void setProductId(int productId) {
this.productId = productId;
}
public float getWeight() {
return weight;
}
public void setWeight(float weight) {
this.weight = weight;
}
public float getEstimatedValue() {
return estimatedValue;
}
public void setEstimatedValue(float estimatedValue) {
this.estimatedValue = estimatedValue;
}
}

View File

@ -0,0 +1,54 @@
package com.baeldung.dddmodules.shippingcontext.model;
import java.util.List;
public class Parcel {
private int orderId;
private String address;
private String trackingId;
private List<PackageItem> packageItems;
public Parcel(int orderId, String address, List<PackageItem> packageItems) {
this.orderId = orderId;
this.address = address;
this.packageItems = packageItems;
}
public float calculateTotalWeight() {
return packageItems.stream().map(PackageItem::getWeight)
.reduce(0F, Float::sum);
}
public boolean isTaxable() {
return calculateEstimatedValue() > 100;
}
public float calculateEstimatedValue() {
return packageItems.stream().map(PackageItem::getWeight)
.reduce(0F, Float::sum);
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getTrackingId() {
return trackingId;
}
public void setTrackingId(String trackingId) {
this.trackingId = trackingId;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}

View File

@ -0,0 +1,38 @@
package com.baeldung.dddmodules.shippingcontext.model;
import java.util.List;
public class ShippableOrder {
private int orderId;
private String address;
private List<PackageItem> packageItems;
public ShippableOrder(int orderId, List<PackageItem> packageItems) {
this.orderId = orderId;
this.packageItems = packageItems;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public List<PackageItem> getPackageItems() {
return packageItems;
}
public void setPackageItems(List<PackageItem> packageItems) {
this.packageItems = packageItems;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.dddmodules.shippingcontext.repository;
import com.baeldung.dddmodules.shippingcontext.model.ShippableOrder;
import java.util.Optional;
public interface ShippingOrderRepository {
Optional<ShippableOrder> findShippableOrder(int orderId);
}

View File

@ -0,0 +1,63 @@
package com.baeldung.dddmodules.shippingcontext.service;
import com.baeldung.dddmodules.sharedkernel.events.ApplicationEvent;
import com.baeldung.dddmodules.sharedkernel.events.EventBus;
import com.baeldung.dddmodules.sharedkernel.events.EventSubscriber;
import com.baeldung.dddmodules.shippingcontext.model.Parcel;
import com.baeldung.dddmodules.shippingcontext.model.ShippableOrder;
import com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class ParcelShippingService implements ShippingService {
public static final String EVENT_ORDER_READY_FOR_SHIPMENT = "OrderReadyForShipmentEvent";
private ShippingOrderRepository orderRepository;
private EventBus eventBus;
private Map<Integer, Parcel> shippedParcels = new HashMap<>();
@Override
public void shipOrder(int orderId) {
Optional<ShippableOrder> order = this.orderRepository.findShippableOrder(orderId);
order.ifPresent(completedOrder -> {
Parcel parcel = new Parcel(completedOrder.getOrderId(), completedOrder.getAddress(), completedOrder.getPackageItems());
if (parcel.isTaxable()) {
// Calculate additional taxes
}
// Ship parcel
this.shippedParcels.put(completedOrder.getOrderId(), parcel);
});
}
@Override
public void listenToOrderEvents() {
this.eventBus.subscribe(EVENT_ORDER_READY_FOR_SHIPMENT, new EventSubscriber() {
@Override
public <E extends ApplicationEvent> void onEvent(E event) {
shipOrder(Integer.parseInt(event.getPayloadValue("order_id")));
}
});
}
@Override
public Optional<Parcel> getParcelByOrderId(int orderId) {
return Optional.ofNullable(this.shippedParcels.get(orderId));
}
public void setOrderRepository(ShippingOrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
@Override
public EventBus getEventBus() {
return eventBus;
}
@Override
public void setEventBus(EventBus eventBus) {
this.eventBus = eventBus;
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.dddmodules.shippingcontext.service;
import com.baeldung.dddmodules.sharedkernel.service.ApplicationService;
import com.baeldung.dddmodules.shippingcontext.model.Parcel;
import com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository;
import java.util.Optional;
public interface ShippingService extends ApplicationService {
void shipOrder(int orderId);
void listenToOrderEvents();
Optional<Parcel> getParcelByOrderId(int orderId);
void setOrderRepository(ShippingOrderRepository orderRepository);
}

View File

@ -0,0 +1,8 @@
module com.baeldung.dddmodules.shippingcontext {
requires com.baeldung.dddmodules.sharedkernel;
exports com.baeldung.dddmodules.shippingcontext.service;
exports com.baeldung.dddmodules.shippingcontext.model;
exports com.baeldung.dddmodules.shippingcontext.repository;
provides com.baeldung.dddmodules.shippingcontext.service.ShippingService
with com.baeldung.dddmodules.shippingcontext.service.ParcelShippingService;
}

View File

@ -0,0 +1,41 @@
repositories {
mavenCentral()
}
apply plugin: 'java'
apply plugin: 'maven'
group = 'com.baeldung'
// by default, pom's artifactId is taken from the directory name
version = '0.0.1-SNAPSHOT'
dependencies {
compile('org.slf4j:slf4j-api')
testCompile('junit:junit')
}
install {
repositories {
mavenInstaller {
pom.version = '0.0.1-maven-SNAPSHOT'
pom.groupId = 'com.baeldung.sample'
pom.artifactId = 'gradle-maven-converter'
pom.project {
inceptionYear '2020'
licenses {
license {
name 'My License'
url 'http://www.mycompany.com/licenses/license.txt'
distribution 'repo'
}
}
}
pom.whenConfigured {pom ->
pom.dependencies.find {dep -> dep.groupId == 'junit' && dep.artifactId == 'junit' }.optional = true
}
pom.writeTo("${mavenPomDir}/${project.group}/${project.name}/pom.xml")
}
}
}

View File

@ -1,15 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Remote Debugger" type="Remote">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="false" />
<option name="SHMEM_ADDRESS" />
<option name="HOST" value="localhost" />
<option name="PORT" value="5005" />
<option name="AUTO_RESTART" value="false" />
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="5005" />
<option name="LOCAL" value="false" />
</RunnerSettings>
<method v="2" />
</configuration>
</component>

View File

@ -1,2 +0,0 @@
If you have not previously done so, please fill out and
submit the https://cla.pivotal.io/sign/spring[Contributor License Agreement].

View File

@ -1,16 +0,0 @@
All code in this repository is:
=======================================================================
Copyright (c) 2013 GoPivotal, Inc. All Rights Reserved
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1 +0,0 @@
Except where otherwise noted, this work is licensed under https://creativecommons.org/licenses/by-nd/3.0/

View File

@ -1,3 +0,0 @@
### Relevant Articles:
- [Remote Debugging with IntelliJ IDEA](https://www.baeldung.com/intellij-remote-debugging)

View File

@ -1,50 +0,0 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>gs-scheduling-tasks</artifactId>
<version>0.1.0</version>
<name>gs-scheduling-tasks</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<properties>
<java.version>1.8</java.version>
<awaitility.version>3.1.2</awaitility.version>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>${awaitility.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,38 +0,0 @@
/*
* Copyright 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package hello;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTasks {
private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
@Scheduled(fixedRate = 5000)
public void reportCurrentTime() {
log.info("The time is now {}", dateFormat.format(new Date()));
}
}

View File

@ -11,3 +11,4 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m
- [Parsing Command-Line Parameters with JCommander](https://www.baeldung.com/jcommander-parsing-command-line-parameters)
- [Guide to the Cactoos Library](https://www.baeldung.com/java-cactoos)
- [Parsing Command-Line Parameters with Airline](https://www.baeldung.com/java-airline)
- [Introduction to cache2k](https://www.baeldung.com/java-cache2k)

View File

@ -73,6 +73,28 @@
<version>${cache2k.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi</artifactId>
<version>${moshi.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-adapters</artifactId>
<version>${moshi.version}</version>
</dependency>
<dependency>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-aspects</artifactId>
<version>${jcabi-aspects.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectjrt.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<repositories>
@ -81,6 +103,36 @@
<url>https://jitpack.io</url>
</repository>
</repositories>
<build>
<finalName>libraries-3</finalName>
<plugins>
<plugin>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-maven-plugin</artifactId>
<version>${jcabi-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>ajc</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectjtools.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectjweaver.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<properties>
<jcommander.version>1.78</jcommander.version>
@ -93,5 +145,11 @@
<cactoos.version>0.43</cactoos.version>
<airline.version>2.7.2</airline.version>
<cache2k.version>1.2.3.Final</cache2k.version>
<moshi.version>1.9.2</moshi.version>
<jcabi-aspects.version>0.22.6</jcabi-aspects.version>
<aspectjrt.version>1.9.2</aspectjrt.version>
<jcabi-maven-plugin.version>0.14.1</jcabi-maven-plugin.version>
<aspectjtools.version>1.9.2</aspectjtools.version>
<aspectjweaver.version>1.9.2</aspectjweaver.version>
</properties>
</project>

View File

@ -4,38 +4,33 @@ import java.util.Objects;
import org.cache2k.Cache;
import org.cache2k.Cache2kBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ProductHelper {
final Logger LOGGER = LoggerFactory.getLogger(ProductHelper.class);
private Cache<String, Integer> cachedDiscounts;
private int cacheMissCount = 0;
public ProductHelper() {
cachedDiscounts = Cache2kBuilder.of(String.class, Integer.class)
.name("discount")
.eternal(true)
.entryCapacity(100)
.build();
initDiscountCache("Sports", 20);
}
public void initDiscountCache(String productType, Integer value) {
cachedDiscounts.put(productType, value);
}
public Integer getDiscount(String productType) {
Integer discount = cachedDiscounts.get(productType);
if (Objects.isNull(discount)) {
LOGGER.info("Discount for {} not found.", productType);
discount = 0;
} else {
LOGGER.info("Discount for {} found.", productType);
cacheMissCount++;
discount = "Sports".equalsIgnoreCase(productType) ? 20 : 10;
cachedDiscounts.put(productType, discount);
}
return discount;
}
public int getCacheMissCount() {
return cacheMissCount;
}
}

View File

@ -1,6 +1,5 @@
package com.baeldung.cache2k;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.cache2k.Cache;
@ -14,28 +13,26 @@ public class ProductHelperUsingLoader {
private Cache<String, Integer> cachedDiscounts;
private int cacheMissCount = 0;
public ProductHelperUsingLoader() {
cachedDiscounts = Cache2kBuilder.of(String.class, Integer.class)
.name("discount-loader")
.eternal(false)
.expireAfterWrite(10, TimeUnit.MILLISECONDS)
.entryCapacity(100)
.loader((key) -> {
LOGGER.info("Calculating discount for {}.", key);
cacheMissCount++;
return "Sports".equalsIgnoreCase(key) ? 20 : 10;
})
.build();
}
public Integer getDiscount(String productType) {
Integer discount = cachedDiscounts.get(productType);
if (Objects.isNull(discount)) {
LOGGER.info("Discount for {} not found.", productType);
discount = 0;
} else {
LOGGER.info("Discount for {} found.", productType);
}
return discount;
return cachedDiscounts.get(productType);
}
public int getCacheMissCount() {
return cacheMissCount;
}
}

View File

@ -1,6 +1,5 @@
package com.baeldung.cache2k;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.cache2k.Cache;
@ -16,14 +15,15 @@ public class ProductHelperWithEventListener {
private Cache<String, Integer> cachedDiscounts;
private int cacheMissCount = 0;
public ProductHelperWithEventListener() {
cachedDiscounts = Cache2kBuilder.of(String.class, Integer.class)
.name("discount-listener")
.eternal(false)
.expireAfterWrite(10, TimeUnit.MILLISECONDS)
.entryCapacity(100)
.loader((key) -> {
LOGGER.info("Calculating discount for {}.", key);
cacheMissCount++;
return "Sports".equalsIgnoreCase(key) ? 20 : 10;
})
.addListener(new CacheEntryCreatedListener<String, Integer>() {
@ -36,14 +36,11 @@ public class ProductHelperWithEventListener {
}
public Integer getDiscount(String productType) {
Integer discount = cachedDiscounts.get(productType);
if (Objects.isNull(discount)) {
LOGGER.info("Discount for {} not found.", productType);
discount = 0;
} else {
LOGGER.info("Discount for {} found.", productType);
}
return discount;
return cachedDiscounts.get(productType);
}
public int getCacheMissCount() {
return cacheMissCount;
}
}

View File

@ -5,39 +5,34 @@ import java.util.concurrent.TimeUnit;
import org.cache2k.Cache;
import org.cache2k.Cache2kBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ProductHelperWithExpiry {
final Logger LOGGER = LoggerFactory.getLogger(ProductHelperWithExpiry.class);
private Cache<String, Integer> cachedDiscounts;
private int cacheMissCount = 0;
public ProductHelperWithExpiry() {
cachedDiscounts = Cache2kBuilder.of(String.class, Integer.class)
.name("discount-expiry")
.eternal(false)
.expireAfterWrite(5, TimeUnit.MILLISECONDS)
.entryCapacity(100)
.build();
initDiscountCache("Sports", 20);
}
public void initDiscountCache(String productType, Integer value) {
cachedDiscounts.put(productType, value);
}
public Integer getDiscount(String productType) {
Integer discount = cachedDiscounts.get(productType);
if (Objects.isNull(discount)) {
LOGGER.info("Discount for {} not found.", productType);
discount = 0;
} else {
LOGGER.info("Discount for {} found.", productType);
cacheMissCount++;
discount = "Sports".equalsIgnoreCase(productType) ? 20 : 10;
cachedDiscounts.put(productType, discount);
}
return discount;
}
public int getCacheMissCount() {
return cacheMissCount;
}
}

View File

@ -0,0 +1,112 @@
package com.baeldung.jcabi;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import com.jcabi.aspects.Async;
import com.jcabi.aspects.Cacheable;
import com.jcabi.aspects.LogExceptions;
import com.jcabi.aspects.Loggable;
import com.jcabi.aspects.Quietly;
import com.jcabi.aspects.RetryOnFailure;
import com.jcabi.aspects.UnitedThrow;
public class JcabiAspectJ {
public static void main(String[] args) {
try {
displayFactorial(10);
getFactorial(10).get();
String result = cacheExchangeRates();
if (result != cacheExchangeRates()) {
System.out.println(result);
}
divideByZero();
} catch(Exception e) {
e.printStackTrace();
}
divideByZeroQuietly();
try {
processFile();
} catch(Exception e) {
e.printStackTrace();
}
}
@Loggable
@Async
public static void displayFactorial(int number) {
long result = factorial(number);
System.out.println(result);
}
@Loggable
@Async
public static Future<Long> getFactorial(int number) {
Future<Long> factorialFuture = CompletableFuture.supplyAsync(() -> factorial(number));
return factorialFuture;
}
/**
* Finds factorial of a number
* @param number
* @return
*/
public static long factorial(int number) {
long result = 1;
for(int i=number;i>0;i--) {
result *= i;
}
return result;
}
@Loggable
@Cacheable(lifetime = 2, unit = TimeUnit.SECONDS)
public static String cacheExchangeRates() {
String result = null;
try {
URL exchangeRateUrl = new URL("https://api.exchangeratesapi.io/latest");
URLConnection con = exchangeRateUrl.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
result = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@LogExceptions
public static void divideByZero() {
int x = 1/0;
}
@RetryOnFailure(attempts = 2, types = {java.lang.NumberFormatException.class})
@Quietly
public static void divideByZeroQuietly() {
int x = 1/0;
}
@UnitedThrow(IllegalStateException.class)
public static void processFile() throws IOException, InterruptedException {
BufferedReader reader = new BufferedReader(new FileReader("baeldung.txt"));
reader.readLine();
Thread thread = new Thread();
thread.wait(2000);
}
}

View File

@ -6,12 +6,13 @@ import org.junit.Test;
public class ProductHelperUnitTest {
ProductHelper productHelper = new ProductHelper();
@Test
public void whenInvokedGetDiscount_thenGetItFromCache() {
public void whenInvokedGetDiscountTwice_thenGetItFromCache() {
ProductHelper productHelper = new ProductHelper();
assertTrue(productHelper.getCacheMissCount() == 0);
assertTrue(productHelper.getDiscount("Sports") == 20);
assertTrue(productHelper.getDiscount("Electronics") == 0);
assertTrue(productHelper.getDiscount("Sports") == 20);
assertTrue(productHelper.getCacheMissCount() == 1);
}
}

View File

@ -6,12 +6,16 @@ import org.junit.Test;
public class ProductHelperUsingLoaderUnitTest {
ProductHelperUsingLoader productHelper = new ProductHelperUsingLoader();
@Test
public void whenInvokedGetDiscount_thenPopulateCache() {
public void whenInvokedGetDiscount_thenPopulateCacheUsingLoader() {
ProductHelperUsingLoader productHelper = new ProductHelperUsingLoader();
assertTrue(productHelper.getCacheMissCount() == 0);
assertTrue(productHelper.getDiscount("Sports") == 20);
assertTrue(productHelper.getCacheMissCount() == 1);
assertTrue(productHelper.getDiscount("Electronics") == 10);
assertTrue(productHelper.getCacheMissCount() == 2);
}
}

View File

@ -6,10 +6,9 @@ import org.junit.Test;
public class ProductHelperWithEventListenerUnitTest {
ProductHelperWithEventListener productHelper = new ProductHelperWithEventListener();
@Test
public void whenEntryAddedInCache_thenEventListenerCalled() {
ProductHelperWithEventListener productHelper = new ProductHelperWithEventListener();
assertTrue(productHelper.getDiscount("Sports") == 20);
}

View File

@ -6,13 +6,17 @@ import org.junit.Test;
public class ProductHelperWithExpiryUnitTest {
ProductHelperWithExpiry productHelper = new ProductHelperWithExpiry();
@Test
public void whenInvokedGetDiscountForExpiredProduct_thenNoDiscount() throws InterruptedException {
public void whenInvokedGetDiscountAfterExpiration_thenDiscountCalculatedAgain() throws InterruptedException {
ProductHelperWithExpiry productHelper = new ProductHelperWithExpiry();
assertTrue(productHelper.getCacheMissCount() == 0);
assertTrue(productHelper.getDiscount("Sports") == 20);
assertTrue(productHelper.getCacheMissCount() == 1);
Thread.sleep(20);
assertTrue(productHelper.getDiscount("Sports") == 0);
assertTrue(productHelper.getDiscount("Sports") == 20);
assertTrue(productHelper.getCacheMissCount() == 2);
}
}

View File

@ -0,0 +1,105 @@
package com.baeldung.moshi;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.time.Instant;
import com.squareup.moshi.FromJson;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonQualifier;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.ToJson;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.junit.Test;
public class AlternativeAdapterUnitTest {
@Test
public void whenSerializing_thenAlternativeAdapterUsed() {
Moshi moshi = new Moshi.Builder()
.add(new EpochMillisAdapter())
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
String json = jsonAdapter.toJson(new Post("Introduction to Moshi Json", "Baeldung", Instant.now()));
System.out.println(json);
}
@Test
public void whenDeserializing_thenAlternativeAdapterUsed() throws IOException {
Moshi moshi = new Moshi.Builder()
.add(new EpochMillisAdapter())
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
String json = "{\"author\":\"Baeldung\",\"posted\":1582095269204,\"title\":\"Introduction to Moshi Json\"}";
Post post = jsonAdapter.fromJson(json);
System.out.println(post);
}
public static class Post {
String title;
String author;
@EpochMillis Instant posted;
public Post() {
}
public Post(String title, String author, Instant posted) {
this.title = title;
this.author = author;
this.posted = posted;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Instant getPosted() {
return posted;
}
public void setPosted(Instant posted) {
this.posted = posted;
}
@Override
public String toString() {
return new ToStringBuilder(this).append("title", title).append("author", author).append("posted", posted)
.toString();
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@JsonQualifier
public @interface EpochMillis {
}
public static class EpochMillisAdapter {
@ToJson
public Long toJson(@EpochMillis Instant input) {
return input.toEpochMilli();
}
@FromJson
@EpochMillis
public Instant fromJson(Long input) {
return Instant.ofEpochMilli(input);
}
}
}

View File

@ -0,0 +1,36 @@
package com.baeldung.moshi;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import org.junit.Test;
public class ArrayUnitTest {
@Test
public void whenSerializingList_thenJsonArrayProduced() {
Moshi moshi = new Moshi.Builder()
.build();
Type type = Types.newParameterizedType(List.class, String.class);
JsonAdapter<List<String>> jsonAdapter = moshi.adapter(type);
String json = jsonAdapter.toJson(Arrays.asList("One", "Two", "Three"));
System.out.println(json);
}
@Test
public void whenDeserializingJsonArray_thenListProduced() throws IOException {
Moshi moshi = new Moshi.Builder()
.build();
Type type = Types.newParameterizedType(List.class, String.class);
JsonAdapter<List<String>> jsonAdapter = moshi.adapter(type);
String json = "[\"One\",\"Two\",\"Three\"]";
List<String> result = jsonAdapter.fromJson(json);
System.out.println(result);
}
}

View File

@ -0,0 +1,94 @@
package com.baeldung.moshi;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import com.squareup.moshi.FromJson;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.ToJson;
import org.junit.Test;
public class ComplexAdapterUnitTest {
@Test
public void whenSerializing_thenCorrectJsonProduced() {
Moshi moshi = new Moshi.Builder()
.add(new JsonDateTimeAdapter())
.build();
JsonAdapter<ZonedDateTime> jsonAdapter = moshi.adapter(ZonedDateTime.class);
String json = jsonAdapter.toJson(ZonedDateTime.now());
System.out.println(json);
}
@Test
public void whenDeserializing_thenCorrectJsonConsumed() throws IOException {
Moshi moshi = new Moshi.Builder()
.add(new JsonDateTimeAdapter())
.build();
JsonAdapter<ZonedDateTime> jsonAdapter = moshi.adapter(ZonedDateTime.class);
String json = "{\"date\":\"2020-02-17\",\"time\":\"07:53:27.064\",\"timezone\":\"Europe/London\"}";
ZonedDateTime now = jsonAdapter.fromJson(json);
System.out.println(now);
}
public static class JsonDateTimeAdapter {
@ToJson
public JsonDateTime toJson(ZonedDateTime input) {
String date = input.toLocalDate().toString();
String time = input.toLocalTime().toString();
String timezone = input.getZone().toString();
return new JsonDateTime(date, time, timezone);
}
@FromJson
public ZonedDateTime fromJson(JsonDateTime input) {
LocalDate date = LocalDate.parse(input.getDate());
LocalTime time = LocalTime.parse(input.getTime());
ZoneId timezone = ZoneId.of(input.getTimezone());
return ZonedDateTime.of(date, time, timezone);
}
}
public static class JsonDateTime {
private String date;
private String time;
private String timezone;
public JsonDateTime() {
}
public JsonDateTime(String date, String time, String timezone) {
this.date = date;
this.time = time;
this.timezone = timezone;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getTimezone() {
return timezone;
}
public void setTimezone(String timezone) {
this.timezone = timezone;
}
}
}

View File

@ -0,0 +1,68 @@
package com.baeldung.moshi;
import java.io.IOException;
import java.time.Instant;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.junit.Test;
public class DefaultUnitTest {
@Test
public void whenDeserializing_thenFieldsGetDefaultValues() throws IOException {
Moshi moshi = new Moshi.Builder()
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
String json = "{\"title\":\"My Post\"}";
Post post = jsonAdapter.fromJson(json);
System.out.println(post);
}
public static class Post {
private String title;
private String author;
private String posted;
public Post() {
posted = Instant.now().toString();
}
public Post(String title, String author, String posted) {
this.title = title;
this.author = author;
this.posted = posted;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPosted() {
return posted;
}
public void setPosted(String posted) {
this.posted = posted;
}
@Override
public String toString() {
return new ToStringBuilder(this).append("title", title).append("author", author).append("posted", posted)
.toString();
}
}
}

View File

@ -0,0 +1,77 @@
package com.baeldung.moshi;
import java.io.IOException;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.junit.Test;
public class PrimitiveUnitTest {
@Test
public void whenSerializing_thenCorrectJsonProduced() {
Moshi moshi = new Moshi.Builder()
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
Post post = new Post("My Post", "Baeldung", "This is my post");
String json = jsonAdapter.toJson(post);
System.out.println(json);
}
@Test
public void whenDeserializing_thenCorrectJsonConsumed() throws IOException {
Moshi moshi = new Moshi.Builder()
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
String json = "{\"author\":\"Baeldung\",\"text\":\"This is my post\",\"title\":\"My Post\"}";
Post post = jsonAdapter.fromJson(json);
System.out.println(post);
}
public static class Post {
private String title;
private String author;
private String text;
public Post() {
}
public Post(String title, String author, String text) {
this.title = title;
this.author = author;
this.text = text;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@Override
public String toString() {
return new ToStringBuilder(this).append("title", title).append("author", author).append("text", text)
.toString();
}
}
}

View File

@ -0,0 +1,68 @@
package com.baeldung.moshi;
import java.io.IOException;
import com.squareup.moshi.Json;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.junit.jupiter.api.Test;
public class RenameUnitTest {
@Test
public void whenSerializing_thenFieldsGetRenamed() {
Moshi moshi = new Moshi.Builder()
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
Post post = new Post("My Post", "Baeldung");
String json = jsonAdapter.toJson(post);
System.out.println(json);
}
@Test
public void whenSerializing_thenRenamedFieldsGetConsumed() throws IOException {
Moshi moshi = new Moshi.Builder()
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
String json = "{\"authored_by\":\"Baeldung\",\"title\":\"My Post\"}";
Post post = jsonAdapter.fromJson(json);
System.out.println(post);
}
public static class Post {
private String title;
@Json(name = "authored_by")
private String author;
public Post() {
}
public Post(String title, String author) {
this.title = title;
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return new ToStringBuilder(this).append("title", title).append("author", author).toString();
}
}
}

View File

@ -0,0 +1,129 @@
package com.baeldung.moshi;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.squareup.moshi.FromJson;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.ToJson;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.junit.Test;
public class SimpleAdapterUnitTest {
@Test
public void whenSerializing_thenAdapterUsed() {
Moshi moshi = new Moshi.Builder()
.add(new AuthorAdapter())
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
Post post = new Post("My Post", new Author("Baeldung", "baeldung@example.com"), "This is my post");
String json = jsonAdapter.toJson(post);
System.out.println(json);
}
@Test
public void whenDeserializing_thenAdapterUsed() throws IOException {
Moshi moshi = new Moshi.Builder()
.add(new AuthorAdapter())
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
String json = "{\"author\":\"Baeldung <baeldung@example.com>\",\"text\":\"This is my post\",\"title\":\"My Post\"}";
Post post = jsonAdapter.fromJson(json);
System.out.println(post);
}
public static class AuthorAdapter {
private Pattern pattern = Pattern.compile("^(.*) <(.*)>$");
@ToJson
public String toJson(Author author) {
return author.name + " <" + author.email + ">";
}
@FromJson
public Author fromJson(String author) {
Matcher matcher = pattern.matcher(author);
return matcher.find() ? new Author(matcher.group(1), matcher.group(2)) : null;
}
}
public static class Author {
private String name;
private String email;
public Author() {
}
public Author(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return new ToStringBuilder(this).append("name", name).append("email", email).toString();
}
}
public static class Post {
private String title;
private Author author;
private String text;
public Post() {
}
public Post(String title, Author author, String text) {
this.title = title;
this.author = author;
this.text = text;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@Override
public String toString() {
return new ToStringBuilder(this).append("title", title).append("author", author).append("text", text)
.toString();
}
}
}

View File

@ -0,0 +1,66 @@
package com.baeldung.moshi;
import java.io.IOException;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.junit.jupiter.api.Test;
public class TransientUnitTest {
@Test
public void whenSerializing_thenTransientFieldIgnored() {
Moshi moshi = new Moshi.Builder()
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
Post post = new Post("My Post", "Baeldung");
String json = jsonAdapter.toJson(post);
System.out.println(json);
}
@Test
public void whenDeserializing_thenTransientFieldIgnored() throws IOException {
Moshi moshi = new Moshi.Builder()
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
String json = "{\"authored_by\":\"Baeldung\",\"title\":\"My Post\"}";
Post post = jsonAdapter.fromJson(json);
System.out.println(post);
}
public static class Post {
private String title;
private transient String author;
public Post() {
}
public Post(String title, String author) {
this.title = title;
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return new ToStringBuilder(this).append("title", title).append("author", author).toString();
}
}
}

View File

@ -36,12 +36,12 @@
<profiles>
<profile>
<id>default-tools.jar</id>
<id>default-profile</id>
<activation>
<property>
<name>java.vendor</name>
<value>Oracle Corporation</value>
</property>
<activeByDefault>true</activeByDefault>
<file>
<exists>${java.home}/../lib/tools.jar</exists>
</file>
</activation>
<dependencies>
<dependency>
@ -53,6 +53,24 @@
</dependency>
</dependencies>
</profile>
<profile>
<id>mac-profile</id>
<activation>
<activeByDefault>false</activeByDefault>
<file>
<exists>${java.home}/../Classes/classes.jar</exists>
</file>
</activation>
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>${java.version}</version>
<scope>system</scope>
<systemPath>${java.home}/../Classes/classes.jar</systemPath>
</dependency>
</dependencies>
</profile>
</profiles>
<properties>

View File

@ -23,6 +23,16 @@
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>

View File

@ -1,14 +1,13 @@
package hello;
package com.baeldung.storedprocedure;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class Application {
public class StoredProcedureApplication {
public static void main(String[] args) {
SpringApplication.run(Application.class);
SpringApplication.run(StoredProcedureApplication.class, args);
}
}

View File

@ -0,0 +1,47 @@
package com.baeldung.storedprocedure.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.storedprocedure.entity.Car;
import com.baeldung.storedprocedure.service.CarService;
@RestController
public class CarController {
@Autowired
private CarService carService;
@GetMapping(path = "/modelcount")
public long getTotalCarsByModel(@RequestParam("model") String model) {
return carService.getTotalCarsByModel(model);
}
@GetMapping(path = "/modelcountP")
public long getTotalCarsByModelProcedureName(@RequestParam("model") String model) {
return carService.getTotalCarsByModelProcedureName(model);
}
@GetMapping(path = "/modelcountV")
public long getTotalCarsByModelVaue(@RequestParam("model") String model) {
return carService.getTotalCarsByModelValue(model);
}
@GetMapping(path = "/modelcountEx")
public long getTotalCarsByModelExplicit(@RequestParam("model") String model) {
return carService.getTotalCarsByModelExplicit(model);
}
@GetMapping(path = "/modelcountEn")
public long getTotalCarsByModelEntity(@RequestParam("model") String model) {
return carService.getTotalCarsByModelEntity(model);
}
@GetMapping(path = "/carsafteryear")
public List<Car> findCarsAfterYear(@RequestParam("year") Integer year) {
return carService.findCarsAfterYear(year);
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.storedprocedure.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.StoredProcedureParameter;
import javax.persistence.ParameterMode;
@Entity
@NamedStoredProcedureQuery(name = "Car.getTotalCardsbyModelEntity", procedureName = "GET_TOTAL_CARS_BY_MODEL", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "model_in", type = String.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "count_out", type = Integer.class) })
public class Car {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private long id;
@Column
private String model;
@Column
private Integer year;
public long getId() {
return id;
}
public String getModel() {
return model;
}
public Integer getYear() {
return year;
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung.storedprocedure.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.query.Procedure;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.baeldung.storedprocedure.entity.Car;
@Repository
public interface CarRepository extends JpaRepository<Car, Integer> {
@Procedure
int GET_TOTAL_CARS_BY_MODEL(String model);
@Procedure("GET_TOTAL_CARS_BY_MODEL")
int getTotalCarsByModel(String model);
@Procedure(procedureName = "GET_TOTAL_CARS_BY_MODEL")
int getTotalCarsByModelProcedureName(String model);
@Procedure(value = "GET_TOTAL_CARS_BY_MODEL")
int getTotalCarsByModelValue(String model);
@Procedure(name = "Car.getTotalCardsbyModelEntity")
int getTotalCarsByModelEntiy(@Param("model_in") String model);
@Query(value = "CALL FIND_CARS_AFTER_YEAR(:year_in);", nativeQuery = true)
List<Car> findCarsAfterYear(@Param("year_in") Integer year_in);
}

View File

@ -0,0 +1,39 @@
package com.baeldung.storedprocedure.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baeldung.storedprocedure.entity.Car;
import com.baeldung.storedprocedure.repository.CarRepository;
@Service
public class CarService {
@Autowired
private CarRepository carRepository;
public int getTotalCarsByModel(String model) {
return carRepository.getTotalCarsByModel(model);
}
public int getTotalCarsByModelProcedureName(String model) {
return carRepository.getTotalCarsByModelProcedureName(model);
}
public int getTotalCarsByModelValue(String model) {
return carRepository.getTotalCarsByModelValue(model);
}
public int getTotalCarsByModelExplicit(String model) {
return carRepository.GET_TOTAL_CARS_BY_MODEL(model);
}
public int getTotalCarsByModelEntity(String model) {
return carRepository.getTotalCarsByModelEntiy(model);
}
public List<Car> findCarsAfterYear(Integer year) {
return carRepository.findCarsAfterYear(year);
}
}

View File

@ -1 +1,5 @@
spring.jpa.show-sql=true
spring.jpa.show-sql=true
#MySql
spring.datasource.url=jdbc:mysql://localhost:3306/baeldung
spring.datasource.username=baeldung
spring.datasource.password=baeldung

View File

@ -0,0 +1,27 @@
DROP TABLE IF EXISTS car;
CREATE TABLE car (id int(10) NOT NULL AUTO_INCREMENT,
model varchar(50) NOT NULL,
year int(4) NOT NULL,
PRIMARY KEY (id));
INSERT INTO car (model, year) VALUES ('BMW', 2000);
INSERT INTO car (model, year) VALUES ('BENZ', 2010);
INSERT INTO car (model, year) VALUES ('PORCHE', 2005);
INSERT INTO car (model, year) VALUES ('PORCHE', 2004);
DELIMITER $$
DROP PROCEDURE IF EXISTS FIND_CARS_AFTER_YEAR$$
CREATE PROCEDURE FIND_CARS_AFTER_YEAR(IN year_in INT)
BEGIN
SELECT * FROM car WHERE year >= year_in ORDER BY year;
END$$
DROP PROCEDURE IF EXISTS GET_TOTAL_CARS_BY_MODEL$$
CREATE PROCEDURE GET_TOTAL_CARS_BY_MODEL(IN model_in VARCHAR(50), OUT count_out INT)
BEGIN
SELECT COUNT(*) into count_out from car WHERE model = model_in;
END$$
DELIMITER ;

View File

@ -0,0 +1,43 @@
package controllers;
import play.data.Form;
import play.data.FormFactory;
import play.mvc.Controller;
import play.mvc.Result;
import javax.inject.Inject;
// Add the following to conf/routes
/*
GET /$model;format="camel"$ controllers.$model;format="Camel"$Controller.$model;format="camel"$Get
POST /$model;format="camel"$ controllers.$model;format="Camel"$Controller.$model;format="camel"$Post
*/
/**
* $model;format="Camel"$ form controller for Play Java
*/
public class $model;format="Camel"$Controller extends Controller {
private final Form<$model;format="Camel"$Data> $model;format="camel"$Form;
@Inject
public $model;format="Camel"$Controller(FormFactory formFactory) {
this.$model;format="camel"$Form = formFactory.form($model;format="Camel"$Data.class);
}
public Result $model;format="camel"$Get() {
return ok(views.html.$model;format="camel"$.form.render($model;format="camel"$Form));
}
public Result $model;format="camel"$Post() {
Form<$model;format="Camel"$Data> boundForm = $model;format="camel"$Form.bindFromRequest();
if (boundForm.hasErrors()) {
return badRequest(views.html.$model;format="camel"$.form.render(boundForm));
} else {
$model;format="Camel"$Data $model;format="camel"$ = boundForm.get();
flash("success", "$model;format="Camel"$ " + $model;format="camel"$);
return redirect(routes.$model;format="Camel"$Controller.$model;format="camel"$Get());
}
}
}

View File

@ -0,0 +1,37 @@
package controllers;
import play.data.validation.Constraints;
public class $model;format="Camel"$Data {
@Constraints.Required
private String name;
@Constraints.Required
private Integer age;
public $model;format="Camel"$Data() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return String.format("$model;format="Camel"$Data(%s, %s)", name, age);
}
}

View File

@ -0,0 +1,12 @@
@($model;format="camel"$Form: Form[$model;format="Camel"$Data])
<h1>$model;format="camel"$ form</h1>
@flash.getOrDefault("success", "")
@helper.form(action = routes.$model;format="Camel"$Controller.$model;format="camel"$Post()) {
@helper.CSRF.formField
@helper.inputText($model;format="camel"$Form("name"))
@helper.inputText($model;format="camel"$Form("age"))
<input type="submit" value="submit"/>
}

View File

@ -0,0 +1,2 @@
description = Generates a Controller with form handling
model = user

View File

@ -0,0 +1 @@
Temporary file until g8-scaffold will generate "test" directory

View File

@ -0,0 +1,50 @@
package controllers;
import org.junit.Test;
import play.Application;
import play.filters.csrf.*;
import play.inject.guice.GuiceApplicationBuilder;
import play.mvc.*;
import play.test.WithApplication;
import java.util.HashMap;
import static org.junit.Assert.assertEquals;
import static play.mvc.Http.RequestBuilder;
import static play.mvc.Http.Status.OK;
import static play.test.Helpers.*;
import static play.api.test.CSRFTokenHelper.*;
public class $model;format="Camel"$ControllerTest extends WithApplication {
@Override
protected Application provideApplication() {
return new GuiceApplicationBuilder().build();
}
@Test
public void test$model;format="Camel"$Get() {
RequestBuilder request = new RequestBuilder()
.method(GET)
.uri("/$model;format="camel"$");
Result result = route(app, request);
assertEquals(OK, result.status());
}
@Test
public void test$model;format="Camel"$Post() {
HashMap<String, String> formData = new HashMap<>();
formData.put("name", "play");
formData.put("age", "4");
RequestBuilder request = addCSRFToken(new RequestBuilder()
.header(Http.HeaderNames.HOST, "localhost")
.method(POST)
.bodyForm(formData)
.uri("/$model;format="camel"$"));
Result result = route(app, request);
assertEquals(SEE_OTHER, result.status());
}
}

8
play-framework/async-http/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
logs
target
/.idea
/.idea_modules
/.classpath
/.project
/.settings
/RUNNING_PID

View File

@ -0,0 +1,38 @@
package controllers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import java.util.Collections;
import java.util.Map;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.Result;
/**
* This controller contains an action to handle HTTP requests to the application's home page.
*/
public class HomeController extends Controller {
/**
* An action that renders an HTML page with a welcome message. The configuration in the
* <code>routes</code> file means that this method will be called when the application receives
* a
* <code>GET</code> request with a path of <code>/</code>.
*/
public Result index(Http.Request request) throws JsonProcessingException {
return ok(printStats(request));
}
private String printStats(Http.Request request) throws JsonProcessingException {
Map<String, String[]> stringMap = request.body()
.asFormUrlEncoded();
Map<String, Object> map = ImmutableMap.of(
"Result", "ok",
"GetParams", request.queryString(),
"PostParams", stringMap == null ? Collections.emptyMap() : stringMap,
"Headers", request.getHeaders().toMap()
);
return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(map);
}
}

View File

@ -0,0 +1,5 @@
@()
@main("Welcome to Play") {
<h1>Welcome to Play!</h1>
}

View File

@ -0,0 +1,24 @@
@*
* This template is called from the `index` template. This template
* handles the rendering of the page header and body tags. It takes
* two arguments, a `String` for the title of the page and an `Html`
* object to insert into the body of the page.
*@
@(title: String)(content: Html)
<!DOCTYPE html>
<html lang="en">
<head>
@* Here's where we render the page title `String`. *@
<title>@title</title>
<link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
</head>
<body>
@* And here's where we render the `Html` object containing
* the page content. *@
@content
<script src="@routes.Assets.versioned("javascripts/main.js")" type="text/javascript"></script>
</body>
</html>

View File

@ -0,0 +1,12 @@
name := """async"""
organization := "com.example"
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayJava)
scalaVersion := "2.13.1"
// comment out the original line
libraryDependencies += guice
libraryDependencies += javaWs

View File

@ -0,0 +1,11 @@
# This is the main configuration file for the application.
# https://www.playframework.com/documentation/latest/ConfigFile
play.ws.followRedirects=false
play.ws.useragent=MyPlayApplication
play.ws.compressionEnabled=true
# time to wait for the connection to be established
play.ws.timeout.connection=30.seconds
# time to wait for data after the connection is open
play.ws.timeout.idle=30.seconds
# max time available to complete the request
play.ws.timeout.request=300.seconds

View File

@ -0,0 +1,36 @@
<!-- https://www.playframework.com/documentation/latest/SettingsLogger -->
<configuration>
<conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${application.home:-.}/logs/application.log</file>
<encoder>
<pattern>%date [%level] from %logger in %thread - %message%n%xException</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} - %message%n%xException{10}</pattern>
</encoder>
</appender>
<appender name="ASYNCFILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="STDOUT" />
</appender>
<logger name="play" level="INFO" />
<logger name="application" level="DEBUG" />
<logger name="controllers" level="DEBUG" />
<root level="WARN">
<appender-ref ref="ASYNCFILE" />
<appender-ref ref="ASYNCSTDOUT" />
</root>
</configuration>

View File

@ -0,0 +1,10 @@
# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~
# An example controller showing a sample home page
GET / controllers.HomeController.index(request: Request)
POST / controllers.HomeController.index(request: Request)
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)

View File

@ -0,0 +1 @@
sbt.version=1.3.3

View File

@ -0,0 +1,7 @@
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.3")
// Defines scaffolding (found under .g8 folder)
// http://www.foundweekends.org/giter8/scaffolding.html
// sbt "g8Scaffold form"
addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0")

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