Merge remote-tracking branch 'eugenp/master'
This commit is contained in:
commit
308b742759
|
@ -0,0 +1,29 @@
|
||||||
|
package com.baeldung.algorithms.rectanglesoverlap;
|
||||||
|
|
||||||
|
public class Point {
|
||||||
|
|
||||||
|
private int x;
|
||||||
|
private int y;
|
||||||
|
|
||||||
|
public Point(int x, int y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(int x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(int y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.baeldung.algorithms.rectanglesoverlap;
|
||||||
|
|
||||||
|
public class Rectangle {
|
||||||
|
|
||||||
|
private Point bottomLeft;
|
||||||
|
private Point topRight;
|
||||||
|
|
||||||
|
public Rectangle(Point bottomLeft, Point topRight) {
|
||||||
|
this.bottomLeft = bottomLeft;
|
||||||
|
this.topRight = topRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point getBottomLeft() {
|
||||||
|
return bottomLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBottomLeft(Point bottomLeft) {
|
||||||
|
this.bottomLeft = bottomLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point getTopRight() {
|
||||||
|
return topRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTopRight(Point topRight) {
|
||||||
|
this.topRight = topRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOverlapping(Rectangle other) {
|
||||||
|
// one rectangle is to the top of the other
|
||||||
|
if (this.topRight.getY() < other.bottomLeft.getY() || this.bottomLeft.getY() > other.topRight.getY()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// one rectangle is to the left of the other
|
||||||
|
if (this.topRight.getX() < other.bottomLeft.getX() || this.bottomLeft.getX() > other.topRight.getX()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.baeldung.algorithms.rectanglesoverlap;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.baeldung.algorithms.rectanglesoverlap.Point;
|
||||||
|
import com.baeldung.algorithms.rectanglesoverlap.Rectangle;
|
||||||
|
|
||||||
|
public class RectangleUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenTwoOverlappingRectangles_whenisOverlappingCalled_shouldReturnTrue() {
|
||||||
|
Rectangle rectangle1 = new Rectangle(new Point(2, 1), new Point(4, 3));
|
||||||
|
Rectangle rectangle2 = new Rectangle(new Point(1, 1), new Point(6, 4));
|
||||||
|
assertTrue(rectangle1.isOverlapping(rectangle2));
|
||||||
|
|
||||||
|
rectangle1 = new Rectangle(new Point(-5, -2), new Point(2, 3));
|
||||||
|
rectangle2 = new Rectangle(new Point(-2, -1), new Point(5, 2));
|
||||||
|
assertTrue(rectangle1.isOverlapping(rectangle2));
|
||||||
|
|
||||||
|
rectangle1 = new Rectangle(new Point(-5, 1), new Point(2, 4));
|
||||||
|
rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, 5));
|
||||||
|
assertTrue(rectangle1.isOverlapping(rectangle2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenTwoNonOverlappingRectangles_whenisOverlappingCalled_shouldReturnFalse() {
|
||||||
|
Rectangle rectangle1 = new Rectangle(new Point(-5, 1), new Point(-3, 4));
|
||||||
|
Rectangle rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, 5));
|
||||||
|
assertFalse(rectangle1.isOverlapping(rectangle2));
|
||||||
|
|
||||||
|
rectangle1 = new Rectangle(new Point(-5, 1), new Point(3, 4));
|
||||||
|
rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, -1));
|
||||||
|
assertFalse(rectangle1.isOverlapping(rectangle2));
|
||||||
|
|
||||||
|
rectangle1 = new Rectangle(new Point(-2, 1), new Point(0, 3));
|
||||||
|
rectangle2 = new Rectangle(new Point(3, 1), new Point(5, 4));
|
||||||
|
assertFalse(rectangle1.isOverlapping(rectangle2));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -95,7 +95,6 @@
|
||||||
<gson.version>2.8.2</gson.version>
|
<gson.version>2.8.2</gson.version>
|
||||||
<aws-java-sdk.version>1.11.241</aws-java-sdk.version>
|
<aws-java-sdk.version>1.11.241</aws-java-sdk.version>
|
||||||
<maven-shade-plugin.version>3.0.0</maven-shade-plugin.version>
|
<maven-shade-plugin.version>3.0.0</maven-shade-plugin.version>
|
||||||
<maven-dependency-plugin.version>2.10</maven-dependency-plugin.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
21
aws/pom.xml
21
aws/pom.xml
|
@ -100,26 +100,6 @@
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<version>${maven-dependency-plugin.version}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>test-compile</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<includeScope>test</includeScope>
|
|
||||||
<includeTypes>so,dll,dylib</includeTypes>
|
|
||||||
<outputDirectory>${project.basedir}/native-libs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
@ -144,7 +124,6 @@
|
||||||
<commons-codec-version>1.10.L001</commons-codec-version>
|
<commons-codec-version>1.10.L001</commons-codec-version>
|
||||||
<jets3t-version>0.9.4.0006L</jets3t-version>
|
<jets3t-version>0.9.4.0006L</jets3t-version>
|
||||||
<maven-shade-plugin.version>3.0.0</maven-shade-plugin.version>
|
<maven-shade-plugin.version>3.0.0</maven-shade-plugin.version>
|
||||||
<maven-dependency-plugin.version>2.10</maven-dependency-plugin.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -41,27 +41,6 @@
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<!-- This plugin will set properties values using dependency information -->
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<!--
|
|
||||||
Goal that sets a property pointing to the artifact file for each project dependency.
|
|
||||||
For each dependency (direct and transitive) a project property will be set which
|
|
||||||
follows the:
|
|
||||||
|
|
||||||
groupId:artifactId:type:[classifier]
|
|
||||||
|
|
||||||
form and contains the path to the resolved artifact. -->
|
|
||||||
<goal>properties</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>${maven-compiler-plugin.version}</version>
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
|
|
|
@ -116,23 +116,6 @@
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# compile logging module
|
||||||
|
# javac --module-path mods -d mods/com.baeldung.logging src/modules/com.baeldung.logging/module-info.java src/modules/com.baeldung.logging/com/baeldung/logging/*.java
|
||||||
|
|
||||||
|
# compile logging slf4j module
|
||||||
|
javac --module-path mods -d mods/com.baeldung.logging.slf4j src/modules/com.baeldung.logging.slf4j/module-info.java src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/*.java
|
||||||
|
|
||||||
|
|
||||||
|
# compile logging main app module
|
||||||
|
javac --module-path mods -d mods/com.baeldung.logging.app src/modules/com.baeldung.logging.app/module-info.java src/modules/com.baeldung.logging.app/com/baeldung/logging/app/*.java
|
||||||
|
|
||||||
|
# run logging main app
|
||||||
|
# java --module-path mods -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp
|
||||||
|
|
||||||
|
# run looging main app using logback
|
||||||
|
java --module-path mods -Dlogback.configurationFile=mods/logback.xml -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<pattern>
|
||||||
|
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} -- %msg%n
|
||||||
|
</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root>
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.baeldung.logging.app;
|
||||||
|
|
||||||
|
import static java.lang.System.Logger.*;
|
||||||
|
|
||||||
|
public class MainApp {
|
||||||
|
|
||||||
|
private static System.Logger LOGGER = System.getLogger("MainApp");
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
LOGGER.log(Level.ERROR, "error test");
|
||||||
|
LOGGER.log(Level.INFO, "info test");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
module com.baeldung.logging.app {
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.baeldung.logging.slf4j;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
public class Slf4jLogger implements System.Logger {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
public Slf4jLogger(String name) {
|
||||||
|
this.name = name;
|
||||||
|
logger = LoggerFactory.getLogger(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoggable(Level level) {
|
||||||
|
switch (level) {
|
||||||
|
case OFF:
|
||||||
|
return false;
|
||||||
|
case TRACE:
|
||||||
|
return logger.isTraceEnabled();
|
||||||
|
case DEBUG:
|
||||||
|
return logger.isDebugEnabled();
|
||||||
|
case INFO:
|
||||||
|
return logger.isInfoEnabled();
|
||||||
|
case WARNING:
|
||||||
|
return logger.isWarnEnabled();
|
||||||
|
case ERROR:
|
||||||
|
return logger.isErrorEnabled();
|
||||||
|
case ALL:
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {
|
||||||
|
if (!isLoggable(level)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (level) {
|
||||||
|
case TRACE:
|
||||||
|
logger.trace(msg, thrown);
|
||||||
|
break;
|
||||||
|
case DEBUG:
|
||||||
|
logger.debug(msg, thrown);
|
||||||
|
break;
|
||||||
|
case INFO:
|
||||||
|
logger.info(msg, thrown);
|
||||||
|
break;
|
||||||
|
case WARNING:
|
||||||
|
logger.warn(msg, thrown);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
logger.error(msg, thrown);
|
||||||
|
break;
|
||||||
|
case ALL:
|
||||||
|
default:
|
||||||
|
logger.info(msg, thrown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log(Level level, ResourceBundle bundle, String format, Object... params) {
|
||||||
|
if (!isLoggable(level)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (level) {
|
||||||
|
case TRACE:
|
||||||
|
logger.trace(format, params);
|
||||||
|
break;
|
||||||
|
case DEBUG:
|
||||||
|
logger.debug(format, params);
|
||||||
|
break;
|
||||||
|
case INFO:
|
||||||
|
logger.info(format, params);
|
||||||
|
break;
|
||||||
|
case WARNING:
|
||||||
|
logger.warn(format, params);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
logger.error(format, params);
|
||||||
|
break;
|
||||||
|
case ALL:
|
||||||
|
default:
|
||||||
|
logger.info(format, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.logging.slf4j;
|
||||||
|
|
||||||
|
public class Slf4jLoggerFinder extends System.LoggerFinder {
|
||||||
|
@Override
|
||||||
|
public System.Logger getLogger(String name, Module module) {
|
||||||
|
return new Slf4jLogger(name);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
module com.baeldung.logging.slf4j {
|
||||||
|
requires org.slf4j;
|
||||||
|
provides java.lang.System.LoggerFinder
|
||||||
|
with com.baeldung.logging.slf4j.Slf4jLoggerFinder;
|
||||||
|
exports com.baeldung.logging.slf4j;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.logging;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
public class ConsoleLogger implements System.Logger {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "ConsoleLogger";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoggable(Level level) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {
|
||||||
|
System.out.printf("ConsoleLogger [%s]: %s - %s%n", level, msg, thrown);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log(Level level, ResourceBundle bundle, String format, Object... params) {
|
||||||
|
System.out.printf("ConsoleLogger [%s]: %s%n", level, MessageFormat.format(format, params));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.baeldung.logging;
|
||||||
|
|
||||||
|
public class CustomLoggerFinder extends System.LoggerFinder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public System.Logger getLogger(String name, Module module) {
|
||||||
|
return new ConsoleLogger();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
module com.baeldung.logging {
|
||||||
|
provides java.lang.System.LoggerFinder
|
||||||
|
with com.baeldung.logging.CustomLoggerFinder;
|
||||||
|
exports com.baeldung.logging;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.baeldung.java.map;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author swpraman
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MapUtil {
|
||||||
|
|
||||||
|
public static <K, V> Stream<K> keys(Map<K, V> map, V value) {
|
||||||
|
return map.entrySet()
|
||||||
|
.stream()
|
||||||
|
.filter(entry -> value.equals(entry.getValue()))
|
||||||
|
.map(Map.Entry::getKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <K, V> Set<K> getKeys(Map<K, V> map, V value) {
|
||||||
|
Set<K> keys = new HashSet<>();
|
||||||
|
for (Entry<K, V> entry : map.entrySet()) {
|
||||||
|
if (entry.getValue().equals(value)) {
|
||||||
|
keys.add(entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <K, V> K getKey(Map<K, V> map, V value) {
|
||||||
|
for (Entry<K, V> entry : map.entrySet()) {
|
||||||
|
if (entry.getValue().equals(value)) {
|
||||||
|
return entry.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.baeldung.collection;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests demonstrating differences between ArrayList#clear() and ArrayList#removeAll()
|
||||||
|
*/
|
||||||
|
class ClearVsRemoveAllUnitTest {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void givenArrayListWithElements_whenClear_thenListBecomesEmpty() {
|
||||||
|
Collection<Integer> collection = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
|
||||||
|
|
||||||
|
collection.clear();
|
||||||
|
|
||||||
|
assertTrue(collection.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenTwoArrayListsWithCommonElements_whenRemoveAll_thenFirstListMissElementsFromSecondList() {
|
||||||
|
Collection<Integer> firstCollection = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
|
||||||
|
Collection<Integer> secondCollection = new ArrayList<>(Arrays.asList(3, 4, 5, 6, 7));
|
||||||
|
|
||||||
|
firstCollection.removeAll(secondCollection);
|
||||||
|
|
||||||
|
assertEquals(Arrays.asList(1, 2), firstCollection);
|
||||||
|
assertEquals(Arrays.asList(3, 4, 5, 6, 7), secondCollection);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.baeldung.java.map;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.BidiMap;
|
||||||
|
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.google.common.collect.HashBiMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author swpraman
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MapUtilUnitTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingImperativeWayForSingleKey_shouldReturnSingleKey() {
|
||||||
|
Map<String, String> capitalCountryMap = new HashMap<>();
|
||||||
|
capitalCountryMap.put("Tokyo", "Japan");
|
||||||
|
capitalCountryMap.put("New Delhi", "India");
|
||||||
|
assertEquals("New Delhi", MapUtil.getKey(capitalCountryMap, "India"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingImperativeWayForAllKeys_shouldReturnAllKeys() {
|
||||||
|
Map<String, String> capitalCountryMap = new HashMap<>();
|
||||||
|
capitalCountryMap.put("Tokyo", "Japan");
|
||||||
|
capitalCountryMap.put("Berlin", "Germany");
|
||||||
|
capitalCountryMap.put("Cape Town", "South Africa");
|
||||||
|
capitalCountryMap.put("Pretoria", "South Africa");
|
||||||
|
capitalCountryMap.put("Bloemfontein", "South Africa");
|
||||||
|
|
||||||
|
assertEquals(new HashSet<String>(Arrays.asList(
|
||||||
|
new String[] {"Cape Town", "Pretoria", "Bloemfontein"})),
|
||||||
|
MapUtil.getKeys(capitalCountryMap, "South Africa"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingFunctionalWayForSingleKey_shouldReturnSingleKey() {
|
||||||
|
Map<String, String> capitalCountryMap = new HashMap<>();
|
||||||
|
capitalCountryMap.put("Tokyo", "Japan");
|
||||||
|
capitalCountryMap.put("Berlin", "Germany");
|
||||||
|
assertEquals("Berlin", MapUtil.keys(capitalCountryMap, "Germany").findFirst().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingFunctionalWayForAllKeys_shouldReturnAllKeys() {
|
||||||
|
Map<String, String> capitalCountryMap = new HashMap<>();
|
||||||
|
capitalCountryMap.put("Tokyo", "Japan");
|
||||||
|
capitalCountryMap.put("Berlin", "Germany");
|
||||||
|
capitalCountryMap.put("Cape Town", "South Africa");
|
||||||
|
capitalCountryMap.put("Pretoria", "South Africa");
|
||||||
|
capitalCountryMap.put("Bloemfontein", "South Africa");
|
||||||
|
assertEquals(new HashSet<String>(Arrays.asList(
|
||||||
|
new String[] {"Cape Town", "Pretoria", "Bloemfontein"})),
|
||||||
|
MapUtil.keys(capitalCountryMap, "South Africa").collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingBidiMap_shouldReturnKey() {
|
||||||
|
BidiMap<String, String> capitalCountryMap = new DualHashBidiMap<String, String>();
|
||||||
|
capitalCountryMap.put("Berlin", "Germany");
|
||||||
|
capitalCountryMap.put("Cape Town", "South Africa");
|
||||||
|
assertEquals("Berlin", capitalCountryMap.getKey("Germany"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingBidiMapAddDuplicateValue_shouldRemoveOldEntry() {
|
||||||
|
BidiMap<String, String> capitalCountryMap = new DualHashBidiMap<String, String>();
|
||||||
|
capitalCountryMap.put("Berlin", "Germany");
|
||||||
|
capitalCountryMap.put("Cape Town", "South Africa");
|
||||||
|
capitalCountryMap.put("Pretoria", "South Africa");
|
||||||
|
assertEquals("Pretoria", capitalCountryMap.getKey("South Africa"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingBiMap_shouldReturnKey() {
|
||||||
|
HashBiMap<String, String> capitalCountryMap = HashBiMap.create();
|
||||||
|
capitalCountryMap.put("Berlin", "Germany");
|
||||||
|
capitalCountryMap.put("Cape Town", "South Africa");
|
||||||
|
assertEquals("Berlin", capitalCountryMap.inverse().get("Germany"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=IllegalArgumentException.class)
|
||||||
|
public void whenUsingBiMapAddDuplicateValue_shouldThrowException() {
|
||||||
|
HashBiMap<String, String> capitalCountryMap = HashBiMap.create();
|
||||||
|
capitalCountryMap.put("Berlin", "Germany");
|
||||||
|
capitalCountryMap.put("Cape Town", "South Africa");
|
||||||
|
capitalCountryMap.put("Pretoria", "South Africa");
|
||||||
|
assertEquals("Berlin", capitalCountryMap.inverse().get("Germany"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -57,26 +57,6 @@
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
</plugins>
|
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -57,26 +57,6 @@
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
</plugins>
|
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.baeldung.concurrent.yield;
|
||||||
|
|
||||||
|
public class ThreadYield {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Runnable r = () -> {
|
||||||
|
int counter = 0;
|
||||||
|
while (counter < 2) {
|
||||||
|
System.out.println(Thread.currentThread()
|
||||||
|
.getName());
|
||||||
|
counter++;
|
||||||
|
Thread.yield();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new Thread(r).start();
|
||||||
|
new Thread(r).start();
|
||||||
|
}
|
||||||
|
}
|
|
@ -166,22 +166,6 @@
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
package com.baeldung.removingdecimals;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.openjdk.jmh.annotations.*;
|
||||||
|
import org.openjdk.jmh.runner.Runner;
|
||||||
|
import org.openjdk.jmh.runner.options.Options;
|
||||||
|
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This benchmark compares some of the approaches to formatting a floating-point
|
||||||
|
* value into a {@link String} while removing the decimal part.
|
||||||
|
*
|
||||||
|
* To run, simply run the {@link RemovingDecimalsManualTest#runBenchmarks()} test
|
||||||
|
* at the end of this class.
|
||||||
|
*
|
||||||
|
* The benchmark takes about 15 minutes to run. Since it is using {@link Mode#Throughput},
|
||||||
|
* higher numbers mean better performance.
|
||||||
|
*/
|
||||||
|
@BenchmarkMode(Mode.Throughput)
|
||||||
|
@Warmup(iterations = 5)
|
||||||
|
@Measurement(iterations = 20)
|
||||||
|
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
public class RemovingDecimalsManualTest {
|
||||||
|
@Param(value = {"345.56", "345345345.56", "345345345345345345.56"}) double doubleValue;
|
||||||
|
|
||||||
|
NumberFormat nf;
|
||||||
|
DecimalFormat df;
|
||||||
|
|
||||||
|
@Setup
|
||||||
|
public void readyFormatters() {
|
||||||
|
nf = NumberFormat.getInstance();
|
||||||
|
nf.setMaximumFractionDigits(0);
|
||||||
|
df = new DecimalFormat("#,###");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public String whenCastToInt_thenValueIsTruncated() {
|
||||||
|
return String.valueOf((int) doubleValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public String whenUsingStringFormat_thenValueIsRounded() {
|
||||||
|
return String.format("%.0f", doubleValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public String whenUsingNumberFormat_thenValueIsRounded() {
|
||||||
|
nf.setRoundingMode(RoundingMode.HALF_UP);
|
||||||
|
return nf.format(doubleValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public String whenUsingNumberFormatWithFloor_thenValueIsTruncated() {
|
||||||
|
nf.setRoundingMode(RoundingMode.FLOOR);
|
||||||
|
return nf.format(doubleValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public String whenUsingDecimalFormat_thenValueIsRounded() {
|
||||||
|
df.setRoundingMode(RoundingMode.HALF_UP);
|
||||||
|
return df.format(doubleValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public String whenUsingDecimalFormatWithFloor_thenValueIsTruncated() {
|
||||||
|
df.setRoundingMode(RoundingMode.FLOOR);
|
||||||
|
return df.format(doubleValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public String whenUsingBigDecimalDoubleValue_thenValueIsTruncated() {
|
||||||
|
BigDecimal big = new BigDecimal(doubleValue);
|
||||||
|
big = big.setScale(0, RoundingMode.FLOOR);
|
||||||
|
return big.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public String whenUsingBigDecimalDoubleValueWithHalfUp_thenValueIsRounded() {
|
||||||
|
BigDecimal big = new BigDecimal(doubleValue);
|
||||||
|
big = big.setScale(0, RoundingMode.HALF_UP);
|
||||||
|
return big.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runBenchmarks() throws Exception {
|
||||||
|
Options options = new OptionsBuilder()
|
||||||
|
.include(this.getClass().getSimpleName()).threads(1)
|
||||||
|
.forks(1).shouldFailOnError(true).shouldDoGC(true)
|
||||||
|
.jvmArgs("-server").build();
|
||||||
|
|
||||||
|
new Runner(options).run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.baeldung.removingdecimals;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that demonstrate some different approaches for formatting a
|
||||||
|
* floating-point value into a {@link String} while removing the decimal part.
|
||||||
|
*/
|
||||||
|
public class RemovingDecimalsUnitTest {
|
||||||
|
private final double doubleValue = 345.56;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCastToInt_thenValueIsTruncated() {
|
||||||
|
String truncated = String.valueOf((int) doubleValue);
|
||||||
|
assertEquals("345", truncated);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenALargeDouble_whenCastToInt_thenValueIsNotTruncated() {
|
||||||
|
double outOfIntRange = 6_000_000_000.56;
|
||||||
|
String truncationAttempt = String.valueOf((int) outOfIntRange);
|
||||||
|
assertNotEquals("6000000000", truncationAttempt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingStringFormat_thenValueIsRounded() {
|
||||||
|
String rounded = String.format("%.0f", doubleValue);
|
||||||
|
assertEquals("346", rounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenALargeDouble_whenUsingStringFormat_thenValueIsStillRounded() {
|
||||||
|
double outOfIntRange = 6_000_000_000.56;
|
||||||
|
String rounded = String.format("%.0f", outOfIntRange);
|
||||||
|
assertEquals("6000000001", rounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingNumberFormat_thenValueIsRounded() {
|
||||||
|
NumberFormat nf = NumberFormat.getInstance();
|
||||||
|
nf.setMaximumFractionDigits(0);
|
||||||
|
nf.setRoundingMode(RoundingMode.HALF_UP);
|
||||||
|
String rounded = nf.format(doubleValue);
|
||||||
|
assertEquals("346", rounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingNumberFormatWithFloor_thenValueIsTruncated() {
|
||||||
|
NumberFormat nf = NumberFormat.getInstance();
|
||||||
|
nf.setMaximumFractionDigits(0);
|
||||||
|
nf.setRoundingMode(RoundingMode.FLOOR);
|
||||||
|
String truncated = nf.format(doubleValue);
|
||||||
|
assertEquals("345", truncated);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingDecimalFormat_thenValueIsRounded() {
|
||||||
|
DecimalFormat df = new DecimalFormat("#,###");
|
||||||
|
df.setRoundingMode(RoundingMode.HALF_UP);
|
||||||
|
String rounded = df.format(doubleValue);
|
||||||
|
assertEquals("346", rounded);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingDecimalFormatWithFloor_thenValueIsTruncated() {
|
||||||
|
DecimalFormat df = new DecimalFormat("#,###");
|
||||||
|
df.setRoundingMode(RoundingMode.FLOOR);
|
||||||
|
String truncated = df.format(doubleValue);
|
||||||
|
assertEquals("345", truncated);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingBigDecimalDoubleValue_thenValueIsTruncated() {
|
||||||
|
BigDecimal big = new BigDecimal(doubleValue);
|
||||||
|
big = big.setScale(0, RoundingMode.FLOOR);
|
||||||
|
String truncated = big.toString();
|
||||||
|
assertEquals("345", truncated);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingBigDecimalDoubleValueWithHalfUp_thenValueIsRounded() {
|
||||||
|
BigDecimal big = new BigDecimal(doubleValue);
|
||||||
|
big = big.setScale(0, RoundingMode.HALF_UP);
|
||||||
|
String truncated = big.toString();
|
||||||
|
assertEquals("346", truncated);
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,6 @@
|
||||||
- [Generics in Kotlin](http://www.baeldung.com/kotlin-generics)
|
- [Generics in Kotlin](http://www.baeldung.com/kotlin-generics)
|
||||||
- [Introduction to Kotlin Coroutines](http://www.baeldung.com/kotlin-coroutines)
|
- [Introduction to Kotlin Coroutines](http://www.baeldung.com/kotlin-coroutines)
|
||||||
- [Destructuring Declarations in Kotlin](http://www.baeldung.com/kotlin-destructuring-declarations)
|
- [Destructuring Declarations in Kotlin](http://www.baeldung.com/kotlin-destructuring-declarations)
|
||||||
- [Kotlin with Mockito](http://www.baeldung.com/kotlin-mockito)
|
|
||||||
- [Lazy Initialization in Kotlin](http://www.baeldung.com/kotlin-lazy-initialization)
|
- [Lazy Initialization in Kotlin](http://www.baeldung.com/kotlin-lazy-initialization)
|
||||||
- [Overview of Kotlin Collections API](http://www.baeldung.com/kotlin-collections-api)
|
- [Overview of Kotlin Collections API](http://www.baeldung.com/kotlin-collections-api)
|
||||||
- [Converting a List to Map in Kotlin](http://www.baeldung.com/kotlin-list-to-map)
|
- [Converting a List to Map in Kotlin](http://www.baeldung.com/kotlin-list-to-map)
|
||||||
|
@ -19,8 +18,6 @@
|
||||||
- [Extension Methods in Kotlin](http://www.baeldung.com/kotlin-extension-methods)
|
- [Extension Methods in Kotlin](http://www.baeldung.com/kotlin-extension-methods)
|
||||||
- [Infix Functions in Kotlin](http://www.baeldung.com/kotlin-infix-functions)
|
- [Infix Functions in Kotlin](http://www.baeldung.com/kotlin-infix-functions)
|
||||||
- [Try-with-resources in Kotlin](http://www.baeldung.com/kotlin-try-with-resources)
|
- [Try-with-resources in Kotlin](http://www.baeldung.com/kotlin-try-with-resources)
|
||||||
- [HTTP Requests with Kotlin and khttp](http://www.baeldung.com/kotlin-khttp)
|
|
||||||
- [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection)
|
|
||||||
- [Regular Expressions in Kotlin](http://www.baeldung.com/kotlin-regular-expressions)
|
- [Regular Expressions in Kotlin](http://www.baeldung.com/kotlin-regular-expressions)
|
||||||
- [Objects in Kotlin](http://www.baeldung.com/kotlin-objects)
|
- [Objects in Kotlin](http://www.baeldung.com/kotlin-objects)
|
||||||
- [Reading from a File in Kotlin](http://www.baeldung.com/kotlin-read-file)
|
- [Reading from a File in Kotlin](http://www.baeldung.com/kotlin-read-file)
|
||||||
|
@ -28,11 +25,7 @@
|
||||||
- [Filtering Kotlin Collections](http://www.baeldung.com/kotlin-filter-collection)
|
- [Filtering Kotlin Collections](http://www.baeldung.com/kotlin-filter-collection)
|
||||||
- [Writing to a File in Kotlin](http://www.baeldung.com/kotlin-write-file)
|
- [Writing to a File in Kotlin](http://www.baeldung.com/kotlin-write-file)
|
||||||
- [Lambda Expressions in Kotlin](http://www.baeldung.com/kotlin-lambda-expressions)
|
- [Lambda Expressions in Kotlin](http://www.baeldung.com/kotlin-lambda-expressions)
|
||||||
- [Writing Specifications with Kotlin and Spek](http://www.baeldung.com/kotlin-spek)
|
|
||||||
- [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson)
|
|
||||||
- [Kotlin String Templates](http://www.baeldung.com/kotlin-string-template)
|
- [Kotlin String Templates](http://www.baeldung.com/kotlin-string-template)
|
||||||
- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security)
|
|
||||||
- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor)
|
|
||||||
- [Working with Enums in Kotlin](http://www.baeldung.com/kotlin-enum)
|
- [Working with Enums in Kotlin](http://www.baeldung.com/kotlin-enum)
|
||||||
- [Create a Java and Kotlin Project with Maven](http://www.baeldung.com/kotlin-maven-java-project)
|
- [Create a Java and Kotlin Project with Maven](http://www.baeldung.com/kotlin-maven-java-project)
|
||||||
- [Reflection with Kotlin](http://www.baeldung.com/kotlin-reflection)
|
- [Reflection with Kotlin](http://www.baeldung.com/kotlin-reflection)
|
||||||
|
@ -40,5 +33,4 @@
|
||||||
- [Idiomatic Logging in Kotlin](http://www.baeldung.com/kotlin-logging)
|
- [Idiomatic Logging in Kotlin](http://www.baeldung.com/kotlin-logging)
|
||||||
- [Kotlin Constructors](https://www.baeldung.com/kotlin-constructors)
|
- [Kotlin Constructors](https://www.baeldung.com/kotlin-constructors)
|
||||||
- [Creational Design Patterns in Kotlin: Builder](https://www.baeldung.com/kotlin-builder-pattern)
|
- [Creational Design Patterns in Kotlin: Builder](https://www.baeldung.com/kotlin-builder-pattern)
|
||||||
- [Kotlin Nested and Inner Classes](https://www.baeldung.com/kotlin-inner-classes)
|
- [Kotlin Nested and Inner Classes](https://www.baeldung.com/kotlin-inner-classes)
|
||||||
- [Guide to the Kotlin Exposed Framework](https://www.baeldung.com/kotlin-exposed-persistence)
|
|
|
@ -6,7 +6,6 @@ version '1.0-SNAPSHOT'
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.2.41'
|
ext.kotlin_version = '1.2.41'
|
||||||
ext.ktor_version = '0.9.2'
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -44,14 +43,6 @@ sourceSets {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "io.ktor:ktor-server-netty:$ktor_version"
|
|
||||||
compile "ch.qos.logback:logback-classic:1.2.1"
|
compile "ch.qos.logback:logback-classic:1.2.1"
|
||||||
compile "io.ktor:ktor-gson:$ktor_version"
|
|
||||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||||
implementation 'com.beust:klaxon:3.0.1'
|
|
||||||
|
|
||||||
}
|
|
||||||
task runServer(type: JavaExec) {
|
|
||||||
main = 'APIServer'
|
|
||||||
classpath = sourceSets.main.runtimeClasspath
|
|
||||||
}
|
}
|
|
@ -1,35 +0,0 @@
|
||||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
|
||||||
|
|
||||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
|
||||||
version="3.0">
|
|
||||||
<!-- path to application.conf file, required -->
|
|
||||||
<!-- note that this file is always loaded as an absolute path from the classpath -->
|
|
||||||
<context-param>
|
|
||||||
<param-name>io.ktor.ktor.config</param-name>
|
|
||||||
<param-value>application.conf</param-value>
|
|
||||||
</context-param>
|
|
||||||
|
|
||||||
<servlet>
|
|
||||||
<display-name>KtorServlet</display-name>
|
|
||||||
<servlet-name>KtorServlet</servlet-name>
|
|
||||||
<servlet-class>io.ktor.server.servlet.ServletApplicationEngine</servlet-class>
|
|
||||||
|
|
||||||
<!-- required! -->
|
|
||||||
<async-supported>true</async-supported>
|
|
||||||
|
|
||||||
<!-- 100mb max file upload, optional -->
|
|
||||||
<multipart-config>
|
|
||||||
<max-file-size>304857600</max-file-size>
|
|
||||||
<max-request-size>304857600</max-request-size>
|
|
||||||
<file-size-threshold>0</file-size-threshold>
|
|
||||||
</multipart-config>
|
|
||||||
</servlet>
|
|
||||||
|
|
||||||
<servlet-mapping>
|
|
||||||
<servlet-name>KtorServlet</servlet-name>
|
|
||||||
<url-pattern>/</url-pattern>
|
|
||||||
</servlet-mapping>
|
|
||||||
|
|
||||||
</web-app>
|
|
|
@ -12,33 +12,7 @@
|
||||||
<relativePath>../parent-kotlin</relativePath>
|
<relativePath>../parent-kotlin</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>exposed</id>
|
|
||||||
<name>exposed</name>
|
|
||||||
<url>https://dl.bintray.com/kotlin/exposed</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.spek</groupId>
|
|
||||||
<artifactId>spek-api</artifactId>
|
|
||||||
<version>1.1.5</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.spek</groupId>
|
|
||||||
<artifactId>spek-subject-extension</artifactId>
|
|
||||||
<version>1.1.5</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.spek</groupId>
|
|
||||||
<artifactId>spek-junit-platform-engine</artifactId>
|
|
||||||
<version>1.1.5</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-math3</artifactId>
|
<artifactId>commons-math3</artifactId>
|
||||||
|
@ -50,38 +24,12 @@
|
||||||
<version>${junit.platform.version}</version>
|
<version>${junit.platform.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>khttp</groupId>
|
|
||||||
<artifactId>khttp</artifactId>
|
|
||||||
<version>${khttp.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.nhaarman</groupId>
|
|
||||||
<artifactId>mockito-kotlin</artifactId>
|
|
||||||
<version>${mockito-kotlin.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.salomonbrys.kodein</groupId>
|
|
||||||
<artifactId>kodein</artifactId>
|
|
||||||
<version>${kodein.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.assertj</groupId>
|
<groupId>org.assertj</groupId>
|
||||||
<artifactId>assertj-core</artifactId>
|
<artifactId>assertj-core</artifactId>
|
||||||
<version>${assertj.version}</version>
|
<version>${assertj.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.beust</groupId>
|
|
||||||
<artifactId>klaxon</artifactId>
|
|
||||||
<version>${klaxon.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.exposed</groupId>
|
|
||||||
<artifactId>exposed</artifactId>
|
|
||||||
<version>${exposed.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
|
@ -107,19 +55,20 @@
|
||||||
<artifactId>fuel-coroutines</artifactId>
|
<artifactId>fuel-coroutines</artifactId>
|
||||||
<version>${fuel.version}</version>
|
<version>${fuel.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>nl.komponents.kovenant</groupId>
|
||||||
|
<artifactId>kovenant</artifactId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
<type>pom</type>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<mockito-kotlin.version>1.5.0</mockito-kotlin.version>
|
|
||||||
<kodein.version>4.1.0</kodein.version>
|
|
||||||
<klaxon.version>3.0.4</klaxon.version>
|
|
||||||
<khttp.version>0.1.0</khttp.version>
|
|
||||||
<commons-math3.version>3.6.1</commons-math3.version>
|
<commons-math3.version>3.6.1</commons-math3.version>
|
||||||
<junit.platform.version>1.1.1</junit.platform.version>
|
<junit.platform.version>1.1.1</junit.platform.version>
|
||||||
<junit.vintage.version>5.2.0</junit.vintage.version>
|
<junit.vintage.version>5.2.0</junit.vintage.version>
|
||||||
<assertj.version>3.10.0</assertj.version>
|
<assertj.version>3.10.0</assertj.version>
|
||||||
<h2database.version>1.4.197</h2database.version>
|
<h2database.version>1.4.197</h2database.version>
|
||||||
<exposed.version>0.10.4</exposed.version>
|
|
||||||
<fuel.version>1.15.0</fuel.version>
|
<fuel.version>1.15.0</fuel.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
@file:JvmName("APIServer")
|
|
||||||
|
|
||||||
|
|
||||||
import io.ktor.application.call
|
|
||||||
import io.ktor.application.install
|
|
||||||
import io.ktor.features.CallLogging
|
|
||||||
import io.ktor.features.ContentNegotiation
|
|
||||||
import io.ktor.features.DefaultHeaders
|
|
||||||
import io.ktor.gson.gson
|
|
||||||
import io.ktor.request.path
|
|
||||||
import io.ktor.request.receive
|
|
||||||
import io.ktor.response.respond
|
|
||||||
import io.ktor.routing.*
|
|
||||||
import io.ktor.server.engine.embeddedServer
|
|
||||||
import io.ktor.server.netty.Netty
|
|
||||||
import org.slf4j.event.Level
|
|
||||||
|
|
||||||
data class Author(val name: String, val website: String)
|
|
||||||
data class ToDo(var id: Int, val name: String, val description: String, val completed: Boolean)
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
|
|
||||||
val toDoList = ArrayList<ToDo>();
|
|
||||||
val jsonResponse = """{
|
|
||||||
"id": 1,
|
|
||||||
"task": "Pay waterbill",
|
|
||||||
"description": "Pay water bill today",
|
|
||||||
}"""
|
|
||||||
|
|
||||||
|
|
||||||
embeddedServer(Netty, 8080) {
|
|
||||||
install(DefaultHeaders) {
|
|
||||||
header("X-Developer", "Baeldung")
|
|
||||||
}
|
|
||||||
install(CallLogging) {
|
|
||||||
level = Level.DEBUG
|
|
||||||
filter { call -> call.request.path().startsWith("/todo") }
|
|
||||||
filter { call -> call.request.path().startsWith("/author") }
|
|
||||||
}
|
|
||||||
install(ContentNegotiation) {
|
|
||||||
gson {
|
|
||||||
setPrettyPrinting()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
routing() {
|
|
||||||
route("/todo") {
|
|
||||||
post {
|
|
||||||
var toDo = call.receive<ToDo>();
|
|
||||||
toDo.id = toDoList.size;
|
|
||||||
toDoList.add(toDo);
|
|
||||||
call.respond("Added")
|
|
||||||
|
|
||||||
}
|
|
||||||
delete("/{id}") {
|
|
||||||
call.respond(toDoList.removeAt(call.parameters["id"]!!.toInt()));
|
|
||||||
}
|
|
||||||
get("/{id}") {
|
|
||||||
|
|
||||||
call.respond(toDoList[call.parameters["id"]!!.toInt()]);
|
|
||||||
}
|
|
||||||
get {
|
|
||||||
call.respond(toDoList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
get("/author"){
|
|
||||||
call.respond(Author("Baeldung","baeldung.com"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}.start(wait = true)
|
|
||||||
}
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
package com.baeldung.kotlin
|
||||||
|
|
||||||
|
import nl.komponents.kovenant.*
|
||||||
|
import nl.komponents.kovenant.Kovenant.deferred
|
||||||
|
import nl.komponents.kovenant.combine.and
|
||||||
|
import nl.komponents.kovenant.combine.combine
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
class KovenantTest {
|
||||||
|
@Before
|
||||||
|
fun setupTestMode() {
|
||||||
|
Kovenant.testMode { error ->
|
||||||
|
println("An unexpected error occurred")
|
||||||
|
Assert.fail(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSuccessfulDeferred() {
|
||||||
|
val def = deferred<Long, Exception>()
|
||||||
|
Assert.assertFalse(def.promise.isDone())
|
||||||
|
|
||||||
|
def.resolve(1L)
|
||||||
|
Assert.assertTrue(def.promise.isDone())
|
||||||
|
Assert.assertTrue(def.promise.isSuccess())
|
||||||
|
Assert.assertFalse(def.promise.isFailure())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFailedDeferred() {
|
||||||
|
val def = deferred<Long, Exception>()
|
||||||
|
Assert.assertFalse(def.promise.isDone())
|
||||||
|
|
||||||
|
def.reject(RuntimeException())
|
||||||
|
Assert.assertTrue(def.promise.isDone())
|
||||||
|
Assert.assertFalse(def.promise.isSuccess())
|
||||||
|
Assert.assertTrue(def.promise.isFailure())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testResolveDeferredTwice() {
|
||||||
|
val def = deferred<Long, Exception>()
|
||||||
|
def.resolve(1L)
|
||||||
|
try {
|
||||||
|
def.resolve(1L)
|
||||||
|
} catch (e: AssertionError) {
|
||||||
|
// Expected.
|
||||||
|
// This is slightly unusual. The AssertionError comes from Assert.fail() from setupTestMode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSuccessfulTask() {
|
||||||
|
val promise = task { 1L }
|
||||||
|
Assert.assertTrue(promise.isDone())
|
||||||
|
Assert.assertTrue(promise.isSuccess())
|
||||||
|
Assert.assertFalse(promise.isFailure())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFailedTask() {
|
||||||
|
val promise = task { throw RuntimeException() }
|
||||||
|
Assert.assertTrue(promise.isDone())
|
||||||
|
Assert.assertFalse(promise.isSuccess())
|
||||||
|
Assert.assertTrue(promise.isFailure())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCallbacks() {
|
||||||
|
val promise = task { 1L }
|
||||||
|
|
||||||
|
promise.success {
|
||||||
|
println("This was a success")
|
||||||
|
Assert.assertEquals(1L, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.fail {
|
||||||
|
println(it)
|
||||||
|
Assert.fail("This shouldn't happen")
|
||||||
|
}
|
||||||
|
|
||||||
|
promise.always {
|
||||||
|
println("This always happens")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetValues() {
|
||||||
|
val promise = task { 1L }
|
||||||
|
Assert.assertEquals(1L, promise.get())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAllSucceed() {
|
||||||
|
val numbers = all(
|
||||||
|
task { 1L },
|
||||||
|
task { 2L },
|
||||||
|
task { 3L }
|
||||||
|
)
|
||||||
|
|
||||||
|
Assert.assertEquals(listOf(1L, 2L, 3L), numbers.get())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testOneFails() {
|
||||||
|
val runtimeException = RuntimeException()
|
||||||
|
|
||||||
|
val numbers = all(
|
||||||
|
task { 1L },
|
||||||
|
task { 2L },
|
||||||
|
task { throw runtimeException }
|
||||||
|
)
|
||||||
|
|
||||||
|
Assert.assertEquals(runtimeException, numbers.getError())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAnySucceeds() {
|
||||||
|
val promise = any(
|
||||||
|
task {
|
||||||
|
TimeUnit.SECONDS.sleep(3)
|
||||||
|
1L
|
||||||
|
},
|
||||||
|
task {
|
||||||
|
TimeUnit.SECONDS.sleep(2)
|
||||||
|
2L
|
||||||
|
},
|
||||||
|
task {
|
||||||
|
TimeUnit.SECONDS.sleep(1)
|
||||||
|
3L
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Assert.assertTrue(promise.isDone())
|
||||||
|
Assert.assertTrue(promise.isSuccess())
|
||||||
|
Assert.assertFalse(promise.isFailure())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAllFails() {
|
||||||
|
val runtimeException = RuntimeException()
|
||||||
|
val ioException = IOException()
|
||||||
|
val illegalStateException = IllegalStateException()
|
||||||
|
val promise = any(
|
||||||
|
task {
|
||||||
|
TimeUnit.SECONDS.sleep(3)
|
||||||
|
throw runtimeException
|
||||||
|
},
|
||||||
|
task {
|
||||||
|
TimeUnit.SECONDS.sleep(2)
|
||||||
|
throw ioException
|
||||||
|
},
|
||||||
|
task {
|
||||||
|
TimeUnit.SECONDS.sleep(1)
|
||||||
|
throw illegalStateException
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Assert.assertTrue(promise.isDone())
|
||||||
|
Assert.assertFalse(promise.isSuccess())
|
||||||
|
Assert.assertTrue(promise.isFailure())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testSimpleCombine() {
|
||||||
|
val promise = task { 1L } and task { "Hello" }
|
||||||
|
val result = promise.get()
|
||||||
|
|
||||||
|
Assert.assertEquals(1L, result.first)
|
||||||
|
Assert.assertEquals("Hello", result.second)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testLongerCombine() {
|
||||||
|
val promise = combine(
|
||||||
|
task { 1L },
|
||||||
|
task { "Hello" },
|
||||||
|
task { Currency.getInstance("USD") }
|
||||||
|
)
|
||||||
|
val result = promise.get()
|
||||||
|
|
||||||
|
Assert.assertEquals(1L, result.first)
|
||||||
|
Assert.assertEquals("Hello", result.second)
|
||||||
|
Assert.assertEquals(Currency.getInstance("USD"), result.third)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.baeldung.kotlin
|
||||||
|
|
||||||
|
import nl.komponents.kovenant.Promise
|
||||||
|
import nl.komponents.kovenant.any
|
||||||
|
import nl.komponents.kovenant.task
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Ignore
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
// Note that this can not run in the same test run if KovenantTest has already been executed
|
||||||
|
class KovenantTimeoutTest {
|
||||||
|
@Test
|
||||||
|
fun testTimeout() {
|
||||||
|
val promise = timedTask(1000) { "Hello" }
|
||||||
|
val result = promise.get()
|
||||||
|
Assert.assertEquals("Hello", result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTimeoutExpired() {
|
||||||
|
val promise = timedTask(1000) {
|
||||||
|
Thread.sleep(3000)
|
||||||
|
"Hello"
|
||||||
|
}
|
||||||
|
val result = promise.get()
|
||||||
|
Assert.assertNull(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> timedTask(millis: Long, body: () -> T) : Promise<T?, List<Exception>> {
|
||||||
|
val timeoutTask = task {
|
||||||
|
Thread.sleep(millis)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
val activeTask = task(body = body)
|
||||||
|
return any(activeTask, timeoutTask)
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,22 +36,6 @@
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.baeldung.hibernate.proxy;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.BatchSize;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@BatchSize(size = 5)
|
||||||
|
public class BatchEmployee implements Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue (strategy = GenerationType.SEQUENCE)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
private Boss boss;
|
||||||
|
|
||||||
|
@Column(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(name = "surname")
|
||||||
|
private String surname;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boss getBoss() {
|
||||||
|
return boss;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBoss(Boss boss) {
|
||||||
|
this.boss = boss;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSurname() {
|
||||||
|
return surname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSurname(String surname) {
|
||||||
|
this.surname = surname;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.baeldung.hibernate.proxy;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Boss implements Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(name = "surname")
|
||||||
|
private String surname;
|
||||||
|
|
||||||
|
public Boss() { }
|
||||||
|
|
||||||
|
public Boss(String name, String surname) {
|
||||||
|
this.name = name;
|
||||||
|
this.surname = surname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSurname() {
|
||||||
|
return surname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSurname(String surname) {
|
||||||
|
this.surname = surname;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.baeldung.hibernate.proxy;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Employee implements Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue (strategy = GenerationType.SEQUENCE)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
private Boss boss;
|
||||||
|
|
||||||
|
@Column(name = "name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(name = "surname")
|
||||||
|
private String surname;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boss getBoss() {
|
||||||
|
return boss;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBoss(Boss boss) {
|
||||||
|
this.boss = boss;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSurname() {
|
||||||
|
return surname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSurname(String surname) {
|
||||||
|
this.surname = surname;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.baeldung.hibernate.proxy;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.boot.Metadata;
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
import org.hibernate.boot.SessionFactoryBuilder;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
public class HibernateUtil {
|
||||||
|
|
||||||
|
private static SessionFactory sessionFactory;
|
||||||
|
private static String PROPERTY_FILE_NAME;
|
||||||
|
|
||||||
|
public static SessionFactory getSessionFactory(String propertyFileName) throws IOException {
|
||||||
|
PROPERTY_FILE_NAME = propertyFileName;
|
||||||
|
if (sessionFactory == null) {
|
||||||
|
ServiceRegistry serviceRegistry = configureServiceRegistry();
|
||||||
|
sessionFactory = getSessionFactoryBuilder(serviceRegistry).build();
|
||||||
|
}
|
||||||
|
return sessionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SessionFactoryBuilder getSessionFactoryBuilder(ServiceRegistry serviceRegistry) {
|
||||||
|
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
|
||||||
|
metadataSources.addPackage("com.baeldung.hibernate.proxy");
|
||||||
|
metadataSources.addAnnotatedClass(Boss.class);
|
||||||
|
metadataSources.addAnnotatedClass(Employee.class);
|
||||||
|
|
||||||
|
Metadata metadata = metadataSources.buildMetadata();
|
||||||
|
return metadata.getSessionFactoryBuilder();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServiceRegistry configureServiceRegistry() throws IOException {
|
||||||
|
Properties properties = getProperties();
|
||||||
|
return new StandardServiceRegistryBuilder().applySettings(properties)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Properties getProperties() throws IOException {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
URL propertiesURL = Thread.currentThread()
|
||||||
|
.getContextClassLoader()
|
||||||
|
.getResource(StringUtils.defaultString(PROPERTY_FILE_NAME, "hibernate.properties"));
|
||||||
|
try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) {
|
||||||
|
properties.load(inputStream);
|
||||||
|
}
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.baeldung.hibernate.proxy;
|
||||||
|
|
||||||
|
import org.hibernate.*;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
public class HibernateProxyUnitTest {
|
||||||
|
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init(){
|
||||||
|
try {
|
||||||
|
session = HibernateUtil.getSessionFactory("hibernate.properties")
|
||||||
|
.openSession();
|
||||||
|
} catch (HibernateException | IOException e) {
|
||||||
|
fail("Failed to initiate Hibernate Session [Exception:" + e.toString() + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
Boss boss = new Boss("Eduard", "Freud");
|
||||||
|
session.save(boss);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void close(){
|
||||||
|
if(session != null) {
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = NullPointerException.class)
|
||||||
|
public void givenAnInexistentEmployeeId_whenUseGetMethod_thenReturnNull() {
|
||||||
|
Employee employee = session.get(Employee.class, new Long(14));
|
||||||
|
assertNull(employee);
|
||||||
|
employee.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAnInexistentEmployeeId_whenUseLoadMethod_thenReturnAProxy() {
|
||||||
|
Employee employee = session.load(Employee.class, new Long(14));
|
||||||
|
assertNotNull(employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenABatchEmployeeList_whenSaveOne_thenSaveTheWholeBatch() {
|
||||||
|
Transaction transaction = session.beginTransaction();
|
||||||
|
|
||||||
|
for (long i = 1; i <= 5; i++) {
|
||||||
|
Employee employee = new Employee();
|
||||||
|
employee.setName("Employee " + i);
|
||||||
|
session.save(employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
//After this line is possible to see all the insertions in the logs
|
||||||
|
session.flush();
|
||||||
|
session.clear();
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
|
||||||
|
List<Employee> employeeList = session.createQuery("from Employee")
|
||||||
|
.setCacheMode(CacheMode.IGNORE).getResultList();
|
||||||
|
|
||||||
|
assertEquals(employeeList.size(), 5);
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,23 +61,6 @@
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
|
|
@ -83,23 +83,6 @@
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.baeldung.maths;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
|
public class BigDecimalDemo {
|
||||||
|
|
||||||
|
/** Calculate total amount to be paid for an item rounded to cents..
|
||||||
|
* @param quantity
|
||||||
|
* @param unitPrice
|
||||||
|
* @param discountRate
|
||||||
|
* @param taxRate
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static BigDecimal calculateTotalAmount(BigDecimal quantity,
|
||||||
|
BigDecimal unitPrice, BigDecimal discountRate, BigDecimal taxRate) {
|
||||||
|
BigDecimal amount = quantity.multiply(unitPrice);
|
||||||
|
BigDecimal discount = amount.multiply(discountRate);
|
||||||
|
BigDecimal discountedAmount = amount.subtract(discount);
|
||||||
|
BigDecimal tax = discountedAmount.multiply(taxRate);
|
||||||
|
BigDecimal total = discountedAmount.add(tax);
|
||||||
|
|
||||||
|
// round to 2 decimal places using HALF_EVEN
|
||||||
|
BigDecimal roundedTotal = total.setScale(2, RoundingMode.HALF_EVEN);
|
||||||
|
|
||||||
|
return roundedTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
package com.baeldung.maths;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.math.MathContext;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class BigDecimalDemoUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBigDecimalCreated_thenValueMatches() {
|
||||||
|
BigDecimal bdFromString = new BigDecimal("0.1");
|
||||||
|
BigDecimal bdFromCharArray = new BigDecimal(
|
||||||
|
new char[] { '3', '.', '1', '6', '1', '5' });
|
||||||
|
BigDecimal bdlFromInt = new BigDecimal(42);
|
||||||
|
BigDecimal bdFromLong = new BigDecimal(123412345678901L);
|
||||||
|
BigInteger bigInteger = BigInteger.probablePrime(100, new Random());
|
||||||
|
BigDecimal bdFromBigInteger = new BigDecimal(bigInteger);
|
||||||
|
|
||||||
|
assertEquals("0.1", bdFromString.toString());
|
||||||
|
assertEquals("3.1615", bdFromCharArray.toString());
|
||||||
|
assertEquals("42", bdlFromInt.toString());
|
||||||
|
assertEquals("123412345678901", bdFromLong.toString());
|
||||||
|
assertEquals(bigInteger.toString(), bdFromBigInteger.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBigDecimalCreatedFromDouble_thenValueMayNotMatch() {
|
||||||
|
BigDecimal bdFromDouble = new BigDecimal(0.1d);
|
||||||
|
assertNotEquals("0.1", bdFromDouble.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBigDecimalCreatedUsingValueOf_thenValueMatches() {
|
||||||
|
BigDecimal bdFromLong1 = BigDecimal.valueOf(123412345678901L);
|
||||||
|
BigDecimal bdFromLong2 = BigDecimal.valueOf(123412345678901L, 2);
|
||||||
|
BigDecimal bdFromDouble = BigDecimal.valueOf(0.1d);
|
||||||
|
|
||||||
|
assertEquals("123412345678901", bdFromLong1.toString());
|
||||||
|
assertEquals("1234123456789.01", bdFromLong2.toString());
|
||||||
|
assertEquals("0.1", bdFromDouble.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenEqualsCalled_thenSizeAndScaleMatched() {
|
||||||
|
BigDecimal bd1 = new BigDecimal("1.0");
|
||||||
|
BigDecimal bd2 = new BigDecimal("1.00");
|
||||||
|
|
||||||
|
assertFalse(bd1.equals(bd2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenComparingBigDecimals_thenExpectedResult() {
|
||||||
|
BigDecimal bd1 = new BigDecimal("1.0");
|
||||||
|
BigDecimal bd2 = new BigDecimal("1.00");
|
||||||
|
BigDecimal bd3 = new BigDecimal("2.0");
|
||||||
|
|
||||||
|
assertTrue(bd1.compareTo(bd3) < 0);
|
||||||
|
assertTrue(bd3.compareTo(bd1) > 0);
|
||||||
|
assertTrue(bd1.compareTo(bd2) == 0);
|
||||||
|
assertTrue(bd1.compareTo(bd3) <= 0);
|
||||||
|
assertTrue(bd1.compareTo(bd2) >= 0);
|
||||||
|
assertTrue(bd1.compareTo(bd3) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenPerformingArithmetic_thenExpectedResult() {
|
||||||
|
BigDecimal bd1 = new BigDecimal("4.0");
|
||||||
|
BigDecimal bd2 = new BigDecimal("2.0");
|
||||||
|
|
||||||
|
BigDecimal sum = bd1.add(bd2);
|
||||||
|
BigDecimal difference = bd1.subtract(bd2);
|
||||||
|
BigDecimal quotient = bd1.divide(bd2);
|
||||||
|
BigDecimal product = bd1.multiply(bd2);
|
||||||
|
|
||||||
|
assertTrue(sum.compareTo(new BigDecimal("6.0")) == 0);
|
||||||
|
assertTrue(difference.compareTo(new BigDecimal("2.0")) == 0);
|
||||||
|
assertTrue(quotient.compareTo(new BigDecimal("2.0")) == 0);
|
||||||
|
assertTrue(product.compareTo(new BigDecimal("8.0")) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGettingAttributes_thenExpectedResult() {
|
||||||
|
BigDecimal bd = new BigDecimal("-12345.6789");
|
||||||
|
|
||||||
|
assertEquals(9, bd.precision());
|
||||||
|
assertEquals(4, bd.scale());
|
||||||
|
assertEquals(-1, bd.signum());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRoundingDecimal_thenExpectedResult() {
|
||||||
|
BigDecimal bd = new BigDecimal("2.5");
|
||||||
|
// Round to 1 digit using HALF_EVEN
|
||||||
|
BigDecimal rounded = bd
|
||||||
|
.round(new MathContext(1, RoundingMode.HALF_EVEN));
|
||||||
|
|
||||||
|
assertEquals("2", rounded.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPurchaseTxn_whenCalculatingTotalAmount_thenExpectedResult() {
|
||||||
|
BigDecimal quantity = new BigDecimal("4.5");
|
||||||
|
BigDecimal unitPrice = new BigDecimal("2.69");
|
||||||
|
BigDecimal discountRate = new BigDecimal("0.10");
|
||||||
|
BigDecimal taxRate = new BigDecimal("0.0725");
|
||||||
|
|
||||||
|
BigDecimal amountToBePaid = BigDecimalDemo
|
||||||
|
.calculateTotalAmount(quantity, unitPrice, discountRate, taxRate);
|
||||||
|
assertEquals("11.68", amountToBePaid.toString());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
package com.baeldung.maths;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class BigIntegerDemoUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBigIntegerCreatedFromConstructor_thenExpectedResult() {
|
||||||
|
BigInteger biFromString = new BigInteger("1234567890987654321");
|
||||||
|
BigInteger biFromByteArray = new BigInteger(
|
||||||
|
new byte[] { 64, 64, 64, 64, 64, 64 });
|
||||||
|
BigInteger biFromSignMagnitude = new BigInteger(-1,
|
||||||
|
new byte[] { 64, 64, 64, 64, 64, 64 });
|
||||||
|
|
||||||
|
assertEquals("1234567890987654321", biFromString.toString());
|
||||||
|
assertEquals("70644700037184", biFromByteArray.toString());
|
||||||
|
assertEquals("-70644700037184", biFromSignMagnitude.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenLongConvertedToBigInteger_thenValueMatches() {
|
||||||
|
BigInteger bi = BigInteger.valueOf(2305843009213693951L);
|
||||||
|
|
||||||
|
assertEquals("2305843009213693951", bi.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenBigIntegers_whentCompared_thenExpectedResult() {
|
||||||
|
BigInteger i = new BigInteger("123456789012345678901234567890");
|
||||||
|
BigInteger j = new BigInteger("123456789012345678901234567891");
|
||||||
|
BigInteger k = new BigInteger("123456789012345678901234567892");
|
||||||
|
|
||||||
|
assertTrue(i.compareTo(i) == 0);
|
||||||
|
assertTrue(j.compareTo(i) > 0);
|
||||||
|
assertTrue(j.compareTo(k) < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenBigIntegers_whenPerformingArithmetic_thenExpectedResult() {
|
||||||
|
BigInteger i = new BigInteger("4");
|
||||||
|
BigInteger j = new BigInteger("2");
|
||||||
|
|
||||||
|
BigInteger sum = i.add(j);
|
||||||
|
BigInteger difference = i.subtract(j);
|
||||||
|
BigInteger quotient = i.divide(j);
|
||||||
|
BigInteger product = i.multiply(j);
|
||||||
|
|
||||||
|
assertEquals(new BigInteger("6"), sum);
|
||||||
|
assertEquals(new BigInteger("2"), difference);
|
||||||
|
assertEquals(new BigInteger("2"), quotient);
|
||||||
|
assertEquals(new BigInteger("8"), product);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenBigIntegers_whenPerformingBitOperations_thenExpectedResult() {
|
||||||
|
BigInteger i = new BigInteger("17");
|
||||||
|
BigInteger j = new BigInteger("7");
|
||||||
|
|
||||||
|
BigInteger and = i.and(j);
|
||||||
|
BigInteger or = i.or(j);
|
||||||
|
BigInteger not = j.not();
|
||||||
|
BigInteger xor = i.xor(j);
|
||||||
|
BigInteger andNot = i.andNot(j);
|
||||||
|
BigInteger shiftLeft = i.shiftLeft(1);
|
||||||
|
BigInteger shiftRight = i.shiftRight(1);
|
||||||
|
|
||||||
|
assertEquals(new BigInteger("1"), and);
|
||||||
|
assertEquals(new BigInteger("23"), or);
|
||||||
|
assertEquals(new BigInteger("-8"), not);
|
||||||
|
assertEquals(new BigInteger("22"), xor);
|
||||||
|
assertEquals(new BigInteger("16"), andNot);
|
||||||
|
assertEquals(new BigInteger("34"), shiftLeft);
|
||||||
|
assertEquals(new BigInteger("8"), shiftRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenBigIntegers_whenPerformingBitManipulations_thenExpectedResult() {
|
||||||
|
BigInteger i = new BigInteger("1018");
|
||||||
|
|
||||||
|
int bitCount = i.bitCount();
|
||||||
|
int bitLength = i.bitLength();
|
||||||
|
int getLowestSetBit = i.getLowestSetBit();
|
||||||
|
boolean testBit3 = i.testBit(3);
|
||||||
|
BigInteger setBit12 = i.setBit(12);
|
||||||
|
BigInteger flipBit0 = i.flipBit(0);
|
||||||
|
BigInteger clearBit3 = i.clearBit(3);
|
||||||
|
|
||||||
|
assertEquals(8, bitCount);
|
||||||
|
assertEquals(10, bitLength);
|
||||||
|
assertEquals(1, getLowestSetBit);
|
||||||
|
assertEquals(true, testBit3);
|
||||||
|
assertEquals(new BigInteger("5114"), setBit12);
|
||||||
|
assertEquals(new BigInteger("1019"), flipBit0);
|
||||||
|
assertEquals(new BigInteger("1010"), clearBit3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenBigIntegers_whenModularCalculation_thenExpectedResult() {
|
||||||
|
BigInteger i = new BigInteger("31");
|
||||||
|
BigInteger j = new BigInteger("24");
|
||||||
|
BigInteger k = new BigInteger("16");
|
||||||
|
|
||||||
|
BigInteger gcd = j.gcd(k);
|
||||||
|
BigInteger multiplyAndmod = j.multiply(k)
|
||||||
|
.mod(i);
|
||||||
|
BigInteger modInverse = j.modInverse(i);
|
||||||
|
BigInteger modPow = j.modPow(k, i);
|
||||||
|
|
||||||
|
assertEquals(new BigInteger("8"), gcd);
|
||||||
|
assertEquals(new BigInteger("12"), multiplyAndmod);
|
||||||
|
assertEquals(new BigInteger("22"), modInverse);
|
||||||
|
assertEquals(new BigInteger("7"), modPow);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenBigIntegers_whenPrimeOperations_thenExpectedResult() {
|
||||||
|
BigInteger i = BigInteger.probablePrime(100, new Random());
|
||||||
|
|
||||||
|
boolean isProbablePrime = i.isProbablePrime(1000);
|
||||||
|
assertEquals(true, isProbablePrime);
|
||||||
|
}
|
||||||
|
}
|
|
@ -86,23 +86,6 @@
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
|
|
@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
|
||||||
public class BenchmarkUnitTest
|
public class BenchmarkManualTest
|
||||||
{
|
{
|
||||||
|
|
||||||
public void
|
public void
|
|
@ -26,3 +26,4 @@
|
||||||
- [Convert a String to Title Case](http://www.baeldung.com/java-string-title-case)
|
- [Convert a String to Title Case](http://www.baeldung.com/java-string-title-case)
|
||||||
- [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string)
|
- [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string)
|
||||||
- [Java Check a String for Lowercase/Uppercase Letter, Special Character and Digit](https://www.baeldung.com/java-lowercase-uppercase-special-character-digit-regex)
|
- [Java Check a String for Lowercase/Uppercase Letter, Special Character and Digit](https://www.baeldung.com/java-lowercase-uppercase-special-character-digit-regex)
|
||||||
|
- [Convert java.util.Date to String](https://www.baeldung.com/java-util-date-to-string)
|
||||||
|
|
|
@ -71,23 +71,6 @@
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>copy-dependencies</id>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy-dependencies</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<outputDirectory>${project.build.directory}/libs</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.baeldung.string;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@ -32,5 +33,12 @@ public class JoinerSplitter {
|
||||||
.mapToObj(item -> (char) item)
|
.mapToObj(item -> (char) item)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Map<String, String> arrayToMap(String[] arrayOfString) {
|
||||||
|
return Arrays.asList(arrayOfString)
|
||||||
|
.stream()
|
||||||
|
.map(str -> str.split(":"))
|
||||||
|
.collect(Collectors.<String[], String, String>toMap(str -> str[0], str -> str[1]));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@ package com.baeldung.string;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
@ -62,5 +64,20 @@ public class JoinerSplitterUnitTest {
|
||||||
assertEquals(result, expectation);
|
assertEquals(result, expectation);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringArray_transformedToStream_convertToMap() {
|
||||||
|
|
||||||
|
String[] programming_languages = new String[] {"language:java","os:linux","editor:emacs"};
|
||||||
|
|
||||||
|
Map<String,String> expectation=new HashMap<>();
|
||||||
|
expectation.put("language", "java");
|
||||||
|
expectation.put("os", "linux");
|
||||||
|
expectation.put("editor", "emacs");
|
||||||
|
|
||||||
|
Map<String, String> result = JoinerSplitter.arrayToMap(programming_languages);
|
||||||
|
assertEquals(result, expectation);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,11 @@ package com.baeldung.string;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
|
|
||||||
|
@ -54,4 +55,18 @@ public class SplitUnitTest {
|
||||||
assertThat(resultList)
|
assertThat(resultList)
|
||||||
.containsExactly("car", "jeep", "scooter");
|
.containsExactly("car", "jeep", "scooter");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringContainsSpaces_whenSplitAndTrim_thenReturnsArray_using_Regex() {
|
||||||
|
assertThat(" car , jeep, scooter ".trim()
|
||||||
|
.split("\\s*,\\s*")).containsExactly("car", "jeep", "scooter");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringContainsSpaces_whenSplitAndTrim_thenReturnsArray_using_java_8() {
|
||||||
|
assertThat(Arrays.stream(" car , jeep, scooter ".split(","))
|
||||||
|
.map(String::trim)
|
||||||
|
.toArray(String[]::new)).containsExactly("car", "jeep", "scooter");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,11 @@
|
||||||
<artifactId>jersey-mvc-freemarker</artifactId>
|
<artifactId>jersey-mvc-freemarker</artifactId>
|
||||||
<version>${jersey.version}</version>
|
<version>${jersey.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.jersey.ext</groupId>
|
||||||
|
<artifactId>jersey-bean-validation</artifactId>
|
||||||
|
<version>${jersey.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.test-framework</groupId>
|
<groupId>org.glassfish.jersey.test-framework</groupId>
|
||||||
<artifactId>jersey-test-framework-core</artifactId>
|
<artifactId>jersey-test-framework-core</artifactId>
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package com.baeldung.jersey.server.config;
|
package com.baeldung.jersey.server.config;
|
||||||
|
|
||||||
import org.glassfish.jersey.server.ResourceConfig;
|
import org.glassfish.jersey.server.ResourceConfig;
|
||||||
|
import org.glassfish.jersey.server.ServerProperties;
|
||||||
import org.glassfish.jersey.server.mvc.freemarker.FreemarkerMvcFeature;
|
import org.glassfish.jersey.server.mvc.freemarker.FreemarkerMvcFeature;
|
||||||
|
|
||||||
public class ViewApplicationConfig extends ResourceConfig {
|
public class ViewApplicationConfig extends ResourceConfig {
|
||||||
|
|
||||||
public ViewApplicationConfig() {
|
public ViewApplicationConfig() {
|
||||||
packages("com.baeldung.jersey.server");
|
packages("com.baeldung.jersey.server");
|
||||||
|
property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
|
||||||
property(FreemarkerMvcFeature.TEMPLATE_BASE_PATH, "templates/freemarker");
|
property(FreemarkerMvcFeature.TEMPLATE_BASE_PATH, "templates/freemarker");
|
||||||
register(FreemarkerMvcFeature.class);;
|
register(FreemarkerMvcFeature.class);;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.baeldung.jersey.server.constraints;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.validation.Constraint;
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
import javax.validation.Payload;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Constraint(validatedBy = { SerialNumber.Validator.class })
|
||||||
|
public @interface SerialNumber {
|
||||||
|
|
||||||
|
String message()
|
||||||
|
|
||||||
|
default "Fruit serial number is not valid";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
|
||||||
|
public class Validator implements ConstraintValidator<SerialNumber, String> {
|
||||||
|
@Override
|
||||||
|
public void initialize(final SerialNumber serial) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(final String serial, final ConstraintValidatorContext constraintValidatorContext) {
|
||||||
|
final String serialNumRegex = "^\\d{3}-\\d{3}-\\d{4}$";
|
||||||
|
return Pattern.matches(serialNumRegex, serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,57 @@
|
||||||
package com.baeldung.jersey.server.model;
|
package com.baeldung.jersey.server.model;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
|
@XmlRootElement
|
||||||
public class Fruit {
|
public class Fruit {
|
||||||
|
|
||||||
private final String name;
|
@Min(value = 10, message = "Fruit weight must be 10 or greater")
|
||||||
private final String colour;
|
private Integer weight;
|
||||||
|
@Size(min = 5, max = 200)
|
||||||
|
private String name;
|
||||||
|
@Size(min = 5, max = 200)
|
||||||
|
private String colour;
|
||||||
|
private String serial;
|
||||||
|
|
||||||
|
public Fruit() {
|
||||||
|
}
|
||||||
|
|
||||||
public Fruit(String name, String colour) {
|
public Fruit(String name, String colour) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.colour = colour;
|
this.colour = colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColour(String colour) {
|
||||||
|
this.colour = colour;
|
||||||
|
}
|
||||||
|
|
||||||
public String getColour() {
|
public String getColour() {
|
||||||
return colour;
|
return colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getWeight() {
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeight(Integer weight) {
|
||||||
|
this.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSerial() {
|
||||||
|
return serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSerial(String serial) {
|
||||||
|
this.serial = serial;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.jersey.server.providers;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintViolation;
|
||||||
|
import javax.validation.ConstraintViolationException;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.ext.ExceptionMapper;
|
||||||
|
|
||||||
|
public class FruitExceptionMapper implements ExceptionMapper<ConstraintViolationException> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response toResponse(final ConstraintViolationException exception) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(prepareMessage(exception))
|
||||||
|
.type("text/plain")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String prepareMessage(ConstraintViolationException exception) {
|
||||||
|
final StringBuilder message = new StringBuilder();
|
||||||
|
for (ConstraintViolation<?> cv : exception.getConstraintViolations()) {
|
||||||
|
message.append(cv.getPropertyPath() + " " + cv.getMessage() + "\n");
|
||||||
|
}
|
||||||
|
return message.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,7 +5,13 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.FormParam;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
|
@ -15,7 +21,9 @@ import org.glassfish.jersey.server.mvc.ErrorTemplate;
|
||||||
import org.glassfish.jersey.server.mvc.Template;
|
import org.glassfish.jersey.server.mvc.Template;
|
||||||
import org.glassfish.jersey.server.mvc.Viewable;
|
import org.glassfish.jersey.server.mvc.Viewable;
|
||||||
|
|
||||||
|
import com.baeldung.jersey.server.constraints.SerialNumber;
|
||||||
import com.baeldung.jersey.server.model.Fruit;
|
import com.baeldung.jersey.server.model.Fruit;
|
||||||
|
import com.baeldung.jersey.service.SimpleStorageService;
|
||||||
|
|
||||||
@Path("/fruit")
|
@Path("/fruit")
|
||||||
public class FruitResource {
|
public class FruitResource {
|
||||||
|
@ -52,4 +60,49 @@ public class FruitResource {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/create")
|
||||||
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
|
public void createFruit(
|
||||||
|
@NotNull(message = "Fruit name must not be null") @FormParam("name") String name,
|
||||||
|
@NotNull(message = "Fruit colour must not be null") @FormParam("colour") String colour) {
|
||||||
|
|
||||||
|
Fruit fruit = new Fruit(name, colour);
|
||||||
|
SimpleStorageService.storeFruit(fruit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("/update")
|
||||||
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
|
public void updateFruit(@SerialNumber @FormParam("serial") String serial) {
|
||||||
|
Fruit fruit = new Fruit();
|
||||||
|
fruit.setSerial(serial);
|
||||||
|
SimpleStorageService.storeFruit(fruit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/create")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public void createFruit(@Valid Fruit fruit) {
|
||||||
|
SimpleStorageService.storeFruit(fruit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Valid
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("/search/{name}")
|
||||||
|
public Fruit findFruitByName(@PathParam("name") String name) {
|
||||||
|
return SimpleStorageService.findByName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.TEXT_HTML)
|
||||||
|
@Path("/exception")
|
||||||
|
@Valid
|
||||||
|
public Fruit exception() {
|
||||||
|
Fruit fruit = new Fruit();
|
||||||
|
fruit.setName("a");
|
||||||
|
fruit.setColour("b");
|
||||||
|
return fruit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.jersey.service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.baeldung.jersey.server.model.Fruit;
|
||||||
|
|
||||||
|
public class SimpleStorageService {
|
||||||
|
|
||||||
|
private static final Map<String, Fruit> fruits = new HashMap<String, Fruit>();
|
||||||
|
|
||||||
|
public static void storeFruit(final Fruit fruit) {
|
||||||
|
fruits.put(fruit.getName(), fruit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Fruit findByName(final String name) {
|
||||||
|
return fruits.entrySet()
|
||||||
|
.stream()
|
||||||
|
.filter(map -> name.equals(map.getKey()))
|
||||||
|
.map(map -> map.getValue())
|
||||||
|
.findFirst()
|
||||||
|
.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,41 +2,116 @@ package com.baeldung.jersey.server.rest;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.allOf;
|
import static org.hamcrest.CoreMatchers.allOf;
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import javax.ws.rs.client.Entity;
|
||||||
import javax.ws.rs.core.Application;
|
import javax.ws.rs.core.Application;
|
||||||
|
import javax.ws.rs.core.Form;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.glassfish.jersey.test.JerseyTest;
|
import org.glassfish.jersey.test.JerseyTest;
|
||||||
import org.junit.Assert;
|
import org.glassfish.jersey.test.TestProperties;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.baeldung.jersey.server.config.ViewApplicationConfig;
|
import com.baeldung.jersey.server.config.ViewApplicationConfig;
|
||||||
|
import com.baeldung.jersey.server.model.Fruit;
|
||||||
|
import com.baeldung.jersey.server.providers.FruitExceptionMapper;
|
||||||
|
|
||||||
public class FruitResourceIntegrationTest extends JerseyTest {
|
public class FruitResourceIntegrationTest extends JerseyTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Application configure() {
|
protected Application configure() {
|
||||||
return new ViewApplicationConfig();
|
enable(TestProperties.LOG_TRAFFIC);
|
||||||
|
enable(TestProperties.DUMP_ENTITY);
|
||||||
|
|
||||||
|
ViewApplicationConfig config = new ViewApplicationConfig();
|
||||||
|
config.register(FruitExceptionMapper.class);
|
||||||
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAllFruit() {
|
public void givenGetAllFruit_whenCorrectRequest_thenAllTemplateInvoked() {
|
||||||
final String response = target("/fruit/all").request()
|
final String response = target("/fruit/all").request()
|
||||||
.get(String.class);
|
.get(String.class);
|
||||||
Assert.assertThat(response, allOf(containsString("banana"), containsString("apple"), containsString("kiwi")));
|
assertThat(response, allOf(containsString("banana"), containsString("apple"), containsString("kiwi")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIndex() {
|
public void givenGetFruit_whenCorrectRequest_thenIndexTemplateInvoked() {
|
||||||
final String response = target("/fruit").request()
|
final String response = target("/fruit").request()
|
||||||
.get(String.class);
|
.get(String.class);
|
||||||
Assert.assertThat(response, containsString("Welcome Fruit Index Page!"));
|
assertThat(response, containsString("Welcome Fruit Index Page!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testErrorTemplate() {
|
public void givenGetFruitByName_whenFruitUnknown_thenErrorTemplateInvoked() {
|
||||||
final String response = target("/fruit/orange").request()
|
final String response = target("/fruit/orange").request()
|
||||||
.get(String.class);
|
.get(String.class);
|
||||||
Assert.assertThat(response, containsString("Error - Fruit not found: orange!"));
|
assertThat(response, containsString("Error - Fruit not found: orange!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenCreateFruit_whenFormContainsNullParam_thenResponseCodeIsBadRequest() {
|
||||||
|
Form form = new Form();
|
||||||
|
form.param("name", "apple");
|
||||||
|
form.param("colour", null);
|
||||||
|
Response response = target("fruit/create").request(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
|
.post(Entity.form(form));
|
||||||
|
|
||||||
|
assertEquals("Http Response should be 400 ", 400, response.getStatus());
|
||||||
|
assertThat(response.readEntity(String.class), containsString("Fruit colour must not be null"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenUpdateFruit_whenFormContainsBadSerialParam_thenResponseCodeIsBadRequest() {
|
||||||
|
Form form = new Form();
|
||||||
|
form.param("serial", "2345-2345");
|
||||||
|
|
||||||
|
Response response = target("fruit/update").request(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
|
.put(Entity.form(form));
|
||||||
|
|
||||||
|
assertEquals("Http Response should be 400 ", 400, response.getStatus());
|
||||||
|
assertThat(response.readEntity(String.class), containsString("Fruit serial number is not valid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenCreateFruit_whenFruitIsInvalid_thenResponseCodeIsBadRequest() {
|
||||||
|
Fruit fruit = new Fruit("Blueberry", "purple");
|
||||||
|
fruit.setWeight(1);
|
||||||
|
|
||||||
|
Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE)
|
||||||
|
.post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
|
assertEquals("Http Response should be 400 ", 400, response.getStatus());
|
||||||
|
assertThat(response.readEntity(String.class), containsString("Fruit weight must be 10 or greater"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenFruitExists_whenSearching_thenResponseContainsFruit() {
|
||||||
|
Fruit fruit = new Fruit();
|
||||||
|
fruit.setName("strawberry");
|
||||||
|
fruit.setWeight(20);
|
||||||
|
Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE)
|
||||||
|
.post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE));
|
||||||
|
|
||||||
|
assertEquals("Http Response should be 204 ", 204, response.getStatus());
|
||||||
|
|
||||||
|
final String json = target("fruit/search/strawberry").request()
|
||||||
|
.get(String.class);
|
||||||
|
assertThat(json, containsString("{\"name\":\"strawberry\",\"weight\":20}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenFruit_whenFruitIsInvalid_thenReponseContainsCustomExceptions() {
|
||||||
|
final Response response = target("fruit/exception").request()
|
||||||
|
.get();
|
||||||
|
|
||||||
|
assertEquals("Http Response should be 400 ", 400, response.getStatus());
|
||||||
|
String responseString = response.readEntity(String.class);
|
||||||
|
assertThat(responseString, containsString("exception.<return value>.colour size must be between 5 and 200"));
|
||||||
|
assertThat(responseString, containsString("exception.<return value>.name size must be between 5 and 200"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>jta-demo</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<description>JEE JTA demo</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.0.4.RELEASE</version>
|
||||||
|
<relativePath/>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jta-bitronix</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<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.hsqldb</groupId>
|
||||||
|
<artifactId>hsqldb</artifactId>
|
||||||
|
<version>2.4.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>autoconfiguration</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>test</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/*LiveTest.java</exclude>
|
||||||
|
<exclude>**/*IntegrationTest.java</exclude>
|
||||||
|
<exclude>**/*IntTest.java</exclude>
|
||||||
|
</excludes>
|
||||||
|
<includes>
|
||||||
|
<include>**/AutoconfigurationTest.java</include>
|
||||||
|
</includes>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<test.mime>json</test.mime>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.baeldung.jtademo;
|
||||||
|
|
||||||
|
import org.hsqldb.jdbc.pool.JDBCXADataSource;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@EnableTransactionManagement
|
||||||
|
@Configuration
|
||||||
|
@ComponentScan
|
||||||
|
public class JtaDemoApplication {
|
||||||
|
|
||||||
|
@Bean("dataSourceAccount")
|
||||||
|
public DataSource dataSource() throws Exception {
|
||||||
|
return createHsqlXADatasource("jdbc:hsqldb:mem:accountDb");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean("dataSourceAudit")
|
||||||
|
public DataSource dataSourceAudit() throws Exception {
|
||||||
|
return createHsqlXADatasource("jdbc:hsqldb:mem:auditDb");
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataSource createHsqlXADatasource(String connectionUrl) throws Exception {
|
||||||
|
JDBCXADataSource dataSource = new JDBCXADataSource();
|
||||||
|
dataSource.setUrl(connectionUrl);
|
||||||
|
dataSource.setUser("sa");
|
||||||
|
BitronixXADataSourceWrapper wrapper = new BitronixXADataSourceWrapper();
|
||||||
|
return wrapper.wrapDataSource(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean("jdbcTemplateAccount")
|
||||||
|
public JdbcTemplate jdbcTemplate(@Qualifier("dataSourceAccount") DataSource dataSource) {
|
||||||
|
return new JdbcTemplate(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean("jdbcTemplateAudit")
|
||||||
|
public JdbcTemplate jdbcTemplateAudit(@Qualifier("dataSourceAudit") DataSource dataSource) {
|
||||||
|
return new JdbcTemplate(dataSource);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.jtademo.dto;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
public class TransferLog {
|
||||||
|
private String fromAccountId;
|
||||||
|
private String toAccountId;
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
public TransferLog(String fromAccountId, String toAccountId, BigDecimal amount) {
|
||||||
|
this.fromAccountId = fromAccountId;
|
||||||
|
this.toAccountId = toAccountId;
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFromAccountId() {
|
||||||
|
return fromAccountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToAccountId() {
|
||||||
|
return toAccountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.jtademo.services;
|
||||||
|
|
||||||
|
import com.baeldung.jtademo.dto.TransferLog;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AuditService {
|
||||||
|
|
||||||
|
final JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public AuditService(@Qualifier("jdbcTemplateAudit") JdbcTemplate jdbcTemplate) {
|
||||||
|
this.jdbcTemplate = jdbcTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(String fromAccount, String toAccount, BigDecimal amount) {
|
||||||
|
jdbcTemplate.update("insert into AUDIT_LOG(FROM_ACCOUNT, TO_ACCOUNT, AMOUNT) values ?,?,?", fromAccount, toAccount, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransferLog lastTransferLog() {
|
||||||
|
return jdbcTemplate.query("select FROM_ACCOUNT,TO_ACCOUNT,AMOUNT from AUDIT_LOG order by ID desc", (ResultSetExtractor<TransferLog>) (rs) -> {
|
||||||
|
if (!rs.next())
|
||||||
|
return null;
|
||||||
|
return new TransferLog(rs.getString(1), rs.getString(2), BigDecimal.valueOf(rs.getDouble(3)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.baeldung.jtademo.services;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class BankAccountService {
|
||||||
|
|
||||||
|
final JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public BankAccountService(@Qualifier("jdbcTemplateAccount") JdbcTemplate jdbcTemplate) {
|
||||||
|
this.jdbcTemplate = jdbcTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void transfer(String fromAccountId, String toAccountId, BigDecimal amount) {
|
||||||
|
jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE-? where ID=?", amount, fromAccountId);
|
||||||
|
jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE+? where ID=?", amount, toAccountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigDecimal balanceOf(String accountId) {
|
||||||
|
return jdbcTemplate.query("select BALANCE from ACCOUNT where ID=?", new Object[] { accountId }, (ResultSetExtractor<BigDecimal>) (rs) -> {
|
||||||
|
rs.next();
|
||||||
|
return new BigDecimal(rs.getDouble(1));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.baeldung.jtademo.services;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import javax.transaction.UserTransaction;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TellerService {
|
||||||
|
private final BankAccountService bankAccountService;
|
||||||
|
private final AuditService auditService;
|
||||||
|
private final UserTransaction userTransaction;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public TellerService(BankAccountService bankAccountService, AuditService auditService, UserTransaction userTransaction) {
|
||||||
|
this.bankAccountService = bankAccountService;
|
||||||
|
this.auditService = auditService;
|
||||||
|
this.userTransaction = userTransaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void executeTransfer(String fromAccontId, String toAccountId, BigDecimal amount) {
|
||||||
|
bankAccountService.transfer(fromAccontId, toAccountId, amount);
|
||||||
|
auditService.log(fromAccontId, toAccountId, amount);
|
||||||
|
BigDecimal balance = bankAccountService.balanceOf(fromAccontId);
|
||||||
|
if (balance.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
throw new RuntimeException("Insufficient fund.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeTransferProgrammaticTx(String fromAccontId, String toAccountId, BigDecimal amount) throws Exception {
|
||||||
|
userTransaction.begin();
|
||||||
|
bankAccountService.transfer(fromAccontId, toAccountId, amount);
|
||||||
|
auditService.log(fromAccontId, toAccountId, amount);
|
||||||
|
BigDecimal balance = bankAccountService.balanceOf(fromAccontId);
|
||||||
|
if (balance.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
userTransaction.rollback();
|
||||||
|
throw new RuntimeException("Insufficient fund.");
|
||||||
|
} else {
|
||||||
|
userTransaction.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.baeldung.jtademo.services;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.datasource.init.ScriptUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class TestHelper {
|
||||||
|
final JdbcTemplate jdbcTemplateAccount;
|
||||||
|
|
||||||
|
final JdbcTemplate jdbcTemplateAudit;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public TestHelper(@Qualifier("jdbcTemplateAccount") JdbcTemplate jdbcTemplateAccount, @Qualifier("jdbcTemplateAudit") JdbcTemplate jdbcTemplateAudit) {
|
||||||
|
this.jdbcTemplateAccount = jdbcTemplateAccount;
|
||||||
|
this.jdbcTemplateAudit = jdbcTemplateAudit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runAccountDbInit() throws SQLException {
|
||||||
|
runScript("account.sql", jdbcTemplateAccount.getDataSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runAuditDbInit() throws SQLException {
|
||||||
|
runScript("audit.sql", jdbcTemplateAudit.getDataSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runScript(String scriptName, DataSource dataSouorce) throws SQLException {
|
||||||
|
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||||
|
Resource script = resourceLoader.getResource(scriptName);
|
||||||
|
try (Connection con = dataSouorce.getConnection()) {
|
||||||
|
ScriptUtils.executeSqlScript(con, script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
DROP SCHEMA PUBLIC CASCADE;
|
||||||
|
|
||||||
|
create table ACCOUNT (
|
||||||
|
ID char(8) PRIMARY KEY,
|
||||||
|
BALANCE NUMERIC(28,10)
|
||||||
|
);
|
||||||
|
|
||||||
|
insert into ACCOUNT(ID, BALANCE) values ('a0000001', 1000);
|
||||||
|
insert into ACCOUNT(ID, BALANCE) values ('a0000002', 2000);
|
|
@ -0,0 +1,8 @@
|
||||||
|
DROP SCHEMA PUBLIC CASCADE;
|
||||||
|
|
||||||
|
create table AUDIT_LOG (
|
||||||
|
ID INTEGER IDENTITY PRIMARY KEY,
|
||||||
|
FROM_ACCOUNT varchar(8),
|
||||||
|
TO_ACCOUNT varchar(8),
|
||||||
|
AMOUNT numeric(28,10)
|
||||||
|
);
|
|
@ -0,0 +1,91 @@
|
||||||
|
package com.baeldung.jtademo;
|
||||||
|
|
||||||
|
import com.baeldung.jtademo.dto.TransferLog;
|
||||||
|
import com.baeldung.jtademo.services.AuditService;
|
||||||
|
import com.baeldung.jtademo.services.BankAccountService;
|
||||||
|
import com.baeldung.jtademo.services.TellerService;
|
||||||
|
import com.baeldung.jtademo.services.TestHelper;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes = JtaDemoApplication.class)
|
||||||
|
public class JtaDemoUnitTest {
|
||||||
|
@Autowired
|
||||||
|
TestHelper testHelper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
TellerService tellerService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
BankAccountService accountService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
AuditService auditService;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void beforeTest() throws Exception {
|
||||||
|
testHelper.runAuditDbInit();
|
||||||
|
testHelper.runAccountDbInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAnnotationTx_whenNoException_thenAllCommitted() throws Exception {
|
||||||
|
tellerService.executeTransfer("a0000001", "a0000002", BigDecimal.valueOf(500));
|
||||||
|
|
||||||
|
assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500));
|
||||||
|
assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500));
|
||||||
|
|
||||||
|
TransferLog lastTransferLog = auditService.lastTransferLog();
|
||||||
|
assertThat(lastTransferLog).isNotNull();
|
||||||
|
assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001");
|
||||||
|
assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002");
|
||||||
|
assertThat(lastTransferLog.getAmount()).isEqualByComparingTo(BigDecimal.valueOf(500));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAnnotationTx_whenException_thenAllRolledBack() throws Exception {
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
tellerService.executeTransfer("a0000002", "a0000001", BigDecimal.valueOf(100000));
|
||||||
|
}).hasMessage("Insufficient fund.");
|
||||||
|
|
||||||
|
assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000));
|
||||||
|
assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000));
|
||||||
|
assertThat(auditService.lastTransferLog()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenProgrammaticTx_whenCommit_thenAllCommitted() throws Exception {
|
||||||
|
tellerService.executeTransferProgrammaticTx("a0000001", "a0000002", BigDecimal.valueOf(500));
|
||||||
|
|
||||||
|
BigDecimal result = accountService.balanceOf("a0000001");
|
||||||
|
assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500));
|
||||||
|
assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500));
|
||||||
|
|
||||||
|
TransferLog lastTransferLog = auditService.lastTransferLog();
|
||||||
|
assertThat(lastTransferLog).isNotNull();
|
||||||
|
assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001");
|
||||||
|
assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002");
|
||||||
|
assertThat(lastTransferLog.getAmount()).isEqualByComparingTo(BigDecimal.valueOf(500));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenProgrammaticTx_whenRollback_thenAllRolledBack() throws Exception {
|
||||||
|
assertThatThrownBy(() -> {
|
||||||
|
tellerService.executeTransferProgrammaticTx("a0000002", "a0000001", BigDecimal.valueOf(100000));
|
||||||
|
}).hasMessage("Insufficient fund.");
|
||||||
|
|
||||||
|
assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000));
|
||||||
|
assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000));
|
||||||
|
assertThat(auditService.lastTransferLog()).isNull();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
## Relevant articles:
|
||||||
|
|
||||||
|
- [Kotlin with Mockito](http://www.baeldung.com/kotlin-mockito)
|
||||||
|
- [HTTP Requests with Kotlin and khttp](http://www.baeldung.com/kotlin-khttp)
|
||||||
|
- [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection)
|
||||||
|
- [Writing Specifications with Kotlin and Spek](http://www.baeldung.com/kotlin-spek)
|
||||||
|
- [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson)
|
||||||
|
- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor)
|
||||||
|
- [Idiomatic Logging in Kotlin](http://www.baeldung.com/kotlin-logging)
|
||||||
|
- [Guide to the Kotlin Exposed Framework](https://www.baeldung.com/kotlin-exposed-persistence)
|
102
core-kotlin/kotlin-ktor/build.gradle → kotlin-libraries/build.gradle
Executable file → Normal file
102
core-kotlin/kotlin-ktor/build.gradle → kotlin-libraries/build.gradle
Executable file → Normal file
|
@ -1,47 +1,57 @@
|
||||||
|
|
||||||
|
|
||||||
group 'com.baeldung.ktor'
|
group 'com.baeldung.ktor'
|
||||||
version '1.0-SNAPSHOT'
|
version '1.0-SNAPSHOT'
|
||||||
|
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.2.41'
|
ext.kotlin_version = '1.2.41'
|
||||||
ext.ktor_version = '0.9.2'
|
ext.ktor_version = '0.9.2'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
||||||
}
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
apply plugin: 'java'
|
|
||||||
apply plugin: 'kotlin'
|
apply plugin: 'java'
|
||||||
apply plugin: 'application'
|
apply plugin: 'kotlin'
|
||||||
|
apply plugin: 'application'
|
||||||
mainClassName = 'APIServer.kt'
|
|
||||||
|
mainClassName = 'APIServer.kt'
|
||||||
sourceCompatibility = 1.8
|
|
||||||
compileKotlin { kotlinOptions.jvmTarget = "1.8" }
|
sourceCompatibility = 1.8
|
||||||
compileTestKotlin { kotlinOptions.jvmTarget = "1.8" }
|
compileKotlin { kotlinOptions.jvmTarget = "1.8" }
|
||||||
|
compileTestKotlin { kotlinOptions.jvmTarget = "1.8" }
|
||||||
kotlin { experimental { coroutines "enable" } }
|
|
||||||
|
kotlin { experimental { coroutines "enable" } }
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
repositories {
|
||||||
jcenter()
|
mavenCentral()
|
||||||
maven { url "https://dl.bintray.com/kotlin/ktor" }
|
jcenter()
|
||||||
}
|
maven { url "https://dl.bintray.com/kotlin/ktor" }
|
||||||
|
}
|
||||||
dependencies {
|
sourceSets {
|
||||||
compile "io.ktor:ktor-server-netty:$ktor_version"
|
main{
|
||||||
compile "ch.qos.logback:logback-classic:1.2.1"
|
kotlin{
|
||||||
compile "io.ktor:ktor-gson:$ktor_version"
|
srcDirs 'com/baeldung/ktor'
|
||||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
task runServer(type: JavaExec) {
|
}
|
||||||
main = 'APIServer'
|
|
||||||
classpath = sourceSets.main.runtimeClasspath
|
dependencies {
|
||||||
|
compile "io.ktor:ktor-server-netty:$ktor_version"
|
||||||
|
compile "ch.qos.logback:logback-classic:1.2.1"
|
||||||
|
compile "io.ktor:ktor-gson:$ktor_version"
|
||||||
|
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||||
|
implementation 'com.beust:klaxon:3.0.1'
|
||||||
|
|
||||||
|
}
|
||||||
|
task runServer(type: JavaExec) {
|
||||||
|
main = 'APIServer'
|
||||||
|
classpath = sourceSets.main.runtimeClasspath
|
||||||
}
|
}
|
0
core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.jar → kotlin-libraries/gradle/wrapper/gradle-wrapper.jar
vendored
Executable file → Normal file
0
core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.jar → kotlin-libraries/gradle/wrapper/gradle-wrapper.jar
vendored
Executable file → Normal file
10
core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.properties → kotlin-libraries/gradle/wrapper/gradle-wrapper.properties
vendored
Executable file → Normal file
10
core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.properties → kotlin-libraries/gradle/wrapper/gradle-wrapper.properties
vendored
Executable file → Normal file
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip
|
168
core-kotlin/kotlin-ktor/gradlew.bat → kotlin-libraries/gradlew.bat
vendored
Executable file → Normal file
168
core-kotlin/kotlin-ktor/gradlew.bat → kotlin-libraries/gradlew.bat
vendored
Executable file → Normal file
|
@ -1,84 +1,84 @@
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@rem
|
@rem
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
set DEFAULT_JVM_OPTS=
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
echo.
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation.
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
:findJavaFromJavaHome
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
echo.
|
echo.
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
echo location of your Java installation.
|
echo location of your Java installation.
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
:init
|
||||||
@rem Get command-line arguments, handling Windows variants
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
:win9xME_args
|
:win9xME_args
|
||||||
@rem Slurp the command line arguments.
|
@rem Slurp the command line arguments.
|
||||||
set CMD_LINE_ARGS=
|
set CMD_LINE_ARGS=
|
||||||
set _SKIP=2
|
set _SKIP=2
|
||||||
|
|
||||||
:win9xME_args_slurp
|
:win9xME_args_slurp
|
||||||
if "x%~1" == "x" goto execute
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
exit /b 1
|
exit /b 1
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
:omega
|
:omega
|
|
@ -0,0 +1,105 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>kotlin-libraries</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-kotlin</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../parent-kotlin</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>exposed</id>
|
||||||
|
<name>exposed</name>
|
||||||
|
<url>https://dl.bintray.com/kotlin/exposed</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains.spek</groupId>
|
||||||
|
<artifactId>spek-api</artifactId>
|
||||||
|
<version>1.1.5</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains.spek</groupId>
|
||||||
|
<artifactId>spek-subject-extension</artifactId>
|
||||||
|
<version>1.1.5</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains.spek</groupId>
|
||||||
|
<artifactId>spek-junit-platform-engine</artifactId>
|
||||||
|
<version>1.1.5</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-math3</artifactId>
|
||||||
|
<version>${commons-math3.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-runner</artifactId>
|
||||||
|
<version>${junit.platform.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>khttp</groupId>
|
||||||
|
<artifactId>khttp</artifactId>
|
||||||
|
<version>${khttp.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.nhaarman</groupId>
|
||||||
|
<artifactId>mockito-kotlin</artifactId>
|
||||||
|
<version>${mockito-kotlin.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.salomonbrys.kodein</groupId>
|
||||||
|
<artifactId>kodein</artifactId>
|
||||||
|
<version>${kodein.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<version>${assertj.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.beust</groupId>
|
||||||
|
<artifactId>klaxon</artifactId>
|
||||||
|
<version>${klaxon.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jetbrains.exposed</groupId>
|
||||||
|
<artifactId>exposed</artifactId>
|
||||||
|
<version>${exposed.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<version>${h2database.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<mockito-kotlin.version>1.5.0</mockito-kotlin.version>
|
||||||
|
<kodein.version>4.1.0</kodein.version>
|
||||||
|
<klaxon.version>3.0.4</klaxon.version>
|
||||||
|
<khttp.version>0.1.0</khttp.version>
|
||||||
|
<commons-math3.version>3.6.1</commons-math3.version>
|
||||||
|
<junit.platform.version>1.1.1</junit.platform.version>
|
||||||
|
<junit.vintage.version>5.2.0</junit.vintage.version>
|
||||||
|
<assertj.version>3.10.0</assertj.version>
|
||||||
|
<h2database.version>1.4.197</h2database.version>
|
||||||
|
<exposed.version>0.10.4</exposed.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
20
core-kotlin/kotlin-ktor/resources/logback.xml → kotlin-libraries/resources/logback.xml
Executable file → Normal file
20
core-kotlin/kotlin-ktor/resources/logback.xml → kotlin-libraries/resources/logback.xml
Executable file → Normal file
|
@ -1,11 +1,11 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<root level="INFO">
|
<root level="INFO">
|
||||||
<appender-ref ref="STDOUT"/>
|
<appender-ref ref="STDOUT"/>
|
||||||
</root>
|
</root>
|
||||||
</configuration>
|
</configuration>
|
4
core-kotlin/kotlin-ktor/settings.gradle → kotlin-libraries/settings.gradle
Executable file → Normal file
4
core-kotlin/kotlin-ktor/settings.gradle → kotlin-libraries/settings.gradle
Executable file → Normal file
|
@ -1,2 +1,2 @@
|
||||||
rootProject.name = 'KtorWithKotlin'
|
rootProject.name = 'KtorWithKotlin'
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.baeldung.kotlin.junit5
|
||||||
|
|
||||||
|
class Calculator {
|
||||||
|
fun add(a: Int, b: Int) = a + b
|
||||||
|
|
||||||
|
fun divide(a: Int, b: Int) = if (b == 0) {
|
||||||
|
throw DivideByZeroException(a)
|
||||||
|
} else {
|
||||||
|
a / b
|
||||||
|
}
|
||||||
|
|
||||||
|
fun square(a: Int) = a * a
|
||||||
|
|
||||||
|
fun squareRoot(a: Int) = Math.sqrt(a.toDouble())
|
||||||
|
|
||||||
|
fun log(base: Int, value: Int) = Math.log(value.toDouble()) / Math.log(base.toDouble())
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
package com.baeldung.kotlin.junit5
|
||||||
|
|
||||||
|
class DivideByZeroException(val numerator: Int) : Exception()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue