diff --git a/core-java-modules/core-java-9-jigsaw/compile-library-core-module.sh b/core-java-modules/core-java-9-jigsaw/compile-library-core-module.sh
new file mode 100644
index 0000000000..fa0d4d5f14
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/compile-library-core-module.sh
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+javac -d mods/com.baeldung.library.core $(find library-core/src/main -name "*.java")
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/compile-library-core-tests.sh b/core-java-modules/core-java-9-jigsaw/compile-library-core-tests.sh
new file mode 100644
index 0000000000..751906103b
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/compile-library-core-tests.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+javac --class-path outDir/library-core/:\
+libs/junit-jupiter-engine-5.9.2.jar:\
+libs/junit-platform-engine-1.9.2.jar:\
+libs/apiguardian-api-1.1.2.jar:\
+libs/junit-jupiter-params-5.9.2.jar:\
+libs/junit-jupiter-api-5.9.2.jar:\
+libs/opentest4j-1.2.0.jar:\
+libs/junit-platform-commons-1.9.2.jar \
+-d outDir/library-test library-core/src/test/java/com/baeldung/library/core/LibraryUnitTest.java
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/compile-library-core-with-tests.sh b/core-java-modules/core-java-9-jigsaw/compile-library-core-with-tests.sh
new file mode 100644
index 0000000000..c873a9003c
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/compile-library-core-with-tests.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+javac --class-path libs/junit-jupiter-engine-5.9.2.jar:\
+libs/junit-platform-engine-1.9.2.jar:\
+libs/apiguardian-api-1.1.2.jar:\
+libs/junit-jupiter-params-5.9.2.jar:\
+libs/junit-jupiter-api-5.9.2.jar:\
+libs/opentest4j-1.2.0.jar:\
+libs/junit-platform-commons-1.9.2.jar \
+-d outDir/library-core \
+library-core/src/main/java/com/baeldung/library/core/Book.java \
+library-core/src/main/java/com/baeldung/library/core/Library.java \
+library-core/src/main/java/com/baeldung/library/core/Main.java \
+library-core/src/test/java/com/baeldung/library/core/LibraryUnitTest.java
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/compile-library-core.sh b/core-java-modules/core-java-9-jigsaw/compile-library-core.sh
new file mode 100644
index 0000000000..7531148d0f
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/compile-library-core.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+javac --class-path libs/junit-jupiter-engine-5.9.2.jar:\
+libs/junit-platform-engine-1.9.2.jar:\
+libs/apiguardian-api-1.1.2.jar:\
+libs/junit-jupiter-params-5.9.2.jar:\
+libs/junit-jupiter-api-5.9.2.jar:\
+libs/opentest4j-1.2.0.jar:\
+libs/junit-platform-commons-1.9.2.jar \
+-d outDir/library-core \
+library-core/src/main/java/com/baeldung/library/core/Book.java \
+library-core/src/main/java/com/baeldung/library/core/Library.java \
+library-core/src/main/java/com/baeldung/library/core/Main.java
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/compile-library-test-module.sh b/core-java-modules/core-java-9-jigsaw/compile-library-test-module.sh
new file mode 100644
index 0000000000..c6fd614fd0
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/compile-library-test-module.sh
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+javac --module-path mods:libs -d mods/com.baeldung.library.test $(find library-test/src/test -name "*.java")
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/download-junit-dependencies.sh b/core-java-modules/core-java-9-jigsaw/download-junit-dependencies.sh
new file mode 100644
index 0000000000..64c72a5429
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/download-junit-dependencies.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+wget -P libs/ https://repo1.maven.org/maven2/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar /
+wget -P libs/ https://repo1.maven.org/maven2/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar /
+wget -P libs/ https://repo1.maven.org/maven2/org/junit/platform/junit-platform-commons/1.9.2/junit-platform-commons-1.9.2.jar /
+wget -P libs/ https://repo1.maven.org/maven2/org/junit/platform/junit-platform-engine/1.9.2/junit-platform-engine-1.9.2.jar /
+wget -P libs/ https://repo1.maven.org/maven2/org/junit/platform/junit-platform-reporting/1.9.2/junit-platform-reporting-1.9.2.jar /
+wget -P libs/ https://repo1.maven.org/maven2/org/junit/platform/junit-platform-console/1.9.2/junit-platform-console-1.9.2.jar /
+wget -P libs/ https://repo1.maven.org/maven2/org/junit/platform/junit-platform-launcher/1.9.2/junit-platform-launcher-1.9.2.jar /
+wget -P libs/ https://repo1.maven.org/maven2/org/junit/jupiter/junit-jupiter-engine/5.9.2/junit-jupiter-engine-5.9.2.jar /
+wget -P libs/ https://repo1.maven.org/maven2/org/junit/jupiter/junit-jupiter-params/5.9.2/junit-jupiter-params-5.9.2.jar
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/library-core/pom.xml b/core-java-modules/core-java-9-jigsaw/library-core/pom.xml
new file mode 100644
index 0000000000..b860d89932
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/library-core/pom.xml
@@ -0,0 +1,55 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ core-java-9-jigsaw
+ 0.2-SNAPSHOT
+
+
+ library-core
+
+
+ 19
+ 19
+ UTF-8
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.9.2
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.9.2
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 9
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0-M5
+
+ false
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/com/baeldung/library/core/Book.java b/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/com/baeldung/library/core/Book.java
new file mode 100644
index 0000000000..782de8fa10
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/com/baeldung/library/core/Book.java
@@ -0,0 +1,52 @@
+package com.baeldung.library.core;
+
+import java.util.Objects;
+
+public class Book {
+
+ private String title;
+ private String author;
+
+ public Book(String title, String author) {
+ this.title = title;
+ this.author = author;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+
+ @Override
+ public String toString() {
+ return "Book [title=" + title + ", author=" + author + "]";
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final Book book = (Book) o;
+
+ if (!Objects.equals(title, book.title)) {
+ return false;
+ }
+ return Objects.equals(author, book.author);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = title != null ? title.hashCode() : 0;
+ result = 31 * result + (author != null ? author.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/com/baeldung/library/core/Library.java b/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/com/baeldung/library/core/Library.java
new file mode 100644
index 0000000000..ee2225810d
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/com/baeldung/library/core/Library.java
@@ -0,0 +1,25 @@
+package com.baeldung.library.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Library {
+
+ private List books = new ArrayList<>();
+
+ public void addBook(Book book) {
+ books.add(book);
+ }
+
+ public List getBooks() {
+ return books;
+ }
+
+ void removeBook(Book book) {
+ books.remove(book);
+ }
+
+ protected void removeBookByAuthor(String author) {
+ books.removeIf(book -> book.getAuthor().equals(author));
+ }
+}
diff --git a/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/com/baeldung/library/core/Main.java b/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/com/baeldung/library/core/Main.java
new file mode 100644
index 0000000000..18839602c2
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/com/baeldung/library/core/Main.java
@@ -0,0 +1,16 @@
+package com.baeldung.library.core;
+
+public class Main {
+
+ public static void main(String[] args) {
+ Library library = new Library();
+ library.addBook(new Book("The Lord of the Rings", "J.R.R. Tolkien"));
+ library.addBook(new Book("The Hobbit", "J.R.R. Tolkien"));
+ library.addBook(new Book("The Silmarillion", "J.R.R. Tolkien"));
+ library.addBook(new Book("The Chronicles of Narnia", "C.S. Lewis"));
+ library.addBook(new Book("The Lion, the Witch and the Wardrobe", "C.S. Lewis"));
+ System.out.println("Welcome to our library!");
+ System.out.println("We have the following books:");
+ library.getBooks().forEach(System.out::println);
+ }
+}
diff --git a/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/module-info.java b/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/module-info.java
new file mode 100644
index 0000000000..bdf88d8bc9
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/library-core/src/main/java/module-info.java
@@ -0,0 +1,3 @@
+module com.baeldung.library.core {
+ exports com.baeldung.library.core;
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/library-core/src/test/java/com/baeldung/library/core/LibraryUnitTest.java b/core-java-modules/core-java-9-jigsaw/library-core/src/test/java/com/baeldung/library/core/LibraryUnitTest.java
new file mode 100644
index 0000000000..20a4889e8c
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/library-core/src/test/java/com/baeldung/library/core/LibraryUnitTest.java
@@ -0,0 +1,47 @@
+package com.baeldung.library.core;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class LibraryUnitTest {
+
+ @Test
+ void givenEmptyLibrary_whenAddABook_thenLibraryHasOneBook() {
+ Library library = new Library();
+ Book theLordOfTheRings = new Book("The Lord of the Rings", "J.R.R. Tolkien");
+ library.addBook(theLordOfTheRings);
+ int expected = 1;
+ int actual = library.getBooks().size();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ void givenTheLibraryWithABook_whenRemoveABook_thenLibraryIsEmpty() {
+ Library library = new Library();
+ Book theLordOfTheRings = new Book("The Lord of the Rings", "J.R.R. Tolkien");
+ library.addBook(theLordOfTheRings);
+ library.removeBook(theLordOfTheRings);
+ int expected = 0;
+ int actual = library.getBooks().size();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ void givenTheLibraryWithSeveralBook_whenRemoveABookByAuthor_thenLibraryHasNoBooksByTheAuthor() {
+ Library library = new Library();
+ Book theLordOfTheRings = new Book("The Lord of the Rings", "J.R.R. Tolkien");
+ Book theHobbit = new Book("The Hobbit", "J.R.R. Tolkien");
+ Book theSilmarillion = new Book("The Silmarillion", "J.R.R. Tolkien");
+ Book theHungerGames = new Book("The Hunger Games", "Suzanne Collins");
+ library.addBook(theLordOfTheRings);
+ library.addBook(theHobbit);
+ library.addBook(theSilmarillion);
+ library.addBook(theHungerGames);
+ library.removeBookByAuthor("J.R.R. Tolkien");
+ int expected = 1;
+ int actual = library.getBooks().size();
+ assertEquals(expected, actual);
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/library-test/src/test/java/com/baeldung/library/test/LibraryUnitTest.java b/core-java-modules/core-java-9-jigsaw/library-test/src/test/java/com/baeldung/library/test/LibraryUnitTest.java
new file mode 100644
index 0000000000..31eae89bba
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/library-test/src/test/java/com/baeldung/library/test/LibraryUnitTest.java
@@ -0,0 +1,53 @@
+package com.baeldung.library.test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.baeldung.library.core.Book;
+import com.baeldung.library.core.Library;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import org.junit.jupiter.api.Test;
+
+class LibraryUnitTest {
+
+ @Test
+ void givenEmptyLibrary_whenAddABook_thenLibraryHasOneBook() {
+ Library library = new Library();
+ Book theLordOfTheRings = new Book("The Lord of the Rings", "J.R.R. Tolkien");
+ library.addBook(theLordOfTheRings);
+ int expected = 1;
+ int actual = library.getBooks().size();
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ void givenTheLibraryWithABook_whenRemoveABook_thenLibraryIsEmpty()
+ throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+ Library library = new Library();
+ Book theLordOfTheRings = new Book("The Lord of the Rings", "J.R.R. Tolkien");
+ library.addBook(theLordOfTheRings);
+ Method removeBook = Library.class.getDeclaredMethod("removeBook", Book.class);
+ removeBook.setAccessible(true);
+ removeBook.invoke(library, theLordOfTheRings);
+ int expected = 0;
+ int actual = library.getBooks().size();
+ assertEquals(expected, actual);
+ }
+@Test
+void givenTheLibraryWithSeveralBook_whenRemoveABookByAuthor_thenLibraryHasNoBooksByTheAuthor() {
+ TestLibrary library = new TestLibrary();
+ Book theLordOfTheRings = new Book("The Lord of the Rings", "J.R.R. Tolkien");
+ Book theHobbit = new Book("The Hobbit", "J.R.R. Tolkien");
+ Book theSilmarillion = new Book("The Silmarillion", "J.R.R. Tolkien");
+ Book theHungerGames = new Book("The Hunger Games", "Suzanne Collins");
+ library.addBook(theLordOfTheRings);
+ library.addBook(theHobbit);
+ library.addBook(theSilmarillion);
+ library.addBook(theHungerGames);
+ library.removeBookByAuthor("J.R.R. Tolkien");
+ int expected = 1;
+ int actual = library.getBooks().size();
+ assertEquals(expected, actual);
+}
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/library-test/src/test/java/com/baeldung/library/test/TestLibrary.java b/core-java-modules/core-java-9-jigsaw/library-test/src/test/java/com/baeldung/library/test/TestLibrary.java
new file mode 100644
index 0000000000..8ee3b0e3fe
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/library-test/src/test/java/com/baeldung/library/test/TestLibrary.java
@@ -0,0 +1,10 @@
+package com.baeldung.library.test;
+
+import com.baeldung.library.core.Library;
+
+public class TestLibrary extends Library {
+ @Override
+ public void removeBookByAuthor(final String author) {
+ super.removeBookByAuthor(author);
+ }
+}
diff --git a/core-java-modules/core-java-9-jigsaw/library-test/src/test/java/module-info.java b/core-java-modules/core-java-9-jigsaw/library-test/src/test/java/module-info.java
new file mode 100644
index 0000000000..8d60b574f2
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/library-test/src/test/java/module-info.java
@@ -0,0 +1,5 @@
+module com.baeldung.library.test {
+ requires com.baeldung.library.core;
+ requires org.junit.jupiter.api;
+ opens com.baeldung.library.test to org.junit.platform.commons;
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/pom.xml b/core-java-modules/core-java-9-jigsaw/pom.xml
index 70a2882234..288254b9cf 100644
--- a/core-java-modules/core-java-9-jigsaw/pom.xml
+++ b/core-java-modules/core-java-9-jigsaw/pom.xml
@@ -5,6 +5,10 @@
4.0.0
core-java-9-jigsaw
core-java-9-jigsaw
+ pom
+
+ library-core
+
com.baeldung
diff --git a/core-java-modules/core-java-9-jigsaw/run-library-core-module-with-patch.sh b/core-java-modules/core-java-9-jigsaw/run-library-core-module-with-patch.sh
new file mode 100644
index 0000000000..70772a3589
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/run-library-core-module-with-patch.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+java --module-path mods:libs \
+--add-modules com.baeldung.library.core \
+--add-opens com.baeldung.library.core/com.baeldung.library.core=org.junit.platform.commons \
+--add-reads com.baeldung.library.core=org.junit.jupiter.api \
+--patch-module com.baeldung.library.core=outDir/library-test \
+--module org.junit.platform.console --select-class com.baeldung.library.core.LibraryUnitTest
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/run-library-core-module.sh b/core-java-modules/core-java-9-jigsaw/run-library-core-module.sh
new file mode 100644
index 0000000000..f2bb976512
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/run-library-core-module.sh
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+java --module-path mods --module com.baeldung.library.core/com.baeldung.library.core.Main
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/run-library-test-class-path.sh b/core-java-modules/core-java-9-jigsaw/run-library-test-class-path.sh
new file mode 100644
index 0000000000..73e3d504bf
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/run-library-test-class-path.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+java --module-path libs \
+org.junit.platform.console.ConsoleLauncher \
+--classpath ./outDir/library-core \
+--select-class com.baeldung.library.core.LibraryUnitTest
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-jigsaw/run-library-test-module-path.sh b/core-java-modules/core-java-9-jigsaw/run-library-test-module-path.sh
new file mode 100644
index 0000000000..08d149dbd7
--- /dev/null
+++ b/core-java-modules/core-java-9-jigsaw/run-library-test-module-path.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+java --module-path mods:libs \
+--add-modules com.baeldung.library.test \
+--add-opens com.baeldung.library.core/com.baeldung.library.core=com.baeldung.library.test \
+org.junit.platform.console.ConsoleLauncher --select-class com.baeldung.library.test.LibraryUnitTest
\ No newline at end of file