Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
823ad5ef7e
|
@ -0,0 +1 @@
|
||||||
|
/bin/
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.java.src;
|
||||||
|
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
public class RoundUpToHundred {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Scanner scanner = new Scanner(System.in);
|
||||||
|
double input = scanner.nextDouble();
|
||||||
|
scanner.close();
|
||||||
|
|
||||||
|
RoundUpToHundred.round(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long round(double input) {
|
||||||
|
long i = (long) Math.ceil(input);
|
||||||
|
return ((i + 99) / 100) * 100;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.java.src;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class RoundUpToHundredTest {
|
||||||
|
@Test
|
||||||
|
public void givenInput_whenRound_thenRoundUpToTheNearestHundred() {
|
||||||
|
assertEquals("Rounded up to hundred", 100, RoundUpToHundred.round(99));
|
||||||
|
assertEquals("Rounded up to three hundred ", 300, RoundUpToHundred.round(200.2));
|
||||||
|
assertEquals("Returns same rounded value", 400, RoundUpToHundred.round(400));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,3 +3,4 @@
|
||||||
- [Apache CXF Support for RESTful Web Services](http://www.baeldung.com/apache-cxf-rest-api)
|
- [Apache CXF Support for RESTful Web Services](http://www.baeldung.com/apache-cxf-rest-api)
|
||||||
- [A Guide to Apache CXF with Spring](http://www.baeldung.com/apache-cxf-with-spring)
|
- [A Guide to Apache CXF with Spring](http://www.baeldung.com/apache-cxf-with-spring)
|
||||||
- [Introduction to Apache CXF](http://www.baeldung.com/introduction-to-apache-cxf)
|
- [Introduction to Apache CXF](http://www.baeldung.com/introduction-to-apache-cxf)
|
||||||
|
- [Server-Sent Events (SSE) In JAX-RS](https://www.baeldung.com/java-ee-jax-rs-sse)
|
||||||
|
|
|
@ -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>
|
|
@ -1 +1,2 @@
|
||||||
/target/
|
/target/
|
||||||
|
.idea/
|
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>
|
|
@ -0,0 +1,184 @@
|
||||||
|
package com.baeldung.rds;
|
||||||
|
|
||||||
|
import com.amazonaws.auth.AWSCredentialsProvider;
|
||||||
|
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||||
|
import com.amazonaws.auth.BasicAWSCredentials;
|
||||||
|
import com.amazonaws.regions.Regions;
|
||||||
|
import com.amazonaws.services.rds.AmazonRDS;
|
||||||
|
import com.amazonaws.services.rds.AmazonRDSClientBuilder;
|
||||||
|
import com.amazonaws.services.rds.model.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class AWSRDSService {
|
||||||
|
|
||||||
|
|
||||||
|
final static Logger logger = Logger.getLogger(AWSRDSService.class.getName());
|
||||||
|
private AWSCredentialsProvider credentials;
|
||||||
|
private AmazonRDS amazonRDS;
|
||||||
|
private String db_username;
|
||||||
|
private String db_password;
|
||||||
|
private String db_database;
|
||||||
|
private String db_hostname;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* User access key and secret key must be set before execute any operation.
|
||||||
|
* Follow the link on how to get the user access and secret key
|
||||||
|
* https://aws.amazon.com/blogs/security/wheres-my-secret-access-key/
|
||||||
|
* **/
|
||||||
|
public AWSRDSService() throws IOException {
|
||||||
|
//Init RDS client with credentials and region.
|
||||||
|
credentials = new
|
||||||
|
AWSStaticCredentialsProvider(new
|
||||||
|
BasicAWSCredentials("<ACCESS_KEY>",
|
||||||
|
"<SECRET_KEY>"));
|
||||||
|
amazonRDS = AmazonRDSClientBuilder.standard().withCredentials(credentials)
|
||||||
|
.withRegion(Regions.AP_SOUTHEAST_2).build();
|
||||||
|
Properties prop = new Properties();
|
||||||
|
InputStream input = AWSRDSService.class.getClassLoader().getResourceAsStream("db.properties");
|
||||||
|
prop.load(input);
|
||||||
|
db_username = prop.getProperty("db_username");
|
||||||
|
db_password = prop.getProperty("db_password");
|
||||||
|
db_database = prop.getProperty("db_database");
|
||||||
|
}
|
||||||
|
|
||||||
|
public AWSRDSService(AmazonRDS amazonRDS){
|
||||||
|
this.amazonRDS = amazonRDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the RDS instance.
|
||||||
|
* After instance creation, update the db_hostname with endpoint in db.properties.
|
||||||
|
* */
|
||||||
|
|
||||||
|
public String launchInstance() {
|
||||||
|
|
||||||
|
String identifier = "";
|
||||||
|
CreateDBInstanceRequest request = new CreateDBInstanceRequest();
|
||||||
|
// RDS instance name
|
||||||
|
request.setDBInstanceIdentifier("Sydney");
|
||||||
|
request.setEngine("postgres");
|
||||||
|
request.setMultiAZ(false);
|
||||||
|
request.setMasterUsername(db_username);
|
||||||
|
request.setMasterUserPassword(db_password);
|
||||||
|
request.setDBName(db_database);
|
||||||
|
request.setStorageType("gp2");
|
||||||
|
request.setAllocatedStorage(10);
|
||||||
|
|
||||||
|
DBInstance instance = amazonRDS.createDBInstance(request);
|
||||||
|
|
||||||
|
// Information about the new RDS instance
|
||||||
|
identifier = instance.getDBInstanceIdentifier();
|
||||||
|
String status = instance.getDBInstanceStatus();
|
||||||
|
Endpoint endpoint = instance.getEndpoint();
|
||||||
|
String endpoint_url = "Endpoint URL not available yet.";
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint_url = endpoint.toString();
|
||||||
|
}
|
||||||
|
logger.info(identifier + "\t" + status);
|
||||||
|
logger.info(endpoint_url);
|
||||||
|
|
||||||
|
return identifier;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describe DB instances
|
||||||
|
public void listInstances() {
|
||||||
|
DescribeDBInstancesResult result = amazonRDS.describeDBInstances();
|
||||||
|
List<DBInstance> instances = result.getDBInstances();
|
||||||
|
for (DBInstance instance : instances) {
|
||||||
|
// Information about each RDS instance
|
||||||
|
String identifier = instance.getDBInstanceIdentifier();
|
||||||
|
String engine = instance.getEngine();
|
||||||
|
String status = instance.getDBInstanceStatus();
|
||||||
|
Endpoint endpoint = instance.getEndpoint();
|
||||||
|
String endpoint_url = "Endpoint URL not available yet.";
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint_url = endpoint.toString();
|
||||||
|
}
|
||||||
|
logger.info(identifier + "\t" + engine + "\t" + status);
|
||||||
|
logger.info("\t" + endpoint_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Delete RDS instance
|
||||||
|
public void terminateInstance(String identifier) {
|
||||||
|
|
||||||
|
DeleteDBInstanceRequest request = new DeleteDBInstanceRequest();
|
||||||
|
request.setDBInstanceIdentifier(identifier);
|
||||||
|
request.setSkipFinalSnapshot(true);
|
||||||
|
|
||||||
|
// Delete the RDS instance
|
||||||
|
DBInstance instance = amazonRDS.deleteDBInstance(request);
|
||||||
|
|
||||||
|
// Information about the RDS instance being deleted
|
||||||
|
String status = instance.getDBInstanceStatus();
|
||||||
|
Endpoint endpoint = instance.getEndpoint();
|
||||||
|
String endpoint_url = "Endpoint URL not available yet.";
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint_url = endpoint.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(identifier + "\t" + status);
|
||||||
|
logger.info(endpoint_url);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void runJdbcTests() throws SQLException, IOException {
|
||||||
|
|
||||||
|
// Getting database properties from db.properties
|
||||||
|
Properties prop = new Properties();
|
||||||
|
InputStream input = AWSRDSService.class.getClassLoader().getResourceAsStream("db.properties");
|
||||||
|
prop.load(input);
|
||||||
|
db_hostname = prop.getProperty("db_hostname");
|
||||||
|
String jdbc_url = "jdbc:postgresql://" + db_hostname + ":5432/" + db_database;
|
||||||
|
|
||||||
|
// Create a connection using the JDBC driver
|
||||||
|
try (Connection conn = DriverManager.getConnection(jdbc_url, db_username, db_password)) {
|
||||||
|
|
||||||
|
// Create the test table if not exists
|
||||||
|
Statement statement = conn.createStatement();
|
||||||
|
String sql = "CREATE TABLE IF NOT EXISTS jdbc_test (id SERIAL PRIMARY KEY, content VARCHAR(80))";
|
||||||
|
statement.executeUpdate(sql);
|
||||||
|
|
||||||
|
// Do some INSERT
|
||||||
|
PreparedStatement preparedStatement = conn.prepareStatement("INSERT INTO jdbc_test (content) VALUES (?)");
|
||||||
|
String content = "" + UUID.randomUUID();
|
||||||
|
preparedStatement.setString(1, content);
|
||||||
|
preparedStatement.executeUpdate();
|
||||||
|
logger.info("INSERT: " + content);
|
||||||
|
|
||||||
|
// Do some SELECT
|
||||||
|
sql = "SELECT * FROM jdbc_test";
|
||||||
|
ResultSet resultSet = statement.executeQuery(sql);
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String count = resultSet.getString("content");
|
||||||
|
logger.info("Total Records: " + count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException, SQLException {
|
||||||
|
AWSRDSService awsrdsService = new AWSRDSService();
|
||||||
|
|
||||||
|
String instanceName = awsrdsService.launchInstance();
|
||||||
|
|
||||||
|
//Add some wait for instance creation.
|
||||||
|
|
||||||
|
awsrdsService.listInstances();
|
||||||
|
|
||||||
|
awsrdsService.runJdbcTests();
|
||||||
|
|
||||||
|
awsrdsService.terminateInstance(instanceName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
db_hostname=<RDS EndPoint>
|
||||||
|
db_username=username
|
||||||
|
db_password=password
|
||||||
|
db_database=mydb
|
|
@ -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>
|
||||||
|
|
|
@ -29,3 +29,6 @@
|
||||||
- [Java 8 Unsigned Arithmetic Support](http://www.baeldung.com/java-unsigned-arithmetic)
|
- [Java 8 Unsigned Arithmetic Support](http://www.baeldung.com/java-unsigned-arithmetic)
|
||||||
- [Generalized Target-Type Inference in Java](http://www.baeldung.com/java-generalized-target-type-inference)
|
- [Generalized Target-Type Inference in Java](http://www.baeldung.com/java-generalized-target-type-inference)
|
||||||
- [Overriding System Time for Testing in Java](http://www.baeldung.com/java-override-system-time)
|
- [Overriding System Time for Testing in Java](http://www.baeldung.com/java-override-system-time)
|
||||||
|
- [Set the Time Zone of a Date in Java](https://www.baeldung.com/java-set-date-time-zone)
|
||||||
|
- [An Overview of Regular Expressions Performance in Java](https://www.baeldung.com/java-regex-performance)
|
||||||
|
- [Java Primitives versus Objects](https://www.baeldung.com/java-primitives-vs-objects)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -24,3 +24,5 @@
|
||||||
- [Optional orElse Optional](http://www.baeldung.com/java-optional-or-else-optional)
|
- [Optional orElse Optional](http://www.baeldung.com/java-optional-or-else-optional)
|
||||||
- [Java 9 java.lang.Module API](http://www.baeldung.com/java-9-module-api)
|
- [Java 9 java.lang.Module API](http://www.baeldung.com/java-9-module-api)
|
||||||
- [Iterate Through a Range of Dates in Java](https://www.baeldung.com/java-iterate-date-range)
|
- [Iterate Through a Range of Dates in Java](https://www.baeldung.com/java-iterate-date-range)
|
||||||
|
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
|
||||||
|
- [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api)
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -48,7 +48,7 @@ class ProcessUnderstandingTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test - windows specific
|
//@Test - windows specific
|
||||||
public void givenSubProcess_thenStartSuccessIsAlive() throws IOException {
|
public void givenSubProcess_whenStarted_thenStartSuccessIsAlive() throws IOException {
|
||||||
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
|
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
|
||||||
assertTrue(builder.start().isAlive());
|
assertTrue(builder.start().isAlive());
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ class ProcessUnderstandingTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Test - windows specific
|
//@Test - windows specific
|
||||||
public void givenSubProcess_checkAlive() throws IOException, InterruptedException {
|
public void givenSubProcess_whenDestroyed_thenCheckIfAlive() throws IOException, InterruptedException {
|
||||||
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
|
ProcessBuilder builder = new ProcessBuilder("notepad.exe");
|
||||||
Process process = builder.start();
|
Process process = builder.start();
|
||||||
Thread.sleep(10000);
|
Thread.sleep(10000);
|
||||||
|
|
|
@ -43,3 +43,9 @@
|
||||||
- [An Introduction to Java.util.Hashtable Class](http://www.baeldung.com/java-hash-table)
|
- [An Introduction to Java.util.Hashtable Class](http://www.baeldung.com/java-hash-table)
|
||||||
- [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another)
|
- [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another)
|
||||||
- [Finding Max/Min of a List or Collection](http://www.baeldung.com/java-collection-min-max)
|
- [Finding Max/Min of a List or Collection](http://www.baeldung.com/java-collection-min-max)
|
||||||
|
- [Java Null-Safe Streams from Collections](https://www.baeldung.com/java-null-safe-streams-from-collections)
|
||||||
|
- [Remove All Occurrences of a Specific Value from a List](https://www.baeldung.com/java-remove-value-from-list)
|
||||||
|
- [Thread Safe LIFO Data Structure Implementations](https://www.baeldung.com/java-lifo-thread-safe)
|
||||||
|
- [Collections.emptyList() vs. New List Instance](https://www.baeldung.com/java-collections-emptylist-new-list)
|
||||||
|
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
|
||||||
|
- [](https://www.baeldung.com/java-hashset-arraylist-contains-performance)
|
||||||
|
|
|
@ -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,77 @@
|
||||||
|
package com.baeldung.performance;
|
||||||
|
|
||||||
|
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.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||||
|
@Warmup(iterations = 10)
|
||||||
|
public class ArrayListBenchmark {
|
||||||
|
|
||||||
|
@State(Scope.Thread)
|
||||||
|
public static class MyState {
|
||||||
|
|
||||||
|
List<Employee> employeeList = new ArrayList<>();
|
||||||
|
//LinkedList<Employee> employeeList = new LinkedList<>();
|
||||||
|
|
||||||
|
long iterations = 100000;
|
||||||
|
|
||||||
|
Employee employee = new Employee(100L, "Harry");
|
||||||
|
|
||||||
|
int employeeIndex = -1;
|
||||||
|
|
||||||
|
@Setup(Level.Trial)
|
||||||
|
public void setUp() {
|
||||||
|
for (long i = 0; i < iterations; i++) {
|
||||||
|
employeeList.add(new Employee(i, "John"));
|
||||||
|
}
|
||||||
|
|
||||||
|
employeeList.add(employee);
|
||||||
|
employeeIndex = employeeList.indexOf(employee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public void testAddAt(ArrayListBenchmark.MyState state) {
|
||||||
|
state.employeeList.add((int) (state.iterations), new Employee(state.iterations, "John"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public boolean testContains(ArrayListBenchmark.MyState state) {
|
||||||
|
return state.employeeList.contains(state.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public int testIndexOf(ArrayListBenchmark.MyState state) {
|
||||||
|
return state.employeeList.indexOf(state.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public Employee testGet(ArrayListBenchmark.MyState state) {
|
||||||
|
return state.employeeList.get(state.employeeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public boolean testRemove(ArrayListBenchmark.MyState state) {
|
||||||
|
return state.employeeList.remove(state.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Benchmark
|
||||||
|
// public void testAdd(ArrayListBenchmark.MyState state) {
|
||||||
|
// state.employeeList.add(new Employee(state.iterations + 1, "John"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Options options = new OptionsBuilder()
|
||||||
|
.include(ArrayListBenchmark.class.getSimpleName()).threads(1)
|
||||||
|
.forks(1).shouldFailOnError(true)
|
||||||
|
.shouldDoGC(true)
|
||||||
|
.jvmArgs("-server").build();
|
||||||
|
new Runner(options).run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
package com.baeldung.performance;
|
||||||
|
|
||||||
|
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.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||||
|
@Warmup(iterations = 10)
|
||||||
|
public class CopyOnWriteBenchmark {
|
||||||
|
|
||||||
|
@State(Scope.Thread)
|
||||||
|
public static class MyState {
|
||||||
|
|
||||||
|
CopyOnWriteArrayList<Employee> employeeList = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
long iterations = 100000;
|
||||||
|
|
||||||
|
Employee employee = new Employee(100L, "Harry");
|
||||||
|
|
||||||
|
int employeeIndex = -1;
|
||||||
|
|
||||||
|
@Setup(Level.Trial)
|
||||||
|
public void setUp() {
|
||||||
|
for (long i = 0; i < iterations; i++) {
|
||||||
|
employeeList.add(new Employee(i, "John"));
|
||||||
|
}
|
||||||
|
|
||||||
|
employeeList.add(employee);
|
||||||
|
|
||||||
|
employeeIndex = employeeList.indexOf(employee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public void testAdd(CopyOnWriteBenchmark.MyState state) {
|
||||||
|
state.employeeList.add(new Employee(state.iterations + 1, "John"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public void testAddAt(CopyOnWriteBenchmark.MyState state) {
|
||||||
|
state.employeeList.add((int) (state.iterations), new Employee(state.iterations, "John"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public boolean testContains(CopyOnWriteBenchmark.MyState state) {
|
||||||
|
return state.employeeList.contains(state.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public int testIndexOf(CopyOnWriteBenchmark.MyState state) {
|
||||||
|
return state.employeeList.indexOf(state.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public Employee testGet(CopyOnWriteBenchmark.MyState state) {
|
||||||
|
return state.employeeList.get(state.employeeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public boolean testRemove(CopyOnWriteBenchmark.MyState state) {
|
||||||
|
return state.employeeList.remove(state.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Options options = new OptionsBuilder()
|
||||||
|
.include(CopyOnWriteBenchmark.class.getSimpleName()).threads(1)
|
||||||
|
.forks(1).shouldFailOnError(true)
|
||||||
|
.shouldDoGC(true)
|
||||||
|
.jvmArgs("-server").build();
|
||||||
|
new Runner(options).run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,22 @@ public class Employee {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package com.baeldung.performance;
|
||||||
|
|
||||||
|
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.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||||
|
@Warmup(iterations = 10)
|
||||||
|
public class HashMapBenchmark {
|
||||||
|
|
||||||
|
@State(Scope.Thread)
|
||||||
|
public static class MyState {
|
||||||
|
|
||||||
|
Map<Long, Employee> employeeMap = new HashMap<>();
|
||||||
|
//LinkedHashMap<Long, Employee> employeeMap = new LinkedHashMap<>();
|
||||||
|
//IdentityHashMap<Long, Employee> employeeMap = new IdentityHashMap<>();
|
||||||
|
//WeakHashMap<Long, Employee> employeeMap = new WeakHashMap<>();
|
||||||
|
//ConcurrentHashMap<Long, Employee> employeeMap = new ConcurrentHashMap<>();
|
||||||
|
//ConcurrentSkipListMap<Long, Employee> employeeMap = new ConcurrentSkipListMap <>();
|
||||||
|
|
||||||
|
// TreeMap
|
||||||
|
|
||||||
|
long iterations = 100000;
|
||||||
|
|
||||||
|
Employee employee = new Employee(100L, "Harry");
|
||||||
|
|
||||||
|
int employeeIndex = -1;
|
||||||
|
|
||||||
|
@Setup(Level.Trial)
|
||||||
|
public void setUp() {
|
||||||
|
for (long i = 0; i < iterations; i++) {
|
||||||
|
employeeMap.put(i, new Employee(i, "John"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//employeeMap.put(iterations, employee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public Employee testGet(HashMapBenchmark.MyState state) {
|
||||||
|
return state.employeeMap.get(state.iterations);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public Employee testRemove(HashMapBenchmark.MyState state) {
|
||||||
|
return state.employeeMap.remove(state.iterations);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public Employee testPut(HashMapBenchmark.MyState state) {
|
||||||
|
return state.employeeMap.put(state.employee.getId(), state.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public Boolean testContainsKey(HashMapBenchmark.MyState state) {
|
||||||
|
return state.employeeMap.containsKey(state.employee.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Options options = new OptionsBuilder()
|
||||||
|
.include(HashMapBenchmark.class.getSimpleName()).threads(1)
|
||||||
|
.forks(1).shouldFailOnError(true)
|
||||||
|
.shouldDoGC(true)
|
||||||
|
.jvmArgs("-server").build();
|
||||||
|
new Runner(options).run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.baeldung.performance;
|
||||||
|
|
||||||
|
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.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.concurrent.ConcurrentSkipListSet;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||||
|
@Warmup(iterations = 10)
|
||||||
|
public class SetBenchMark {
|
||||||
|
|
||||||
|
@State(Scope.Thread)
|
||||||
|
public static class MyState {
|
||||||
|
|
||||||
|
//Set<Employee> employeeSet = new HashSet<>();
|
||||||
|
LinkedHashSet<Employee> employeeSet = new LinkedHashSet<>();
|
||||||
|
//ConcurrentSkipListSet<Employee> employeeSet = new ConcurrentSkipListSet <>();
|
||||||
|
|
||||||
|
// TreeSet
|
||||||
|
|
||||||
|
long iterations = 1000;
|
||||||
|
Employee employee = new Employee(100L, "Harry");
|
||||||
|
|
||||||
|
@Setup(Level.Trial)
|
||||||
|
public void setUp() {
|
||||||
|
for (long i = 0; i < iterations; i++) {
|
||||||
|
employeeSet.add(new Employee(i, "John"));
|
||||||
|
}
|
||||||
|
|
||||||
|
//employeeSet.add(employee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public boolean testAdd(SetBenchMark.MyState state) {
|
||||||
|
return state.employeeSet.add(state.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public Boolean testContains(SetBenchMark.MyState state) {
|
||||||
|
return state.employeeSet.contains(state.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public boolean testRemove(SetBenchMark.MyState state) {
|
||||||
|
return state.employeeSet.remove(state.employee);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Options options = new OptionsBuilder()
|
||||||
|
.include(SetBenchMark.class.getSimpleName()).threads(1)
|
||||||
|
.forks(1).shouldFailOnError(true)
|
||||||
|
.shouldDoGC(true)
|
||||||
|
.jvmArgs("-server").build();
|
||||||
|
new Runner(options).run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,3 +30,4 @@
|
||||||
- [Download a File From an URL in Java](http://www.baeldung.com/java-download-file)
|
- [Download a File From an URL in Java](http://www.baeldung.com/java-download-file)
|
||||||
- [Create a Symbolic Link with Java](http://www.baeldung.com/java-symlink)
|
- [Create a Symbolic Link with Java](http://www.baeldung.com/java-symlink)
|
||||||
- [Quick Use of FilenameFilter](http://www.baeldung.com/java-filename-filter)
|
- [Quick Use of FilenameFilter](http://www.baeldung.com/java-filename-filter)
|
||||||
|
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.baeldung.file;
|
package com.baeldung.file;
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -120,4 +121,14 @@ public class FileOperationsManualTest {
|
||||||
|
|
||||||
return resultStringBuilder.toString();
|
return resultStringBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenFileName_whenUsingIOUtils_thenFileData() throws IOException {
|
||||||
|
String expectedData = "This is a content of the file";
|
||||||
|
|
||||||
|
FileInputStream fis = new FileInputStream("src/test/resources/fileToRead.txt");
|
||||||
|
String data = IOUtils.toString(fis, "UTF-8");
|
||||||
|
|
||||||
|
assertEquals(expectedData, data.trim());
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -6,3 +6,4 @@
|
||||||
- [Introduction to JDBC](http://www.baeldung.com/java-jdbc)
|
- [Introduction to JDBC](http://www.baeldung.com/java-jdbc)
|
||||||
- [Batch Processing in JDBC](http://www.baeldung.com/jdbc-batch-processing)
|
- [Batch Processing in JDBC](http://www.baeldung.com/jdbc-batch-processing)
|
||||||
- [Introduction to the JDBC RowSet Interface in Java](http://www.baeldung.com/java-jdbc-rowset)
|
- [Introduction to the JDBC RowSet Interface in Java](http://www.baeldung.com/java-jdbc-rowset)
|
||||||
|
- [A Simple Guide to Connection Pooling in Java](https://www.baeldung.com/java-connection-pooling)
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -145,3 +145,9 @@
|
||||||
- [Common Java Exceptions](http://www.baeldung.com/java-common-exceptions)
|
- [Common Java Exceptions](http://www.baeldung.com/java-common-exceptions)
|
||||||
- [Java Constructors vs Static Factory Methods](https://www.baeldung.com/java-constructors-vs-static-factory-methods)
|
- [Java Constructors vs Static Factory Methods](https://www.baeldung.com/java-constructors-vs-static-factory-methods)
|
||||||
- [Differences Between Final, Finally and Finalize in Java](https://www.baeldung.com/java-final-finally-finalize)
|
- [Differences Between Final, Finally and Finalize in Java](https://www.baeldung.com/java-final-finally-finalize)
|
||||||
|
- [Static and Dynamic Binding in Java](https://www.baeldung.com/java-static-dynamic-binding)
|
||||||
|
- [Java List Initialization in One Line](https://www.baeldung.com/java-init-list-one-line)
|
||||||
|
- [Difference Between Throw and Throws in Java](https://www.baeldung.com/java-throw-throws)
|
||||||
|
- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist)
|
||||||
|
- [Throw Exception in Optional in Java 8](https://www.baeldung.com/java-optional-throw-exception)
|
||||||
|
- [Add a Character to a String at a Given Position](https://www.baeldung.com/java-add-character-to-string)
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.baeldung.doubles;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
public class SplitFloatingPointNumbers {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
double doubleNumber = 24.04;
|
||||||
|
splitUsingFloatingTypes(doubleNumber);
|
||||||
|
splitUsingString(doubleNumber);
|
||||||
|
splitUsingBigDecimal(doubleNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void splitUsingFloatingTypes(double doubleNumber) {
|
||||||
|
System.out.println("Using Floating Point Arithmetics:");
|
||||||
|
int intPart = (int) doubleNumber;
|
||||||
|
System.out.println("Double Number: "+doubleNumber);
|
||||||
|
System.out.println("Integer Part: "+ intPart);
|
||||||
|
System.out.println("Decimal Part: "+ (doubleNumber - intPart));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void splitUsingString(double doubleNumber) {
|
||||||
|
System.out.println("Using String Operations:");
|
||||||
|
String doubleAsString = String.valueOf(doubleNumber);
|
||||||
|
int indexOfDecimal = doubleAsString.indexOf(".");
|
||||||
|
System.out.println("Double Number: "+doubleNumber);
|
||||||
|
System.out.println("Integer Part: "+ doubleAsString.substring(0, indexOfDecimal));
|
||||||
|
System.out.println("Decimal Part: "+ doubleAsString.substring(indexOfDecimal));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void splitUsingBigDecimal(double doubleNumber) {
|
||||||
|
System.out.println("Using BigDecimal Operations:");
|
||||||
|
BigDecimal bigDecimal = new BigDecimal(String.valueOf(doubleNumber));
|
||||||
|
int intValue = bigDecimal.intValue();
|
||||||
|
System.out.println("Double Number: "+bigDecimal.toPlainString());
|
||||||
|
System.out.println("Integer Part: "+intValue);
|
||||||
|
System.out.println("Decimal Part: "+bigDecimal.subtract(new BigDecimal(intValue)).toPlainString());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.heapdump;
|
||||||
|
|
||||||
|
import com.sun.management.HotSpotDiagnosticMXBean;
|
||||||
|
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public class HeapDump {
|
||||||
|
|
||||||
|
public static void dumpHeap(String filePath, boolean live) throws IOException {
|
||||||
|
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(
|
||||||
|
server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
|
||||||
|
mxBean.dumpHeap(filePath, live);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
String file = Paths.get("dump.hprof").toFile().getPath();
|
||||||
|
|
||||||
|
dumpHeap(file, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
package com.baeldung.passwordhashing;
|
||||||
|
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.KeySpec;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKeyFactory;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash passwords for storage, and test passwords against password tokens.
|
||||||
|
*
|
||||||
|
* Instances of this class can be used concurrently by multiple threads.
|
||||||
|
*
|
||||||
|
* @author erickson
|
||||||
|
* @see <a href="http://stackoverflow.com/a/2861125/3474">StackOverflow</a>
|
||||||
|
*/
|
||||||
|
public final class PBKDF2Hasher
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each token produced by this class uses this identifier as a prefix.
|
||||||
|
*/
|
||||||
|
public static final String ID = "$31$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum recommended cost, used by default
|
||||||
|
*/
|
||||||
|
public static final int DEFAULT_COST = 16;
|
||||||
|
|
||||||
|
private static final String ALGORITHM = "PBKDF2WithHmacSHA1";
|
||||||
|
|
||||||
|
private static final int SIZE = 128;
|
||||||
|
|
||||||
|
private static final Pattern layout = Pattern.compile("\\$31\\$(\\d\\d?)\\$(.{43})");
|
||||||
|
|
||||||
|
private final SecureRandom random;
|
||||||
|
|
||||||
|
private final int cost;
|
||||||
|
|
||||||
|
public PBKDF2Hasher()
|
||||||
|
{
|
||||||
|
this(DEFAULT_COST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a password manager with a specified cost
|
||||||
|
*
|
||||||
|
* @param cost the exponential computational cost of hashing a password, 0 to 30
|
||||||
|
*/
|
||||||
|
public PBKDF2Hasher(int cost)
|
||||||
|
{
|
||||||
|
iterations(cost); /* Validate cost */
|
||||||
|
this.cost = cost;
|
||||||
|
this.random = new SecureRandom();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int iterations(int cost)
|
||||||
|
{
|
||||||
|
if ((cost < 0) || (cost > 30))
|
||||||
|
throw new IllegalArgumentException("cost: " + cost);
|
||||||
|
return 1 << cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash a password for storage.
|
||||||
|
*
|
||||||
|
* @return a secure authentication token to be stored for later authentication
|
||||||
|
*/
|
||||||
|
public String hash(char[] password)
|
||||||
|
{
|
||||||
|
byte[] salt = new byte[SIZE / 8];
|
||||||
|
random.nextBytes(salt);
|
||||||
|
byte[] dk = pbkdf2(password, salt, 1 << cost);
|
||||||
|
byte[] hash = new byte[salt.length + dk.length];
|
||||||
|
System.arraycopy(salt, 0, hash, 0, salt.length);
|
||||||
|
System.arraycopy(dk, 0, hash, salt.length, dk.length);
|
||||||
|
Base64.Encoder enc = Base64.getUrlEncoder().withoutPadding();
|
||||||
|
return ID + cost + '$' + enc.encodeToString(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate with a password and a stored password token.
|
||||||
|
*
|
||||||
|
* @return true if the password and token match
|
||||||
|
*/
|
||||||
|
public boolean checkPassword(char[] password, String token)
|
||||||
|
{
|
||||||
|
Matcher m = layout.matcher(token);
|
||||||
|
if (!m.matches())
|
||||||
|
throw new IllegalArgumentException("Invalid token format");
|
||||||
|
int iterations = iterations(Integer.parseInt(m.group(1)));
|
||||||
|
byte[] hash = Base64.getUrlDecoder().decode(m.group(2));
|
||||||
|
byte[] salt = Arrays.copyOfRange(hash, 0, SIZE / 8);
|
||||||
|
byte[] check = pbkdf2(password, salt, iterations);
|
||||||
|
int zero = 0;
|
||||||
|
for (int idx = 0; idx < check.length; ++idx)
|
||||||
|
zero |= hash[salt.length + idx] ^ check[idx];
|
||||||
|
return zero == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] pbkdf2(char[] password, byte[] salt, int iterations)
|
||||||
|
{
|
||||||
|
KeySpec spec = new PBEKeySpec(password, salt, iterations, SIZE);
|
||||||
|
try {
|
||||||
|
SecretKeyFactory f = SecretKeyFactory.getInstance(ALGORITHM);
|
||||||
|
return f.generateSecret(spec).getEncoded();
|
||||||
|
}
|
||||||
|
catch (NoSuchAlgorithmException ex) {
|
||||||
|
throw new IllegalStateException("Missing algorithm: " + ALGORITHM, ex);
|
||||||
|
}
|
||||||
|
catch (InvalidKeySpecException ex) {
|
||||||
|
throw new IllegalStateException("Invalid SecretKeyFactory", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash a password in an immutable {@code String}.
|
||||||
|
*
|
||||||
|
* <p>Passwords should be stored in a {@code char[]} so that it can be filled
|
||||||
|
* with zeros after use instead of lingering on the heap and elsewhere.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link #hash(char[])} instead
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public String hash(String password)
|
||||||
|
{
|
||||||
|
return hash(password.toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate with a password in an immutable {@code String} and a stored
|
||||||
|
* password token.
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link #checkPassword(char[],String)} instead.
|
||||||
|
* @see #hash(String)
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public boolean checkPassword(String password, String token)
|
||||||
|
{
|
||||||
|
return checkPassword(password.toCharArray(), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.baeldung.passwordhashing;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
|
||||||
|
/** A really simple SHA_512 Encryption example.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SHA512Hasher {
|
||||||
|
|
||||||
|
public String hash(String passwordToHash, byte[] salt){
|
||||||
|
String generatedPassword = null;
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA-512");
|
||||||
|
md.update(salt);
|
||||||
|
byte[] bytes = md.digest(passwordToHash.getBytes(StandardCharsets.UTF_8));
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for(int i=0; i< bytes.length ;i++){
|
||||||
|
sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
|
||||||
|
}
|
||||||
|
generatedPassword = sb.toString();
|
||||||
|
}
|
||||||
|
catch (NoSuchAlgorithmException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return generatedPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkPassword(String hash, String attempt, byte[] salt){
|
||||||
|
String generatedHash = hash(attempt, salt);
|
||||||
|
return hash.equals(generatedHash);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.baeldung.passwordhashing;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKeyFactory;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
|
import java.security.spec.KeySpec;
|
||||||
|
|
||||||
|
/** A really simple SimplePBKDF2 Encryption example.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SimplePBKDF2Hasher {
|
||||||
|
|
||||||
|
public static String hashSimple(String password, byte[] salt) throws Exception{
|
||||||
|
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
|
||||||
|
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||||
|
byte[] hash = f.generateSecret(spec).getEncoded();
|
||||||
|
return String.valueOf(hash);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.baeldung.zoneddatetime;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
|
public class OffsetDateTimeExample {
|
||||||
|
|
||||||
|
public OffsetDateTime getCurrentTimeByZoneOffset(String offset) {
|
||||||
|
ZoneOffset zoneOffSet= ZoneOffset.of(offset);
|
||||||
|
OffsetDateTime date = OffsetDateTime.now(zoneOffSet);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.baeldung.zoneddatetime;
|
||||||
|
|
||||||
|
import java.time.OffsetTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
|
public class OffsetTimeExample {
|
||||||
|
|
||||||
|
public OffsetTime getCurrentTimeByZoneOffset(String offset) {
|
||||||
|
ZoneOffset zoneOffSet = ZoneOffset.of(offset);
|
||||||
|
OffsetTime time = OffsetTime.now(zoneOffSet);
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.zoneddatetime;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
public class ZoneDateTimeExample {
|
||||||
|
|
||||||
|
public ZonedDateTime getCurrentTimeByZoneId(String region) {
|
||||||
|
ZoneId zone = ZoneId.of(region);
|
||||||
|
ZonedDateTime date = ZonedDateTime.now(zone);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZonedDateTime convertZonedDateTime(ZonedDateTime sourceDate, String destZone) {
|
||||||
|
|
||||||
|
ZoneId destZoneId = ZoneId.of(destZone);
|
||||||
|
ZonedDateTime destDate = sourceDate.withZoneSameInstant(destZoneId);
|
||||||
|
|
||||||
|
return destDate;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.baeldung.passwordhashing;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
|
||||||
|
public class PBKDF2HasherUnitTest {
|
||||||
|
|
||||||
|
private PBKDF2Hasher mPBKDF2Hasher;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mPBKDF2Hasher = new PBKDF2Hasher();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenCorrectMessageAndHash_whenAuthenticated_checkAuthenticationSucceeds() throws Exception {
|
||||||
|
String message1 = "password123";
|
||||||
|
|
||||||
|
String hash1 = mPBKDF2Hasher.hash(message1.toCharArray());
|
||||||
|
|
||||||
|
assertTrue(mPBKDF2Hasher.checkPassword(message1.toCharArray(), hash1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenWrongMessage_whenAuthenticated_checkAuthenticationFails() throws Exception {
|
||||||
|
String message1 = "password123";
|
||||||
|
|
||||||
|
String hash1 = mPBKDF2Hasher.hash(message1.toCharArray());
|
||||||
|
|
||||||
|
String wrongPasswordAttempt = "IamWrong";
|
||||||
|
|
||||||
|
assertFalse(mPBKDF2Hasher.checkPassword(wrongPasswordAttempt.toCharArray(), hash1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.baeldung.passwordhashing;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by PhysicsSam on 06-Sep-18.
|
||||||
|
*/
|
||||||
|
public class SHA512HasherUnitTest {
|
||||||
|
|
||||||
|
private SHA512Hasher hasher;
|
||||||
|
private SecureRandom secureRandom;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
hasher = new SHA512Hasher();
|
||||||
|
secureRandom = new SecureRandom();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSamePasswordAndSalt_whenHashed_checkResultingHashesAreEqual() throws Exception {
|
||||||
|
|
||||||
|
byte[] salt = new byte[16];
|
||||||
|
secureRandom.nextBytes(salt);
|
||||||
|
|
||||||
|
String hash1 = hasher.hash("password", salt);
|
||||||
|
String hash2 = hasher.hash("password", salt);
|
||||||
|
|
||||||
|
assertEquals(hash1, hash2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSamePasswordAndDifferentSalt_whenHashed_checkResultingHashesNotEqual() throws Exception {
|
||||||
|
|
||||||
|
byte[] salt = new byte[16];
|
||||||
|
secureRandom.nextBytes(salt);
|
||||||
|
String hash1 = hasher.hash("password", salt);
|
||||||
|
//generate a second salt
|
||||||
|
byte[] secondSalt = new byte[16];
|
||||||
|
String hash2 = hasher.hash("password", secondSalt);
|
||||||
|
|
||||||
|
assertNotEquals(hash1, hash2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPredefinedHash_whenCorrectAttemptGiven_checkAuthenticationSucceeds() throws Exception {
|
||||||
|
byte[] salt = new byte[16];
|
||||||
|
secureRandom.nextBytes(salt);
|
||||||
|
|
||||||
|
String originalHash = hasher.hash("password123", salt);
|
||||||
|
|
||||||
|
assertTrue(hasher.checkPassword(originalHash, "password123", salt));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPredefinedHash_whenIncorrectAttemptGiven_checkAuthenticationFails() throws Exception {
|
||||||
|
byte[] salt = new byte[16];
|
||||||
|
secureRandom.nextBytes(salt);
|
||||||
|
|
||||||
|
String originalHash = hasher.hash("password123", salt);
|
||||||
|
|
||||||
|
assertFalse(hasher.checkPassword(originalHash, "password124", salt));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.baeldung.zoneddatetime;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class OffsetDateTimeExampleUnitTest {
|
||||||
|
|
||||||
|
OffsetDateTimeExample offsetDateTimeExample = new OffsetDateTimeExample();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenZoneOffset_whenGetCurrentTime_thenResultHasZone() {
|
||||||
|
String offset = "+02:00";
|
||||||
|
OffsetDateTime time = offsetDateTimeExample.getCurrentTimeByZoneOffset(offset);
|
||||||
|
|
||||||
|
assertTrue(time.getOffset()
|
||||||
|
.equals(ZoneOffset.of(offset)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.baeldung.zoneddatetime;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.time.OffsetTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class OffsetTimeExampleUnitTest {
|
||||||
|
|
||||||
|
OffsetTimeExample offsetTimeExample = new OffsetTimeExample();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenZoneOffset_whenGetCurrentTime_thenResultHasZone() {
|
||||||
|
String offset = "+02:00";
|
||||||
|
OffsetTime time = offsetTimeExample.getCurrentTimeByZoneOffset(offset);
|
||||||
|
|
||||||
|
assertTrue(time.getOffset()
|
||||||
|
.equals(ZoneOffset.of(offset)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.zoneddatetime;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ZoneDateTimeExampleUnitTest {
|
||||||
|
|
||||||
|
ZoneDateTimeExample zoneDateTimeExample = new ZoneDateTimeExample();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenZone_whenGetCurrentTime_thenResultHasZone() {
|
||||||
|
String zone = "Europe/Berlin";
|
||||||
|
ZonedDateTime time = zoneDateTimeExample.getCurrentTimeByZoneId(zone);
|
||||||
|
|
||||||
|
assertTrue(time.getZone()
|
||||||
|
.equals(ZoneId.of(zone)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenZones_whenConvertDateByZone_thenGetConstantDiff() {
|
||||||
|
String sourceZone = "Europe/Berlin";
|
||||||
|
String destZone = "Asia/Tokyo";
|
||||||
|
ZonedDateTime sourceDate = zoneDateTimeExample.getCurrentTimeByZoneId(sourceZone);
|
||||||
|
ZonedDateTime destDate = zoneDateTimeExample.convertZonedDateTime(sourceDate, destZone);
|
||||||
|
|
||||||
|
assertTrue(sourceDate.toInstant()
|
||||||
|
.compareTo(destDate.toInstant()) == 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,13 +25,12 @@
|
||||||
- [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)
|
||||||
- [Get a Random Number in Kotlin](http://www.baeldung.com/kotlin-random-number)
|
- [Get a Random Number in Kotlin](http://www.baeldung.com/kotlin-random-number)
|
||||||
- [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)
|
||||||
|
- [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)
|
|
@ -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,56 +24,52 @@
|
||||||
<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>
|
||||||
<version>${h2database.version}</version>
|
<version>${h2database.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.kittinunf.fuel</groupId>
|
||||||
|
<artifactId>fuel</artifactId>
|
||||||
|
<version>${fuel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.kittinunf.fuel</groupId>
|
||||||
|
<artifactId>fuel-gson</artifactId>
|
||||||
|
<version>${fuel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.kittinunf.fuel</groupId>
|
||||||
|
<artifactId>fuel-rxjava</artifactId>
|
||||||
|
<version>${fuel.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.kittinunf.fuel</groupId>
|
||||||
|
<artifactId>fuel-coroutines</artifactId>
|
||||||
|
<version>${fuel.version}</version>
|
||||||
|
</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>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.baeldung.fuel
|
||||||
|
|
||||||
|
import com.github.kittinunf.fuel.core.Request
|
||||||
|
|
||||||
|
fun tokenInterceptor() = {
|
||||||
|
next: (Request) -> Request ->
|
||||||
|
{ req: Request ->
|
||||||
|
req.header(mapOf("Authorization" to "Bearer AbCdEf123456"))
|
||||||
|
next(req)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.fuel
|
||||||
|
|
||||||
|
import com.github.kittinunf.fuel.core.ResponseDeserializable
|
||||||
|
import com.google.gson.Gson
|
||||||
|
|
||||||
|
data class Post(var userId:Int,
|
||||||
|
var id:Int,
|
||||||
|
var title:String,
|
||||||
|
var body:String){
|
||||||
|
|
||||||
|
|
||||||
|
class Deserializer : ResponseDeserializable<Array<Post>> {
|
||||||
|
override fun deserialize(content: String): Array<Post> = Gson().fromJson(content, Array<Post>::class.java)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.baeldung.fuel
|
||||||
|
|
||||||
|
import com.github.kittinunf.fuel.core.Method
|
||||||
|
import com.github.kittinunf.fuel.util.FuelRouting
|
||||||
|
|
||||||
|
sealed class PostRoutingAPI : FuelRouting {
|
||||||
|
|
||||||
|
override val basePath = "https://jsonplaceholder.typicode.com"
|
||||||
|
|
||||||
|
class posts(val id: String, override val body: String?): PostRoutingAPI()
|
||||||
|
|
||||||
|
class comments(val postId: String, override val body: String?): PostRoutingAPI()
|
||||||
|
|
||||||
|
override val method: Method
|
||||||
|
get() {
|
||||||
|
return when(this) {
|
||||||
|
is PostRoutingAPI.posts -> Method.GET
|
||||||
|
is PostRoutingAPI.comments -> Method.GET
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val path: String
|
||||||
|
get() {
|
||||||
|
return when(this) {
|
||||||
|
is PostRoutingAPI.posts -> "/posts"
|
||||||
|
is PostRoutingAPI.comments -> "/comments"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val params: List<Pair<String, Any?>>?
|
||||||
|
get() {
|
||||||
|
return when(this) {
|
||||||
|
is PostRoutingAPI.posts -> listOf("id" to this.id)
|
||||||
|
is PostRoutingAPI.comments -> listOf("postId" to this.postId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val headers: Map<String, String>?
|
||||||
|
get() {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -93,6 +93,7 @@ internal class BuilderPatternUnitTest {
|
||||||
Assertions.assertNull(foodOrder.fish)
|
Assertions.assertNull(foodOrder.fish)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun whenBuildingFoodOrderApplySettingValues_thenFieldsNotNull() {
|
fun whenBuildingFoodOrderApplySettingValues_thenFieldsNotNull() {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,286 @@
|
||||||
|
package com.baeldung.fuel
|
||||||
|
|
||||||
|
import awaitObjectResult
|
||||||
|
import awaitStringResponse
|
||||||
|
import com.github.kittinunf.fuel.Fuel
|
||||||
|
import com.github.kittinunf.fuel.core.FuelManager
|
||||||
|
import com.github.kittinunf.fuel.core.Request
|
||||||
|
import com.github.kittinunf.fuel.core.interceptors.cUrlLoggingRequestInterceptor
|
||||||
|
import com.github.kittinunf.fuel.gson.responseObject
|
||||||
|
import com.github.kittinunf.fuel.httpGet
|
||||||
|
import com.github.kittinunf.fuel.rx.rx_object
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import kotlinx.coroutines.experimental.runBlocking
|
||||||
|
import org.junit.jupiter.api.Assertions
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import java.io.File
|
||||||
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
|
internal class FuelHttpUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakingAsyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
|
||||||
|
|
||||||
|
val latch = CountDownLatch(1)
|
||||||
|
|
||||||
|
"http://httpbin.org/get".httpGet().response{
|
||||||
|
request, response, result ->
|
||||||
|
|
||||||
|
val (data, error) = result
|
||||||
|
|
||||||
|
Assertions.assertNull(error)
|
||||||
|
Assertions.assertNotNull(data)
|
||||||
|
Assertions.assertEquals(200,response.statusCode)
|
||||||
|
|
||||||
|
latch.countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
latch.await()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
|
||||||
|
|
||||||
|
val (request, response, result) = "http://httpbin.org/get".httpGet().response()
|
||||||
|
val (data, error) = result
|
||||||
|
|
||||||
|
Assertions.assertNull(error)
|
||||||
|
Assertions.assertNotNull(data)
|
||||||
|
Assertions.assertEquals(200,response.statusCode)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakingSyncHttpGetURLEncodedRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
|
||||||
|
|
||||||
|
val (request, response, result) =
|
||||||
|
"https://jsonplaceholder.typicode.com/posts"
|
||||||
|
.httpGet(listOf("id" to "1")).response()
|
||||||
|
val (data, error) = result
|
||||||
|
|
||||||
|
Assertions.assertNull(error)
|
||||||
|
Assertions.assertNotNull(data)
|
||||||
|
Assertions.assertEquals(200,response.statusCode)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakingAsyncHttpPostRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
|
||||||
|
|
||||||
|
val latch = CountDownLatch(1)
|
||||||
|
|
||||||
|
Fuel.post("http://httpbin.org/post").response{
|
||||||
|
request, response, result ->
|
||||||
|
|
||||||
|
val (data, error) = result
|
||||||
|
|
||||||
|
Assertions.assertNull(error)
|
||||||
|
Assertions.assertNotNull(data)
|
||||||
|
Assertions.assertEquals(200,response.statusCode)
|
||||||
|
|
||||||
|
latch.countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
latch.await()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakingSyncHttpPostRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
|
||||||
|
|
||||||
|
val (request, response, result) = Fuel.post("http://httpbin.org/post").response()
|
||||||
|
val (data, error) = result
|
||||||
|
|
||||||
|
Assertions.assertNull(error)
|
||||||
|
Assertions.assertNotNull(data)
|
||||||
|
Assertions.assertEquals(200,response.statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakingSyncHttpPostRequestwithBody_thenResponseNotNullAndErrorNullAndStatusCode200() {
|
||||||
|
|
||||||
|
val (request, response, result) = Fuel.post("https://jsonplaceholder.typicode.com/posts")
|
||||||
|
.body("{ \"title\" : \"foo\",\"body\" : \"bar\",\"id\" : \"1\"}")
|
||||||
|
.response()
|
||||||
|
|
||||||
|
val (data, error) = result
|
||||||
|
|
||||||
|
Assertions.assertNull(error)
|
||||||
|
Assertions.assertNotNull(data)
|
||||||
|
Assertions.assertEquals(201,response.statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenFuelInstance_whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
|
||||||
|
|
||||||
|
FuelManager.instance.basePath = "http://httpbin.org"
|
||||||
|
FuelManager.instance.baseHeaders = mapOf("OS" to "macOS High Sierra")
|
||||||
|
|
||||||
|
FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor())
|
||||||
|
FuelManager.instance.addRequestInterceptor(tokenInterceptor())
|
||||||
|
|
||||||
|
|
||||||
|
val (request, response, result) = "/get"
|
||||||
|
.httpGet().response()
|
||||||
|
val (data, error) = result
|
||||||
|
|
||||||
|
Assertions.assertNull(error)
|
||||||
|
Assertions.assertNotNull(data)
|
||||||
|
Assertions.assertEquals(200,response.statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenInterceptors_whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() {
|
||||||
|
|
||||||
|
FuelManager.instance.basePath = "http://httpbin.org"
|
||||||
|
FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor())
|
||||||
|
FuelManager.instance.addRequestInterceptor(tokenInterceptor())
|
||||||
|
|
||||||
|
val (request, response, result) = "/get"
|
||||||
|
.httpGet().response()
|
||||||
|
val (data, error) = result
|
||||||
|
|
||||||
|
Assertions.assertNull(error)
|
||||||
|
Assertions.assertNotNull(data)
|
||||||
|
Assertions.assertEquals(200,response.statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenDownloadFile_thenCreateFileResponseNotNullAndErrorNullAndStatusCode200() {
|
||||||
|
|
||||||
|
Fuel.download("http://httpbin.org/bytes/32768").destination { response, url ->
|
||||||
|
File.createTempFile("temp", ".tmp")
|
||||||
|
}.response{
|
||||||
|
request, response, result ->
|
||||||
|
|
||||||
|
val (data, error) = result
|
||||||
|
Assertions.assertNull(error)
|
||||||
|
Assertions.assertNotNull(data)
|
||||||
|
Assertions.assertEquals(200,response.statusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenDownloadFilewithProgressHandler_thenCreateFileResponseNotNullAndErrorNullAndStatusCode200() {
|
||||||
|
|
||||||
|
val (request, response, result) = Fuel.download("http://httpbin.org/bytes/327680")
|
||||||
|
.destination { response, url -> File.createTempFile("temp", ".tmp")
|
||||||
|
}.progress { readBytes, totalBytes ->
|
||||||
|
val progress = readBytes.toFloat() / totalBytes.toFloat()
|
||||||
|
}.response ()
|
||||||
|
|
||||||
|
val (data, error) = result
|
||||||
|
Assertions.assertNull(error)
|
||||||
|
Assertions.assertNotNull(data)
|
||||||
|
Assertions.assertEquals(200,response.statusCode)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakeGetRequest_thenDeserializePostwithGson() {
|
||||||
|
|
||||||
|
val latch = CountDownLatch(1)
|
||||||
|
|
||||||
|
"https://jsonplaceholder.typicode.com/posts/1".httpGet().responseObject<Post> { _,_, result ->
|
||||||
|
val post = result.component1()
|
||||||
|
Assertions.assertEquals(1, post?.userId)
|
||||||
|
latch.countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
latch.await()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakePOSTRequest_thenSerializePostwithGson() {
|
||||||
|
|
||||||
|
val post = Post(1,1, "Lorem", "Lorem Ipse dolor sit amet")
|
||||||
|
|
||||||
|
val (request, response, result) = Fuel.post("https://jsonplaceholder.typicode.com/posts")
|
||||||
|
.header("Content-Type" to "application/json")
|
||||||
|
.body(Gson().toJson(post).toString())
|
||||||
|
.response()
|
||||||
|
|
||||||
|
Assertions.assertEquals(201,response.statusCode)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakeGETRequestWithRxJava_thenDeserializePostwithGson() {
|
||||||
|
|
||||||
|
val latch = CountDownLatch(1)
|
||||||
|
|
||||||
|
|
||||||
|
"https://jsonplaceholder.typicode.com/posts?id=1"
|
||||||
|
.httpGet().rx_object(Post.Deserializer()).subscribe{
|
||||||
|
res, throwable ->
|
||||||
|
|
||||||
|
val post = res.component1()
|
||||||
|
Assertions.assertEquals(1, post?.get(0)?.userId)
|
||||||
|
latch.countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
latch.await()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakeGETRequestUsingCoroutines_thenResponseStatusCode200() {
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
val (request, response, result) = Fuel.get("http://httpbin.org/get").awaitStringResponse()
|
||||||
|
|
||||||
|
result.fold({ data ->
|
||||||
|
Assertions.assertEquals(200, response.statusCode)
|
||||||
|
|
||||||
|
}, { error -> })
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakeGETRequestUsingCoroutines_thenDeserializeResponse() {
|
||||||
|
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
Fuel.get("https://jsonplaceholder.typicode.com/posts?id=1").awaitObjectResult(Post.Deserializer())
|
||||||
|
.fold({ data ->
|
||||||
|
Assertions.assertEquals(1, data.get(0).userId)
|
||||||
|
}, { error -> })
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakeGETPostRequestUsingRoutingAPI_thenDeserializeResponse() {
|
||||||
|
|
||||||
|
val latch = CountDownLatch(1)
|
||||||
|
|
||||||
|
Fuel.request(PostRoutingAPI.posts("1",null))
|
||||||
|
.responseObject(Post.Deserializer()) {
|
||||||
|
request, response, result ->
|
||||||
|
Assertions.assertEquals(1, result.component1()?.get(0)?.userId)
|
||||||
|
latch.countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
latch.await()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenMakeGETCommentRequestUsingRoutingAPI_thenResponseStausCode200() {
|
||||||
|
|
||||||
|
val latch = CountDownLatch(1)
|
||||||
|
|
||||||
|
Fuel.request(PostRoutingAPI.comments("1",null))
|
||||||
|
.responseString { request, response, result ->
|
||||||
|
Assertions.assertEquals(200, response.statusCode)
|
||||||
|
latch.countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
latch.await()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.baeldung.kotlin
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class StringConcatenationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenTwoStrings_concatenateWithTemplates_thenEquals() {
|
||||||
|
val a = "Hello"
|
||||||
|
val b = "Baeldung"
|
||||||
|
val c = "$a $b"
|
||||||
|
|
||||||
|
assertEquals("Hello Baeldung", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenTwoStrings_concatenateWithPlusOperator_thenEquals() {
|
||||||
|
val a = "Hello"
|
||||||
|
val b = "Baeldung"
|
||||||
|
val c = a + " " + b
|
||||||
|
|
||||||
|
assertEquals("Hello Baeldung", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenTwoStrings_concatenateWithStringBuilder_thenEquals() {
|
||||||
|
val a = "Hello"
|
||||||
|
val b = "Baeldung"
|
||||||
|
|
||||||
|
val builder = StringBuilder()
|
||||||
|
builder.append(a).append(" ").append(b)
|
||||||
|
|
||||||
|
val c = builder.toString()
|
||||||
|
|
||||||
|
assertEquals("Hello Baeldung", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenTwoStrings_concatenateWithPlusMethod_thenEquals() {
|
||||||
|
val a = "Hello"
|
||||||
|
val b = "Baeldung"
|
||||||
|
val c = a.plus(" ").plus(b)
|
||||||
|
|
||||||
|
assertEquals("Hello Baeldung", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.baeldung.kotlin.gson
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class GsonUnitTest {
|
||||||
|
|
||||||
|
var gson = Gson()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenObject_thenGetJSONString() {
|
||||||
|
var jsonString = gson.toJson(TestModel(1,"Test"))
|
||||||
|
Assert.assertEquals(jsonString, "{\"id\":1,\"description\":\"Test\"}")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun givenJSONString_thenGetObject() {
|
||||||
|
var jsonString = "{\"id\":1,\"description\":\"Test\"}";
|
||||||
|
var testModel = gson.fromJson(jsonString, TestModel::class.java)
|
||||||
|
Assert.assertEquals(testModel.id, 1)
|
||||||
|
Assert.assertEquals(testModel.description, "Test")
|
||||||
|
}
|
||||||
|
|
||||||
|
data class TestModel(
|
||||||
|
val id: Int,
|
||||||
|
val description: String
|
||||||
|
)
|
||||||
|
}
|
|
@ -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>
|
||||||
|
|
|
@ -48,12 +48,18 @@
|
||||||
<artifactId>poi-ooxml</artifactId>
|
<artifactId>poi-ooxml</artifactId>
|
||||||
<version>${apache-poi-version}</version>
|
<version>${apache-poi-version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.optaplanner</groupId>
|
||||||
|
<artifactId>optaplanner-core</artifactId>
|
||||||
|
<version>${opta-planner-version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<http-component-version>4.4.6</http-component-version>
|
<http-component-version>4.4.6</http-component-version>
|
||||||
<drools-version>7.4.1.Final</drools-version>
|
<drools-version>7.4.1.Final</drools-version>
|
||||||
<apache-poi-version>3.13</apache-poi-version>
|
<apache-poi-version>3.13</apache-poi-version>
|
||||||
|
<opta-planner-version>7.10.0.Final</opta-planner-version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.baeldung.drools.optaplanner;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
|
||||||
|
import org.optaplanner.core.api.domain.solution.PlanningScore;
|
||||||
|
import org.optaplanner.core.api.domain.solution.PlanningSolution;
|
||||||
|
import org.optaplanner.core.api.domain.solution.drools.ProblemFactCollectionProperty;
|
||||||
|
import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
|
||||||
|
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@PlanningSolution
|
||||||
|
public class CourseSchedule {
|
||||||
|
|
||||||
|
Logger logger = LoggerFactory.getLogger("CourseSchedule");
|
||||||
|
|
||||||
|
private List<Integer> roomList;
|
||||||
|
private List<Integer> periodList;
|
||||||
|
private List<Lecture> lectureList;
|
||||||
|
private HardSoftScore score;
|
||||||
|
|
||||||
|
public CourseSchedule(){
|
||||||
|
roomList = new ArrayList<>();
|
||||||
|
periodList = new ArrayList<>();
|
||||||
|
lectureList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ValueRangeProvider(id = "availableRooms")
|
||||||
|
@ProblemFactCollectionProperty
|
||||||
|
public List<Integer> getRoomList() {
|
||||||
|
return roomList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ValueRangeProvider(id = "availablePeriods")
|
||||||
|
@ProblemFactCollectionProperty
|
||||||
|
public List<Integer> getPeriodList() {
|
||||||
|
return periodList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PlanningEntityCollectionProperty
|
||||||
|
public List<Lecture> getLectureList() {
|
||||||
|
return lectureList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PlanningScore
|
||||||
|
public HardSoftScore getScore() {
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScore(HardSoftScore score) {
|
||||||
|
this.score = score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printCourseSchedule() {
|
||||||
|
lectureList.stream()
|
||||||
|
.map(c -> "Lecture in Room " + c.getRoomNumber().toString() + " during Period " + c.getPeriod().toString())
|
||||||
|
.forEach(k -> logger.info(k));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.baeldung.drools.optaplanner;
|
||||||
|
|
||||||
|
import org.optaplanner.core.api.domain.entity.PlanningEntity;
|
||||||
|
import org.optaplanner.core.api.domain.variable.PlanningVariable;
|
||||||
|
|
||||||
|
@PlanningEntity
|
||||||
|
public class Lecture {
|
||||||
|
|
||||||
|
private Integer roomNumber;
|
||||||
|
private Integer period;
|
||||||
|
|
||||||
|
@PlanningVariable(valueRangeProviderRefs = {"availablePeriods"})
|
||||||
|
public Integer getPeriod() {
|
||||||
|
return period;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PlanningVariable(valueRangeProviderRefs = {"availableRooms"})
|
||||||
|
public Integer getRoomNumber() {
|
||||||
|
return roomNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPeriod(Integer period) {
|
||||||
|
this.period = period;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoomNumber(Integer roomNumber) {
|
||||||
|
this.roomNumber = roomNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.baeldung.drools.optaplanner;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import org.optaplanner.core.api.score.Score;
|
||||||
|
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
|
||||||
|
import org.optaplanner.core.impl.score.director.easy.EasyScoreCalculator;
|
||||||
|
|
||||||
|
public class ScoreCalculator implements EasyScoreCalculator<CourseSchedule> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Score calculateScore(CourseSchedule courseSchedule) {
|
||||||
|
int hardScore = 0;
|
||||||
|
int softScore = 0;
|
||||||
|
|
||||||
|
HashSet<String> occupiedRooms = new HashSet<>();
|
||||||
|
for (Lecture lecture : courseSchedule.getLectureList()) {
|
||||||
|
if(lecture.getPeriod() != null && lecture.getRoomNumber() != null) {
|
||||||
|
String roomInUse = lecture.getPeriod().toString() + ":" + lecture.getRoomNumber().toString();
|
||||||
|
if (occupiedRooms.contains(roomInUse)) {
|
||||||
|
hardScore += -1;
|
||||||
|
} else {
|
||||||
|
occupiedRooms.add(roomInUse);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hardScore += -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return HardSoftScore.valueOf(hardScore, softScore);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.drools.optaplanner
|
||||||
|
|
||||||
|
import com.baeldung.drools.optaplanner.Lecture;
|
||||||
|
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;
|
||||||
|
|
||||||
|
global HardSoftScoreHolder scoreHolder;
|
||||||
|
|
||||||
|
rule "noNullRoomPeriod"
|
||||||
|
when
|
||||||
|
Lecture( roomNumber == null );
|
||||||
|
Lecture( period == null );
|
||||||
|
then
|
||||||
|
scoreHolder.addHardConstraintMatch(kcontext, -1);
|
||||||
|
end
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<solver>
|
||||||
|
<scanAnnotatedClasses/>
|
||||||
|
|
||||||
|
<scoreDirectorFactory>
|
||||||
|
<scoreDrl>courseSchedule.drl</scoreDrl>
|
||||||
|
</scoreDirectorFactory>
|
||||||
|
|
||||||
|
<termination>
|
||||||
|
<secondsSpentLimit>10</secondsSpentLimit>
|
||||||
|
</termination>
|
||||||
|
</solver>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<solver>
|
||||||
|
<scanAnnotatedClasses/>
|
||||||
|
|
||||||
|
<scoreDirectorFactory>
|
||||||
|
<easyScoreCalculatorClass>com.baeldung.drools.optaplanner.ScoreCalculator</easyScoreCalculatorClass>
|
||||||
|
</scoreDirectorFactory>
|
||||||
|
|
||||||
|
<termination>
|
||||||
|
<secondsSpentLimit>10</secondsSpentLimit>
|
||||||
|
</termination>
|
||||||
|
</solver>
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.baeldung.drools.optaplanner;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.optaplanner.core.api.solver.Solver;
|
||||||
|
import org.optaplanner.core.api.solver.SolverFactory;
|
||||||
|
|
||||||
|
public class OptaPlannerUnitTest {
|
||||||
|
|
||||||
|
static CourseSchedule unsolvedCourseSchedule;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void setUp() {
|
||||||
|
|
||||||
|
unsolvedCourseSchedule = new CourseSchedule();
|
||||||
|
|
||||||
|
for(int i = 0; i < 10; i++){
|
||||||
|
unsolvedCourseSchedule.getLectureList().add(new Lecture());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsolvedCourseSchedule.getPeriodList().addAll(Arrays.asList(new Integer[] { 1, 2, 3 }));
|
||||||
|
unsolvedCourseSchedule.getRoomList().addAll(Arrays.asList(new Integer[] { 1, 2 }));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_whenCustomJavaSolver() {
|
||||||
|
|
||||||
|
SolverFactory<CourseSchedule> solverFactory = SolverFactory.createFromXmlResource("courseScheduleSolverConfiguration.xml");
|
||||||
|
Solver<CourseSchedule> solver = solverFactory.buildSolver();
|
||||||
|
CourseSchedule solvedCourseSchedule = solver.solve(unsolvedCourseSchedule);
|
||||||
|
|
||||||
|
Assert.assertNotNull(solvedCourseSchedule.getScore());
|
||||||
|
Assert.assertEquals(-4, solvedCourseSchedule.getScore().getHardScore());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_whenDroolsSolver() {
|
||||||
|
|
||||||
|
SolverFactory<CourseSchedule> solverFactory = SolverFactory.createFromXmlResource("courseScheduleSolverConfigDrools.xml");
|
||||||
|
Solver<CourseSchedule> solver = solverFactory.buildSolver();
|
||||||
|
CourseSchedule solvedCourseSchedule = solver.solve(unsolvedCourseSchedule);
|
||||||
|
|
||||||
|
Assert.assertNotNull(solvedCourseSchedule.getScore());
|
||||||
|
Assert.assertEquals(0, solvedCourseSchedule.getScore().getHardScore());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
## Relevant articles:
|
|
|
@ -1,25 +0,0 @@
|
||||||
package com.baeldung.enterprise.patterns.front.controller.filters;
|
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class AuditFilter extends BaseFilter {
|
|
||||||
@Override
|
|
||||||
public void doFilter(
|
|
||||||
ServletRequest request,
|
|
||||||
ServletResponse response,
|
|
||||||
FilterChain chain
|
|
||||||
) throws IOException, ServletException {
|
|
||||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
|
||||||
HttpSession session = httpServletRequest.getSession(false);
|
|
||||||
if (session != null && session.getAttribute("username") != null) {
|
|
||||||
request.setAttribute("username", session.getAttribute("username"));
|
|
||||||
}
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
package com.baeldung.enterprise.patterns.front.controller.filters;
|
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.ServletResponse;
|
|
||||||
import javax.servlet.annotation.WebFilter;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
@WebFilter(servletNames = "front-controller")
|
|
||||||
public class VisitorCounterFilter extends BaseFilter {
|
|
||||||
private int counter;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doFilter(
|
|
||||||
ServletRequest request,
|
|
||||||
ServletResponse response,
|
|
||||||
FilterChain chain
|
|
||||||
) throws IOException, ServletException {
|
|
||||||
request.setAttribute("counter", ++counter);
|
|
||||||
chain.doFilter(request, response);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.baeldung.enterprise.patterns</groupId>
|
|
||||||
<artifactId>enterprise-patterns-parent</artifactId>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-modules</artifactId>
|
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<modules>
|
|
||||||
<module>spring-dispatcher-servlet</module>
|
|
||||||
</modules>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -7,3 +7,4 @@
|
||||||
- [Gson Deserialization Cookbook](http://www.baeldung.com/gson-deserialization-guide)
|
- [Gson Deserialization Cookbook](http://www.baeldung.com/gson-deserialization-guide)
|
||||||
- [Jackson vs Gson](http://www.baeldung.com/jackson-vs-gson)
|
- [Jackson vs Gson](http://www.baeldung.com/jackson-vs-gson)
|
||||||
- [Exclude Fields from Serialization in Gson](http://www.baeldung.com/gson-exclude-fields-serialization)
|
- [Exclude Fields from Serialization in Gson](http://www.baeldung.com/gson-exclude-fields-serialization)
|
||||||
|
- [Save Data to a JSON File with Gson](https://www.baeldung.com/gson-save-file)
|
||||||
|
|
|
@ -33,3 +33,4 @@
|
||||||
- [Using Guava CountingOutputStream](http://www.baeldung.com/guava-counting-outputstream)
|
- [Using Guava CountingOutputStream](http://www.baeldung.com/guava-counting-outputstream)
|
||||||
- [Hamcrest Text Matchers](http://www.baeldung.com/hamcrest-text-matchers)
|
- [Hamcrest Text Matchers](http://www.baeldung.com/hamcrest-text-matchers)
|
||||||
- [Quick Guide to the Guava RateLimiter](http://www.baeldung.com/guava-rate-limiter)
|
- [Quick Guide to the Guava RateLimiter](http://www.baeldung.com/guava-rate-limiter)
|
||||||
|
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [Guide to Hazelcast with Java](http://www.baeldung.com/java-hazelcast)
|
- [Guide to Hazelcast with Java](http://www.baeldung.com/java-hazelcast)
|
||||||
|
- [Introduction to Hazelcast Jet](https://www.baeldung.com/hazelcast-jet)
|
||||||
|
|
|
@ -13,3 +13,4 @@
|
||||||
- [Pessimistic Locking in JPA](http://www.baeldung.com/jpa-pessimistic-locking)
|
- [Pessimistic Locking in JPA](http://www.baeldung.com/jpa-pessimistic-locking)
|
||||||
- [Bootstrapping JPA Programmatically in Java](http://www.baeldung.com/java-bootstrap-jpa)
|
- [Bootstrapping JPA Programmatically in Java](http://www.baeldung.com/java-bootstrap-jpa)
|
||||||
- [Optimistic Locking in JPA](http://www.baeldung.com/jpa-optimistic-locking)
|
- [Optimistic Locking in JPA](http://www.baeldung.com/jpa-optimistic-locking)
|
||||||
|
- [Hibernate Entity Lifecycle](https://www.baeldung.com/hibernate-entity-lifecycle)
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
package com.baeldung.hibernate;
|
package com.baeldung.hibernate;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import com.baeldung.hibernate.entities.DeptEmployee;
|
||||||
import com.baeldung.hibernate.optimisticlocking.OptimisticLockingCourse;
|
import com.baeldung.hibernate.optimisticlocking.OptimisticLockingCourse;
|
||||||
import com.baeldung.hibernate.optimisticlocking.OptimisticLockingStudent;
|
import com.baeldung.hibernate.optimisticlocking.OptimisticLockingStudent;
|
||||||
import com.baeldung.hibernate.pessimisticlocking.Individual;
|
import com.baeldung.hibernate.pessimisticlocking.Individual;
|
||||||
|
@ -16,10 +22,30 @@ import org.hibernate.boot.MetadataSources;
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import com.baeldung.hibernate.pojo.Course;
|
||||||
import java.io.IOException;
|
import com.baeldung.hibernate.pojo.Employee;
|
||||||
import java.net.URL;
|
import com.baeldung.hibernate.pojo.EntityDescription;
|
||||||
import java.util.Properties;
|
import com.baeldung.hibernate.pojo.OrderEntry;
|
||||||
|
import com.baeldung.hibernate.pojo.OrderEntryIdClass;
|
||||||
|
import com.baeldung.hibernate.pojo.OrderEntryPK;
|
||||||
|
import com.baeldung.hibernate.pojo.Person;
|
||||||
|
import com.baeldung.hibernate.pojo.Phone;
|
||||||
|
import com.baeldung.hibernate.pojo.PointEntity;
|
||||||
|
import com.baeldung.hibernate.pojo.PolygonEntity;
|
||||||
|
import com.baeldung.hibernate.pojo.Product;
|
||||||
|
import com.baeldung.hibernate.pojo.Student;
|
||||||
|
import com.baeldung.hibernate.pojo.TemporalValues;
|
||||||
|
import com.baeldung.hibernate.pojo.User;
|
||||||
|
import com.baeldung.hibernate.pojo.UserProfile;
|
||||||
|
import com.baeldung.hibernate.pojo.inheritance.Animal;
|
||||||
|
import com.baeldung.hibernate.pojo.inheritance.Bag;
|
||||||
|
import com.baeldung.hibernate.pojo.inheritance.Book;
|
||||||
|
import com.baeldung.hibernate.pojo.inheritance.Car;
|
||||||
|
import com.baeldung.hibernate.pojo.inheritance.MyEmployee;
|
||||||
|
import com.baeldung.hibernate.pojo.inheritance.MyProduct;
|
||||||
|
import com.baeldung.hibernate.pojo.inheritance.Pen;
|
||||||
|
import com.baeldung.hibernate.pojo.inheritance.Pet;
|
||||||
|
import com.baeldung.hibernate.pojo.inheritance.Vehicle;
|
||||||
|
|
||||||
public class HibernateUtil {
|
public class HibernateUtil {
|
||||||
private static SessionFactory sessionFactory;
|
private static SessionFactory sessionFactory;
|
||||||
|
@ -72,6 +98,8 @@ public class HibernateUtil {
|
||||||
metadataSources.addAnnotatedClass(PessimisticLockingCourse.class);
|
metadataSources.addAnnotatedClass(PessimisticLockingCourse.class);
|
||||||
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pessimisticlocking.Customer.class);
|
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pessimisticlocking.Customer.class);
|
||||||
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pessimisticlocking.Address.class);
|
metadataSources.addAnnotatedClass(com.baeldung.hibernate.pessimisticlocking.Address.class);
|
||||||
|
metadataSources.addAnnotatedClass(DeptEmployee.class);
|
||||||
|
metadataSources.addAnnotatedClass(com.baeldung.hibernate.entities.Department.class);
|
||||||
metadataSources.addAnnotatedClass(OptimisticLockingCourse.class);
|
metadataSources.addAnnotatedClass(OptimisticLockingCourse.class);
|
||||||
metadataSources.addAnnotatedClass(OptimisticLockingStudent.class);
|
metadataSources.addAnnotatedClass(OptimisticLockingStudent.class);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.baeldung.hibernate.entities;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Department {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy="department")
|
||||||
|
private List<DeptEmployee> employees;
|
||||||
|
|
||||||
|
public Department(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 List<DeptEmployee> getEmployees() {
|
||||||
|
return employees;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmployees(List<DeptEmployee> employees) {
|
||||||
|
this.employees = employees;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.baeldung.hibernate.entities;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class DeptEmployee {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
private String employeeNumber;
|
||||||
|
|
||||||
|
private String designation;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Department department;
|
||||||
|
|
||||||
|
public DeptEmployee(String name, String employeeNumber, Department department) {
|
||||||
|
this.name = name;
|
||||||
|
this.employeeNumber = employeeNumber;
|
||||||
|
this.department = department;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmployeeNumber() {
|
||||||
|
return employeeNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmployeeNumber(String employeeNumber) {
|
||||||
|
this.employeeNumber = employeeNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Department getDepartment() {
|
||||||
|
return department;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDepartment(Department department) {
|
||||||
|
this.department = department;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDesignation() {
|
||||||
|
return designation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDesignation(String designation) {
|
||||||
|
this.designation = designation;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
public class Result {
|
||||||
|
private String employeeName;
|
||||||
|
|
||||||
|
private String departmentName;
|
||||||
|
|
||||||
|
public Result(String employeeName, String departmentName) {
|
||||||
|
this.employeeName = employeeName;
|
||||||
|
this.departmentName = departmentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmployeeName() {
|
||||||
|
return employeeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmployeeName(String employeeName) {
|
||||||
|
this.employeeName = employeeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDepartmentName() {
|
||||||
|
return departmentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDepartmentName(String departmentName) {
|
||||||
|
this.departmentName = departmentName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,77 @@
|
||||||
|
package com.baeldung.hibernate;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baeldung.hibernate.entities.DeptEmployee;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.query.Query;
|
||||||
|
import org.hibernate.transform.Transformers;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import com.baeldung.hibernate.entities.Department;
|
||||||
|
import com.baeldung.hibernate.pojo.Result;
|
||||||
|
|
||||||
|
public class CustomClassIntegrationTest {
|
||||||
|
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
private Transaction transaction;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp() throws IOException {
|
||||||
|
session = HibernateUtil.getSessionFactory().openSession();
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
session.createNativeQuery("delete from manager").executeUpdate();
|
||||||
|
session.createNativeQuery("delete from department").executeUpdate();
|
||||||
|
Department department = new Department("Sales");
|
||||||
|
DeptEmployee employee = new DeptEmployee("John Smith", "001", department);
|
||||||
|
session.persist(department);
|
||||||
|
session.persist(employee);
|
||||||
|
transaction.commit();
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenAllManagersAreSelected_ThenObjectGraphIsReturned() {
|
||||||
|
Query<DeptEmployee> query = session.createQuery("from com.baeldung.hibernate.entities.DeptEmployee");
|
||||||
|
List<DeptEmployee> deptEmployees = query.list();
|
||||||
|
DeptEmployee deptEmployee = deptEmployees.get(0);
|
||||||
|
assertEquals("John Smith", deptEmployee.getName());
|
||||||
|
assertEquals("Sales", deptEmployee.getDepartment().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenIndividualPropertiesAreSelected_ThenObjectArrayIsReturned() {
|
||||||
|
Query query = session.createQuery("select m.name, m.department.name from com.baeldung.hibernate.entities.DeptEmployee m");
|
||||||
|
List managers = query.list();
|
||||||
|
Object[] manager = (Object[]) managers.get(0);
|
||||||
|
assertEquals("John Smith", manager[0]);
|
||||||
|
assertEquals("Sales", manager[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenResultConstructorInSelect_ThenListOfResultIsReturned() {
|
||||||
|
Query<Result> query = session.createQuery("select new com.baeldung.hibernate.pojo.Result(m.name, m.department.name) "
|
||||||
|
+ "from DeptEmployee m");
|
||||||
|
List<Result> results = query.list();
|
||||||
|
Result result = results.get(0);
|
||||||
|
assertEquals("John Smith", result.getEmployeeName());
|
||||||
|
assertEquals("Sales", result.getDepartmentName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenResultTransformerOnQuery_ThenListOfResultIsReturned() {
|
||||||
|
Query query = session.createQuery("select m.name as employeeName, m.department.name as departmentName "
|
||||||
|
+ "from com.baeldung.hibernate.entities.DeptEmployee m");
|
||||||
|
query.setResultTransformer(Transformers.aliasToBean(Result.class));
|
||||||
|
List<Result> results = query.list();
|
||||||
|
Result result = results.get(0);
|
||||||
|
assertEquals("John Smith", result.getEmployeeName());
|
||||||
|
assertEquals("Sales", result.getDepartmentName());
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue