diff --git a/resteasy-core/src/main/java/org/jboss/resteasy/core/providerfactory/ResteasyProviderFactoryImpl.java b/resteasy-core/src/main/java/org/jboss/resteasy/core/providerfactory/ResteasyProviderFactoryImpl.java
index f8afa52a05..5be8654d7f 100644
--- a/resteasy-core/src/main/java/org/jboss/resteasy/core/providerfactory/ResteasyProviderFactoryImpl.java
+++ b/resteasy-core/src/main/java/org/jboss/resteasy/core/providerfactory/ResteasyProviderFactoryImpl.java
@@ -42,6 +42,7 @@ import org.jboss.resteasy.spi.metadata.ResourceClassProcessor;
 import org.jboss.resteasy.spi.statistics.StatisticsController;
 import org.jboss.resteasy.spi.util.PickConstructor;
 import org.jboss.resteasy.spi.util.Types;
+import org.jboss.resteasy.spi.config.DefaultConfiguration;
 import org.jboss.resteasy.statistics.StatisticsControllerImpl;
 import org.jboss.resteasy.tracing.RESTEasyTracingLogger;
 import org.jboss.resteasy.util.FeatureContextDelegate;
@@ -86,6 +87,7 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
+import java.math.BigDecimal;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -98,6 +100,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.CompletableFuture;
@@ -109,7 +112,7 @@ import java.util.concurrent.ConcurrentHashMap;
  * @version $Revision: 1 $
  */
 @SuppressWarnings({"unchecked", "rawtypes"})
-public class ResteasyProviderFactoryImpl extends ResteasyProviderFactory implements Providers, HeaderValueProcessor, Configurable<ResteasyProviderFactory>, Configuration
+public class ResteasyProviderFactoryImpl extends ResteasyProviderFactory implements Providers, HeaderValueProcessor, Configurable<ResteasyProviderFactory>, Configuration, org.jboss.resteasy.spi.config.Configuration
 {
    protected ClientHelper clientHelper;
    protected ServerHelper serverHelper;
@@ -139,6 +142,8 @@ public class ResteasyProviderFactoryImpl extends ResteasyProviderFactory impleme
    protected boolean lockSnapshots;
    protected StatisticsControllerImpl statisticsController = new StatisticsControllerImpl();
 
+   protected DefaultConfiguration defaultConfig = new DefaultConfiguration();
+
    public ResteasyProviderFactoryImpl()
    {
       // NOTE!!! It is important to put all initialization into initialize() as ThreadLocalResteasyProviderFactory
@@ -1796,4 +1801,66 @@ public class ResteasyProviderFactoryImpl extends ResteasyProviderFactory impleme
    protected boolean isOnServer() {
       return ResteasyContext.searchContextData(Dispatcher.class) != null;
    }
+
+   @Override
+   public <T> Optional<T> getOptionalValue(String name, Class<T> type) {
+      final Object value = getProperty(name);
+      if (value == null) {
+         Optional<T> optionalObj =  defaultConfig.getOptionalValue(name, type);
+         if (optionalObj.isPresent()) {
+            properties.put(name, optionalObj.get());
+         }
+         return optionalObj;
+      }
+
+      final Object typedValue;
+      if (type == String.class) {
+         typedValue = type.cast(value);
+      } else if (type == Boolean.class) {
+         typedValue = (Boolean)value;
+      } else if ( type == boolean.class) {
+         typedValue = (boolean)value;
+      } else if (type == Character.class) {
+         typedValue = (Character)value;
+      } else if (type == char.class) {
+         typedValue = (char)value;
+      } else if (type == Byte.class) {
+         typedValue = (Byte)value;
+      } else if (type == byte.class) {
+         typedValue = (byte)value;
+      } else if (type == Short.class) {
+         typedValue = (Short)value;
+      } else if (type == short.class) {
+         typedValue = (short)value;
+      } else if (type == Integer.class) {
+         typedValue = (Integer)value;
+      } else if (type == int.class) {
+         typedValue = (int)value;
+      } else if (type == Long.class) {
+         typedValue = (Long)value;
+      } else if (type == long.class) {
+         typedValue = (long)value;
+      } else if (type == Float.class) {
+         typedValue = (Float)value;
+      } else if (type == float.class) {
+         typedValue = (float)value;
+      } else if (type == Double.class) {
+         typedValue = (Double)value;
+      } else if (type == double.class) {
+         typedValue = (double)value;
+      } else if (type == BigDecimal.class) {
+         typedValue = (BigDecimal)value;
+      } else if (type.isEnum()) {
+         typedValue = (Enum)value;
+      }  else {
+         throw Messages.MESSAGES.cannotConvertParameter(value, type, name);
+      }
+
+      return (Optional<T>) Optional.of(typedValue);
+   }
+   @Override
+   public <T> T getValue(String name, Class<T> type) {
+      // .orElse(null)
+      return getOptionalValue(name, type).get();
+   }
 }
