diff --git a/CHANGELOG.md b/CHANGELOG.md
index a7cf5d3..5e4e152 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,8 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
### Changed
+* HalResourecWrapperis#EmbeddedOriginallyAList is now private
### Fixed
+* Single scalars (e.g. String, Integers, Boolean, etc.) are now not allowed in Wrappers and will result in an exception
## [1.0.0]
diff --git a/README.md b/README.md
index 05e7e75..6f69879 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,15 @@ ___
hateoflux is a lightweight, reactive-first Java library designed to streamline the creation of hypermedia-driven APIs in Spring WebFlux applications. It addresses the limitations of Spring HATEOAS in reactive environments, offering a more intuitive and maintainable approach to building HAL+JSON compliant APIs.
+
+
+Getting Started |
+Cookbook |
+Documentation |
+Demos
+
+
+
## Table of Contents
- [Why hateoflux?](#why-hateoflux)
diff --git a/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalEmbeddedWrapper.java b/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalEmbeddedWrapper.java
index f2e37f0..7f9d3b7 100644
--- a/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalEmbeddedWrapper.java
+++ b/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalEmbeddedWrapper.java
@@ -113,6 +113,8 @@ public static HalEmbeddedWrapper wrap(EmbeddedT resourceT
}
Assert.isTrue(!(resourceToWrap instanceof Iterable>), valueIsNotAllowedToBeOfType("Resource to embed",
"collection/iterable"));
+ Assert.isTrue(!isScalar(resourceToWrap.getClass()), valueIsNotAllowedToBeOfType("Embedded",
+ "scalar (e.g. String, int, etc.)"));
return new HalEmbeddedWrapper<>(resourceToWrap);
}
diff --git a/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalResourceWrapper.java b/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalResourceWrapper.java
index 917a97f..237f1e8 100644
--- a/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalResourceWrapper.java
+++ b/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalResourceWrapper.java
@@ -23,8 +23,10 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import de.kamillionlabs.hateoflux.model.link.Link;
+import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
+import lombok.Setter;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
@@ -65,6 +67,8 @@ public final class HalResourceWrapper
private Map.Entry>> embedded;
@JsonIgnore
+ @Getter(AccessLevel.NONE)
+ @Setter(AccessLevel.NONE)
private Boolean isEmbeddedOriginallyAList;
@JsonProperty("_embedded")
@@ -131,6 +135,8 @@ public static HalResourceWrapper wrap(@NonNull Reso
Assert.isTrue(!(resource instanceof Iterable>), valueIsNotAllowedToBeOfType("Resource", "collection" +
"/iterable. " +
"Use HalListWrapper instead"));
+ Assert.isTrue(!isScalar(resource.getClass()), valueIsNotAllowedToBeOfType("Resource",
+ "scalar (e.g. String, int, etc.)"));
return new HalResourceWrapper<>(resource);
}
diff --git a/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalWrapper.java b/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalWrapper.java
index 1ac1a23..f27b4f8 100644
--- a/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalWrapper.java
+++ b/src/main/java/de/kamillionlabs/hateoflux/model/hal/HalWrapper.java
@@ -281,5 +281,13 @@ protected static String determineRelationNameForObject(Object object) {
}
}
+ protected static boolean isScalar(Class> clazz) {
+ return clazz.isPrimitive()
+ || clazz.equals(String.class)
+ || Number.class.isAssignableFrom(clazz)
+ || clazz.equals(Boolean.class)
+ || clazz.equals(Character.class);
+ }
+
}
diff --git a/src/test/java/de/kamillionlabs/hateoflux/model/hal/HalEmbeddedWrapperTest.java b/src/test/java/de/kamillionlabs/hateoflux/model/hal/HalEmbeddedWrapperTest.java
new file mode 100644
index 0000000..55b22a3
--- /dev/null
+++ b/src/test/java/de/kamillionlabs/hateoflux/model/hal/HalEmbeddedWrapperTest.java
@@ -0,0 +1,45 @@
+package de.kamillionlabs.hateoflux.model.hal;
+
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
+
+class HalEmbeddedWrapperTest {
+
+ @Test
+ void givenString_whenWrapping_thenThrowsException() {
+ assertThatThrownBy(() -> HalEmbeddedWrapper.wrap("hello"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Embedded is not allowed to be of type scalar (e.g. String, int, etc.)");
+ }
+
+ @Test
+ void givenCharacter_whenWrapping_thenThrowsException() {
+ assertThatThrownBy(() -> HalEmbeddedWrapper.wrap('h'))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Embedded is not allowed to be of type scalar (e.g. String, int, etc.)");
+ }
+
+ @Test
+ void givenPrimitiveInt_whenWrapping_thenThrowsException() {
+ assertThatThrownBy(() -> HalEmbeddedWrapper.wrap(3))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Embedded is not allowed to be of type scalar (e.g. String, int, etc.)");
+ }
+
+ @Test
+ void givenBigDecimal_whenWrapping_thenThrowsException() {
+ assertThatThrownBy(() -> HalEmbeddedWrapper.wrap(new BigDecimal("4536433.58")))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Embedded is not allowed to be of type scalar (e.g. String, int, etc.)");
+ }
+
+ @Test
+ void givenBoolean_whenWrapping_thenThrowsException() {
+ assertThatThrownBy(() -> HalEmbeddedWrapper.wrap(false))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Embedded is not allowed to be of type scalar (e.g. String, int, etc.)");
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/de/kamillionlabs/hateoflux/model/hal/HalWrapperTest.java b/src/test/java/de/kamillionlabs/hateoflux/model/hal/HalWrapperTest.java
index 03f92d4..f442864 100644
--- a/src/test/java/de/kamillionlabs/hateoflux/model/hal/HalWrapperTest.java
+++ b/src/test/java/de/kamillionlabs/hateoflux/model/hal/HalWrapperTest.java
@@ -7,6 +7,7 @@
import org.assertj.core.api.AssertionsForClassTypes;
import org.junit.jupiter.api.Test;
+import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -79,4 +80,39 @@ void givenEmptyCollection_whenDetermineRelationNameForObject_thenThrowsException
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Iterable cannot be empty when determining relation names");
}
+
+ @Test
+ void givenString_whenWrapping_thenThrowsException() {
+ assertThatThrownBy(() -> HalResourceWrapper.wrap("hello"))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Resource is not allowed to be of type scalar (e.g. String, int, etc.)");
+ }
+
+ @Test
+ void givenCharacter_whenWrapping_thenThrowsException() {
+ assertThatThrownBy(() -> HalResourceWrapper.wrap('h'))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Resource is not allowed to be of type scalar (e.g. String, int, etc.)");
+ }
+
+ @Test
+ void givenPrimitiveInt_whenWrapping_thenThrowsException() {
+ assertThatThrownBy(() -> HalResourceWrapper.wrap(3))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Resource is not allowed to be of type scalar (e.g. String, int, etc.)");
+ }
+
+ @Test
+ void givenBigDecimal_whenWrapping_thenThrowsException() {
+ assertThatThrownBy(() -> HalResourceWrapper.wrap(new BigDecimal("4536433.58")))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Resource is not allowed to be of type scalar (e.g. String, int, etc.)");
+ }
+
+ @Test
+ void givenBoolean_whenWrapping_thenThrowsException() {
+ assertThatThrownBy(() -> HalResourceWrapper.wrap(false))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Resource is not allowed to be of type scalar (e.g. String, int, etc.)");
+ }
}
\ No newline at end of file
diff --git a/src/test/java/de/kamillionlabs/hateoflux/model/hal/serialization/ManualSerializationTest.java b/src/test/java/de/kamillionlabs/hateoflux/model/hal/serialization/ManualSerializationTest.java
index a25dad4..4fdc2ce 100644
--- a/src/test/java/de/kamillionlabs/hateoflux/model/hal/serialization/ManualSerializationTest.java
+++ b/src/test/java/de/kamillionlabs/hateoflux/model/hal/serialization/ManualSerializationTest.java
@@ -309,7 +309,6 @@ public void givenHalListWrapperWithEmbeddingListsAndEmptyOnes_whenSerialized_the
String actualJson = mapper.writeValueAsString(halListWrapper);
// THEN
- System.out.println(actualJson);
JSONAssert.assertEquals("""
{
"_embedded": {