SPI Config API for Jersey (#4116)

Config SPI API for Jersey

Signed-off-by: Maxim Nesen <maxim.nesen@oracle.com>
diff --git a/bom/pom.xml b/bom/pom.xml
index e2b5ccb..a0bb9cd 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -150,6 +150,11 @@
             </dependency>
             <dependency>
                 <groupId>org.glassfish.jersey.ext</groupId>
+                <artifactId>jersey-mp-config</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jersey.ext</groupId>
                 <artifactId>jersey-mvc</artifactId>
                 <version>${project.version}</version>
             </dependency>
diff --git a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java
index 3218d3b..654d9e7 100644
--- a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java
+++ b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java
@@ -217,6 +217,17 @@
     public static final String OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER = "jersey.config.server.contentLength.buffer";
 
     /**
+     * Property which allows (if true) default System properties configuration provider.
+     *
+     * Effective if there are no any external properties providers
+     *
+     * Shall be set (if used) in system properties.
+     * @since 2.29
+     */
+
+    public static final String ALLOW_SYSTEM_PROPERTIES_PROVIDER = "jersey.config.allowSystemPropertiesProvider";
+
+    /**
      * Prevent instantiation.
      */
     private CommonProperties() {
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesAutoDiscoverable.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesAutoDiscoverable.java
new file mode 100644
index 0000000..e7d0adc
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesAutoDiscoverable.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.internal.config;
+
+import org.glassfish.jersey.internal.spi.AutoDiscoverable;
+
+import javax.annotation.Priority;
+import javax.ws.rs.ConstrainedTo;
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.core.FeatureContext;
+
+@ConstrainedTo(RuntimeType.CLIENT) //server is configured directly in ResourceConfig
+@Priority(AutoDiscoverable.DEFAULT_PRIORITY)
+public class ExternalPropertiesAutoDiscoverable implements AutoDiscoverable {
+    @Override
+    public void configure(FeatureContext context) {
+        if (!context.getConfiguration().isRegistered(ExternalPropertiesConfigurationFeature.class)) {
+            context.register(ExternalPropertiesConfigurationFeature.class);
+        }
+    }
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFactory.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFactory.java
new file mode 100644
index 0000000..35ca77a
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFactory.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.internal.config;
+
+import org.glassfish.jersey.internal.ServiceFinder;
+import org.glassfish.jersey.spi.ExternalConfigurationModel;
+import org.glassfish.jersey.spi.ExternalConfigurationProvider;
+
+import javax.annotation.Priority;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.core.Configurable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Factory for external properties providers
+ * Offers methods to work with properties loaded from providers or
+ * just configure Jersey's Configurables with loaded properties from providers
+ */
+public class ExternalPropertiesConfigurationFactory {
+
+    private static final List<ExternalConfigurationProvider> EXTERNAL_CONFIGURATION_PROVIDERS =
+            getExternalConfigurations();
+
+
+    /**
+     * Map of merged properties from all found providers
+     *
+     * @return map of merged properties from all found/plugged providers
+     */
+    static Map<String, Object> readExternalPropertiesMap() {
+
+        final ExternalConfigurationProvider provider = mergeConfigs(EXTERNAL_CONFIGURATION_PROVIDERS);
+        return provider == null ? Collections.emptyMap() : provider.getProperties();
+    }
+
+
+    /**
+     * Input Configurable object shall be provided in order to be filled with all found properties
+     *
+     * @param config Input Configurable initialised object to be filled with properties
+     * @return true if configured false otherwise
+     */
+
+    public static boolean configure(Configurable config) {
+
+        if (config instanceof ExternalConfigurationModel) {
+            return false; //shall not configure itself
+        }
+
+        final Map<String, Object> properties = readExternalPropertiesMap();
+
+        properties.forEach((k, v) -> config.property(k, v));
+
+        return true;
+    }
+
+    /**
+     * Merged config model from all found configuration models
+     *
+     * @return merged Model object with all properties
+     */
+    static ExternalConfigurationModel getConfig() {
+        final ExternalConfigurationProvider provider = mergeConfigs(getExternalConfigurations());
+        return provider == null ? null : provider.getConfiguration();
+    }
+
+    /**
+     * List of all found models as they are found by Jersey
+     *
+     * @return list of models (or empty list)
+     */
+    private static List<ExternalConfigurationProvider> getExternalConfigurations() {
+        final List<ExternalConfigurationProvider> providers = new ArrayList<>();
+        final ServiceFinder<ExternalConfigurationProvider> finder =
+                ServiceFinder.find(ExternalConfigurationProvider.class);
+        if (finder.iterator().hasNext()) {
+            finder.forEach(providers::add);
+        } else {
+            providers.add(new SystemPropertiesConfigurationProvider());
+        }
+        return providers;
+    }
+
+    private static ExternalConfigurationProvider mergeConfigs(List<ExternalConfigurationProvider> configurations) {
+        final Set<ExternalConfigurationProvider> orderedConfigurations = orderConfigs(configurations);
+        final Iterator<ExternalConfigurationProvider> configurationIterator = orderedConfigurations.iterator();
+        if (!configurationIterator.hasNext()) {
+            return null;
+        }
+        final ExternalConfigurationProvider firstConfig = configurationIterator.next();
+        while (configurationIterator.hasNext()) {
+            final ExternalConfigurationProvider nextConfig = configurationIterator.next();
+            firstConfig.merge(nextConfig.getConfiguration());
+        }
+
+        return firstConfig;
+    }
+
+    private static Set<ExternalConfigurationProvider> orderConfigs(List<ExternalConfigurationProvider> configurations) {
+
+        final SortedSet<ExternalConfigurationProvider> sortedSet = new TreeSet<>(new ConfigComparator());
+        sortedSet.addAll(configurations);
+        return Collections.unmodifiableSortedSet(sortedSet);
+    }
+
+    private static class ConfigComparator implements Comparator<ExternalConfigurationProvider> {
+
+        @Override
+        public int compare(ExternalConfigurationProvider config1, ExternalConfigurationProvider config2) {
+
+            boolean config1PriorityPresent = config1.getClass().isAnnotationPresent(Priority.class);
+            boolean config2PriorityPresent = config2.getClass().isAnnotationPresent(Priority.class);
+
+            int priority1 = Priorities.USER;
+            int priority2 = Priorities.USER;
+
+            if (config1PriorityPresent) {
+                priority1 = config1.getClass().getAnnotation(Priority.class).value();
+            }
+            if (config2PriorityPresent) {
+                priority2 = config2.getClass().getAnnotation(Priority.class).value();
+            }
+
+            if (priority1 == priority2) {
+                return config1.getClass().getName().compareTo(config2.getClass().getName());
+            }
+            return Integer.compare(priority1, priority2);
+        }
+    }
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFeature.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFeature.java
new file mode 100644
index 0000000..acdab23
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFeature.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.internal.config;
+
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.FeatureContext;
+
+public class ExternalPropertiesConfigurationFeature implements Feature {
+
+    @Override
+    public boolean configure(FeatureContext configurableContext) {
+        return ExternalPropertiesConfigurationFactory.configure(configurableContext);
+    }
+
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModel.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModel.java
new file mode 100644
index 0000000..3c0fd7a
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationModel.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.internal.config;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.internal.LocalizationMessages;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.spi.ExternalConfigurationModel;
+
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.core.Feature;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.logging.Logger;
+
+
+class SystemPropertiesConfigurationModel implements ExternalConfigurationModel<Void> {
+
+    private static final Logger log = Logger.getLogger(SystemPropertiesConfigurationModel.class.getName());
+
+
+    private static final Map<Class, Function> converters = new HashMap<>();
+    static {
+        converters.put(String.class, (Function<String, String>) s -> s);
+        converters.put(Integer.class, (Function<String, Integer>) s -> Integer.valueOf(s));
+        converters.put(Boolean.class, (Function<String, Boolean>) s -> s.equalsIgnoreCase("1")
+                ? true
+                : Boolean.parseBoolean(s));
+    }
+
+    private String getSystemProperty(String name) {
+        return AccessController.doPrivileged(PropertiesHelper.getSystemProperty(name));
+    }
+
+    @Override
+    public <T> T as(String name, Class<T> clazz) {
+        if (converters.get(clazz) == null) {
+            throw new IllegalArgumentException("Unsupported class type");
+        }
+        return (name != null && clazz != null && isProperty(name))
+                ? clazz.cast(converters.get(clazz).apply(getSystemProperty(name)))
+                : null;
+    }
+
+
+
+    @Override
+    public <T> Optional<T> getOptionalProperty(String name, Class<T> clazz) {
+        return Optional.of(as(name, clazz));
+    }
+
+    @Override
+    public ExternalConfigurationModel mergeProperties(Map<String, Object> inputProperties) {
+        return this;
+    }
+
+    @Override
+    public Void getConfig() {
+        return null;
+    }
+
+    @Override
+    public boolean isProperty(String name) {
+        return Optional.ofNullable(
+                AccessController.doPrivileged(
+                        PropertiesHelper.getSystemProperty(name)
+                )
+        ).isPresent();
+    }
+
+    @Override
+    public RuntimeType getRuntimeType() {
+        return null;
+    }
+
+    @Override
+    public Map<String, Object> getProperties() {
+        final Map<String, Object> result = new HashMap<>();
+
+        final Boolean allowSystemPropertiesProvider = as(
+                CommonProperties.ALLOW_SYSTEM_PROPERTIES_PROVIDER, Boolean.class
+        );
+        if (!Boolean.TRUE.equals(allowSystemPropertiesProvider)) {
+            log.finer(LocalizationMessages.WARNING_PROPERTIES());
+            return result;
+        }
+
+        try {
+            AccessController.doPrivileged(PropertiesHelper.getSystemProperties())
+                    .forEach((k, v) -> result.put(String.valueOf(k), v));
+        } catch (SecurityException se) {
+            log.warning(LocalizationMessages.SYSTEM_PROPERTIES_WARNING());
+            return getExpectedSystemProperties();
+        }
+        return result;
+    }
+
+    private Map<String, Object> getExpectedSystemProperties() {
+
+
+        final Map<String, Object> result = new HashMap<>();
+
+        mapFieldsToProperties(result, CommonProperties.class);
+
+
+
+        mapFieldsToProperties(result,
+                AccessController.doPrivileged(
+                        ReflectionHelper.classForNamePA("org.glassfish.jersey.server.ServerProperties")
+                )
+        );
+
+        mapFieldsToProperties(result,
+                AccessController.doPrivileged(
+                        ReflectionHelper.classForNamePA("org.glassfish.jersey.client.ClientProperties")
+                )
+        );
+
+
+        return  result;
+    }
+
+    private <T> void mapFieldsToProperties(Map<String, Object> properties, Class<T> clazz) {
+        if (clazz == null) {
+            return;
+        }
+
+        final Field[] fields = AccessController.doPrivileged(
+                ReflectionHelper.getDeclaredFieldsPA(clazz)
+        );
+
+        for (final Field field : fields) {
+            if (field.getType().isAssignableFrom(String.class)) {
+                final String propertyValue = getPropertyNameByField(field);
+                properties.put(propertyValue, PropertiesHelper.getSystemProperty(propertyValue));
+            }
+        }
+    }
+
+    private String getPropertyNameByField(Field field) {
+        return  AccessController.doPrivileged((PrivilegedAction<String>) () -> {
+            try {
+                return (String) field.get(null);
+            } catch (IllegalAccessException e) {
+                log.warning(e.getLocalizedMessage());
+            }
+            return null;
+        });
+    }
+
+    @Override
+    public Object getProperty(String name) {
+        return getSystemProperty(name);
+    }
+
+    @Override
+    public Collection<String> getPropertyNames() {
+        return PropertiesHelper.getSystemProperties().run().stringPropertyNames();
+    }
+
+    @Override
+    public boolean isEnabled(Feature feature) {
+        return false;
+    }
+
+    @Override
+    public boolean isEnabled(Class<? extends Feature> featureClass) {
+        return false;
+    }
+
+    @Override
+    public boolean isRegistered(Object component) {
+        return false;
+    }
+
+    @Override
+    public boolean isRegistered(Class<?> componentClass) {
+        return false;
+    }
+
+    @Override
+    public Map<Class<?>, Integer> getContracts(Class<?> componentClass) {
+        return null;
+    }
+
+    @Override
+    public Set<Class<?>> getClasses() {
+        return null;
+    }
+
+    @Override
+    public Set<Object> getInstances() {
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationProvider.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationProvider.java
new file mode 100644
index 0000000..145f5f7
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/config/SystemPropertiesConfigurationProvider.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.internal.config;
+
+import org.glassfish.jersey.spi.ExternalConfigurationModel;
+import org.glassfish.jersey.spi.ExternalConfigurationProvider;
+
+import java.util.Map;
+
+class SystemPropertiesConfigurationProvider implements ExternalConfigurationProvider {
+
+    private final SystemPropertiesConfigurationModel model = new SystemPropertiesConfigurationModel();
+    @Override
+    public Map<String, Object> getProperties() {
+        return model.getProperties();
+    }
+
+    @Override
+    public ExternalConfigurationModel getConfiguration() {
+        return model;
+    }
+
+    @Override
+    public ExternalConfigurationModel merge(ExternalConfigurationModel input) {
+        return input == null ? model : model.mergeProperties(input.getProperties());
+    }
+
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/package-info.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/package-info.java
new file mode 100644
index 0000000..21206bd
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/config/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/**
+ * Configuration factory to handle external properties from different config SPI implementations
+ *
+ * @since 2.29
+ */
+package org.glassfish.jersey.internal.config;
\ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/spi/ExternalConfigurationModel.java b/core-common/src/main/java/org/glassfish/jersey/spi/ExternalConfigurationModel.java
new file mode 100644
index 0000000..333cd35
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/spi/ExternalConfigurationModel.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.spi;
+
+import org.glassfish.jersey.ExtendedConfig;
+
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Model of configuration for external properties. Requires certain utilities methods to be implemented
+ * @param <CONFIG> type of an external config
+ */
+public interface ExternalConfigurationModel<CONFIG> extends ExtendedConfig {
+
+    /**
+     * Get value of a property as a definite type
+     *
+     * property shall exist in order for this method to be used. Otherwise exception is thrown
+     *
+     * @param name property name
+     * @param clazz class type of an expected value
+     * @param <T> type of an expected value
+     * @return value of an expected type
+     */
+    <T> T as(String name, Class<T> clazz);
+
+    /**
+     * Get value of a property as a definite type
+     *
+     * property may not exist, an empty Optional object is returned in case of an empty property
+     *
+     * @param name property name
+     * @param clazz class type of an expected value
+     * @param <T> type of an expected value
+     * @return Optional object filled by a value of an expected type or by the NULL value (
+     */
+    <T> Optional<T> getOptionalProperty(String name, Class<T> clazz);
+
+    /**
+     * Merge properties from other (found) external configuration.
+     *
+     * @param inputProperties those properties will be merged into ours
+     * @return current instance of the model
+     */
+    ExternalConfigurationModel mergeProperties(Map<String, Object> inputProperties);
+
+    /**
+     * Obtain config object
+     *
+     * @return external config provider
+     */
+    CONFIG getConfig();
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/spi/ExternalConfigurationProvider.java b/core-common/src/main/java/org/glassfish/jersey/spi/ExternalConfigurationProvider.java
new file mode 100644
index 0000000..80e0784
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/spi/ExternalConfigurationProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+
+package org.glassfish.jersey.spi;
+
+import java.util.Map;
+
+/**
+ * Provider interface for external (SPI) providers to provide
+ * their configuration properties implementations
+ *
+ * Priority of providers can be adjusted by Priority annotation
+ * or just alphabetically (if no Provider annotation is found)
+ */
+public interface ExternalConfigurationProvider {
+
+    /**
+     * Map of properties from the model (external config file)
+     *
+     * @return Map of properties loaded by a model from config file
+     */
+    Map<String, Object> getProperties();
+
+    /**
+     * obrain model object which has direct access to external configuration
+     *
+     * @return model of external properties
+     */
+    ExternalConfigurationModel getConfiguration();
+
+    /**
+     * Merge properties from other provider/model
+     *
+     * @param input those properties will be merged into ours
+     * @return current instance of provider
+     */
+    ExternalConfigurationModel merge(ExternalConfigurationModel input);
+}
diff --git a/core-common/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable b/core-common/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
index 371b37b..abc1825 100644
--- a/core-common/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
+++ b/core-common/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
@@ -1 +1,2 @@
-org.glassfish.jersey.logging.LoggingFeatureAutoDiscoverable
\ No newline at end of file
+org.glassfish.jersey.logging.LoggingFeatureAutoDiscoverable
+org.glassfish.jersey.internal.config.ExternalPropertiesAutoDiscoverable
\ No newline at end of file
diff --git a/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties b/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties
index e7abfd8..6b56cf5 100644
--- a/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties
+++ b/core-common/src/main/resources/org/glassfish/jersey/internal/localization.properties
@@ -193,3 +193,5 @@
 warning.provider.constrainedTo.wrong.package=A registered provider {0} constrained (via @ConstrainedTo) to {1} runtime implements interface {2} which is only usable in a {3} runtime context.
 # {0} - List of arbitrary localized messages, e.g.: [FATAL] <localized_message>; source=<object>
 warnings.detected=The following warnings have been detected: {0}
+warning.properties=System properties configuration provider not allowed
+system.properties.warning=Could not read system properties
diff --git a/core-common/src/test/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFactoryTest.java b/core-common/src/test/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFactoryTest.java
new file mode 100644
index 0000000..d0df568
--- /dev/null
+++ b/core-common/src/test/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFactoryTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.internal.config;
+
+import org.glassfish.jersey.CommonProperties;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFactory.getConfig;
+import static org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFactory.readExternalPropertiesMap;
+
+public class ExternalPropertiesConfigurationFactoryTest {
+
+    /**
+     * Predefine some properties to be read from config
+     */
+    @BeforeClass
+    public static void setUp() {
+        System.setProperty(CommonProperties.ALLOW_SYSTEM_PROPERTIES_PROVIDER, Boolean.TRUE.toString());
+
+        System.setProperty("jersey.config.server.provider.scanning.recursive", "PASSED");
+        System.setProperty(CommonProperties.JSON_PROCESSING_FEATURE_DISABLE, "1");
+        System.setProperty("jersey.config.client.readTimeout", "10");
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        System.clearProperty("jersey.config.server.provider.scanning.recursive");
+        System.clearProperty(CommonProperties.JSON_PROCESSING_FEATURE_DISABLE);
+        System.clearProperty("jersey.config.client.readTimeout");
+    }
+
+    @Test
+    public void readSystemPropertiesTest() {
+        final Object result =
+                readExternalPropertiesMap().get("jersey.config.server.provider.scanning.recursive");
+        Assert.assertNull(result);
+        Assert.assertEquals(Boolean.TRUE,
+                getConfig().as(CommonProperties.JSON_PROCESSING_FEATURE_DISABLE, Boolean.class));
+        Assert.assertEquals(Boolean.FALSE,
+                getConfig().as("jersey.config.client.readTimeout", Boolean.class));
+        Assert.assertEquals(1,
+                getConfig().as(CommonProperties.JSON_PROCESSING_FEATURE_DISABLE, Integer.class));
+        Assert.assertEquals(10,
+                getConfig().as("jersey.config.client.readTimeout", Integer.class));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void unsupportedMapperTest() {
+        getConfig().as(CommonProperties.JSON_PROCESSING_FEATURE_DISABLE, Double.class);
+    }
+
+    @Test
+    public void mergePropertiesTest() {
+        final Map<String, Object> inputProperties = new HashMap<>();
+        inputProperties.put("jersey.config.server.provider.scanning.recursive", "MODIFIED");
+        inputProperties.put("org.jersey.microprofile.config.added", "ADDED");
+        getConfig().mergeProperties(inputProperties);
+        final Object result = readExternalPropertiesMap().get("jersey.config.server.provider.scanning.recursive");
+        Assert.assertNull(result);
+        Assert.assertNull(readExternalPropertiesMap().get("org.jersey.microprofile.config.added"));
+    }
+
+}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java b/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java
index 2560fd2..ecf884d 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java
@@ -38,6 +38,7 @@
 import javax.ws.rs.core.Feature;
 
 import org.glassfish.jersey.internal.Errors;
+import org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFactory;
 import org.glassfish.jersey.internal.inject.Binder;
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.internal.spi.AutoDiscoverable;
@@ -56,6 +57,7 @@
 import org.glassfish.jersey.server.internal.scanning.PackageNamesScanner;
 import org.glassfish.jersey.server.model.Resource;
 
+
 /**
  * The resource configuration for configuring a web application.
  *
@@ -713,6 +715,7 @@
         final State current = state;
         if (!(current instanceof ImmutableState)) {
             setupApplicationName();
+            ExternalPropertiesConfigurationFactory.configure(state);
             state = new ImmutableState(current);
         }
     }
@@ -1297,4 +1300,5 @@
             setApplicationName(appName);
         }
     }
+
 }
diff --git a/ext/microprofile/config/pom.xml b/ext/microprofile/config/pom.xml
new file mode 100644
index 0000000..39d5029
--- /dev/null
+++ b/ext/microprofile/config/pom.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+
+    This program and the accompanying materials are made available under the
+    terms of the Eclipse Public License v. 2.0, which is available at
+    http://www.eclipse.org/legal/epl-2.0.
+
+    This Source Code may also be made available under the following Secondary
+    Licenses when the conditions for such availability set forth in the
+    Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+    version 2 with the GNU Classpath Exception, which is available at
+    https://www.gnu.org/software/classpath/license.html.
+
+    SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>project</artifactId>
+        <groupId>org.glassfish.jersey.ext</groupId>
+        <version>2.29-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>jersey-mp-config</artifactId>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.eclipse.microprofile.config</groupId>
+            <artifactId>microprofile-config-api</artifactId>
+            <version>${config.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>jakarta.ws.rs</groupId>
+            <artifactId>jakarta.ws.rs-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-jetty</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.inject</groupId>
+            <artifactId>jersey-hk2</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-core</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-jetty</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>io.helidon.microprofile.config</groupId>
+            <artifactId>helidon-microprofile-config</artifactId>
+            <version>${helidon.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+</project>
diff --git a/ext/microprofile/config/src/main/java/org/glassfish/jersey/microprofile/config/ConfigurationModel.java b/ext/microprofile/config/src/main/java/org/glassfish/jersey/microprofile/config/ConfigurationModel.java
new file mode 100644
index 0000000..8de143e
--- /dev/null
+++ b/ext/microprofile/config/src/main/java/org/glassfish/jersey/microprofile/config/ConfigurationModel.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.microprofile.config;
+
+import org.eclipse.microprofile.config.Config;
+import org.glassfish.jersey.spi.ExternalConfigurationModel;
+
+import javax.ws.rs.RuntimeType;
+import javax.ws.rs.core.Feature;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Generic class which implements default properties provider's logic and wraps not used methods from ExtConfig
+ *
+ * @param <CONFIG> type of MP configuration impl
+ */
+public class ConfigurationModel<CONFIG extends Config>
+        implements ExternalConfigurationModel<CONFIG> {
+
+    private final Map<String, Object> properties;
+    private final CONFIG config;
+
+    public ConfigurationModel(CONFIG config) {
+        this.properties = new HashMap<>();
+        this.config = config;
+    }
+
+    @Override
+    public <T> T as(String name, Class<T> clazz) {
+        return config.getValue(name, clazz);
+    }
+
+    @Override
+    public <T> Optional<T> getOptionalProperty(String name, Class<T> clazz) {
+        return config.getOptionalValue(name, clazz);
+    }
+
+    @Override
+    public CONFIG getConfig() {
+        return config;
+    }
+
+    @Override
+    public boolean isProperty(String name) {
+        return properties.isEmpty() ? getValueFromConfig(name) != null : properties.containsKey(name);
+    }
+
+    /**
+     * Allows ancestors to work with native configuration providers
+     *
+     * @param name property name
+     * @return  property's value if any
+     */
+    public  Object getValueFromConfig(String name){
+        return getConfig().getValue(name, Object.class);
+    }
+
+    @Override
+    public RuntimeType getRuntimeType() {
+
+        return null;
+    }
+
+    @Override
+    public Map<String, Object> getProperties() {
+        if (properties.isEmpty()) {
+            config.getPropertyNames().forEach(c -> properties.put(c, config.getValue(c, String.class)));
+        }
+
+        return properties;
+    }
+
+    @Override
+    public Object getProperty(String name) {
+        return properties.isEmpty() ? getValueFromConfig(name) : properties.get(name);
+    }
+
+    @Override
+    public Collection<String> getPropertyNames() {
+        final Set<String> names = new HashSet<>(properties.keySet());
+        if (names.isEmpty()) {
+            config.getPropertyNames().forEach(names::add);
+        }
+        return names;
+    }
+
+    public ExternalConfigurationModel mergeProperties(Map<String, Object> inputProperties) {
+        if (inputProperties == null || inputProperties.isEmpty()) {
+            return this;
+        }
+        if (properties.isEmpty()) {
+            getProperties();
+        }
+        properties.putAll(inputProperties);
+
+        return this;
+
+    }
+
+    @Override
+    public boolean isEnabled(Feature feature) {
+        return false;
+    }
+
+    @Override
+    public boolean isEnabled(Class<? extends Feature> featureClass) {
+        return false;
+    }
+
+    @Override
+    public boolean isRegistered(Object component) {
+        return false;
+    }
+
+    @Override
+    public boolean isRegistered(Class<?> componentClass) {
+        return false;
+    }
+
+    @Override
+    public Map<Class<?>, Integer> getContracts(Class<?> componentClass) {
+        return null;
+    }
+
+    @Override
+    public Set<Class<?>> getClasses() {
+        return null;
+    }
+
+    @Override
+    public Set<Object> getInstances() {
+        return null;
+    }
+}
diff --git a/ext/microprofile/config/src/main/java/org/glassfish/jersey/microprofile/config/ConfigurationProvider.java b/ext/microprofile/config/src/main/java/org/glassfish/jersey/microprofile/config/ConfigurationProvider.java
new file mode 100644
index 0000000..df50eee
--- /dev/null
+++ b/ext/microprofile/config/src/main/java/org/glassfish/jersey/microprofile/config/ConfigurationProvider.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.microprofile.config;
+
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.glassfish.jersey.spi.ExternalConfigurationModel;
+import org.glassfish.jersey.spi.ExternalConfigurationProvider;
+
+import java.util.Map;
+
+public class ConfigurationProvider implements ExternalConfigurationProvider {
+
+
+    private ConfigurationModel<Config> configModel;
+
+    public ConfigurationProvider() {
+
+        configModel = new ConfigurationModel(ConfigProvider.getConfig());
+    }
+
+    @Override
+    public Map<String, Object> getProperties() {
+        return configModel.getProperties();
+    }
+
+    @Override
+    public ExternalConfigurationModel getConfiguration() {
+        return configModel;
+    }
+
+    @Override
+    public ExternalConfigurationModel merge(ExternalConfigurationModel input) {
+        return input == null ? this.configModel : this.configModel.mergeProperties(input.getProperties());
+    }
+}
diff --git a/ext/microprofile/config/src/main/java/org/glassfish/jersey/microprofile/config/package-info.java b/ext/microprofile/config/src/main/java/org/glassfish/jersey/microprofile/config/package-info.java
new file mode 100644
index 0000000..da40c5a
--- /dev/null
+++ b/ext/microprofile/config/src/main/java/org/glassfish/jersey/microprofile/config/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/**
+ * Support for microprofile external configurations in Jersey
+ *
+ * Configuration properties for Jersey (client/server/common) could be passed from different sources
+ * using this implementation
+ *
+ * @since 2.29
+ */
+package org.glassfish.jersey.microprofile.config;
\ No newline at end of file
diff --git a/ext/microprofile/config/src/main/resources/META-INF/services/org.glassfish.jersey.spi.ExternalConfigurationProvider b/ext/microprofile/config/src/main/resources/META-INF/services/org.glassfish.jersey.spi.ExternalConfigurationProvider
new file mode 100644
index 0000000..e7aa15a
--- /dev/null
+++ b/ext/microprofile/config/src/main/resources/META-INF/services/org.glassfish.jersey.spi.ExternalConfigurationProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.microprofile.config.ConfigurationProvider
\ No newline at end of file
diff --git a/ext/microprofile/config/src/test/java/org/glassfish/jersey/microprofile/config/ExternalPropertiesConfigurationFactoryTest.java b/ext/microprofile/config/src/test/java/org/glassfish/jersey/microprofile/config/ExternalPropertiesConfigurationFactoryTest.java
new file mode 100644
index 0000000..2c4e70b
--- /dev/null
+++ b/ext/microprofile/config/src/test/java/org/glassfish/jersey/microprofile/config/ExternalPropertiesConfigurationFactoryTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.microprofile.config;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.inject.Singleton;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+public class ExternalPropertiesConfigurationFactoryTest extends JerseyTest {
+
+    private static final ApplicationPropertiesConfig applicationPropertiesConfig = new ApplicationPropertiesConfig();
+
+    private static class ApplicationPropertiesConfig extends ResourceConfig {
+
+        public ApplicationPropertiesConfig() {
+            register(MyResource.class);
+        }
+    }
+
+    @Path("/")
+    @Singleton
+    public static class MyResource {
+
+
+        @GET
+        @Path("readProperty/{key}")
+        @Produces(MediaType.APPLICATION_JSON)
+        public Response readProperties(@PathParam("key") String key) {
+            return Response.ok(String.valueOf(applicationPropertiesConfig.getProperty(key))).build();
+        }
+
+        @GET
+        @Path("getPropertyValue/{key}")
+        @Produces(MediaType.WILDCARD)
+        public Boolean getPropertyValue(@PathParam("key") String key) {
+            final Object value = applicationPropertiesConfig.getProperty(key);
+            return value == null ? null : Boolean.valueOf(value.toString());
+        }
+
+    }
+
+
+    @Override
+    protected Application configure() {
+
+        return applicationPropertiesConfig;
+
+    }
+
+    @Override
+    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+        return new JettyTestContainerFactory();
+    }
+
+    @Test
+    public void readConfigTest() {
+
+        final Boolean responce = target("getPropertyValue/{key}")
+                .resolveTemplate("key", "jersey.config.disableMetainfServicesLookup").request().get(Boolean.class);
+        Assert.assertEquals(Boolean.TRUE, responce);
+    }
+
+    @Test
+    public void smallRyeConfigTest() {
+
+        final String responce = target("readProperty/{key}")
+                .resolveTemplate("key", "jersey.config.disableAutoDiscovery").request().get(String.class);
+        Assert.assertEquals("1", responce);
+    }
+
+    @Test
+    public void defaultHeaderValueTest() {
+        final String responce = target("readProperty/{key}")
+                .resolveTemplate("key", "jersey.config.disableJsonProcessing").request().get(String.class);
+        Assert.assertEquals("true", responce);
+    }
+}
\ No newline at end of file
diff --git a/ext/microprofile/config/src/test/resources/META-INF/microprofile-config.properties b/ext/microprofile/config/src/test/resources/META-INF/microprofile-config.properties
new file mode 100644
index 0000000..dbb4a93
--- /dev/null
+++ b/ext/microprofile/config/src/test/resources/META-INF/microprofile-config.properties
@@ -0,0 +1,3 @@
+jersey.config.disableJsonProcessing = true
+jersey.config.disableAutoDiscovery=1
+jersey.config.disableMetainfServicesLookup=true
\ No newline at end of file
diff --git a/ext/pom.xml b/ext/pom.xml
index 672d697..22245f1 100644
--- a/ext/pom.xml
+++ b/ext/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2011, 2019 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Public License v. 2.0, which is available at
@@ -44,6 +44,7 @@
         <module>cdi</module>
         <module>entity-filtering</module>
         <module>metainf-services</module>
+	    <module>microprofile/config</module>
         <module>mvc</module>
         <module>mvc-bean-validation</module>
         <module>mvc-freemarker</module>
diff --git a/pom.xml b/pom.xml
index cfdf004..ba9780e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2048,6 +2048,8 @@
         <weld3.version>3.0.0.Final</weld3.version>
         <xerces.version>2.11.0</xerces.version>
         <yasson.version>1.0.3</yasson.version>
+        <helidon.version>1.0.3</helidon.version>
+        <config.version>1.2.1</config.version>
         <skip.e2e>false</skip.e2e>
     </properties>
 </project>
diff --git a/tests/integration/microprofile/config/helidon/pom.xml b/tests/integration/microprofile/config/helidon/pom.xml
new file mode 100644
index 0000000..84f0d84
--- /dev/null
+++ b/tests/integration/microprofile/config/helidon/pom.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+
+    This program and the accompanying materials are made available under the
+    terms of the Eclipse Public License v. 2.0, which is available at
+    http://www.eclipse.org/legal/epl-2.0.
+
+    This Source Code may also be made available under the following Secondary
+    Licenses when the conditions for such availability set forth in the
+    Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+    version 2 with the GNU Classpath Exception, which is available at
+    https://www.gnu.org/software/classpath/license.html.
+
+    SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>project</artifactId>
+        <groupId>org.glassfish.jersey.tests.integration</groupId>
+        <version>2.29-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>helidon-config-webapp</artifactId>
+    <packaging>war</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.tests.integration</groupId>
+            <artifactId>config-webapp</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.ext</groupId>
+            <artifactId>jersey-mp-config</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.helidon.config</groupId>
+            <artifactId>helidon-config</artifactId>
+            <version>${helidon.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.helidon.microprofile.config</groupId>
+            <artifactId>helidon-microprofile-config</artifactId>
+            <version>${helidon.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework</groupId>
+            <artifactId>jersey-test-framework-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-bundle</artifactId>
+            <type>pom</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.mortbay.jetty</groupId>
+                <artifactId>jetty-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/tests/integration/microprofile/config/helidon/src/main/java/webapp/WEB-INF/web.xml b/tests/integration/microprofile/config/helidon/src/main/java/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..b27c40e
--- /dev/null
+++ b/tests/integration/microprofile/config/helidon/src/main/java/webapp/WEB-INF/web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+
+    This program and the accompanying materials are made available under the
+    terms of the Eclipse Public License v. 2.0, which is available at
+    http://www.eclipse.org/legal/epl-2.0.
+
+    This Source Code may also be made available under the following Secondary
+    Licenses when the conditions for such availability set forth in the
+    Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+    version 2 with the GNU Classpath Exception, which is available at
+    https://www.gnu.org/software/classpath/license.html.
+
+    SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+    <servlet>
+        <servlet-name>helidonConfigApplicationServlet</servlet-name>
+        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+        <init-param>
+            <param-name>javax.ws.rs.Application</param-name>
+            <param-value>org.glassfish.jersey.tests.integration.config.MyApplication</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>helidonConfigApplicationServlet</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+</web-app>
\ No newline at end of file
diff --git a/tests/integration/microprofile/config/helidon/src/test/java/org/glassfish/jersey/tests/integration/config/HelidonConfigApplicationTest.java b/tests/integration/microprofile/config/helidon/src/test/java/org/glassfish/jersey/tests/integration/config/HelidonConfigApplicationTest.java
new file mode 100644
index 0000000..0543f63
--- /dev/null
+++ b/tests/integration/microprofile/config/helidon/src/test/java/org/glassfish/jersey/tests/integration/config/HelidonConfigApplicationTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.config;
+
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+
+public class HelidonConfigApplicationTest extends JerseyTest {
+
+    @Override
+    protected Application configure() {
+        return new MyApplication();
+    }
+
+    @Override
+    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+        return new GrizzlyTestContainerFactory();
+    }
+
+    @Test
+    public void testGetConfigProperty() {
+        final String response = target("/config/getProperty/{name}")
+                .resolveTemplate("name", "jersey.config.disableMetainfServicesLookup")
+                .request(MediaType.TEXT_PLAIN).get(String.class);
+        Assert.assertEquals("true", response);
+    }
+}
\ No newline at end of file
diff --git a/tests/integration/microprofile/config/webapp/pom.xml b/tests/integration/microprofile/config/webapp/pom.xml
new file mode 100644
index 0000000..116ef93
--- /dev/null
+++ b/tests/integration/microprofile/config/webapp/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+
+    This program and the accompanying materials are made available under the
+    terms of the Eclipse Public License v. 2.0, which is available at
+    http://www.eclipse.org/legal/epl-2.0.
+
+    This Source Code may also be made available under the following Secondary
+    Licenses when the conditions for such availability set forth in the
+    Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+    version 2 with the GNU Classpath Exception, which is available at
+    https://www.gnu.org/software/classpath/license.html.
+
+    SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>project</artifactId>
+        <groupId>org.glassfish.jersey.tests.integration</groupId>
+        <version>2.29-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>config-webapp</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-server</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.bundles</groupId>
+            <artifactId>jaxrs-ri</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.mortbay.jetty</groupId>
+                <artifactId>jetty-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/tests/integration/microprofile/config/webapp/src/main/java/org/glassfish/jersey/tests/integration/config/MyApplication.java b/tests/integration/microprofile/config/webapp/src/main/java/org/glassfish/jersey/tests/integration/config/MyApplication.java
new file mode 100644
index 0000000..1f12a24
--- /dev/null
+++ b/tests/integration/microprofile/config/webapp/src/main/java/org/glassfish/jersey/tests/integration/config/MyApplication.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.config;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import javax.ws.rs.ApplicationPath;
+
+@ApplicationPath("/")
+public class MyApplication
+        extends ResourceConfig {
+
+    public MyApplication() {
+        register(new MyResource(this));
+    }
+}
\ No newline at end of file
diff --git a/tests/integration/microprofile/config/webapp/src/main/java/org/glassfish/jersey/tests/integration/config/MyResource.java b/tests/integration/microprofile/config/webapp/src/main/java/org/glassfish/jersey/tests/integration/config/MyResource.java
new file mode 100644
index 0000000..eafefd5
--- /dev/null
+++ b/tests/integration/microprofile/config/webapp/src/main/java/org/glassfish/jersey/tests/integration/config/MyResource.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.integration.config;
+
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Response;
+
+@Path("config")
+public class MyResource {
+    private ResourceConfig config;
+
+    public MyResource(ResourceConfig config) {
+        this.config = config;
+    }
+
+    @GET
+    @Path("getProperty/{name}")
+    public Response getProperty(@PathParam("name") String name) {
+        return Response.ok(config.getProperty(name)).build();
+    }
+}
diff --git a/tests/integration/microprofile/config/webapp/src/main/resources/META-INF/microprofile-config.properties b/tests/integration/microprofile/config/webapp/src/main/resources/META-INF/microprofile-config.properties
new file mode 100644
index 0000000..dbb4a93
--- /dev/null
+++ b/tests/integration/microprofile/config/webapp/src/main/resources/META-INF/microprofile-config.properties
@@ -0,0 +1,3 @@
+jersey.config.disableJsonProcessing = true
+jersey.config.disableAutoDiscovery=1
+jersey.config.disableMetainfServicesLookup=true
\ No newline at end of file
diff --git a/tests/integration/pom.xml b/tests/integration/pom.xml
index 65371a7..2aa40ef 100644
--- a/tests/integration/pom.xml
+++ b/tests/integration/pom.xml
@@ -134,6 +134,8 @@
         <!-- TODO: conflict in ASM version (too old) of jetty plugin -->
         <!--<module>spring4</module>-->
         <module>tracing-support</module>
+        <module>microprofile/config/helidon</module>
+        <module>microprofile/config/webapp</module>
     </modules>
 
     <profiles>