diff --git a/todolist/config/spotbugs/exclude.xml b/todolist/config/spotbugs/exclude.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e10c615e8d797fb3c89ba5554e17d8a60efb60f8
--- /dev/null
+++ b/todolist/config/spotbugs/exclude.xml
@@ -0,0 +1,11 @@
+<FindBugsFilter>
+    <Match>
+        <Bug pattern="SA_LOCAL_SELF_COMPARISON" />
+    </Match>
+    <Match>
+        <Bug pattern="EI_EXPOSE_REP" />
+    </Match>
+    <Match>
+        <Bug pattern="EI_EXPOSE_REP2" />
+    </Match>
+</FindBugsFilter>
diff --git a/todolist/core/src/main/java/module-info.java b/todolist/core/src/main/java/module-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..baf3e8381649ecba8764352e98e6644689cf4fd9
--- /dev/null
+++ b/todolist/core/src/main/java/module-info.java
@@ -0,0 +1,6 @@
+module todolist.core {
+    requires transitive com.fasterxml.jackson.databind;
+
+    exports todolist.core;
+    exports todolist.json;
+}
diff --git a/todolist/core/src/main/java/todolist/json/TodoPersistence.java b/todolist/core/src/main/java/todolist/json/TodoPersistence.java
index e4816eb55485987ccb78803bfe35981bc20d7d76..84cdc50626e69075b9b421baf7c3b460bb2d4e89 100644
--- a/todolist/core/src/main/java/todolist/json/TodoPersistence.java
+++ b/todolist/core/src/main/java/todolist/json/TodoPersistence.java
@@ -1,6 +1,7 @@
 package todolist.json;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -10,6 +11,7 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import todolist.core.TodoModel;
+import todolist.json.internal.TodoModule;
 
 /**
  * Wrapper class for JSON serialization,
@@ -20,8 +22,16 @@ public class TodoPersistence {
   private ObjectMapper mapper;
 
   public TodoPersistence() {
-    mapper = new ObjectMapper();
-    mapper.registerModule(new TodoModule());
+    mapper = createObjectMapper();
+  }
+
+  public static SimpleModule createJacksonModule(boolean deep) {
+    return new TodoModule(deep);
+  }
+
+  public static ObjectMapper createObjectMapper() {
+    return new ObjectMapper()
+      .registerModule(createJacksonModule(true));
   }
 
   public TodoModel readTodoModel(Reader reader) throws IOException {
diff --git a/todolist/core/src/main/java/todolist/json/TodoItemDeserializer.java b/todolist/core/src/main/java/todolist/json/internal/TodoItemDeserializer.java
similarity index 97%
rename from todolist/core/src/main/java/todolist/json/TodoItemDeserializer.java
rename to todolist/core/src/main/java/todolist/json/internal/TodoItemDeserializer.java
index 1279de0f49e96487cc4a8c1700ce9628f09157cc..1c22f4c81460798891aaf02bad56b0ac32ee4c20 100644
--- a/todolist/core/src/main/java/todolist/json/TodoItemDeserializer.java
+++ b/todolist/core/src/main/java/todolist/json/internal/TodoItemDeserializer.java
@@ -1,4 +1,4 @@
-package todolist.json;
+package todolist.json.internal;
 
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonProcessingException;
diff --git a/todolist/core/src/main/java/todolist/json/TodoItemSerializer.java b/todolist/core/src/main/java/todolist/json/internal/TodoItemSerializer.java
similarity index 96%
rename from todolist/core/src/main/java/todolist/json/TodoItemSerializer.java
rename to todolist/core/src/main/java/todolist/json/internal/TodoItemSerializer.java
index e3f2ef40675151a96794c296268c0cb5e0bc2c18..f52fe40d3bd69f026894ddbd19f0aad085b2ce67 100644
--- a/todolist/core/src/main/java/todolist/json/TodoItemSerializer.java
+++ b/todolist/core/src/main/java/todolist/json/internal/TodoItemSerializer.java
@@ -1,4 +1,4 @@
-package todolist.json;
+package todolist.json.internal;
 
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.JsonSerializer;
diff --git a/todolist/core/src/main/java/todolist/json/TodoListDeserializer.java b/todolist/core/src/main/java/todolist/json/internal/TodoListDeserializer.java
similarity index 98%
rename from todolist/core/src/main/java/todolist/json/TodoListDeserializer.java
rename to todolist/core/src/main/java/todolist/json/internal/TodoListDeserializer.java
index e0da11323cdc656341322bcdca7631ec84b65344..953611e57450774a55c172dd44c836da9020593b 100644
--- a/todolist/core/src/main/java/todolist/json/TodoListDeserializer.java
+++ b/todolist/core/src/main/java/todolist/json/internal/TodoListDeserializer.java
@@ -1,4 +1,4 @@
-package todolist.json;
+package todolist.json.internal;
 
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonProcessingException;
diff --git a/todolist/core/src/main/java/todolist/json/TodoListSerializer.java b/todolist/core/src/main/java/todolist/json/internal/TodoListSerializer.java
similarity index 97%
rename from todolist/core/src/main/java/todolist/json/TodoListSerializer.java
rename to todolist/core/src/main/java/todolist/json/internal/TodoListSerializer.java
index d6d6339b3304b305df0390760965f1918dc26889..1124d6874175d289cf4de2a036e63d53053a04be 100644
--- a/todolist/core/src/main/java/todolist/json/TodoListSerializer.java
+++ b/todolist/core/src/main/java/todolist/json/internal/TodoListSerializer.java
@@ -1,4 +1,4 @@
-package todolist.json;
+package todolist.json.internal;
 
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.JsonSerializer;
diff --git a/todolist/core/src/main/java/todolist/json/TodoModelDeserializer.java b/todolist/core/src/main/java/todolist/json/internal/TodoModelDeserializer.java
similarity index 97%
rename from todolist/core/src/main/java/todolist/json/TodoModelDeserializer.java
rename to todolist/core/src/main/java/todolist/json/internal/TodoModelDeserializer.java
index e4dd3a09c5a3be6556d3ec87f0a97418f519e5b3..100866f9ff012b9d083f0f0caeca2bfdd34619cc 100644
--- a/todolist/core/src/main/java/todolist/json/TodoModelDeserializer.java
+++ b/todolist/core/src/main/java/todolist/json/internal/TodoModelDeserializer.java
@@ -1,4 +1,4 @@
-package todolist.json;
+package todolist.json.internal;
 
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonProcessingException;
diff --git a/todolist/core/src/main/java/todolist/json/TodoModelSerializer.java b/todolist/core/src/main/java/todolist/json/internal/TodoModelSerializer.java
similarity index 97%
rename from todolist/core/src/main/java/todolist/json/TodoModelSerializer.java
rename to todolist/core/src/main/java/todolist/json/internal/TodoModelSerializer.java
index 202bc4608f4650e36ad0f52b8182e740c0fc4d90..a1aa0c855d2ceefdfb3fe6c52c4b05a41a38059f 100644
--- a/todolist/core/src/main/java/todolist/json/TodoModelSerializer.java
+++ b/todolist/core/src/main/java/todolist/json/internal/TodoModelSerializer.java
@@ -1,4 +1,4 @@
-package todolist.json;
+package todolist.json.internal;
 
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.JsonSerializer;
diff --git a/todolist/core/src/main/java/todolist/json/TodoModule.java b/todolist/core/src/main/java/todolist/json/internal/TodoModule.java
similarity index 97%
rename from todolist/core/src/main/java/todolist/json/TodoModule.java
rename to todolist/core/src/main/java/todolist/json/internal/TodoModule.java
index ecf0a39d67e553a834be9ce0a944a10d72f2e95d..97502fb6e6b038a7db9c313c23b43641f1ff01e7 100644
--- a/todolist/core/src/main/java/todolist/json/TodoModule.java
+++ b/todolist/core/src/main/java/todolist/json/internal/TodoModule.java
@@ -1,4 +1,4 @@
-package todolist.json;
+package todolist.json.internal;
 
 import com.fasterxml.jackson.core.Version;
 import com.fasterxml.jackson.databind.module.SimpleModule;
diff --git a/todolist/core/src/test/java/todolist/json/TodoModuleTest.java b/todolist/core/src/test/java/todolist/json/TodoModuleTest.java
index 88248d6ad938876f72aa27715e77d9a570679055..0a7317d623f2e14095bb558e8f7d79bf5f5cc488 100644
--- a/todolist/core/src/test/java/todolist/json/TodoModuleTest.java
+++ b/todolist/core/src/test/java/todolist/json/TodoModuleTest.java
@@ -14,6 +14,7 @@ import todolist.core.AbstractTodoList;
 import todolist.core.TodoItem;
 import todolist.core.TodoList;
 import todolist.core.TodoModel;
+import todolist.json.internal.TodoModule;
 
 public class TodoModuleTest {
 
diff --git a/todolist/fxui/pom.xml b/todolist/fxui/pom.xml
index 70d43d8e329e36d58a6377b6ebca7783f8d1b640..1a3280ee949dd2e9aa2fa5a5b3eaab17d28a179d 100644
--- a/todolist/fxui/pom.xml
+++ b/todolist/fxui/pom.xml
@@ -11,6 +11,10 @@
 
     <artifactId>fxui</artifactId>
 
+    <properties>
+        <skipUiTests>false</skipUiTests>
+    </properties>
+
     <dependencies>
         <dependency>
             <groupId>it1901.todolist</groupId>
@@ -173,6 +177,12 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skipTests>${skipUiTests}</skipTests>
+                    <argLine>
+                    --add-opens todolist.ui/todolist.ui=ALL-UNNAMED --add-exports javafx.graphics/com.sun.javafx.application=ALL-UNNAMED
+                    </argLine>
+                </configuration>
             </plugin>
             <plugin>
                 <groupId>org.openjfx</groupId>
diff --git a/todolist/fxui/src/main/java/module-info.java b/todolist/fxui/src/main/java/module-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..b1707f4ef6ea8238bc99c8cac4dfd7921e43e8a6
--- /dev/null
+++ b/todolist/fxui/src/main/java/module-info.java
@@ -0,0 +1,14 @@
+module todolist.ui {
+    requires com.fasterxml.jackson.databind;
+
+    requires java.net.http;
+
+    requires javafx.base;
+    requires javafx.controls;
+    requires javafx.fxml;
+
+    requires todolist.core;
+    requires fxutil;
+
+    opens todolist.ui to javafx.graphics, javafx.fxml;
+}
diff --git a/todolist/fxui/src/main/java/todolist/ui/RemoteTodoModelAccess.java b/todolist/fxui/src/main/java/todolist/ui/RemoteTodoModelAccess.java
index 808d9d20515d9ec62988c6796cf237982a83c6f5..9e48d594548cfc35afe936b10b09d1b886e443cc 100644
--- a/todolist/fxui/src/main/java/todolist/ui/RemoteTodoModelAccess.java
+++ b/todolist/fxui/src/main/java/todolist/ui/RemoteTodoModelAccess.java
@@ -14,7 +14,7 @@ import java.util.Collection;
 import todolist.core.AbstractTodoList;
 import todolist.core.TodoList;
 import todolist.core.TodoModel;
-import todolist.json.TodoModule;
+import todolist.json.TodoPersistence;
 
 /**
  * Class that centralizes access to a TodoModel. Makes it easier to support transparent use of a
@@ -30,7 +30,7 @@ public class RemoteTodoModelAccess implements TodoModelAccess {
 
   public RemoteTodoModelAccess(URI endpointBaseUri) {
     this.endpointBaseUri = endpointBaseUri;
-    objectMapper = new ObjectMapper().registerModule(new TodoModule());
+    objectMapper = TodoPersistence.createObjectMapper();
   }
 
   private TodoModel getTodoModel() {
@@ -44,7 +44,6 @@ public class RemoteTodoModelAccess implements TodoModelAccess {
             HttpClient.newBuilder().build().send(request, HttpResponse.BodyHandlers.ofString());
         final String responseString = response.body();
         this.todoModel = objectMapper.readValue(responseString, TodoModel.class);
-        System.out.println("TodoModel: " + this.todoModel);
       } catch (IOException | InterruptedException e) {
         throw new RuntimeException(e);
       }
diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoApp.java b/todolist/fxui/src/main/java/todolist/ui/TodoApp.java
index a69c47b49bedc0586a2fde364fbfffd2eb718359..ff4f8268f17c25b391decfe102b439ad1c8b8c07 100644
--- a/todolist/fxui/src/main/java/todolist/ui/TodoApp.java
+++ b/todolist/fxui/src/main/java/todolist/ui/TodoApp.java
@@ -6,6 +6,9 @@ import javafx.scene.Parent;
 import javafx.scene.Scene;
 import javafx.stage.Stage;
 
+/**
+ * Standalone version of the app.
+ */
 public class TodoApp extends Application {
 
   @Override
diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoAppController.java b/todolist/fxui/src/main/java/todolist/ui/TodoAppController.java
index 9bff89e6c3ee641a931014492791164ee509d52b..456e27e7aa8a348773e42e04043f2f49571c947e 100644
--- a/todolist/fxui/src/main/java/todolist/ui/TodoAppController.java
+++ b/todolist/fxui/src/main/java/todolist/ui/TodoAppController.java
@@ -14,11 +14,31 @@ import todolist.core.TodoList;
 import todolist.core.TodoModel;
 import todolist.json.TodoPersistence;
 
+/**
+ * Top-level controller.
+ */
 public class TodoAppController {
 
-  private static final String todoListWithTwoItems =
-      "{\"lists\":[" + "{\"name\":\"todo\",\"items\":[{\"text\":\"item1\",\"checked\":false},"
-          + "{\"text\":\"item2\",\"checked\":true,\"deadline\":\"2020-10-01T14:53:11\"}]}" + "]}";
+  private static final String todoListWithTwoItems = """
+      {
+        "lists" : [
+          {
+            "name": "todo",
+            "items": [
+              {
+                "text": "item1",
+                "checked":false
+              },
+              {
+                "text": "item2",
+                "checked": true,
+                "deadline": "2020-10-01T14:53:11"
+              }
+            ]
+          }
+        ]
+      }
+      """;
 
   @FXML
   String userTodoModelPath;
diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoDocumentApp.java b/todolist/fxui/src/main/java/todolist/ui/TodoDocumentApp.java
index 81fa81eac8b60f894de053e7e84287ffe66675ef..0e3424b992f32b20c2bce35d247676ee2c8b9196 100644
--- a/todolist/fxui/src/main/java/todolist/ui/TodoDocumentApp.java
+++ b/todolist/fxui/src/main/java/todolist/ui/TodoDocumentApp.java
@@ -6,6 +6,9 @@ import javafx.scene.Parent;
 import javafx.scene.Scene;
 import javafx.stage.Stage;
 
+/**
+ * Variant of the app with document metaphor and File menu.
+ */
 public class TodoDocumentApp extends Application {
 
   private TodoDocumentAppController controller;
diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoDocumentAppController.java b/todolist/fxui/src/main/java/todolist/ui/TodoDocumentAppController.java
index b9730ccf6c8827cac1b855780714095661f48c54..a6958ff5fe2edd73e51bfe0c840ccfd4de900700 100644
--- a/todolist/fxui/src/main/java/todolist/ui/TodoDocumentAppController.java
+++ b/todolist/fxui/src/main/java/todolist/ui/TodoDocumentAppController.java
@@ -18,6 +18,9 @@ import java.util.List;
 import javafx.fxml.FXML;
 import todolist.core.TodoModel;
 
+/**
+ * Controller for the document metaphor variant of the app.
+ */
 public class TodoDocumentAppController implements DocumentListener<TodoModel, File> {
 
   private final TodoModelStorage todoModelStorage;
diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoItemListCell.java b/todolist/fxui/src/main/java/todolist/ui/TodoItemListCell.java
index 3223e8a14cbebd218aa099107457d1743d5432a0..0eb783245557926976711c48982808de6ffb3d0d 100644
--- a/todolist/fxui/src/main/java/todolist/ui/TodoItemListCell.java
+++ b/todolist/fxui/src/main/java/todolist/ui/TodoItemListCell.java
@@ -10,6 +10,10 @@ import javafx.scene.control.TextField;
 import javafx.scene.layout.HBox;
 import todolist.core.TodoItem;
 
+/**
+ * ListCell for TodoItems.
+ * Supports editing the text and checking the item.
+ */
 public class TodoItemListCell extends ListCell<TodoItem> {
 
   // for whole row
diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoListController.java b/todolist/fxui/src/main/java/todolist/ui/TodoListController.java
index d77155c9c999cf6b4462e7128a7cdbca036049ce..83eeaac9f75ab35e0a0d364c11a9c52375ba28b5 100644
--- a/todolist/fxui/src/main/java/todolist/ui/TodoListController.java
+++ b/todolist/fxui/src/main/java/todolist/ui/TodoListController.java
@@ -15,6 +15,10 @@ import todolist.core.TodoItem;
 import todolist.core.TodoList;
 import todolist.core.TodoListListener;
 
+/**
+ * Controller for a TodoList.
+ * Supports adding, editing and removing elements.
+ */
 public class TodoListController {
 
   @FXML
@@ -33,7 +37,7 @@ public class TodoListController {
 
   private TodoList todoList = null;
 
-  public TodoList getTodoList() {
+  TodoList getTodoList() {
     return todoList;
   }
 
diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoModelController.java b/todolist/fxui/src/main/java/todolist/ui/TodoModelController.java
index f42bf42121d9f1c98de07c3e42328380b3b68fec..409f1ed09f91291d9c695276f55b86301bc644e3 100644
--- a/todolist/fxui/src/main/java/todolist/ui/TodoModelController.java
+++ b/todolist/fxui/src/main/java/todolist/ui/TodoModelController.java
@@ -8,6 +8,11 @@ import javafx.scene.control.ComboBox;
 import todolist.core.AbstractTodoList;
 import todolist.core.TodoList;
 
+/**
+ * Controller for TodoModel objects.
+ * Supports adding new TodoList objects and
+ * selecting one for viewing and editing.
+ */
 public class TodoModelController {
 
   private TodoModelAccess todoModelAccess;
@@ -73,7 +78,7 @@ public class TodoModelController {
           // retrieve actual list
           todoList = todoModelAccess.getTodoList(todoList.getName());
         }
-        todoListViewController.setTodoList(todoList instanceof TodoList ? (TodoList) todoList : null);
+        todoListViewController.setTodoList(todoList instanceof TodoList tl ? tl : null);
       }
     });
   }
diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoModelStorage.java b/todolist/fxui/src/main/java/todolist/ui/TodoModelStorage.java
index 4c987183af15643780735baed224dbab8b4023d6..df9a6c8209521b4b88413a5321ff49b08fce580f 100644
--- a/todolist/fxui/src/main/java/todolist/ui/TodoModelStorage.java
+++ b/todolist/fxui/src/main/java/todolist/ui/TodoModelStorage.java
@@ -12,6 +12,9 @@ import java.nio.charset.StandardCharsets;
 import todolist.core.TodoModel;
 import todolist.json.TodoPersistence;
 
+/**
+ * DocumentStorage for TodoModel objects addressed by File.
+ */
 public class TodoModelStorage extends AbstractDocumentStorage<TodoModel, File> {
 
   @Override
diff --git a/todolist/fxui/src/main/java/todolist/ui/TodoRemoteApp.java b/todolist/fxui/src/main/java/todolist/ui/TodoRemoteApp.java
index 6a849cd9474335c0c98d6eed94118af2ee1f3436..f25325c8168a9d608c782f106e739478e7114919 100644
--- a/todolist/fxui/src/main/java/todolist/ui/TodoRemoteApp.java
+++ b/todolist/fxui/src/main/java/todolist/ui/TodoRemoteApp.java
@@ -6,6 +6,9 @@ import javafx.scene.Parent;
 import javafx.scene.Scene;
 import javafx.stage.Stage;
 
+/**
+ * Variant of the app that connects to a REST service.
+ */
 public class TodoRemoteApp extends Application {
 
   @Override
diff --git a/todolist/fxutil/src/main/java/module-info.java b/todolist/fxutil/src/main/java/module-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..1191da6dba86341100124c06de2f4013ca1096cc
--- /dev/null
+++ b/todolist/fxutil/src/main/java/module-info.java
@@ -0,0 +1,8 @@
+module fxutil {
+    requires javafx.base;
+    requires javafx.controls;
+    requires javafx.fxml;
+
+    exports fxutil.doc;
+    opens fxutil to javafx.graphics, javafx.fxml;
+}
diff --git a/todolist/pom.xml b/todolist/pom.xml
index f469e16b50433d6c0a62a9af86a72c65a95f5e67..f5d53ffc35f41e18e1c531a8c30dafda65d41d43 100644
--- a/todolist/pom.xml
+++ b/todolist/pom.xml
@@ -118,6 +118,7 @@
                     <configuration>
                         <xmlOutput>false</xmlOutput>
                         <htmlOutput>true</htmlOutput>
+                        <excludeFilterFile>config/spotbugs/exclude.xml</excludeFilterFile>
                     </configuration>
                     <executions>
                         <execution>
@@ -146,7 +147,7 @@
                             <id>jacoco-report</id>
                             <phase>verify</phase>
                             <goals>
-                                <goal>report-aggregate</goal>
+                                <goal>report</goal>
                             </goals>
                         </execution>
                     </executions>
diff --git a/todolist/rest/pom.xml b/todolist/rest/pom.xml
index bfae03943b07a0a639c93edc38dc0853e94b591b..de5ab94e1aa9a63f430ceb310f41dd974273c612 100644
--- a/todolist/rest/pom.xml
+++ b/todolist/rest/pom.xml
@@ -12,8 +12,8 @@
     <artifactId>rest</artifactId>
 
     <properties>
-        <slf4jVersion>1.7.25</slf4jVersion>
-        <jerseyVersion>3.0.1</jerseyVersion>
+        <slf4jVersion>2.0.0-alpha5</slf4jVersion>
+        <jerseyVersion>3.0.3</jerseyVersion>
     </properties>
 
     <dependencies>
@@ -140,26 +140,6 @@
             <version>1.1.1</version>
             <scope>runtime</scope>
         </dependency>
-        <!-- 
-        <dependency>
-            <groupId>javax.xml.bind</groupId>
-            <artifactId>jaxb-api</artifactId>
-            <version>2.3.0</version>
-            <scope>runtime</scope>
-        </dependency>
-            <dependency>
-                <groupId>com.sun.xml.bind</groupId>
-                <artifactId>jaxb-core</artifactId>
-                <version>2.3.0</version>
-                <scope>runtime</scope>
-            </dependency>
-            <dependency>
-                <groupId>com.sun.xml.bind</groupId>
-                <artifactId>jaxb-impl</artifactId>
-                <version>2.3.0</version>
-                <scope>runtime</scope>
-            </dependency>
-        -->
     </dependencies>
 
     <build>
@@ -170,6 +150,11 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <argLine>
+                    --add-opens todolist.rest/todolist.restapi=ALL-UNNAMED
+                    </argLine>
+                </configuration>
             </plugin>
             <!-- Run the checkstyle code quality tool -->
             <plugin>
diff --git a/todolist/rest/src/main/java/module-info.java b/todolist/rest/src/main/java/module-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff69a622b4c6111fc354b68ec7f8f0fde7b204a0
--- /dev/null
+++ b/todolist/rest/src/main/java/module-info.java
@@ -0,0 +1,14 @@
+module todolist.rest {
+    requires jakarta.ws.rs;
+
+    requires jersey.common;
+    requires jersey.server;
+    requires jersey.media.json.jackson;
+
+    requires org.glassfish.hk2.api;
+    requires org.slf4j;
+
+    requires todolist.core;
+
+    opens todolist.restapi to jersey.server;
+}
\ No newline at end of file
diff --git a/todolist/rest/src/main/java/todolist/restserver/TodoModuleObjectMapperProvider.java b/todolist/rest/src/main/java/todolist/restserver/TodoModuleObjectMapperProvider.java
index 9846a28ab08063d3f9d2db1a1644b6a6c9ab6792..dd0f81bf8dee5a57af842804d76a30035b7f784f 100644
--- a/todolist/rest/src/main/java/todolist/restserver/TodoModuleObjectMapperProvider.java
+++ b/todolist/rest/src/main/java/todolist/restserver/TodoModuleObjectMapperProvider.java
@@ -6,7 +6,7 @@ import jakarta.ws.rs.Produces;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.ext.ContextResolver;
 import jakarta.ws.rs.ext.Provider;
-import todolist.json.TodoModule;
+import todolist.json.TodoPersistence;
 
 /**
  * Provides the Jackson module used for JSON serialization.
@@ -19,7 +19,7 @@ public class TodoModuleObjectMapperProvider implements ContextResolver<ObjectMap
   private final ObjectMapper objectMapper;
 
   public TodoModuleObjectMapperProvider() {
-    objectMapper = new ObjectMapper().registerModule(new TodoModule(false));
+    objectMapper = TodoPersistence.createObjectMapper();
   }
 
   @Override
diff --git a/todolist/rest/src/test/java/todolist/restserver/TodoServiceTest.java b/todolist/rest/src/test/java/todolist/restserver/TodoServiceTest.java
index e6ad88c16fae033eabd0a63b2c2e22e0616e7893..243679c970bdfb101d160cae83d2ea9de3c606b0 100644
--- a/todolist/rest/src/test/java/todolist/restserver/TodoServiceTest.java
+++ b/todolist/rest/src/test/java/todolist/restserver/TodoServiceTest.java
@@ -23,7 +23,7 @@ import todolist.restapi.TodoModelService;
 public class TodoServiceTest extends JerseyTest {
 
   protected boolean shouldLog() {
-    return false;
+    return true;
   }
 
   @Override
diff --git a/todolist/springboot/restserver/pom.xml b/todolist/springboot/restserver/pom.xml
index 7d478893b386bee7afeba55c022b44bd41041aa8..9fe41ce93f3c142abd0e3de70ffdde4b43f0b38b 100644
--- a/todolist/springboot/restserver/pom.xml
+++ b/todolist/springboot/restserver/pom.xml
@@ -59,6 +59,7 @@
                 </exclusion>
             </exclusions>
         </dependency>
+
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-jetty</artifactId>
diff --git a/todolist/springboot/restserver/src/main/java/module-info.java b/todolist/springboot/restserver/src/main/java/module-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..34e44fb78c1bf630b909f3da07fb935474bc802e
--- /dev/null
+++ b/todolist/springboot/restserver/src/main/java/module-info.java
@@ -0,0 +1,10 @@
+module todolist.springboot.rest {
+    requires com.fasterxml.jackson.databind;
+
+    requires spring.web;
+    requires spring.beans;
+    requires spring.boot;
+    requires spring.boot.autoconfigure;
+
+    requires todolist.core;
+}
diff --git a/todolist/springboot/restserver/src/main/java/todolist/springboot/restserver/TodoModelApplication.java b/todolist/springboot/restserver/src/main/java/todolist/springboot/restserver/TodoModelApplication.java
index 60fed1dea90123f1cbb3e282aff454e85f6a9254..f9d9fbb54233a0957371203e52b3c140e366d1f8 100644
--- a/todolist/springboot/restserver/src/main/java/todolist/springboot/restserver/TodoModelApplication.java
+++ b/todolist/springboot/restserver/src/main/java/todolist/springboot/restserver/TodoModelApplication.java
@@ -4,14 +4,16 @@ import com.fasterxml.jackson.databind.Module;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.context.annotation.Bean;
-import todolist.json.TodoModule;
+
+import todolist.json.TodoPersistence;
+import todolist.json.internal.TodoModule;
 
 @SpringBootApplication
 public class TodoModelApplication {
 
   @Bean
   public Module objectMapperModule() {
-    return new TodoModule(false);
+    return TodoPersistence.createJacksonModule(false);
   }
 
   public static void main(String[] args) {
diff --git a/todolist/springboot/restserver/src/test/java/todolist/springboot/restserver/TodoModelApplicationTest.java b/todolist/springboot/restserver/src/test/java/todolist/springboot/restserver/TodoModelApplicationTest.java
index da70736cc095f069b48764ee1ee019d43efd764d..c69570c47d76d34e361571f829199a0b8414305a 100644
--- a/todolist/springboot/restserver/src/test/java/todolist/springboot/restserver/TodoModelApplicationTest.java
+++ b/todolist/springboot/restserver/src/test/java/todolist/springboot/restserver/TodoModelApplicationTest.java
@@ -20,7 +20,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
 import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
 import todolist.core.AbstractTodoList;
 import todolist.core.TodoModel;
-import todolist.json.TodoModule;
+import todolist.json.TodoPersistence;
 
 @AutoConfigureMockMvc
 @ContextConfiguration(classes = { TodoModelController.class, TodoModelService.class, TodoModelApplication.class })
@@ -34,7 +34,7 @@ public class TodoModelApplicationTest {
 
   @BeforeEach
   public void setup() throws Exception {
-    objectMapper = new ObjectMapper().registerModule(new TodoModule(false));;
+    objectMapper = TodoPersistence.createObjectMapper();
   }
 
   private String todoUrl(String... segments) {