From e8ea3f1f804f4bf220e4279b3a4f02a59029b7e8 Mon Sep 17 00:00:00 2001 From: Jonathan Paul Cook Date: Sat, 13 Oct 2018 19:39:00 +0200 Subject: [PATCH 1/5] BAEL-2268 - Guide to JerseyTest - second attempt without formatting changes --- .../baeldung/jersey/server/model/Fruit.java | 5 +++ .../jersey/server/rest/FruitResource.java | 12 +++++++ .../GreetingsResourceIntegrationTest.java | 33 +++++++++++++++++++ .../rest/FruitResourceIntegrationTest.java | 27 +++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java diff --git a/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java b/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java index c55362487b..1a648290a3 100644 --- a/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java +++ b/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java @@ -54,4 +54,9 @@ public class Fruit { public void setSerial(String serial) { this.serial = serial; } + + @Override + public String toString() { + return "Fruit [name: " + getName() + " colour: " + getColour() + "]"; + } } diff --git a/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java b/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java index ee34cdd3ca..88692dcc55 100644 --- a/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java +++ b/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java @@ -16,6 +16,8 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; import org.glassfish.jersey.server.mvc.ErrorTemplate; import org.glassfish.jersey.server.mvc.Template; @@ -86,6 +88,16 @@ public class FruitResource { public void createFruit(@Valid Fruit fruit) { SimpleStorageService.storeFruit(fruit); } + + @POST + @Path("/created") + @Consumes(MediaType.APPLICATION_JSON) + public Response createNewFruit(@Valid Fruit fruit) { + String result = "Fruit saved : " + fruit; + return Response.status(Status.CREATED.getStatusCode()) + .entity(result) + .build(); + } @GET @Valid diff --git a/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java b/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java new file mode 100644 index 0000000000..c89e2fe23c --- /dev/null +++ b/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java @@ -0,0 +1,33 @@ +package com.baeldung.jersey.server; + +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.core.Application; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Test; + +public class GreetingsResourceIntegrationTest extends JerseyTest { + + @Override + protected Application configure() { + return new ResourceConfig(Greetings.class); + } + + @Test + public void givenGetHiGreeting_whenCorrectRequest_thenResponseIsOkAndContainsHi() { + Response response = target("/greetings/hi").request() + .get(); + + assertEquals("Http Response should be 200: ", Status.OK.getStatusCode(), response.getStatus()); + assertEquals("Http Content-Type should be: ", MediaType.TEXT_HTML, response.getHeaderString(HttpHeaders.CONTENT_TYPE)); + + String content = response.readEntity(String.class); + assertEquals("Content of ressponse is: ", "hi", content); + } +} \ No newline at end of file diff --git a/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java b/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java index 2eeb5710cb..376c8c1e75 100644 --- a/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java +++ b/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java @@ -10,6 +10,7 @@ import javax.ws.rs.core.Application; import javax.ws.rs.core.Form; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; import org.glassfish.jersey.test.JerseyTest; import org.glassfish.jersey.test.TestProperties; @@ -63,6 +64,15 @@ public class FruitResourceIntegrationTest extends JerseyTest { assertEquals("Http Response should be 400 ", 400, response.getStatus()); assertThat(response.readEntity(String.class), containsString("Fruit colour must not be null")); } + + @Test + public void givenCreateFruit_whenJsonIsCorrect_thenResponseCodeIsCreated() { + Response response = target("fruit/created").request() + .post(Entity.json("{\"name\":\"strawberry\",\"weight\":20}")); + + assertEquals("Http Response should be 201 ", Status.CREATED.getStatusCode(), response.getStatus()); + assertThat(response.readEntity(String.class), containsString("Fruit saved : Fruit [name: strawberry colour: null]")); + } @Test public void givenUpdateFruit_whenFormContainsBadSerialParam_thenResponseCodeIsBadRequest() { @@ -102,6 +112,23 @@ public class FruitResourceIntegrationTest extends JerseyTest { .get(String.class); assertThat(json, containsString("{\"name\":\"strawberry\",\"weight\":20}")); } + + @Test + public void givenFruitExists_whenSearching_thenResponseContainsFruitEntity() { + Fruit fruit = new Fruit(); + fruit.setName("strawberry"); + fruit.setWeight(20); + Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE) + .post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE)); + + assertEquals("Http Response should be 204 ", 204, response.getStatus()); + + final Fruit entity = target("fruit/search/strawberry").request() + .get(Fruit.class); + + assertEquals("Fruit name: ", "strawberry", entity.getName()); + assertEquals("Fruit weight: ", Integer.valueOf(20), entity.getWeight()); + } @Test public void givenFruit_whenFruitIsInvalid_thenReponseContainsCustomExceptions() { From 04ed393ba18daa7cd850de10cabd17a935935380 Mon Sep 17 00:00:00 2001 From: Jonathan Paul Cook Date: Sat, 13 Oct 2018 19:42:18 +0200 Subject: [PATCH 2/5] BAEL-2268 - Guide to JerseyTest - Add line break to end of file --- .../jersey/server/GreetingsResourceIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java b/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java index c89e2fe23c..8953f4161c 100644 --- a/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java +++ b/jersey/src/test/java/com/baeldung/jersey/server/GreetingsResourceIntegrationTest.java @@ -30,4 +30,4 @@ public class GreetingsResourceIntegrationTest extends JerseyTest { String content = response.readEntity(String.class); assertEquals("Content of ressponse is: ", "hi", content); } -} \ No newline at end of file +} From 1da262956246d688a5d996760cac5ad2f9cc42ef Mon Sep 17 00:00:00 2001 From: Jonathan Paul Cook Date: Mon, 29 Oct 2018 19:51:15 +0100 Subject: [PATCH 3/5] BAEL-2193 - Merge 2 java.util.Properties objects --- .../properties/MergePropertiesUnitTest.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java b/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java new file mode 100644 index 0000000000..2318104b8d --- /dev/null +++ b/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java @@ -0,0 +1,84 @@ +package com.baeldung.properties; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.stream.Stream; + +import org.junit.Test; + +public class MergePropertiesUnitTest { + + @Test + public void givenTwoProperties_whenMergedUsingIteration_thenAllPropertiesInResult() throws Exception { + Properties globalProperties = mergePropertiesByIteratingKeySet(propertiesA(), propertiesB()); + + testMergedProperties(globalProperties); + } + + @Test + public void givenTwoProperties_whenMergedUsingPutAll_thenAllPropertiesInResult() throws Exception { + Properties globalProperties = mergePropertiesByUsingPutAll(propertiesA(), propertiesB()); + + testMergedProperties(globalProperties); + } + + @Test + public void givenTwoProperties_whenMergedUsingStreamAPI_thenAllPropertiesInResult() throws Exception { + Properties globalProperties = mergePropertiesByUsingStreamApi(propertiesB(), propertiesA()); + + testMergedProperties(globalProperties); + } + + private Properties mergePropertiesByIteratingKeySet(Properties... properties) { + Properties mergedProperties = new Properties(); + for (Properties property : properties) { + Set propertyNames = property.stringPropertyNames(); + for (String name : propertyNames) { + String propertyValue = property.getProperty(name); + mergedProperties.setProperty(name, propertyValue); + } + } + return mergedProperties; + } + + private Properties mergePropertiesByUsingPutAll(Properties... properties) { + Properties mergedProperties = new Properties(); + for (Properties property : properties) { + mergedProperties.putAll(property); + } + return mergedProperties; + } + + private Properties mergePropertiesByUsingStreamApi(Properties... properties) { + return Stream.of(properties) + .collect(Properties::new, Map::putAll, Map::putAll); + } + + private Properties propertiesA() { + Properties properties = new Properties(); + properties.setProperty("application.name", "my-app"); + properties.setProperty("application.version", "1.0"); + return properties; + } + + private Properties propertiesB() { + Properties properties = new Properties(); + properties.setProperty("property-1", "sample property"); + properties.setProperty("property-2", "another sample property"); + return properties; + } + + private void testMergedProperties(Properties globalProperties) { + assertThat("There should be 4 properties", globalProperties.size(), equalTo(4)); + assertEquals("Property should be", globalProperties.getProperty("application.name"), "my-app"); + assertEquals("Property should be", globalProperties.getProperty("application.version"), "1.0"); + assertEquals("Property should be", globalProperties.getProperty("property-1"), "sample property"); + assertEquals("Property should be", globalProperties.getProperty("property-2"), "another sample property"); + } + +} From 5930d0d363c144e7a74c9fe09580b7e4d69a09ea Mon Sep 17 00:00:00 2001 From: Jonathan Paul Cook Date: Tue, 30 Oct 2018 08:39:11 +0100 Subject: [PATCH 4/5] BAEL-2193 - Merge 2 java.util.Properties object --- .../com/baeldung/properties/MergePropertiesUnitTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java b/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java index 2318104b8d..8720aff36b 100644 --- a/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java +++ b/core-java/src/test/java/com/baeldung/properties/MergePropertiesUnitTest.java @@ -14,21 +14,21 @@ import org.junit.Test; public class MergePropertiesUnitTest { @Test - public void givenTwoProperties_whenMergedUsingIteration_thenAllPropertiesInResult() throws Exception { + public void givenTwoProperties_whenMergedUsingIteration_thenAllPropertiesInResult() { Properties globalProperties = mergePropertiesByIteratingKeySet(propertiesA(), propertiesB()); testMergedProperties(globalProperties); } @Test - public void givenTwoProperties_whenMergedUsingPutAll_thenAllPropertiesInResult() throws Exception { + public void givenTwoProperties_whenMergedUsingPutAll_thenAllPropertiesInResult() { Properties globalProperties = mergePropertiesByUsingPutAll(propertiesA(), propertiesB()); testMergedProperties(globalProperties); } @Test - public void givenTwoProperties_whenMergedUsingStreamAPI_thenAllPropertiesInResult() throws Exception { + public void givenTwoProperties_whenMergedUsingStreamAPI_thenAllPropertiesInResult() { Properties globalProperties = mergePropertiesByUsingStreamApi(propertiesB(), propertiesA()); testMergedProperties(globalProperties); From ab2ee364f262ddc8a6d19ea50e458ce5d4cb52d5 Mon Sep 17 00:00:00 2001 From: Jonathan Paul Cook Date: Sun, 16 Dec 2018 22:32:09 +0100 Subject: [PATCH 5/5] BAEL-2175 - Verbose Garbage Collection in Java --- .../gc/VerboseGarbageCollectorRunner.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java diff --git a/core-java/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java b/core-java/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java new file mode 100644 index 0000000000..f57580bbb5 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/gc/VerboseGarbageCollectorRunner.java @@ -0,0 +1,63 @@ +package com.baeldung.gc; + +import java.util.HashMap; +import java.util.Map; + +/** + * A simple Java program to demonstrate how to enable verbose Garbage Collection (GC) logging. + *

+ * This simple program loads 3 million {@link java.lang.String} instances into a {@link java.util.HashMap} + * object before making an explicit call to the garbage collector using System.gc(). + *

+ * Finally, it removes 2 million of the {@link java.lang.String} instances from the {@link java.util.HashMap}. + * We also explicitly use System.out.println to make interpreting the output easier. + *

+ * Run this program with the following arguments to see verbose GC logging in its complete form: + *

+ * -XX:+UseSerialGC -Xms1024m -Xmx1024m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/path/to/file/gc.log
+ * 
+ * Where: + *
    + *
  • -XX:+UseSerialGC - specify the serial garbage collector.
  • + *
  • -Xms1024m - specify the minimal heap size.
  • + *
  • -Xmx1024m - specify the maximal heap size.
  • + *
  • -verbose:gc - activate the logging of garbage collection information in its simplest form.
  • + *
  • -XX:+PrintGCDetails - activate detailed information about garbage collection.
  • + *
  • -XX:+PrintGCTimeStamps - include a timestamp in the output reflecting the real-time passed in seconds since the JVM started.
  • + *
  • -XX:+PrintGCDateStamps - include the absolute date and time at the start of each line.
  • + *
  • -Xloggc - by default the GC log is written to stdout. Specify an output file via this argument.
  • + *
+ *

+ * It should be noted that the first three arguments are not strictly necessary but for the purposes or the example + * help really simplify things. + * + */ +public class VerboseGarbageCollectorRunner { + + private static Map stringContainer = new HashMap<>(); + + public static void main(String[] args) { + System.out.println("Start of program!"); + String stringWithPrefix = "stringWithPrefix"; + + // Load Java Heap with 3 M java.lang.String instances + for (int i = 0; i < 3000000; i++) { + String newString = stringWithPrefix + i; + stringContainer.put(newString, newString); + } + System.out.println("MAP size: " + stringContainer.size()); + + // Explicit GC! + System.gc(); + + // Remove 2 M out of 3 M + for (int i = 0; i < 2000000; i++) { + String newString = stringWithPrefix + i; + stringContainer.remove(newString); + } + + System.out.println("MAP size: " + stringContainer.size()); + System.out.println("End of program!"); + } + +}