Merge pull request #98 from apache/jakartaee-10-tck

WIP Jakarta EE 10 TCK setup
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/CommentsJsonStreamParserImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/CommentsJsonStreamParserImpl.java
index f9d298e..fb199bd 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/CommentsJsonStreamParserImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/CommentsJsonStreamParserImpl.java
@@ -27,8 +27,8 @@
                                         final int maxStringLength,
                                         final BufferStrategy.BufferProvider<char[]> bufferProvider,
                                         final BufferStrategy.BufferProvider<char[]> valueBuffer,
-                                        final boolean autoAdjust) {
-        super(inputStream, maxStringLength, bufferProvider, valueBuffer, autoAdjust);
+                                        final boolean autoAdjust, final JsonProviderImpl provider) {
+        super(inputStream, maxStringLength, bufferProvider, valueBuffer, autoAdjust, provider);
     }
 
     public CommentsJsonStreamParserImpl(final InputStream inputStream,
@@ -36,16 +36,16 @@
                                         final int maxStringLength,
                                         final BufferStrategy.BufferProvider<char[]> bufferProvider,
                                         final BufferStrategy.BufferProvider<char[]> valueBuffer,
-                                        final boolean autoAdjust) {
-        super(inputStream, encoding, maxStringLength, bufferProvider, valueBuffer, autoAdjust);
+                                        final boolean autoAdjust, final JsonProviderImpl provider) {
+        super(inputStream, encoding, maxStringLength, bufferProvider, valueBuffer, autoAdjust, provider);
     }
 
     public CommentsJsonStreamParserImpl(final Reader reader,
                                         final int maxStringLength,
                                         final BufferStrategy.BufferProvider<char[]> bufferProvider,
                                         final BufferStrategy.BufferProvider<char[]> valueBuffer,
-                                        final boolean autoAdjust) {
-        super(reader, maxStringLength, bufferProvider, valueBuffer, autoAdjust);
+                                        final boolean autoAdjust, final JsonProviderImpl provider) {
+        super(reader, maxStringLength, bufferProvider, valueBuffer, autoAdjust, provider);
     }
 
     @Override
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java
index 235696e..af0e9cf 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JohnzonJsonParserImpl.java
@@ -50,6 +50,13 @@
 
     private boolean manualNext = false;
 
+    private final JsonProviderImpl provider;
+
+    protected JohnzonJsonParserImpl(final JsonProviderImpl provider) {
+        this.provider = provider;
+    }
+
+
     @Override
     public Event next() {
         manualNext = true;
@@ -65,7 +72,7 @@
             throw new IllegalStateException(current + " doesn't support getObject()");
         }
 
-        JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider(), RejectDuplicateKeysMode.DEFAULT);
+        JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider(), RejectDuplicateKeysMode.DEFAULT, provider);
         return jsonReader.readObject();
     }
 
@@ -77,7 +84,7 @@
             throw new IllegalStateException(current + " doesn't support getArray()");
         }
 
-        JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider(), RejectDuplicateKeysMode.DEFAULT);
+        JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider(), RejectDuplicateKeysMode.DEFAULT, provider);
         return jsonReader.readArray();
     }
 
@@ -87,7 +94,7 @@
         switch (current) {
             case START_ARRAY:
             case START_OBJECT:
-                JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider(), RejectDuplicateKeysMode.DEFAULT);
+                JsonReaderImpl jsonReader = new JsonReaderImpl(this, true, getCharArrayProvider(), RejectDuplicateKeysMode.DEFAULT, provider);
                 return jsonReader.readValue();
             case VALUE_TRUE:
                 return JsonValue.TRUE;
@@ -102,7 +109,7 @@
                 if (isFitLong()) {
                     return new JsonLongImpl(getLong());
                 }
-                return new JsonNumberImpl(getBigDecimal());
+                return new JsonNumberImpl(getBigDecimal(), provider::checkBigDecimalScale);
             default:
                 throw new IllegalStateException(current + " doesn't support getValue()");
         }
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
index 675cc14..3aaa280 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
@@ -36,6 +36,7 @@
 
 class JsonArrayBuilderImpl implements JsonArrayBuilder, Serializable {
     private RejectDuplicateKeysMode rejectDuplicateKeysMode;
+    private JsonProviderImpl jsonProvider;
     private List<JsonValue> tmpList;
     private BufferStrategy.BufferProvider<char[]> bufferProvider;
 
@@ -45,14 +46,15 @@
 
     public JsonArrayBuilderImpl(final JsonArray initialData,
                                 final BufferStrategy.BufferProvider<char[]> provider,
-                                final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
+                                final RejectDuplicateKeysMode rejectDuplicateKeysMode, final JsonProviderImpl jsonProvider) {
         this.tmpList = new ArrayList<>(initialData);
         this.bufferProvider = provider;
         this.rejectDuplicateKeysMode = rejectDuplicateKeysMode;
+        this.jsonProvider = jsonProvider;
     }
 
     public JsonArrayBuilderImpl(final Collection<?> initialData, final BufferStrategy.BufferProvider<char[]> provider,
-                                final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
+                                final RejectDuplicateKeysMode rejectDuplicateKeysMode, final JsonProviderImpl jsonProvider) {
         this.bufferProvider = provider;
         this.rejectDuplicateKeysMode = rejectDuplicateKeysMode;
         this.tmpList = new ArrayList<>();
@@ -61,6 +63,7 @@
                 add(initialValue);
             }
         }
+        this.jsonProvider = jsonProvider;
     }
 
     @Override
@@ -83,13 +86,13 @@
 
     @Override
     public JsonArrayBuilder add(final int index, final BigDecimal value) {
-        addValue(index, new JsonNumberImpl(value));
+        addValue(index, new JsonNumberImpl(value, jsonProvider::checkBigDecimalScale));
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(final int index, final BigInteger value) {
-        addValue(index, new JsonNumberImpl(new BigDecimal(value)));
+        addValue(index, new JsonNumberImpl(new BigDecimal(value), jsonProvider::checkBigDecimalScale));
         return this;
     }
 
@@ -149,13 +152,13 @@
 
     @Override
     public JsonArrayBuilder set(final int index, final BigDecimal value) {
-        setValue(index, new JsonNumberImpl(value));
+        setValue(index, new JsonNumberImpl(value, jsonProvider::checkBigDecimalScale));
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(final int index, final BigInteger value) {
-        setValue(index, new JsonNumberImpl(new BigDecimal(value)));
+        setValue(index, new JsonNumberImpl(new BigDecimal(value), jsonProvider::checkBigDecimalScale));
         return this;
     }
 
@@ -225,12 +228,12 @@
         } else if (value instanceof String) {
             add((String) value);
         } else if (value instanceof Map) {
-            add(new JsonObjectBuilderImpl(Map.class.cast(value), bufferProvider, rejectDuplicateKeysMode).build());
+            add(new JsonObjectBuilderImpl(Map.class.cast(value), bufferProvider, rejectDuplicateKeysMode, jsonProvider).build());
         } else if (value instanceof Collection) {
-            add(new JsonArrayBuilderImpl(Collection.class.cast(value), bufferProvider, rejectDuplicateKeysMode).build());
+            add(new JsonArrayBuilderImpl(Collection.class.cast(value), bufferProvider, rejectDuplicateKeysMode, jsonProvider).build());
         } else if (value.getClass().isArray()) {
             final Collection<Object> collection = ArrayUtil.newCollection(value);
-            add(new JsonArrayBuilderImpl(collection, bufferProvider, rejectDuplicateKeysMode).build());
+            add(new JsonArrayBuilderImpl(collection, bufferProvider, rejectDuplicateKeysMode, jsonProvider).build());
         } else {
             throw new JsonException("Illegal JSON type! type=" + value.getClass());
         }
@@ -252,13 +255,13 @@
 
     @Override
     public JsonArrayBuilder add(final BigDecimal value) {
-        addValue(new JsonNumberImpl(value));
+        addValue(new JsonNumberImpl(value, jsonProvider::checkBigDecimalScale));
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(final BigInteger value) {
-        addValue(new JsonNumberImpl(new BigDecimal(value)));
+        addValue(new JsonNumberImpl(new BigDecimal(value), jsonProvider::checkBigDecimalScale));
         return this;
     }
 
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java
index bea58cb..8323a1a 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonBuilderFactoryImpl.java
@@ -37,6 +37,7 @@
 class JsonBuilderFactoryImpl implements JsonBuilderFactory, Serializable {
     private final Map<String, Object> internalConfig = new HashMap<String, Object>();
     private RejectDuplicateKeysMode rejectDuplicateKeysMode;
+    private JsonProviderImpl provider;
     private BufferStrategy.BufferProvider<char[]> bufferProvider;
     private static final List<String> SUPPORTED_CONFIG_KEYS = RejectDuplicateKeysMode.CONFIG_KEYS;
 
@@ -45,9 +46,10 @@
     }
 
     JsonBuilderFactoryImpl(final Map<String, ?> config, final BufferStrategy.BufferProvider<char[]> bufferProvider,
-                           final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
+                           final RejectDuplicateKeysMode rejectDuplicateKeysMode, final JsonProviderImpl provider) {
         this.bufferProvider = bufferProvider;
         this.rejectDuplicateKeysMode = rejectDuplicateKeysMode;
+        this.provider = provider;
         if (config != null && !config.isEmpty()) {
             for (String configKey : config.keySet()) {
                 if(SUPPORTED_CONFIG_KEYS.contains(configKey)) {
@@ -62,28 +64,28 @@
 
     @Override
     public JsonObjectBuilder createObjectBuilder() {
-        return new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
+        return new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode, provider);
     }
 
     @Override
     public JsonObjectBuilder createObjectBuilder(JsonObject initialData) {
-        return new JsonObjectBuilderImpl(initialData, bufferProvider, rejectDuplicateKeysMode);
+        return new JsonObjectBuilderImpl(initialData, bufferProvider, rejectDuplicateKeysMode, provider);
     }
 
     @Override
     public JsonArrayBuilder createArrayBuilder() {
-        return new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode);
+        return new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode, provider);
     }
 
 
     @Override
     public JsonArrayBuilder createArrayBuilder(JsonArray initialData) {
-        return new JsonArrayBuilderImpl(initialData, bufferProvider, rejectDuplicateKeysMode);
+        return new JsonArrayBuilderImpl(initialData, bufferProvider, rejectDuplicateKeysMode, provider);
     }
 
     @Override
     public JsonArrayBuilder createArrayBuilder(Collection<?> initialData) {
-        return new JsonArrayBuilderImpl(initialData, bufferProvider, rejectDuplicateKeysMode);
+        return new JsonArrayBuilderImpl(initialData, bufferProvider, rejectDuplicateKeysMode, provider);
     }
 
     @Override
@@ -93,7 +95,7 @@
 
     @Override
     public JsonObjectBuilder createObjectBuilder(Map<String, Object> initialValues) {
-        return new JsonObjectBuilderImpl(initialValues, bufferProvider, rejectDuplicateKeysMode);
+        return new JsonObjectBuilderImpl(initialValues, bufferProvider, rejectDuplicateKeysMode, provider);
     }
 
 }
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonInMemoryParser.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonInMemoryParser.java
index 70cf553..7dad95c 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonInMemoryParser.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonInMemoryParser.java
@@ -216,12 +216,16 @@
 
     }
 
-    JsonInMemoryParser(final JsonObject object, final BufferStrategy.BufferProvider<char[]> bufferProvider) {
+    JsonInMemoryParser(final JsonObject object, final BufferStrategy.BufferProvider<char[]> bufferProvider,
+                      final JsonProviderImpl provider) {
+        super(provider);
         stack.push(new ObjectIterator(object));
         this.bufferProvider = bufferProvider;
     }
 
-    JsonInMemoryParser(final JsonArray array, final BufferStrategy.BufferProvider<char[]> bufferProvider) {
+    JsonInMemoryParser(final JsonArray array, final BufferStrategy.BufferProvider<char[]> bufferProvider,
+                       final JsonProviderImpl provider) {
+        super(provider);
         stack.push(new ArrayIterator(array));
         this.bufferProvider = bufferProvider;
     }
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchDiff.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchDiff.java
index cb449c0..221f55d 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchDiff.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchDiff.java
@@ -32,20 +32,23 @@
     private final BufferStrategy.BufferProvider<char[]> bufferProvider;
     private final JsonValue source;
     private final JsonValue target;
+    private JsonProviderImpl provider;
 
     public JsonMergePatchDiff(final JsonValue source, final JsonValue target,
-                              final BufferStrategy.BufferProvider<char[]> bufferProvider) {
+                              final BufferStrategy.BufferProvider<char[]> bufferProvider,
+                              final JsonProviderImpl provider) {
         this.bufferProvider = bufferProvider;
         this.source = source;
         this.target = target;
+        this.provider = provider;
     }
 
     public JsonMergePatch calculateDiff() {
-        return new JsonMergePatchImpl(diff(source, target), bufferProvider);
+        return new JsonMergePatchImpl(diff(source, target), bufferProvider, provider);
     }
 
     private JsonValue diff(JsonValue source, JsonValue target) {
-        JsonObjectBuilder builder = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, RejectDuplicateKeysMode.DEFAULT);
+        JsonObjectBuilder builder = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, RejectDuplicateKeysMode.DEFAULT, provider);
 
         if (isJsonObject(source) && isJsonObject(target)) {
             JsonObject srcObj = source.asJsonObject();
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchImpl.java
index 8a4065b..a974cca 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonMergePatchImpl.java
@@ -31,10 +31,13 @@
 public class JsonMergePatchImpl implements JsonMergePatch, Serializable {
     private JsonValue patch;
     private BufferStrategy.BufferProvider<char[]> bufferProvider;
+    private JsonProviderImpl provider;
 
-    public JsonMergePatchImpl(final JsonValue patch, final BufferStrategy.BufferProvider<char[]> bufferProvider) {
+    public JsonMergePatchImpl(final JsonValue patch, final BufferStrategy.BufferProvider<char[]> bufferProvider,
+                              final JsonProviderImpl provider) {
         this.patch = patch;
         this.bufferProvider = bufferProvider;
+        this.provider = provider;
     }
 
     @Override
@@ -51,14 +54,14 @@
 
             return applyJsonObjectPatch(valueToApplyPatchOn.asJsonObject(), patchObject);
         } else {
-            // this must be a native JsonValue or JsonObject, so we just replace the
+            // this must be a native JsonValue or JsonObject, so we just replace
             // the whole original valueToApplyPatchOn with the new jsonValue
             return patch;
         }
     }
 
     private JsonValue applyJsonObjectPatch(JsonObject jsonObject, JsonObject patch) {
-        JsonObjectBuilder builder = new JsonObjectBuilderImpl(jsonObject, bufferProvider, RejectDuplicateKeysMode.DEFAULT);
+        JsonObjectBuilder builder = new JsonObjectBuilderImpl(jsonObject, bufferProvider, RejectDuplicateKeysMode.DEFAULT, provider);
 
         for (Map.Entry<String, JsonValue> patchAttrib : patch.entrySet()) {
             String attribName = patchAttrib.getKey();
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java
index 19cc239..e5ebebd 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonNumberImpl.java
@@ -22,12 +22,15 @@
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.function.Consumer;
 
 final class JsonNumberImpl implements JsonNumber, Serializable {
     private final BigDecimal value;
     private transient Integer hashCode = null;
+    private transient Consumer<BigDecimal> maxBigDecimalScale = (bigDecimal) -> {}; // for deserialization?
 
-    JsonNumberImpl(final BigDecimal decimal) {
+    JsonNumberImpl(final BigDecimal decimal, final Consumer<BigDecimal> maxBigDecimalScale) {
+        this.maxBigDecimalScale = maxBigDecimalScale;
         if (decimal == null) {
             throw new NullPointerException("decimal must not be null");
         }
@@ -69,11 +72,13 @@
 
     @Override
     public BigInteger bigIntegerValue() {
+        maxBigDecimalScale.accept(value);
         return value.toBigInteger();
     }
 
     @Override
     public BigInteger bigIntegerValueExact() {
+        maxBigDecimalScale.accept(value);
         return value.toBigIntegerExact();
     }
 
@@ -117,4 +122,5 @@
             throw new ArithmeticException("Not an int/long, use other value readers");
         }
     }
+
 }
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java
index ae690f9..56383f5 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java
@@ -37,6 +37,7 @@
 
 class JsonObjectBuilderImpl implements JsonObjectBuilder, Serializable {
     private RejectDuplicateKeysMode rejectDuplicateKeysMode;
+    private JsonProviderImpl provider;
     private BufferStrategy.BufferProvider<char[]> bufferProvider;
     private Map<String, JsonValue> attributeMap = new LinkedHashMap<>();
 
@@ -46,17 +47,21 @@
 
     public JsonObjectBuilderImpl(final JsonObject initialData,
                                  final BufferStrategy.BufferProvider<char[]> bufferProvider,
-                                 final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
+                                 final RejectDuplicateKeysMode rejectDuplicateKeysMode,
+                                 final JsonProviderImpl provider) {
         this.bufferProvider = bufferProvider;
         this.rejectDuplicateKeysMode = rejectDuplicateKeysMode;
+        this.provider = provider;
         this.attributeMap = new LinkedHashMap<>(initialData);
     }
 
     public JsonObjectBuilderImpl(final Map<String, Object> initialValues,
                                  final BufferStrategy.BufferProvider<char[]> bufferProvider,
-                                 final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
+                                 final RejectDuplicateKeysMode rejectDuplicateKeysMode,
+                                 final JsonProviderImpl provider) {
         this.bufferProvider = bufferProvider;
         this.rejectDuplicateKeysMode = rejectDuplicateKeysMode;
+        this.provider = provider;
         if (!initialValues.isEmpty()) {
             for (Map.Entry<String, Object> entry : initialValues.entrySet()) {
                 add(entry.getKey(), entry.getValue());
@@ -88,12 +93,12 @@
         } else if (value == null) {
             addNull(name);
         } else if (value instanceof Map) {
-            add(name, new JsonObjectBuilderImpl(Map.class.cast(value), bufferProvider, rejectDuplicateKeysMode).build());
+            add(name, new JsonObjectBuilderImpl(Map.class.cast(value), bufferProvider, rejectDuplicateKeysMode, provider).build());
         } else if (value instanceof Collection) {
-            add(name, new JsonArrayBuilderImpl(Collection.class.cast(value), bufferProvider, rejectDuplicateKeysMode).build());
+            add(name, new JsonArrayBuilderImpl(Collection.class.cast(value), bufferProvider, rejectDuplicateKeysMode, provider).build());
         } else if (value.getClass().isArray()) {
             final Collection<Object> collection = ArrayUtil.newCollection(value);
-            add(name, new JsonArrayBuilderImpl(collection, bufferProvider, rejectDuplicateKeysMode).build());
+            add(name, new JsonArrayBuilderImpl(collection, bufferProvider, rejectDuplicateKeysMode, provider).build());
         } else {
             throw new JsonException("Illegal JSON type! name=" + name + " type=" + value.getClass());
         }
@@ -113,13 +118,13 @@
 
     @Override
     public JsonObjectBuilder add(final String name, final BigInteger value) {
-        putValue(name, new JsonNumberImpl(new BigDecimal(value)));
+        putValue(name, new JsonNumberImpl(new BigDecimal(value), provider::checkBigDecimalScale));
         return this;
     }
 
     @Override
     public JsonObjectBuilder add(final String name, final BigDecimal value) {
-        putValue(name, new JsonNumberImpl(value));
+        putValue(name, new JsonNumberImpl(value, provider::checkBigDecimalScale));
         return this;
     }
 
@@ -177,9 +182,12 @@
         return this;
     }
 
-    private void putValue(final String name, final JsonValue value){
-        if(name == null || value == null) {
-            throw new NullPointerException("name or value/builder must not be null");
+    private void putValue(final String name, final JsonValue value) {
+        if(name == null) {
+            throw new NullPointerException("name must not be null");
+        }
+        if(value == null) {
+            throw new NullPointerException("value/builder must not be null for name: " + name);
         }
         rejectDuplicateKeysMode.put().put(attributeMap, name, value);
     }
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java
index 50e7726..fb961b8 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java
@@ -53,9 +53,11 @@
     private final boolean supportsComments;
     private final boolean autoAdjustBuffers;
     private final Charset defaultEncoding;
+    private final JsonProviderImpl provider;
 
-    JsonParserFactoryImpl(final Map<String, ?> config) {
+    JsonParserFactoryImpl(final Map<String, ?> config, final JsonProviderImpl provider) {
         super(config, SUPPORTED_CONFIG_KEYS, null);
+        this.provider = provider;
 
         final int bufferSize = getInt(BUFFER_LENGTH, DEFAULT_BUFFER_LENGTH);
         if (bufferSize <= 0) {
@@ -79,26 +81,26 @@
             return getDefaultJsonParserImpl(in, defaultEncoding);
         }
         if (supportsComments) {
-            return new CommentsJsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers);
+            return new CommentsJsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers, provider);
         }
         //UTF Auto detection RFC 4627
-        return new JsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers);
+        return new JsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers, provider);
     }
 
     private JsonStreamParserImpl getDefaultJsonParserImpl(final InputStream in, final Charset charset) {
         if (supportsComments) {
-            return new CommentsJsonStreamParserImpl(in, charset, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers);
+            return new CommentsJsonStreamParserImpl(in, charset, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers, provider);
         }
         //use provided charset
-        return new JsonStreamParserImpl(in, charset, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers);
+        return new JsonStreamParserImpl(in, charset, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers, provider);
     }
 
     private JsonStreamParserImpl getDefaultJsonParserImpl(final Reader in) {
         if (supportsComments) {
-            return new CommentsJsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers);
+            return new CommentsJsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers, provider);
         }
         //no charset necessary
-        return new JsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers);
+        return new JsonStreamParserImpl(in, maxSize, bufferProvider, valueBufferProvider, autoAdjustBuffers, provider);
     }
 
     @Override
@@ -119,13 +121,13 @@
     @Override
     public JsonParser createParser(final JsonObject obj) {
         // no need of a comment version since JsonObject has no comment event
-        return new JsonInMemoryParser(obj, bufferProvider);
+        return new JsonInMemoryParser(obj, bufferProvider, provider);
     }
 
     @Override
     public JsonParser createParser(final JsonArray array) {
         // no need of a comment version since JsonObject has no comment event
-        return new JsonInMemoryParser(array, bufferProvider);
+        return new JsonInMemoryParser(array, bufferProvider, provider);
     }
 
     @Override
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java
index afd34f9..76a9edb 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java
@@ -34,6 +34,8 @@
 import jakarta.json.JsonValue;
 import jakarta.json.spi.JsonProvider;
 
+import static java.util.Locale.ROOT;
+
 class JsonPatchImpl implements JsonPatch {
 
     private final JsonProvider provider;
@@ -238,7 +240,7 @@
                 synchronized (this) {
                     if (json == null) {
                         JsonObjectBuilder builder = provider.createObjectBuilder()
-                                .add("op", operation.name().toLowerCase())
+                                .add("op", operation.name().toLowerCase(ROOT))
                                 .add("path", path);
 
                         if (fromPointer != null) {
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
index dc664fe..31dd7e1 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
@@ -57,12 +57,13 @@
         BufferStrategyFactory.valueOf(System.getProperty(AbstractJsonFactory.BUFFER_STRATEGY, "QUEUE"))
             .newCharProvider(Integer.getInteger("org.apache.johnzon.default-char-provider.length", 1024)));
 
-    private final JsonReaderFactory readerFactory = new JsonReaderFactoryImpl(null);
-    private final JsonParserFactory parserFactory = new JsonParserFactoryImpl(null);
+    private final JsonReaderFactory readerFactory = new JsonReaderFactoryImpl(null, this);
+    private final JsonParserFactory parserFactory = new JsonParserFactoryImpl(null, this);
     private final JsonGeneratorFactory generatorFactory = new JsonGeneratorFactoryImpl(null);
     private final JsonWriterFactory writerFactory = new JsonWriterFactoryImpl(null);
     private final Supplier<JsonBuilderFactory> builderFactory = new Cached<>(() ->
-            new JsonBuilderFactoryImpl(null, bufferProvider.get(), RejectDuplicateKeysMode.DEFAULT));
+            new JsonBuilderFactoryImpl(null, bufferProvider.get(), RejectDuplicateKeysMode.DEFAULT, this));
+    private int maxBigDecimalScale = Integer.getInteger("johnzon.max-big-decimal-scale", 1_000);
     @Override
     public JsonParser createParser(final InputStream in) {
         return parserFactory.createParser(in);
@@ -85,12 +86,12 @@
 
     @Override
     public JsonParserFactory createParserFactory(final Map<String, ?> config) {
-        return (config == null || config.isEmpty()) ? parserFactory : new JsonParserFactoryImpl(config);
+        return (config == null || config.isEmpty()) ? parserFactory : new JsonParserFactoryImpl(config, this);
     }
 
     @Override
     public JsonReaderFactory createReaderFactory(final Map<String, ?> config) {
-        return (config == null || config.isEmpty()) ? readerFactory : new JsonReaderFactoryImpl(config);
+        return (config == null || config.isEmpty()) ? readerFactory : new JsonReaderFactoryImpl(config, this);
     }
 
     @Override
@@ -175,19 +176,19 @@
 
     @Override
     public JsonNumber createValue(final BigDecimal value) {
-        return new JsonNumberImpl(value);
+        return new JsonNumberImpl(value, this::checkBigDecimalScale);
     }
 
     @Override
     public JsonNumber createValue(final BigInteger value) {
-        return new JsonNumberImpl(new BigDecimal(value.toString()));
+        return new JsonNumberImpl(new BigDecimal(value.toString()), this::checkBigDecimalScale);
     }
 
     @Override
     public JsonBuilderFactory createBuilderFactory(final Map<String, ?> config) {
         final JsonBuilderFactory builderFactory = this.builderFactory.get();
         return (config == null || config.isEmpty()) ?
-                builderFactory : new JsonBuilderFactoryImpl(config, bufferProvider.get(), RejectDuplicateKeysMode.from(config));
+                builderFactory : new JsonBuilderFactoryImpl(config, bufferProvider.get(), RejectDuplicateKeysMode.from(config), this);
     }
 
     @Override
@@ -217,12 +218,20 @@
 
     @Override
     public JsonMergePatch createMergePatch(JsonValue patch) {
-        return new JsonMergePatchImpl(patch, bufferProvider.get());
+        return new JsonMergePatchImpl(patch, bufferProvider.get(), this);
     }
 
     @Override
     public JsonMergePatch createMergeDiff(JsonValue source, JsonValue target) {
-        return new JsonMergePatchDiff(source, target, bufferProvider.get()).calculateDiff();
+        return new JsonMergePatchDiff(source, target, bufferProvider.get(), this).calculateDiff();
+    }
+
+    public int getMaxBigDecimalScale() {
+        return maxBigDecimalScale;
+    }
+
+    public void setMaxBigDecimalScale(final int maxBigDecimalScale) {
+        this.maxBigDecimalScale = maxBigDecimalScale;
     }
 
     /**
@@ -249,4 +258,17 @@
             return computed;
         }
     }
+
+    public void checkBigDecimalScale(final BigDecimal value) {
+        // should be fine enough. Maybe we should externalize so users can pick something better if they need to
+        // it becomes their responsibility to fix the limit and may expose them to a DoS attack
+        final int limit = maxBigDecimalScale;
+        final int absScale = Math.abs(value.scale());
+
+        if (absScale > limit) {
+            throw new ArithmeticException(String.format(
+                "BigDecimal scale (%d) limit exceeds maximum allowed (%d)",
+                value.scale(), limit));
+        }
+    }
 }
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java
index a9b2a31..cd1081e 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java
@@ -34,33 +34,35 @@
 
     private final JsonParserFactoryImpl parserFactory;
     private final RejectDuplicateKeysMode rejectDuplicateKeys;
+    private JsonProviderImpl provider;
 
-    JsonReaderFactoryImpl(final Map<String, ?> config) {
+    JsonReaderFactoryImpl(final Map<String, ?> config, final JsonProviderImpl provider) {
         super(config, SUPPORTED_CONFIG_KEYS, JsonParserFactoryImpl.SUPPORTED_CONFIG_KEYS);
+        this.provider = provider;
         if (!internalConfig.isEmpty()) {
             RejectDuplicateKeysMode.CONFIG_KEYS.forEach(internalConfig::remove);
         }
-        this.parserFactory = new JsonParserFactoryImpl(internalConfig);
+        this.parserFactory = new JsonParserFactoryImpl(internalConfig, provider);
         this.rejectDuplicateKeys = RejectDuplicateKeysMode.from(config);
     }
 
     @Override
     public JsonReader createReader(final Reader reader) {
-        return new JsonReaderImpl(parserFactory.createInternalParser(reader), parserFactory.getValueBufferProvider(), rejectDuplicateKeys);
+        return new JsonReaderImpl(parserFactory.createInternalParser(reader), parserFactory.getValueBufferProvider(), rejectDuplicateKeys, provider);
     }
 
     @Override
     public JsonReader createReader(final InputStream in) {
-        return new JsonReaderImpl(parserFactory.createInternalParser(in), parserFactory.getValueBufferProvider(), rejectDuplicateKeys);
+        return new JsonReaderImpl(parserFactory.createInternalParser(in), parserFactory.getValueBufferProvider(), rejectDuplicateKeys, provider);
     }
 
     @Override
     public JsonReader createReader(final InputStream in, final Charset charset) {
-        return new JsonReaderImpl(parserFactory.createInternalParser(in, charset), parserFactory.getValueBufferProvider(), rejectDuplicateKeys);
+        return new JsonReaderImpl(parserFactory.createInternalParser(in, charset), parserFactory.getValueBufferProvider(), rejectDuplicateKeys, provider);
     }
 
     public JsonReader createReader(final JsonParser parser) {
-        return new JsonReaderImpl(parser, parserFactory.getValueBufferProvider(), rejectDuplicateKeys);
+        return new JsonReaderImpl(parser, parserFactory.getValueBufferProvider(), rejectDuplicateKeys, provider);
     }
 
     @Override
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java
index b7046c5..b615892 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java
@@ -36,14 +36,15 @@
 public class JsonReaderImpl implements JsonReader {
     private final JohnzonJsonParser parser;
     private final BufferStrategy.BufferProvider<char[]> bufferProvider;
+    private JsonProviderImpl provider;
     private final RejectDuplicateKeysMode rejectDuplicateKeysMode;
     private boolean closed = false;
 
     private boolean subStreamReader;
 
     public JsonReaderImpl(final JsonParser parser, final BufferStrategy.BufferProvider<char[]> bufferProvider,
-                          final RejectDuplicateKeysMode rejectDuplicateKeysMode) {
-        this(parser, false, bufferProvider, rejectDuplicateKeysMode);
+                          final RejectDuplicateKeysMode rejectDuplicateKeysMode, final JsonProviderImpl provider) {
+        this(parser, false, bufferProvider, rejectDuplicateKeysMode, provider);
     }
 
     /**
@@ -54,8 +55,9 @@
      */
     public JsonReaderImpl(final JsonParser parser, boolean subStreamReader,
                           final BufferStrategy.BufferProvider<char[]> bufferProvider,
-                          final RejectDuplicateKeysMode rejectDuplicateKeys) {
+                          final RejectDuplicateKeysMode rejectDuplicateKeys, final JsonProviderImpl provider) {
         this.bufferProvider = bufferProvider;
+        this.provider = provider;
         if (parser instanceof JohnzonJsonParser) {
             this.parser = (JohnzonJsonParser) parser;
         } else {
@@ -89,14 +91,14 @@
 
         switch (next) {
             case START_OBJECT:
-                final JsonObjectBuilder objectBuilder = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
+                final JsonObjectBuilder objectBuilder = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode, provider);
                 parseObject(objectBuilder);
                 if (!subStreamReader && parser.hasNext()) {
                     throw new JsonParsingException("Expected end of file", parser.getLocation());
                 }
                 return objectBuilder.build();
             case START_ARRAY:
-                final JsonArrayBuilder arrayBuilder = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode);
+                final JsonArrayBuilder arrayBuilder = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode, provider);
                 parseArray(arrayBuilder);
                 if (!subStreamReader && parser.hasNext()) {
                     throw new JsonParsingException("Expected end of file", parser.getLocation());
@@ -128,7 +130,7 @@
                 if (parser.isFitLong()) {
                     number = new JsonLongImpl(parser.getLong());
                 } else {
-                    number = new JsonNumberImpl(parser.getBigDecimal());
+                    number = new JsonNumberImpl(parser.getBigDecimal(), provider::checkBigDecimalScale);
                 }
                 if (!subStreamReader && parser.hasNext()) {
                     throw new JsonParsingException("Expected end of file", parser.getLocation());
@@ -182,13 +184,13 @@
                     break;
 
                 case START_OBJECT:
-                    JsonObjectBuilder subObject = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
+                    JsonObjectBuilder subObject = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode, provider);
                     parseObject(subObject);
                     builder.add(key, subObject);
                     break;
 
                 case START_ARRAY:
-                    JsonArrayBuilder subArray = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode);
+                    JsonArrayBuilder subArray = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode, provider);
                     parseArray(subArray);
                     builder.add(key, subArray);
                     break;
@@ -197,7 +199,7 @@
                     if (parser.isIntegralNumber() && parser.isNotTooLong()) {
                         builder.add(key, new JsonLongImpl(parser.getLong()));
                     } else {
-                        builder.add(key, new JsonNumberImpl(parser.getBigDecimal()));
+                        builder.add(key, new JsonNumberImpl(parser.getBigDecimal(), provider::checkBigDecimalScale));
                     }
                     break;
 
@@ -237,19 +239,19 @@
                     if (parser.isFitLong()) {
                         builder.add(new JsonLongImpl(parser.getLong()));
                     } else {
-                        builder.add(new JsonNumberImpl(parser.getBigDecimal()));
+                        builder.add(new JsonNumberImpl(parser.getBigDecimal(), provider::checkBigDecimalScale));
                     }
                     break;
 
                 case START_OBJECT:
-                    JsonObjectBuilder subObject = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode);
+                    JsonObjectBuilder subObject = new JsonObjectBuilderImpl(emptyMap(), bufferProvider, rejectDuplicateKeysMode, provider);
                     parseObject(subObject);
                     builder.add(subObject);
                     break;
 
                 case START_ARRAY:
                     JsonArrayBuilder subArray = null;
-                    parseArray(subArray = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode));
+                    parseArray(subArray = new JsonArrayBuilderImpl(emptyList(), bufferProvider, rejectDuplicateKeysMode, provider));
                     builder.add(subArray);
                     break;
 
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java
index 2ad2c2e..8468f3e 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java
@@ -118,29 +118,30 @@
     //detect charset according to RFC 4627
     public JsonStreamParserImpl(final InputStream inputStream, final int maxStringLength,
                                 final BufferStrategy.BufferProvider<char[]> bufferProvider, final BufferStrategy.BufferProvider<char[]> valueBuffer,
-                                final boolean autoAdjust) {
+                                final boolean autoAdjust, final JsonProviderImpl provider) {
 
-        this(inputStream, null, null, maxStringLength, bufferProvider, valueBuffer, autoAdjust);
+        this(inputStream, null, null, maxStringLength, bufferProvider, valueBuffer, autoAdjust, provider);
     }
 
     //use charset provided
     public JsonStreamParserImpl(final InputStream inputStream, final Charset encoding, final int maxStringLength,
                                 final BufferStrategy.BufferProvider<char[]> bufferProvider, final BufferStrategy.BufferProvider<char[]> valueBuffer,
-                                final boolean autoAdjust) {
+                                final boolean autoAdjust, final JsonProviderImpl provider) {
 
-        this(inputStream, null, encoding, maxStringLength, bufferProvider, valueBuffer, autoAdjust);
+        this(inputStream, null, encoding, maxStringLength, bufferProvider, valueBuffer, autoAdjust, provider);
     }
 
     public JsonStreamParserImpl(final Reader reader, final int maxStringLength, final BufferStrategy.BufferProvider<char[]> bufferProvider,
-                                final BufferStrategy.BufferProvider<char[]> valueBuffer, final boolean autoAdjust) {
+                                final BufferStrategy.BufferProvider<char[]> valueBuffer, final boolean autoAdjust, final JsonProviderImpl provider) {
 
-        this(null, reader, null, maxStringLength, bufferProvider, valueBuffer, autoAdjust);
+        this(null, reader, null, maxStringLength, bufferProvider, valueBuffer, autoAdjust, provider);
     }
 
     private JsonStreamParserImpl(final InputStream inputStream, final Reader reader, final Charset encoding, final int maxStringLength,
                                  final BufferStrategy.BufferProvider<char[]> bufferProvider, final BufferStrategy.BufferProvider<char[]> valueBuffer,
-                                 final boolean autoAdjust) {
+                                 final boolean autoAdjust, final JsonProviderImpl provider) {
 
+        super(provider);
         this.autoAdjust = autoAdjust;
         this.maxValueLength = maxStringLength <= 0 ? 8192 : maxStringLength;
         this.fallBackCopyBuffer = valueBuffer.newBuffer();
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java
index 81ee765..77d2866 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonNumberTest.java
@@ -26,7 +26,9 @@
 import jakarta.json.JsonNumber;
 import java.io.StringReader;
 import java.io.StringWriter;
+import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.concurrent.TimeUnit;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
@@ -62,20 +64,62 @@
     
     @Test(expected=ArithmeticException.class)
     public void testBigIntegerExact() {
-       
         JsonArray array = Json.createArrayBuilder().add(100.0200).build();
         array.getJsonNumber(0).bigIntegerValueExact();
-
-       
     }
-    
+
     @Test
     public void testBigInteger() {
-       
         JsonArray array = Json.createArrayBuilder().add(100.0200).build();
         Assert.assertEquals(new BigInteger("100"), array.getJsonNumber(0).bigIntegerValue());
+    }
 
-       
+    @Test
+    public void testSlowBigIntegerConversion() {
+        JsonArray array = Json.createArrayBuilder()
+                              .add(new BigDecimal("1e1000")) // 1e20000000 --> lost of damage
+                              .add(Double.MAX_VALUE)
+                              .build();
+
+        { // for Double
+            long start = System.nanoTime();
+            for (int i = 1; i < 5; i++) {
+                // if it takes a few seconds in any machine, that's already too much
+                if (TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) > 1) {
+                    fail("took too long: " + TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) + " s" +
+                         " to compute " + i + " conversions toBigInteger");
+                }
+
+                array.getJsonNumber(1).bigIntegerValue();
+            }
+            long end = System.nanoTime();
+            System.out.println("took: " + TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
+        }
+
+        { // for Number
+            long start = System.nanoTime();
+            for (int i = 1; i < 100; i++) {
+                // if it takes a second in any machine, that's already too much
+                // depends on the allowed scale in JsonNumberImpl#checkBigDecimalScale
+                if (TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) > 1) {
+                    fail("took too long: " + TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start) + " s" +
+                         " to compute " + i + " conversions toBigInteger");
+                }
+
+                array.getJsonNumber(0).bigIntegerValue();
+            }
+            long end = System.nanoTime();
+            System.out.println("took: " + TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
+        }
+    }
+
+    @Test(expected = ArithmeticException.class)
+    public void testBigIntegerConversionLimit() {
+        JsonArray array = Json.createArrayBuilder()
+                              .add(new BigDecimal("1e1001")) // limit is 1000 by default
+                              .build();
+
+        array.getJsonNumber(0).bigIntegerValue();
     }
 
     @Test
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectBuilderImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectBuilderImplTest.java
index 99aa39f..c57f94f 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectBuilderImplTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonObjectBuilderImplTest.java
@@ -133,6 +133,15 @@
         builder.add("a", (Integer) null);
     }
 
+    @Test
+    public void testNullCheckValueExceptionMessage() {
+        final JsonObjectBuilder builder = Json.createObjectBuilder();
+        try {
+            builder.add("name", (JsonValue) null);
+        } catch (final NullPointerException e) {
+            assertEquals("value/builder must not be null for name: name", e.getMessage());
+        }
+    }
     @Test(expected = NullPointerException.class)
     public void testNullCheckName() {
         final JsonObjectBuilder builder = Json.createObjectBuilder();
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserStreamingTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserStreamingTest.java
index 19ff327..9ffbcc5 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserStreamingTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserStreamingTest.java
@@ -49,7 +49,8 @@
 
         final BufferStrategy.BufferProvider<char[]> bs = BufferStrategyFactory.valueOf("QUEUE").newCharProvider(len);
         try (final InputStream stream = new ByteArrayInputStream(bytes);
-                final JsonStreamParserImpl impl = new JsonStreamParserImpl(stream, len, bs, bs, false)) {
+                final JsonStreamParserImpl impl = new JsonStreamParserImpl(stream, len, bs, bs, false,
+                                                               (JsonProviderImpl) JsonProviderImpl.provider())) {
 
             while (impl.hasNext()) {
                 impl.next();
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
index c2e8b5e..d01c499 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
@@ -355,10 +355,10 @@
     public void simpleInMemory() {
         final JsonObjectBuilder ob = Json.createObjectBuilder();
         ob.add("a", new JsonStringImpl("b"));
-        ob.add("c", new JsonNumberImpl(new BigDecimal(4)));
+        ob.add("c", new JsonNumberImpl(new BigDecimal(4), ((JsonProviderImpl)JsonProviderImpl.provider())::checkBigDecimalScale));
         JsonArrayBuilder ab = Json.createArrayBuilder();
-        ab.add(new JsonNumberImpl(new BigDecimal(1)));
-        ab.add(new JsonNumberImpl(new BigDecimal(-2)));
+        ab.add(new JsonNumberImpl(new BigDecimal(1), ((JsonProviderImpl)JsonProviderImpl.provider())::checkBigDecimalScale));
+        ab.add(new JsonNumberImpl(new BigDecimal(-2), ((JsonProviderImpl)JsonProviderImpl.provider())::checkBigDecimalScale));
         
         ob.add("d", ab);
         ob.add ("e", Json.createObjectBuilder()
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonStreamParserImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonStreamParserImplTest.java
index 77efec5..2440650 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonStreamParserImplTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonStreamParserImplTest.java
@@ -35,9 +35,9 @@
     @Test
     public void ensureNoArrayBoundErrorWhenOverflow() throws IOException {
         final String json = new JsonObjectBuilderImpl(
-                emptyMap(),
-                BufferStrategyFactory.valueOf("QUEUE").newCharProvider(100),
-                RejectDuplicateKeysMode.TRUE)
+            emptyMap(),
+            BufferStrategyFactory.valueOf("QUEUE").newCharProvider(100),
+            RejectDuplicateKeysMode.TRUE, (JsonProviderImpl) JsonProviderImpl.provider())
                 .add("content", "{\"foo\":\"barbar\\barbarbar\"}")
                 .build()
                 .toString();
@@ -46,7 +46,7 @@
                 10,
                 BufferStrategyFactory.valueOf("QUEUE").newCharProvider(10),
                 BufferStrategyFactory.valueOf("QUEUE").newCharProvider(10),
-                true);
+                true, (JsonProviderImpl) JsonProviderImpl.provider());
         final List<String> events = new ArrayList<>();
         while (parser.hasNext()) {
             final JsonParser.Event event = parser.next();
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/SerializationTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/SerializationTest.java
index 633d9d3..3a19b19 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/SerializationTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/SerializationTest.java
@@ -52,7 +52,8 @@
 
     @Test
     public void jsonNumber() throws IOException, ClassNotFoundException {
-        final JsonNumber source = new JsonNumberImpl(new BigDecimal("1.0"));
+        final JsonNumber source = new JsonNumberImpl(new BigDecimal("1.0"),
+                                                     ((JsonProviderImpl) JsonProviderImpl.provider())::checkBigDecimalScale);
         final JsonNumber deserialized = serialDeser(source);
         assertNotSame(source, deserialized);
         assertEquals(1.0, deserialized.doubleValue(), 0.);
diff --git a/johnzon-distribution/pom.xml b/johnzon-distribution/pom.xml
index e77d1ee..f91dc17 100644
--- a/johnzon-distribution/pom.xml
+++ b/johnzon-distribution/pom.xml
@@ -26,6 +26,7 @@
   <modelVersion>4.0.0</modelVersion>
 
   <artifactId>apache-johnzon</artifactId>
+  <packaging>pom</packaging>
   <name>Johnzon :: Distribution</name>
 
   <dependencies>
@@ -197,27 +198,6 @@
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-source-plugin</artifactId>
-        <configuration>
-          <skipSource>true</skipSource>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-jar-plugin</artifactId>
-        <configuration>
-          <skipIfEmpty>false</skipIfEmpty>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-javadoc-plugin</artifactId>
-        <configuration>
-          <skip>true</skip>
-        </configuration>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-site-plugin</artifactId>
         <configuration>
           <skip>true</skip>
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
index 520f8c1..6c8daa0 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
@@ -109,8 +109,9 @@
         final boolean skipCdi = shouldSkipCdi();
 
         // todo: global spec toggle to disable all these ones at once?
-        builder.setUseBigDecimalForObjectNumbers(
-                config.getProperty("johnzon.use-big-decimal-for-object").map(this::toBool).orElse(true));
+        builder.setUseBigDecimalForObjectNumbers(config.getProperty("johnzon.use-big-decimal-for-object").map(this::toBool).orElse(true));
+        builder.setMaxBigDecimalScale(config.getProperty("johnzon.max-big-decimal-scale").map(this::toInt).orElse(1000));
+
         builder.setSupportEnumContainerDeserialization( // https://github.com/eclipse-ee4j/jakartaee-tck/issues/103
                 toBool(System.getProperty("johnzon.support-enum-container-deserialization", config.getProperty("johnzon.support-enum-container-deserialization")
                         .map(String::valueOf).orElse("true"))));
@@ -293,10 +294,8 @@
             getBeanManager(); // force detection
         }
 
-        builder.setReadAttributeBeforeWrite(
-                config.getProperty("johnzon.readAttributeBeforeWrite").map(Boolean.class::cast).orElse(false));
-        builder.setAutoAdjustStringBuffers(
-                config.getProperty("johnzon.autoAdjustBuffer").map(Boolean.class::cast).orElse(true));
+        builder.setReadAttributeBeforeWrite(config.getProperty("johnzon.readAttributeBeforeWrite").map(Boolean.class::cast).orElse(false));
+        builder.setAutoAdjustStringBuffers(config.getProperty("johnzon.autoAdjustBuffer").map(Boolean.class::cast).orElse(true));
         config.getProperty("johnzon.serialize-value-filter")
                 .map(s -> {
                     if (String.class.isInstance(s)) {
@@ -378,6 +377,10 @@
         return !Boolean.class.isInstance(v) ? Boolean.parseBoolean(v.toString()) : Boolean.class.cast(v);
     }
 
+    private Integer toInt(final Object v) {
+        return !Integer.class.isInstance(v) ? Integer.parseInt(v.toString()) : Integer.class.cast(v);
+    }
+
     private AccessMode toAccessMode(final Object s) {
         if (String.class.isInstance(s)) {
             try {
diff --git a/johnzon-mapper/pom.xml b/johnzon-mapper/pom.xml
index c466613..a97e686 100644
--- a/johnzon-mapper/pom.xml
+++ b/johnzon-mapper/pom.xml
@@ -39,11 +39,13 @@
       <groupId>jakarta.persistence</groupId>
       <artifactId>jakarta.persistence-api</artifactId>
       <version>3.1.0</version>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>jakarta.transaction</groupId>
       <artifactId>jakarta.transaction-api</artifactId>
       <version>2.0.1</version>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.openjpa</groupId>
@@ -61,7 +63,7 @@
     <dependency>
       <groupId>com.h2database</groupId>
       <artifactId>h2</artifactId>
-      <version>2.1.210</version>
+      <version>2.1.214</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ExceptionMessages.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ExceptionMessages.java
index 33690c0..7745af3 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ExceptionMessages.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ExceptionMessages.java
@@ -28,6 +28,7 @@
 import static jakarta.json.JsonValue.ValueType.OBJECT;
 import static jakarta.json.JsonValue.ValueType.STRING;
 import static jakarta.json.JsonValue.ValueType.TRUE;
+import static java.util.Locale.ROOT;
 
 public final class ExceptionMessages {
 
@@ -79,7 +80,7 @@
 
     public static String description(final JsonValue.ValueType type) {
         if (type == OBJECT || type == ARRAY || type == STRING) {
-            return "json " + type.toString().toLowerCase() + " value";
+            return "json " + type.toString().toLowerCase(ROOT) + " value";
         }
         if (type == NUMBER) {
             return "json numeric value";
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
index a217f80..9b08896 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
@@ -23,6 +23,7 @@
 import static java.util.Locale.ROOT;
 
 // import org.apache.johnzon.core.JsonParserFactoryImpl; // don't depend on core in mapper
+import org.apache.johnzon.mapper.util.JsonProviderUtil;
 import org.apache.johnzon.mapper.access.AccessMode;
 import org.apache.johnzon.mapper.access.BaseAccessMode;
 import org.apache.johnzon.mapper.access.FieldAccessMode;
@@ -104,6 +105,7 @@
     private Boolean deduplicateObjects = null;
     private boolean useJsRange;
     private boolean useBigDecimalForObjectNumbers;
+    private int maxBigDecimalScale = 1000;
     private boolean supportEnumContainerDeserialization = true;
     private Function<Class<?>, MapperConfig.CustomEnumConverter<?>> enumConverterFactory = type -> new EnumConverter(type);
     private boolean skipAccessModeWrapper;
@@ -123,6 +125,7 @@
                 provider = this.provider;
             } else {
                 provider = JsonProvider.provider();
+                JsonProviderUtil.setMaxBigDecimalScale(provider, maxBigDecimalScale);
                 this.provider = provider;
             }
             final Map<String, Object> config = new HashMap<String, Object>();
@@ -141,7 +144,7 @@
             }
 
             if (readerFactory == null) {
-                config.remove(JsonGenerator.PRETTY_PRINTING); // doesnt mean anything anymore for reader
+                config.remove(JsonGenerator.PRETTY_PRINTING); // doesn't mean anything anymore for reader
                 if (supportsComments) {
                     config.put("org.apache.johnzon.supports-comments", "true");
                 }
@@ -158,6 +161,7 @@
             }
         } else if (this.provider == null) {
             this.provider = JsonProvider.provider();
+            JsonProviderUtil.setMaxBigDecimalScale(provider, maxBigDecimalScale);
         }
         if (builderFactory == null) {
             builderFactory = provider.createBuilderFactory(emptyMap());
@@ -234,7 +238,7 @@
                         treatByteArrayAsBase64, treatByteArrayAsBase64URL, readAttributeBeforeWrite,
                         accessMode, encoding, attributeOrder, failOnUnknownProperties,
                         serializeValueFilter, useBigDecimalForFloats, deduplicateObjects,
-                        interfaceImplementationMapping, useJsRange, useBigDecimalForObjectNumbers,
+                        interfaceImplementationMapping, useJsRange, useBigDecimalForObjectNumbers, maxBigDecimalScale,
                         supportEnumContainerDeserialization,
                         typeLoader, discriminatorMapper, discriminator,
                         deserializationPredicate, serializationPredicate,
@@ -541,6 +545,11 @@
         return this;
     }
 
+    public MapperBuilder setMaxBigDecimalScale(final int maxBigDecimalScale) {
+        this.maxBigDecimalScale = maxBigDecimalScale;
+        return this;
+    }
+
     public MapperBuilder setSupportEnumContainerDeserialization(final boolean supportEnumContainerDeserialization) {
         this.supportEnumContainerDeserialization = supportEnumContainerDeserialization;
         return this;
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
index dd0ab71..23b78dc 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
@@ -81,7 +81,7 @@
     private final Boolean deduplicateObjects;
     private final Map<Class<?>, Class<?>> interfaceImplementationMapping;
     private final boolean useBigDecimalForObjectNumbers;
-
+    private int maxBigDecimalScale;
     private final Function<String, Class<?>> typeLoader;
     private final Function<Class<?>, String> discriminatorMapper;
     private final Predicate<Class<?>> serializationPredicate;
@@ -118,6 +118,7 @@
                         final Map<Class<?>, Class<?>> interfaceImplementationMapping,
                         final boolean useJsRange,
                         final boolean useBigDecimalForObjectNumbers,
+                        final int maxBigDecimalScale,
                         final boolean supportEnumMapDeserialization,
                         final Function<String, Class<?>> typeLoader,
                         final Function<Class<?>, String> discriminatorMapper,
@@ -129,7 +130,7 @@
         this(adapters, objectConverterWriters, objectConverterReaders, version, close, skipNull, skipEmptyArray,
                 treatByteArrayAsBase64, treatByteArrayAsBase64URL, readAttributeBeforeWrite, accessMode, encoding,
                 attributeOrder, failOnUnknown, serializeValueFilter, useBigDecimalForFloats, deduplicateObjects, interfaceImplementationMapping,
-                useJsRange, useBigDecimalForObjectNumbers, supportEnumMapDeserialization, typeLoader,
+                useJsRange, useBigDecimalForObjectNumbers, maxBigDecimalScale, supportEnumMapDeserialization, typeLoader,
                 discriminatorMapper, discriminator, deserializationPredicate, serializationPredicate, enumConverterFactory,
                 JohnzonCores.snippetFactory(50, Json.createGeneratorFactory(emptyMap())), null);
     }
@@ -152,6 +153,7 @@
                         final Map<Class<?>, Class<?>> interfaceImplementationMapping,
                         final boolean useJsRange,
                         final boolean useBigDecimalForObjectNumbers,
+                        final int maxBigDecimalScale,
                         final boolean supportEnumMapDeserialization,
                         final Function<String, Class<?>> typeLoader,
                         final Function<Class<?>, String> discriminatorMapper,
@@ -175,6 +177,7 @@
         this.encoding = encoding;
         this.useJsRange = useJsRange;
         this.useBigDecimalForObjectNumbers = useBigDecimalForObjectNumbers;
+        this.maxBigDecimalScale = maxBigDecimalScale;
         this.supportEnumMapDeserialization = supportEnumMapDeserialization;
         this.typeLoader = typeLoader;
         this.discriminatorMapper = discriminatorMapper;
@@ -243,6 +246,10 @@
         return useBigDecimalForObjectNumbers;
     }
 
+    public int getMaxBigDecimalScale() {
+        return maxBigDecimalScale;
+    }
+
     public boolean isUseJsRange() {
         return useJsRange;
     }
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/util/JsonProviderUtil.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/util/JsonProviderUtil.java
new file mode 100644
index 0000000..bce61fe
--- /dev/null
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/util/JsonProviderUtil.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.johnzon.mapper.util;
+
+import jakarta.json.spi.JsonProvider;
+import org.apache.johnzon.core.JsonProviderImpl;
+
+import java.lang.reflect.Method;
+
+/**
+ * ClassLoader related utils to avoid direct access to our JSON provider from the mapper
+ */
+public final class JsonProviderUtil {
+
+    private final static Method SET_MAX_BIG_DECIMAL_SCALE;
+
+    static {
+        try {
+            SET_MAX_BIG_DECIMAL_SCALE =
+                JsonProviderImpl.class.getDeclaredMethod("setMaxBigDecimalScale", Integer.TYPE);
+            SET_MAX_BIG_DECIMAL_SCALE.setAccessible(true);
+        } catch (final NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private JsonProviderUtil() {
+        // private utility class ct
+    }
+
+    /**
+     * Sets the max big decimal scale property on the given provider instance.
+     * <p>
+     * This method is intentionally not receiving the property name, so we know exactly what will be passed in and what
+     * the method is supposed to set on the provider.
+     * <p>
+     * If the provider is not an instance of our JohnzonProviderImpl (org.apache.johnzon.core.JsonProviderImpl), the
+     * method is a noop.
+     *
+     * @param provider the provider to configure. Must be an instance of org.apache.johnzon.core.JsonProviderImpl
+     * @param value the max big decimal scale to set on the provider
+     */
+    public static void setMaxBigDecimalScale(final JsonProvider provider, final int value) {
+        if (!"org.apache.johnzon.core.JsonProviderImpl".equals(provider.getClass().getName())) {
+            return;
+        }
+
+        try {
+            SET_MAX_BIG_DECIMAL_SCALE.invoke(provider, value);
+        } catch (final Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java
index 0314e86..c942953 100644
--- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java
@@ -169,7 +169,7 @@
                                 new FieldAccessMode(true, true),
                                 StandardCharsets.UTF_8,
                                 null,
-                                false, null, false, false, emptyMap(), true, false, true,
+                                false, null, false, false, emptyMap(), true, false, 1000, true,
                                 null, null, null, null, null,
                                 type -> new EnumConverter(type));
     }
diff --git a/johnzon-mapper/src/test/java/org/superbiz/ExtendMappingTest.java b/johnzon-mapper/src/test/java/org/superbiz/ExtendMappingTest.java
index 2a8be6c..70308fa 100644
--- a/johnzon-mapper/src/test/java/org/superbiz/ExtendMappingTest.java
+++ b/johnzon-mapper/src/test/java/org/superbiz/ExtendMappingTest.java
@@ -62,7 +62,7 @@
                     -1, true, true, true, false, false, false,
                     new FieldAccessMode(false, false),
                     StandardCharsets.UTF_8, String::compareTo, false, null, false, false,
-                    emptyMap(), true, false, true, null,
+                    emptyMap(), true, false, 1000, true, null,
                     null, null, null, null,
                     type -> new EnumConverter(type)));
         }
diff --git a/pom.xml b/pom.xml
index a86249b..6739533 100644
--- a/pom.xml
+++ b/pom.xml
@@ -114,32 +114,32 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
-          <version>3.10.1</version>
+          <version>3.11.0</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-source-plugin</artifactId>
-          <version>3.2.1</version>
+          <version>3.3.0</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-javadoc-plugin</artifactId>
-          <version>3.4.1</version>
+          <version>3.5.0</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-enforcer-plugin</artifactId>
-          <version>3.1.0</version>
+          <version>3.4.0</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-plugin</artifactId>
-          <version>3.0.0</version>
+          <version>3.1.2</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-report-plugin</artifactId>
-          <version>3.0.0-M7</version>
+          <version>3.1.2</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
@@ -149,7 +149,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-release-plugin</artifactId>
-          <version>3.0.0-M6</version>
+          <version>3.0.1</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
@@ -165,17 +165,17 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-pmd-plugin</artifactId>
-          <version>3.19.0</version>
+          <version>3.21.0</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-project-info-reports-plugin</artifactId>
-          <version>3.4.1</version>
+          <version>3.4.5</version>
         </plugin>
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
           <artifactId>versions-maven-plugin</artifactId>
-          <version>2.14.2</version>
+          <version>2.16.0</version>
         </plugin>
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
@@ -281,12 +281,12 @@
           <dependency>
             <groupId>org.apache.maven.doxia</groupId>
             <artifactId>doxia-core</artifactId>
-            <version>1.7</version>
+            <version>1.10</version>
           </dependency>
           <dependency>
             <groupId>org.apache.maven.doxia</groupId>
             <artifactId>doxia-module-markdown</artifactId>
-            <version>1.7</version>
+            <version>1.11.1</version>
           </dependency>
         </dependencies>
       </plugin>
diff --git a/src/site/markdown/download.md b/src/site/markdown/download.md
index 1788244..aaf449e 100644
--- a/src/site/markdown/download.md
+++ b/src/site/markdown/download.md
@@ -34,6 +34,17 @@
 
 ----------
 
+## Johnzon-2.0.x
+
+Apache Johnzon 2.0.x implements the JSON-P 2.1 and JSON-B 3.0 specifications which on a level of JavaEE 10. This version is not backward compatible due to the namespace change from `javax` to `jakarta`. 
+Apache Johnzon does not implement Jakarta EE 9 per se, because there was no change in terms of APIs except the namespace change. 
+So we decided to use Apache Johnzon 1.2.x bellow and publish a Jakarta compatible version using bytecode transformation. All artifacts can be used with the classifier `jakarta`.
+
+#### Source
+
+This version is currently only available as snapshot. 
+We are still actively working on passing the TCK but so far most of the implementation is ready.
+
 ## Johnzon-1.2.x
 
 Apache Johnzon 1.2.x implements the JSON-P 1.1 and JSON-B 1.0 specifications which on a level of JavaEE 8.
@@ -41,9 +52,9 @@
 #### Source
 Should you want to build any of the above binaries, this source bundle is the right one and covers them all.
 
-* [johnzon-1.2.16-source-release.zip](https://www.apache.org/dyn/closer.lua/1.2.16/johnzon-1.2.16-source-release.zip)
-* [johnzon-1.2.16-source-release.zip.sha512](https://www.apache.org/dist/johnzon/1.2.16/johnzon-1.2.16-source-release.zip.sha512)
-* [johnzon-1.2.16-source-release.zip.asc](https://www.apache.org/dist/johnzon/1.2.16/johnzon-1.2.16-source-release.zip.asc)
+* [johnzon-1.2.20-source-release.zip](https://www.apache.org/dyn/closer.lua/1.2.20/johnzon-1.2.20-source-release.zip)
+* [johnzon-1.2.20-source-release.zip.sha512](https://www.apache.org/dist/johnzon/1.2.20/johnzon-1.2.20-source-release.zip.sha512)
+* [johnzon-1.2.20-source-release.zip.asc](https://www.apache.org/dist/johnzon/1.2.20/johnzon-1.2.20-source-release.zip.asc)
 
 
 ## Johnzon-1.0.x
@@ -69,6 +80,23 @@
 
 ### Maven Dependencies
 
+#### APIs for Johnzon-2.0.x (Jakarta EE 10)
+
+Since Java EE got open sourced to become Jakarta EE, the APIs can be used without license restrictions, so we moved away from our Apache APIs.
+
+    <dependency>
+        <groupId>jakarta.json</groupId>
+        <artifactId>jakarta.json-api</artifactId>
+        <version>2.1.1</version>
+        <scope>provided</scope>
+    </dependency>
+    <dependency>
+        <groupId>jakarta.json.bind</groupId>
+        <artifactId>jakarta.json.bind-api</artifactId>
+        <version>3.0</version>
+        <scope>provided</scope>
+    </dependency>
+
 #### APIs for Johnzon-1.1.x (JavaEE 8)
 
     <dependency>
diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md
index 324684d..0cc87b8 100644
--- a/src/site/markdown/index.md
+++ b/src/site/markdown/index.md
@@ -369,13 +369,13 @@
 
 <pre class="prettyprint linenums"><![CDATA[
 final JsonValueReader<Simple> reader = new JsonValueReader<>(Json.createObjectBuilder().add("value", "simple").build());
-final Jsonb jsonb = getJohnsonJsonb();
+final Jsonb jsonb = getJohnzonJsonb();
 final Simple simple = jsonb.fromJson(reader, SomeModel.class);
 ]]></pre>
 
 <pre class="prettyprint linenums"><![CDATA[
 final JsonValueWriter writer = new JsonValueWriter();
-final Jsonb jsonb = getJohnsonJsonb();
+final Jsonb jsonb = getJohnzonJsonb();
 jsonb.toJson(object, writer);
 final JsonObject jsonObject = writer.getObject();
 ]]></pre>
diff --git a/src/site/markdown/security.md b/src/site/markdown/security.md
index f072a33..0b554bb 100644
--- a/src/site/markdown/security.md
+++ b/src/site/markdown/security.md
@@ -37,3 +37,13 @@
 should be addressed to the [mailing list](http://johnzon.apache.org/mail-lists.html).
 
 The private security mailing address is: security (at) apache (dot) org
+
+## BigInteger and Java
+
+JSON-P/JSON-B exposes API using `BigDecimal` and `BigInteger`.
+The bridge between these two types is `BigDecimal#toBigInteger` which has a slow implementation in Java without careness or scale max validation.
+
+Johnzon does some sanity checks on this value but at some point we recommend you to stay away from these API and handle big numbers using `String` type and parse them yourself since you are the only ones knowing the correct functional and relevant validation of the scale before a instantiation.
+
+If you know you don't need such big types, prefer using plain primitives (or wrappers).
+