Initial Contribution

Signed-off-by: Jan Supol <jan.supol@oracle.com>
diff --git a/ext/spring4/pom.xml b/ext/spring4/pom.xml
new file mode 100644
index 0000000..450eba3
--- /dev/null
+++ b/ext/spring4/pom.xml
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2012, 2018 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">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.glassfish.jersey.ext</groupId>
+        <artifactId>project</artifactId>
+        <version>2.28-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>jersey-spring4</artifactId>
+    <name>jersey-spring4</name>
+
+    <packaging>jar</packaging>
+
+    <description>
+        Jersey extension module providing support for Spring 4 integration.
+    </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-server</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.inject</groupId>
+            <artifactId>jersey-hk2</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.containers</groupId>
+            <artifactId>jersey-container-servlet-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+            <version>1.2</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.hk2</groupId>
+            <artifactId>hk2</artifactId>
+            <version>${hk2.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.glassfish.hk2</groupId>
+            <artifactId>spring-bridge</artifactId>
+            <version>${hk2.version}</version>
+            <exclusions>
+                <exclusion>  <!-- already pulled in by jersey-server -->
+                    <groupId>javax.inject</groupId>
+                    <artifactId>javax.inject</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.glassfish.hk2</groupId>
+                    <artifactId>hk2-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+            <version>${spring4.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>${spring4.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>commons-logging</groupId>
+                    <artifactId>commons-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>${spring4.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aop</artifactId>
+            <version>${spring4.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>3.0.1</version>
+            <scope>provided</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>org.aspectj</groupId>
+            <artifactId>aspectjrt</artifactId>
+            <version>1.6.11</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <version>1.6.11</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+    <properties>
+        <spring4.version>4.3.4.RELEASE</spring4.version>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.sun.istack</groupId>
+                <artifactId>maven-istack-commons-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <inherited>true</inherited>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>delayed-strategy-skip-test</id>
+            <activation>
+                <property>
+                    <name>org.glassfish.jersey.injection.manager.strategy</name>
+                    <value>delayed</value>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <skipTests>true</skipTests>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/AutowiredInjectResolver.java b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/AutowiredInjectResolver.java
new file mode 100644
index 0000000..36b8178
--- /dev/null
+++ b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/AutowiredInjectResolver.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2013, 2018 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.server.spring;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.inject.Singleton;
+
+import org.glassfish.jersey.internal.inject.Injectee;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.config.DependencyDescriptor;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.MethodParameter;
+
+/**
+ * HK2 injection resolver for Spring framework {@link Autowired} annotation injection.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ * @author Vetle Leinonen-Roeim (vetle at roeim.net)
+ */
+@Singleton
+public class AutowiredInjectResolver implements InjectionResolver<Autowired> {
+
+    private static final Logger LOGGER = Logger.getLogger(AutowiredInjectResolver.class.getName());
+
+    private volatile ApplicationContext ctx;
+
+    /**
+     * Create a new instance.
+     *
+     * @param ctx Spring application context.
+     */
+    public AutowiredInjectResolver(ApplicationContext ctx) {
+        this.ctx = ctx;
+    }
+
+    @Override
+    public Object resolve(Injectee injectee) {
+        AnnotatedElement parent = injectee.getParent();
+        String beanName = null;
+        if (parent != null) {
+            Qualifier an = parent.getAnnotation(Qualifier.class);
+            if (an != null) {
+                beanName = an.value();
+            }
+        }
+        boolean required = parent != null ? parent.getAnnotation(Autowired.class).required() : false;
+        return getBeanFromSpringContext(beanName, injectee, required);
+    }
+
+    private Object getBeanFromSpringContext(String beanName, Injectee injectee, final boolean required) {
+        try {
+            DependencyDescriptor dependencyDescriptor = createSpringDependencyDescriptor(injectee);
+            Set<String> autowiredBeanNames = new HashSet<>(1);
+            autowiredBeanNames.add(beanName);
+            return ctx.getAutowireCapableBeanFactory().resolveDependency(dependencyDescriptor, null,
+                    autowiredBeanNames, null);
+        } catch (NoSuchBeanDefinitionException e) {
+            if (required) {
+                LOGGER.warning(e.getMessage());
+                throw e;
+            }
+            return null;
+        }
+    }
+
+    private DependencyDescriptor createSpringDependencyDescriptor(final Injectee injectee) {
+        AnnotatedElement annotatedElement = injectee.getParent();
+
+        if (annotatedElement.getClass().isAssignableFrom(Field.class)) {
+            return new DependencyDescriptor((Field) annotatedElement, !injectee.isOptional());
+        } else if (annotatedElement.getClass().isAssignableFrom(Method.class)) {
+            return new DependencyDescriptor(
+                    new MethodParameter((Method) annotatedElement, injectee.getPosition()), !injectee.isOptional());
+        } else {
+            return new DependencyDescriptor(
+                    new MethodParameter((Constructor) annotatedElement, injectee.getPosition()), !injectee.isOptional());
+        }
+    }
+
+    @Override
+    public boolean isConstructorParameterIndicator() {
+        return false;
+    }
+
+    @Override
+    public boolean isMethodParameterIndicator() {
+        return false;
+    }
+
+    @Override
+    public Class<Autowired> getAnnotation() {
+        return Autowired.class;
+    }
+}
diff --git a/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/SpringComponentProvider.java b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/SpringComponentProvider.java
new file mode 100644
index 0000000..19f45b3
--- /dev/null
+++ b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/SpringComponentProvider.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2013, 2018 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.server.spring;
+
+import java.util.Set;
+import java.util.function.Supplier;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.servlet.ServletContext;
+
+import org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.server.ApplicationHandler;
+import org.glassfish.jersey.server.spi.ComponentProvider;
+
+import org.jvnet.hk2.spring.bridge.api.SpringBridge;
+import org.jvnet.hk2.spring.bridge.api.SpringIntoHK2Bridge;
+
+import org.springframework.aop.framework.Advised;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+/**
+ * Custom ComponentProvider class.
+ * Responsible for 1) bootstrapping Jersey 2 Spring integration and
+ * 2) making Jersey skip JAX-RS Spring component life-cycle management and leave it to us.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public class SpringComponentProvider implements ComponentProvider {
+
+    private static final Logger LOGGER = Logger.getLogger(SpringComponentProvider.class.getName());
+    private static final String DEFAULT_CONTEXT_CONFIG_LOCATION = "applicationContext.xml";
+    private static final String PARAM_CONTEXT_CONFIG_LOCATION = "contextConfigLocation";
+    private static final String PARAM_SPRING_CONTEXT = "contextConfig";
+
+    private volatile InjectionManager injectionManager;
+    private volatile ApplicationContext ctx;
+
+    @Override
+    public void initialize(InjectionManager injectionManager) {
+        this.injectionManager = injectionManager;
+
+        if (LOGGER.isLoggable(Level.FINE)) {
+            LOGGER.fine(LocalizationMessages.CTX_LOOKUP_STARTED());
+        }
+
+        ServletContext sc = injectionManager.getInstance(ServletContext.class);
+
+        if (sc != null) {
+            // servlet container
+            ctx = WebApplicationContextUtils.getWebApplicationContext(sc);
+        } else {
+            // non-servlet container
+            ctx = createSpringContext();
+        }
+        if (ctx == null) {
+            LOGGER.severe(LocalizationMessages.CTX_LOOKUP_FAILED());
+            return;
+        }
+        LOGGER.config(LocalizationMessages.CTX_LOOKUP_SUCESSFUL());
+
+        // initialize HK2 spring-bridge
+
+        ImmediateHk2InjectionManager hk2InjectionManager = (ImmediateHk2InjectionManager) injectionManager;
+        SpringBridge.getSpringBridge().initializeSpringBridge(hk2InjectionManager.getServiceLocator());
+        SpringIntoHK2Bridge springBridge = injectionManager.getInstance(SpringIntoHK2Bridge.class);
+        springBridge.bridgeSpringBeanFactory(ctx);
+
+        injectionManager.register(Bindings.injectionResolver(new AutowiredInjectResolver(ctx)));
+        injectionManager.register(Bindings.service(ctx).to(ApplicationContext.class).named("SpringContext"));
+        LOGGER.config(LocalizationMessages.SPRING_COMPONENT_PROVIDER_INITIALIZED());
+    }
+
+    // detect JAX-RS classes that are also Spring @Components.
+    // register these with HK2 ServiceLocator to manage their lifecycle using Spring.
+    @Override
+    public boolean bind(Class<?> component, Set<Class<?>> providerContracts) {
+
+        if (ctx == null) {
+            return false;
+        }
+
+        if (AnnotationUtils.findAnnotation(component, Component.class) != null) {
+            String[] beanNames = ctx.getBeanNamesForType(component);
+            if (beanNames == null || beanNames.length != 1) {
+                LOGGER.severe(LocalizationMessages.NONE_OR_MULTIPLE_BEANS_AVAILABLE(component));
+                return false;
+            }
+            String beanName = beanNames[0];
+
+            Binding binding = Bindings.supplier(new SpringManagedBeanFactory(ctx, injectionManager, beanName))
+                    .to(component)
+                    .to(providerContracts);
+            injectionManager.register(binding);
+
+            LOGGER.config(LocalizationMessages.BEAN_REGISTERED(beanNames[0]));
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void done() {
+    }
+
+    private ApplicationContext createSpringContext() {
+        ApplicationHandler applicationHandler = injectionManager.getInstance(ApplicationHandler.class);
+        ApplicationContext springContext = (ApplicationContext) applicationHandler.getConfiguration()
+                .getProperty(PARAM_SPRING_CONTEXT);
+        if (springContext == null) {
+            String contextConfigLocation = (String) applicationHandler.getConfiguration()
+                    .getProperty(PARAM_CONTEXT_CONFIG_LOCATION);
+            springContext = createXmlSpringConfiguration(contextConfigLocation);
+        }
+        return springContext;
+    }
+
+    private ApplicationContext createXmlSpringConfiguration(String contextConfigLocation) {
+        if (contextConfigLocation == null) {
+            contextConfigLocation = DEFAULT_CONTEXT_CONFIG_LOCATION;
+        }
+        return ctx = new ClassPathXmlApplicationContext(contextConfigLocation, "jersey-spring-applicationContext.xml");
+    }
+
+    private static class SpringManagedBeanFactory implements Supplier {
+
+        private final ApplicationContext ctx;
+        private final InjectionManager injectionManager;
+        private final String beanName;
+
+        private SpringManagedBeanFactory(ApplicationContext ctx, InjectionManager injectionManager, String beanName) {
+            this.ctx = ctx;
+            this.injectionManager = injectionManager;
+            this.beanName = beanName;
+        }
+
+        @Override
+        public Object get() {
+            Object bean = ctx.getBean(beanName);
+            if (bean instanceof Advised) {
+                try {
+                    // Unwrap the bean and inject the values inside of it
+                    Object localBean = ((Advised) bean).getTargetSource().getTarget();
+                    injectionManager.inject(localBean);
+                } catch (Exception e) {
+                    // Ignore and let the injection happen as it normally would.
+                    injectionManager.inject(bean);
+                }
+            } else {
+                injectionManager.inject(bean);
+            }
+            return bean;
+        }
+    }
+}
diff --git a/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/SpringLifecycleListener.java b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/SpringLifecycleListener.java
new file mode 100644
index 0000000..70a57a5
--- /dev/null
+++ b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/SpringLifecycleListener.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, 2018 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.server.spring;
+
+import javax.ws.rs.ext.Provider;
+
+import javax.inject.Inject;
+
+import org.glassfish.jersey.server.spi.Container;
+import org.glassfish.jersey.server.spi.ContainerLifecycleListener;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+
+/**
+ * JAX-RS Provider class for processing Jersey 2 Spring integration container life-cycle events.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+@Provider
+public class SpringLifecycleListener implements ContainerLifecycleListener {
+
+    @Inject
+    private ApplicationContext ctx;
+
+    @Override
+    public void onStartup(Container container) {
+    }
+
+    @Override
+    public void onReload(Container container) {
+        if (ctx instanceof ConfigurableApplicationContext) {
+            ((ConfigurableApplicationContext) ctx).refresh();
+        }
+    }
+
+    @Override
+    public void onShutdown(Container container) {
+        if (ctx instanceof ConfigurableApplicationContext) {
+            ((ConfigurableApplicationContext) ctx).close();
+        }
+    }
+}
diff --git a/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/SpringWebApplicationInitializer.java b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/SpringWebApplicationInitializer.java
new file mode 100644
index 0000000..80a054f
--- /dev/null
+++ b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/SpringWebApplicationInitializer.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 2018 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.server.spring;
+
+import java.util.logging.Logger;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.springframework.web.WebApplicationInitializer;
+
+/**
+ * Spring WebApplicationInitializer implementation initializes Spring context by
+ * adding a Spring ContextLoaderListener to the ServletContext.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ */
+public class SpringWebApplicationInitializer implements WebApplicationInitializer {
+
+    private static final Logger LOGGER = Logger.getLogger(SpringWebApplicationInitializer.class.getName());
+
+    private static final String PAR_NAME_CTX_CONFIG_LOCATION = "contextConfigLocation";
+
+    @Override
+    public void onStartup(ServletContext sc) throws ServletException {
+        if (sc.getInitParameter(PAR_NAME_CTX_CONFIG_LOCATION) == null) {
+            LOGGER.config(LocalizationMessages.REGISTERING_CTX_LOADER_LISTENER());
+            sc.setInitParameter(PAR_NAME_CTX_CONFIG_LOCATION, "classpath:applicationContext.xml");
+            sc.addListener("org.springframework.web.context.ContextLoaderListener");
+            sc.addListener("org.springframework.web.context.request.RequestContextListener");
+        } else {
+            LOGGER.config(LocalizationMessages.SKIPPING_CTX_LODAER_LISTENER_REGISTRATION());
+        }
+    }
+}
diff --git a/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/package-info.java b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/package-info.java
new file mode 100644
index 0000000..0176470
--- /dev/null
+++ b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013, 2018 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
+ */
+
+/**
+ * Jersey server-side Spring 4 integration classes.
+ *
+ */
+package org.glassfish.jersey.server.spring;
diff --git a/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/JaxrsRequestAttributes.java b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/JaxrsRequestAttributes.java
new file mode 100644
index 0000000..c1eb321
--- /dev/null
+++ b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/JaxrsRequestAttributes.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013, 2018 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.server.spring.scope;
+
+import javax.ws.rs.container.ContainerRequestContext;
+
+import org.glassfish.jersey.server.spring.LocalizationMessages;
+import org.springframework.util.StringUtils;
+import org.springframework.web.context.request.AbstractRequestAttributes;
+
+/**
+ * JAX-RS based Spring RequestAttributes implementation.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+class JaxrsRequestAttributes extends AbstractRequestAttributes {
+
+    private final ContainerRequestContext requestContext;
+
+    /**
+     * Create a new instance.
+     *
+     * @param requestContext JAX-RS container request context
+     */
+    public JaxrsRequestAttributes(ContainerRequestContext requestContext) {
+        this.requestContext = requestContext;
+    }
+
+    @Override
+    protected void updateAccessedSessionAttributes() {
+        // sessions not supported
+    }
+
+    @Override
+    public Object getAttribute(String name, int scope) {
+        return requestContext.getProperty(name);
+    }
+
+    @Override
+    public void setAttribute(String name, Object value, int scope) {
+        requestContext.setProperty(name, value);
+    }
+
+    @Override
+    public void removeAttribute(String name, int scope) {
+        requestContext.removeProperty(name);
+    }
+
+    @Override
+    public String[] getAttributeNames(int scope) {
+        if (!isRequestActive()) {
+            throw new IllegalStateException(LocalizationMessages.NOT_IN_REQUEST_SCOPE());
+        }
+        return StringUtils.toStringArray(requestContext.getPropertyNames());
+    }
+
+    @Override
+    public void registerDestructionCallback(String name, Runnable callback, int scope) {
+        registerRequestDestructionCallback(name, callback);
+    }
+
+    @Override
+    public Object resolveReference(String key) {
+        if (REFERENCE_REQUEST.equals(key)) {
+            return requestContext;
+        }
+        return null;
+    }
+
+    @Override
+    public String getSessionId() {
+        return null;
+    }
+
+    @Override
+    public Object getSessionMutex() {
+        return null;
+    }
+}
diff --git a/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/JaxrsServletRequestAttributes.java b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/JaxrsServletRequestAttributes.java
new file mode 100644
index 0000000..6da105f
--- /dev/null
+++ b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/JaxrsServletRequestAttributes.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, 2018 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.server.spring.scope;
+
+import javax.ws.rs.container.ContainerRequestContext;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+/**
+ * JAX-RS based Spring RequestAttributes implementation for Servlet-based applications.
+ *
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+class JaxrsServletRequestAttributes extends ServletRequestAttributes {
+
+    private final ContainerRequestContext requestContext;
+
+    /**
+     * Create a new JAX-RS ServletRequestAttributes instance for the given request.
+     *
+     * @param request        current HTTP request
+     * @param requestContext JAX-RS request context
+     */
+    public JaxrsServletRequestAttributes(final HttpServletRequest request, final ContainerRequestContext requestContext) {
+        super(request);
+        this.requestContext = requestContext;
+    }
+
+    @Override
+    public Object resolveReference(String key) {
+        if (REFERENCE_REQUEST.equals(key)) {
+            return this.requestContext;
+        } else if (REFERENCE_SESSION.equals(key)) {
+            return super.getSession(true);
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/RequestContextFilter.java b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/RequestContextFilter.java
new file mode 100644
index 0000000..1cbcbd7
--- /dev/null
+++ b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/RequestContextFilter.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013, 2018 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.server.spring.scope;
+
+import java.io.IOException;
+
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.container.PreMatching;
+import javax.ws.rs.ext.Provider;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.request.AbstractRequestAttributes;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+
+/**
+ * Spring filter to provide a bridge between JAX-RS and Spring request attributes.
+ *
+ * @author Marko Asplund (marko.asplund at yahoo.com)
+ * @author Jakub Podlesak (jakub.podlesak at oracle.com)
+ * @author Marek Potociar (marek.potociar at oracle.com)
+ */
+@Provider
+@PreMatching
+public final class RequestContextFilter implements ContainerRequestFilter, ContainerResponseFilter {
+
+    private static final String REQUEST_ATTRIBUTES_PROPERTY = RequestContextFilter.class.getName() + ".REQUEST_ATTRIBUTES";
+
+    private final SpringAttributeController attributeController;
+
+    private static final SpringAttributeController EMPTY_ATTRIBUTE_CONTROLLER = new SpringAttributeController() {
+        @Override
+        public void setAttributes(final ContainerRequestContext requestContext) {
+        }
+
+        @Override
+        public void resetAttributes(final ContainerRequestContext requestContext) {
+        }
+    };
+
+    private interface SpringAttributeController {
+
+        void setAttributes(final ContainerRequestContext requestContext);
+
+        void resetAttributes(final ContainerRequestContext requestContext);
+    }
+
+    /**
+     * Create a new request context filter instance.
+     *
+     * @param injectionManager injection manager.
+     */
+    @Inject
+    public RequestContextFilter(final InjectionManager injectionManager) {
+        final ApplicationContext appCtx = injectionManager.getInstance(ApplicationContext.class);
+        final boolean isWebApp = appCtx instanceof WebApplicationContext;
+
+        attributeController = appCtx != null ? new SpringAttributeController() {
+
+            @Override
+            public void setAttributes(final ContainerRequestContext requestContext) {
+                final RequestAttributes attributes;
+                if (isWebApp) {
+                    final HttpServletRequest httpRequest = injectionManager.getInstance(HttpServletRequest.class);
+                    attributes = new JaxrsServletRequestAttributes(httpRequest, requestContext);
+                } else {
+                    attributes = new JaxrsRequestAttributes(requestContext);
+                }
+                requestContext.setProperty(REQUEST_ATTRIBUTES_PROPERTY, attributes);
+                RequestContextHolder.setRequestAttributes(attributes);
+            }
+
+            @Override
+            public void resetAttributes(final ContainerRequestContext requestContext) {
+                final AbstractRequestAttributes attributes =
+                        (AbstractRequestAttributes) requestContext.getProperty(REQUEST_ATTRIBUTES_PROPERTY);
+                RequestContextHolder.resetRequestAttributes();
+                attributes.requestCompleted();
+            }
+        } : EMPTY_ATTRIBUTE_CONTROLLER;
+    }
+
+    @Override
+    public void filter(final ContainerRequestContext requestContext) throws IOException {
+        attributeController.setAttributes(requestContext);
+    }
+
+    @Override
+    public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext)
+            throws IOException {
+        attributeController.resetAttributes(requestContext);
+    }
+}
diff --git a/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/package-info.java b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/package-info.java
new file mode 100644
index 0000000..e15b2c5
--- /dev/null
+++ b/ext/spring4/src/main/java/org/glassfish/jersey/server/spring/scope/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013, 2018 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
+ */
+
+/**
+ * Jersey server-side Spring 4 integration injection scopes related classes.
+ *
+ */
+package org.glassfish.jersey.server.spring.scope;
diff --git a/ext/spring4/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ComponentProvider b/ext/spring4/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ComponentProvider
new file mode 100644
index 0000000..5aec207
--- /dev/null
+++ b/ext/spring4/src/main/resources/META-INF/services/org.glassfish.jersey.server.spi.ComponentProvider
@@ -0,0 +1 @@
+org.glassfish.jersey.server.spring.SpringComponentProvider
diff --git a/ext/spring4/src/main/resources/jersey-spring-applicationContext.xml b/ext/spring4/src/main/resources/jersey-spring-applicationContext.xml
new file mode 100644
index 0000000..00e4dda
--- /dev/null
+++ b/ext/spring4/src/main/resources/jersey-spring-applicationContext.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2013, 2018 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
+
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
+        <property name="scopes">
+            <map>
+                <entry key="request">
+                    <bean class="org.springframework.web.context.request.RequestScope"/>
+                </entry>
+            </map>
+        </property>
+    </bean>
+</beans>
diff --git a/ext/spring4/src/main/resources/org/glassfish/jersey/server/spring/localization.properties b/ext/spring4/src/main/resources/org/glassfish/jersey/server/spring/localization.properties
new file mode 100644
index 0000000..6fd0a06
--- /dev/null
+++ b/ext/spring4/src/main/resources/org/glassfish/jersey/server/spring/localization.properties
@@ -0,0 +1,26 @@
+#
+# Copyright (c) 2013, 2018 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
+#
+
+no.beans.found.for.type=No beans found. Resolution failed for type {0}.
+ctx.lookup.started=Spring context lookup started.
+ctx.lookup.failed=Spring context lookup failed, skipping spring component provider initialization.
+ctx.lookup.sucessful=Spring context lookup done.
+spring.component.provider.initialized=Spring component provider initialized.
+none.or.multiple.beans.available=None or multiple beans found in Spring context for type {0}, skipping the type.
+bean.registered=Spring managed bean, {0}, registered with HK2.
+registering.ctx.loader.listener=Registering Spring ContextLoaderListener
+skipping.ctx.lodaer.listener.registration=Presuming Spring ContextLoaderListener was manually registered. Skipping context loader registration.
+not.in.request.scope=Cannot ask for request attributes - request is not active anymore!
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/NoComponent.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/NoComponent.java
new file mode 100644
index 0000000..111361c
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/NoComponent.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring;
+
+public class NoComponent {
+
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/SpringTestConfiguration.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/SpringTestConfiguration.java
new file mode 100644
index 0000000..5a8123c
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/SpringTestConfiguration.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan(basePackages = "org.glassfish.jersey.server.spring")
+public class SpringTestConfiguration {
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent1.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent1.java
new file mode 100644
index 0000000..7a065c1
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent1.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestComponent1 {
+
+    public String result() {
+        return "test ok";
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent2.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent2.java
new file mode 100644
index 0000000..792d9b8
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent2.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring;
+
+public interface TestComponent2 {
+    String result();
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent2Impl1.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent2Impl1.java
new file mode 100644
index 0000000..c8c61d0
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent2Impl1.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestComponent2Impl1 implements TestComponent2 {
+    @Override
+    public String result() {
+        return "test ok";
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent2Impl2.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent2Impl2.java
new file mode 100644
index 0000000..9900cd4
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/TestComponent2Impl2.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestComponent2Impl2 implements TestComponent2 {
+    @Override
+    public String result() {
+        return "test ok";
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/Aspect4JTest.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/Aspect4JTest.java
new file mode 100644
index 0000000..6b64034
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/Aspect4JTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.aspect4j;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.junit.Assert.assertEquals;
+
+public class Aspect4JTest extends JerseyTest {
+
+    private ClassPathXmlApplicationContext applicationContext;
+
+    private TestAspect testAspect;
+
+    @Before
+    public void before() {
+        testAspect.reset();
+    }
+
+    @Override
+    protected Application configure() {
+        applicationContext = new ClassPathXmlApplicationContext("jersey-spring-aspect4j-applicationContext.xml");
+        testAspect = applicationContext.getBean(TestAspect.class);
+        return new Aspect4jJerseyConfig()
+                .property("contextConfig", applicationContext);
+    }
+
+    @Test
+    public void methodCallShouldNotBeIntercepted() {
+        target("test1").request().get(String.class);
+        assertEquals(0, testAspect.getInterceptions());
+    }
+
+    @Test
+    public void methodCallShouldBeIntercepted() {
+        target("test2").request().get(String.class);
+        assertEquals(1, applicationContext.getBean(TestAspect.class).getInterceptions());
+    }
+
+    @Test
+    public void JERSEY_3126() {
+        final String result = target("JERSEY-3126").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/Aspect4jJerseyConfig.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/Aspect4jJerseyConfig.java
new file mode 100644
index 0000000..4506c7e
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/Aspect4jJerseyConfig.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.aspect4j;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
+
+public class Aspect4jJerseyConfig extends ResourceConfig {
+
+    public Aspect4jJerseyConfig() {
+        register(RequestContextFilter.class);
+        register(NoComponentResource.class);
+        register(ComponentResource.class);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/ComponentResource.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/ComponentResource.java
new file mode 100644
index 0000000..b9b3596
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/ComponentResource.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.aspect4j;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+
+import org.glassfish.jersey.server.spring.TestComponent1;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Path("/")
+@Component
+public class ComponentResource {
+
+    @Autowired
+    private TestComponent1 testComponent1;
+    @Context
+    private UriInfo uriInfo;
+
+    @Path("test2")
+    @GET
+    public String test2() {
+        return testComponent1.result();
+    }
+
+    @Path("JERSEY-3126")
+    @GET
+    public String JERSEY_3126() {
+        return uriInfo == null ? "test failed" : "test ok";
+    }
+
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/NoComponentResource.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/NoComponentResource.java
new file mode 100644
index 0000000..eaa3643
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/NoComponentResource.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.aspect4j;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.glassfish.jersey.server.spring.TestComponent1;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Path("/")
+public class NoComponentResource {
+
+    @Autowired
+    private TestComponent1 testComponent1;
+
+    @Path("test1")
+    @GET
+    public String test1() {
+        return testComponent1.result();
+    }
+
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/TestAspect.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/TestAspect.java
new file mode 100644
index 0000000..3a80614
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/aspect4j/TestAspect.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.aspect4j;
+
+import javax.inject.Singleton;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+
+@Aspect
+@Singleton
+public class TestAspect {
+
+    private int interceptions = 0;
+
+    @Before("execution(* org.glassfish.jersey.server.spring.aspect4j.*.*())")
+    public void intercept(JoinPoint joinPoint) {
+        interceptions++;
+    }
+
+    public int getInterceptions() {
+        return interceptions;
+    }
+
+    public void reset() {
+        interceptions = 0;
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/fieldinjection/SpringFieldInjectionJerseyTestConfig.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/fieldinjection/SpringFieldInjectionJerseyTestConfig.java
new file mode 100644
index 0000000..df30805
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/fieldinjection/SpringFieldInjectionJerseyTestConfig.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.fieldinjection;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
+
+public class SpringFieldInjectionJerseyTestConfig extends ResourceConfig {
+    public SpringFieldInjectionJerseyTestConfig() {
+        register(RequestContextFilter.class);
+        register(SpringFieldInjectionTestResource.class);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/fieldinjection/SpringFieldInjectionTest.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/fieldinjection/SpringFieldInjectionTest.java
new file mode 100644
index 0000000..9ec3a54
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/fieldinjection/SpringFieldInjectionTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.fieldinjection;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.spring.SpringTestConfiguration;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.Assert.assertEquals;
+
+public class SpringFieldInjectionTest extends JerseyTest {
+
+    @Override
+    protected Application configure() {
+        ApplicationContext context = new AnnotationConfigApplicationContext(SpringTestConfiguration.class);
+        return new SpringFieldInjectionJerseyTestConfig()
+                .property("contextConfig", context);
+    }
+
+    @Test
+    public void testInjectionOfSingleBean() {
+        String result = target("test1").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+
+    @Test
+    public void testInjectionOfListOfBeans() {
+        String result = target("test2").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+
+    @Test
+    public void testInjectionOfSetOfBeans() {
+        String result = target("test3").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+
+    @Test
+    public void JERSEY_2643() {
+        String result = target("JERSEY-2643").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/fieldinjection/SpringFieldInjectionTestResource.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/fieldinjection/SpringFieldInjectionTestResource.java
new file mode 100644
index 0000000..16e6de1
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/fieldinjection/SpringFieldInjectionTestResource.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.fieldinjection;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.glassfish.jersey.server.spring.NoComponent;
+import org.glassfish.jersey.server.spring.TestComponent1;
+import org.glassfish.jersey.server.spring.TestComponent2;
+import org.springframework.beans.factory.annotation.Autowired;
+
+@Path("/")
+public class SpringFieldInjectionTestResource {
+
+    @Autowired
+    private TestComponent1 testComponent1;
+
+    @Autowired
+    private List<TestComponent2> testComponent2List;
+
+    @Autowired
+    Set<TestComponent2> testComponent2Set;
+
+    @Autowired(required = false)
+    private NoComponent noComponent;
+
+    @Path("test1")
+    @GET
+    public String test1() {
+        return testComponent1.result();
+    }
+
+    @Path("test2")
+    @GET
+    public String test2() {
+        return (testComponent2List.size() == 2 && "test ok".equals(testComponent2List.get(0).result())
+                && "test ok".equals(testComponent2List.get(1).result())) ? "test ok" : "test failed";
+    }
+
+    @Path("test3")
+    @GET
+    public String test3() {
+        Iterator<TestComponent2> iterator = testComponent2Set.iterator();
+        return (testComponent2Set.size() == 2 && "test ok".equals(iterator.next().result())
+                && "test ok".equals(iterator.next().result())) ? "test ok" : "test failed";
+    }
+
+    @Path("JERSEY-2643")
+    @GET
+    public String JERSEY_2643() {
+        return noComponent == null ? "test ok" : "test failed";
+    }
+
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/Counter.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/Counter.java
new file mode 100644
index 0000000..28de237
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/Counter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, 2018 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.server.spring.filter;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class Counter {
+
+    private int count = 0;
+
+    public void inc() {
+        count++;
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/FilterTest.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/FilterTest.java
new file mode 100644
index 0000000..539b633
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/FilterTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.filter;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.server.spring.SpringTestConfiguration;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.junit.Assert.assertEquals;
+
+public class FilterTest extends JerseyTest {
+
+    private ApplicationContext context;
+
+    @Override
+    protected Application configure() {
+        context = new AnnotationConfigApplicationContext(SpringTestConfiguration.class);
+        return new JerseyTestConfig()
+                .property("contextConfig", context);
+    }
+
+    @Test
+    public void testInjectionOfSingleBean() {
+        target("test1").request().get(String.class);
+        assertEquals(1, context.getBean(Counter.class).getCount());
+    }
+
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/JerseyTestConfig.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/JerseyTestConfig.java
new file mode 100644
index 0000000..9fb32a8
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/JerseyTestConfig.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.filter;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
+
+public class JerseyTestConfig extends ResourceConfig {
+
+    public JerseyTestConfig() {
+        register(RequestContextFilter.class);
+        register(TestResource.class);
+        register(TestFilter.class);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/TestFilter.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/TestFilter.java
new file mode 100644
index 0000000..dbc4afb
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/TestFilter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2018 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.server.spring.filter;
+
+import java.io.IOException;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+
+import org.springframework.stereotype.Component;
+
+@Component
+@Singleton
+public class TestFilter implements ContainerRequestFilter {
+
+    @Inject
+    private Counter counter;
+
+    @Override
+    public void filter(final ContainerRequestContext requestContext) throws IOException {
+        counter.inc();
+    }
+
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/TestResource.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/TestResource.java
new file mode 100644
index 0000000..4401629
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/filter/TestResource.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.filter;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+@Path("/")
+public class TestResource {
+
+    @Path("test1")
+    @GET
+    public String test1() {
+        return "Hello, Test!";
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/methodinjection/SpringMethodInjectionJerseyTestConfig.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/methodinjection/SpringMethodInjectionJerseyTestConfig.java
new file mode 100644
index 0000000..5a9d3b7
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/methodinjection/SpringMethodInjectionJerseyTestConfig.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.methodinjection;
+
+import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
+import org.glassfish.jersey.server.ResourceConfig;
+
+public class SpringMethodInjectionJerseyTestConfig extends ResourceConfig {
+    public SpringMethodInjectionJerseyTestConfig() {
+        register(RequestContextFilter.class);
+        register(SpringMethodInjectionTestResource.class);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/methodinjection/SpringMethodInjectionTest.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/methodinjection/SpringMethodInjectionTest.java
new file mode 100644
index 0000000..5ce4fec
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/methodinjection/SpringMethodInjectionTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.methodinjection;
+
+import static org.junit.Assert.assertEquals;
+
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.glassfish.jersey.server.spring.SpringTestConfiguration;
+
+import javax.ws.rs.core.Application;
+
+public class SpringMethodInjectionTest extends JerseyTest {
+
+    @Override
+    protected Application configure() {
+        ApplicationContext context = new AnnotationConfigApplicationContext(SpringTestConfiguration.class);
+        return new SpringMethodInjectionJerseyTestConfig()
+                .property("contextConfig", context);
+    }
+
+    @Test
+    public void testInjectionOfSingleBean() {
+        String result = target("test1").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+
+    @Test
+    public void testInjectionOfListOfBeans() {
+        String result = target("test2").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+
+    @Test
+    public void testInjectionOfSetOfBeans() {
+        String result = target("test3").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/methodinjection/SpringMethodInjectionTestResource.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/methodinjection/SpringMethodInjectionTestResource.java
new file mode 100644
index 0000000..0cb3d68
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/methodinjection/SpringMethodInjectionTestResource.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.methodinjection;
+
+import org.glassfish.jersey.server.spring.NoComponent;
+import org.glassfish.jersey.server.spring.TestComponent1;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+@Path("/")
+public class SpringMethodInjectionTestResource {
+
+    private TestComponent1 testComponent1;
+    private List<org.glassfish.jersey.server.spring.TestComponent2> testComponent2List;
+    private Set<org.glassfish.jersey.server.spring.TestComponent2> testComponent2Set;
+    private NoComponent noComponent;
+
+    @Autowired
+    public void setTestComponent1(TestComponent1 testComponent1) {
+        this.testComponent1 = testComponent1;
+    }
+
+    @Autowired
+    public void setTestComponent2List(List<org.glassfish.jersey.server.spring.TestComponent2> testComponent2List) {
+        this.testComponent2List = testComponent2List;
+    }
+
+    @Autowired
+    public void setTestComponent2Set(Set<org.glassfish.jersey.server.spring.TestComponent2> testComponent2Set) {
+        this.testComponent2Set = testComponent2Set;
+    }
+
+    @Autowired(required = false)
+    public void setNoComponent(NoComponent noComponent) {
+        this.noComponent = noComponent;
+    }
+
+    @Path("test1")
+    @GET
+    public String test1() {
+        return testComponent1.result();
+    }
+
+    @Path("test2")
+    @GET
+    public String test2() {
+        return (testComponent2List.size() == 2 && "test ok".equals(testComponent2List.get(0).result())
+                && "test ok".equals(testComponent2List.get(1).result())) ? "test ok" : "test failed";
+    }
+
+    @Path("test3")
+    @GET
+    public String test3() {
+        java.util.Iterator<org.glassfish.jersey.server.spring.TestComponent2> iterator = testComponent2Set.iterator();
+        return (testComponent2Set.size() == 2 && "test ok".equals(iterator.next().result())
+                && "test ok".equals(iterator.next().result())) ? "test ok" : "test failed";
+    }
+
+    @Path("JERSEY-2643")
+    @GET
+    public String JERSEY_2643() {
+        return noComponent == null ? "test ok" : "test failed";
+    }
+
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/parameterinjection/SpringParameterInjectionJerseyTestConfig.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/parameterinjection/SpringParameterInjectionJerseyTestConfig.java
new file mode 100644
index 0000000..d67ebd4
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/parameterinjection/SpringParameterInjectionJerseyTestConfig.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.parameterinjection;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
+
+public class SpringParameterInjectionJerseyTestConfig extends ResourceConfig {
+    public SpringParameterInjectionJerseyTestConfig() {
+        register(RequestContextFilter.class);
+        register(SpringParameterInjectionTestResource.class);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/parameterinjection/SpringParameterInjectionTest.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/parameterinjection/SpringParameterInjectionTest.java
new file mode 100644
index 0000000..35caa98
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/parameterinjection/SpringParameterInjectionTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.parameterinjection;
+
+import org.glassfish.jersey.server.spring.SpringTestConfiguration;
+import org.glassfish.jersey.server.spring.fieldinjection.SpringFieldInjectionJerseyTestConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import javax.ws.rs.core.Application;
+
+import static org.junit.Assert.assertEquals;
+
+public class SpringParameterInjectionTest extends JerseyTest {
+    @Override
+    protected Application configure() {
+        ApplicationContext context = new AnnotationConfigApplicationContext(SpringTestConfiguration.class);
+        return new SpringParameterInjectionJerseyTestConfig()
+                .property("contextConfig", context);
+    }
+
+    @Test
+    public void testInjectionOfSingleBean() {
+        String result = target("test1").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+
+    @Test
+    public void testInjectionOfListOfBeans() {
+        String result = target("test2").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+
+    @Test
+    public void testInjectionOfSetOfBeans() {
+        String result = target("test3").request().get(String.class);
+        assertEquals("test ok", result);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/parameterinjection/SpringParameterInjectionTestResource.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/parameterinjection/SpringParameterInjectionTestResource.java
new file mode 100644
index 0000000..aefb0d1
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/parameterinjection/SpringParameterInjectionTestResource.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.parameterinjection;
+
+import org.glassfish.jersey.server.spring.TestComponent1;
+import org.glassfish.jersey.server.spring.TestComponent2;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+@Path("/")
+public class SpringParameterInjectionTestResource {
+
+    private final TestComponent1 testComponent1;
+    private final List<TestComponent2> testComponent2List;
+    private final Set<TestComponent2> testComponent2Set;
+
+    @Autowired
+    public SpringParameterInjectionTestResource(final TestComponent1 testComponent1,
+                                                final List<TestComponent2> testComponent2List,
+                                                final Set<TestComponent2> testComponent2Set) {
+        this.testComponent1 = testComponent1;
+        this.testComponent2List = testComponent2List;
+        this.testComponent2Set = testComponent2Set;
+    }
+
+    @Path("test1")
+    @GET
+    public String test1() {
+        return testComponent1.result();
+    }
+
+    @Path("test2")
+    @GET
+    public String test2() {
+        return (testComponent2List.size() == 2 && "test ok".equals(testComponent2List.get(0).result())
+                && "test ok".equals(testComponent2List.get(1).result())) ? "test ok" : "test failed";
+    }
+
+    @Path("test3")
+    @GET
+    public String test3() {
+        Iterator<TestComponent2> iterator = testComponent2Set.iterator();
+        return (testComponent2Set.size() == 2 && "test ok".equals(iterator.next().result())
+                && "test ok".equals(iterator.next().result())) ? "test ok" : "test failed";
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/DefaultTestService.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/DefaultTestService.java
new file mode 100644
index 0000000..040d053
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/DefaultTestService.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.profiles;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public class DefaultTestService implements TestService {
+
+    @Override
+    public String test() {
+        return "default";
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/DevTestService.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/DevTestService.java
new file mode 100644
index 0000000..dc3c995
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/DevTestService.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.profiles;
+
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Component;
+
+@Component
+@Primary
+@Profile("dev")
+public class DevTestService implements TestService {
+
+    @Override
+    public String test() {
+        return "dev";
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringDefaultProfileResourceTest.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringDefaultProfileResourceTest.java
new file mode 100644
index 0000000..f390c5c
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringDefaultProfileResourceTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.profiles;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+public class SpringDefaultProfileResourceTest extends JerseyTest {
+
+    @Override
+    protected Application configure() {
+        System.setProperty("spring.profiles.active", "");
+        ApplicationContext context = new AnnotationConfigApplicationContext("org.glassfish.jersey.server.spring.profiles");
+        return new ResourceConfig()
+                .register(RequestContextFilter.class)
+                .register(LoggingFeature.class)
+                .packages("org.glassfish.jersey.server.spring.profiles")
+                .property("contextConfig", context);
+    }
+
+    @Test
+    public void shouldUseDefaultComponent() {
+        final String result = target("spring-resource").request().get(String.class);
+        Assert.assertEquals("default", result);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringDevProfileResourceTest.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringDevProfileResourceTest.java
new file mode 100644
index 0000000..6c8450c
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringDevProfileResourceTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.profiles;
+
+import javax.ws.rs.core.Application;
+
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
+import org.glassfish.jersey.test.JerseyTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+public class SpringDevProfileResourceTest extends JerseyTest {
+
+    @Override
+    protected Application configure() {
+        System.setProperty("spring.profiles.active", "dev");
+        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
+                "org.glassfish.jersey.server.spring.profiles");
+        return new ResourceConfig()
+                .register(RequestContextFilter.class)
+                .register(LoggingFeature.class)
+                .packages("org.glassfish.jersey.server.spring.profiles")
+                .property("contextConfig", context);
+    }
+
+    @Test
+    public void shouldUseDevProfileBean() {
+        final String result = target("spring-resource").request().get(String.class);
+        Assert.assertEquals("dev", result);
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringProfilesTest.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringProfilesTest.java
new file mode 100644
index 0000000..8bccbe3
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringProfilesTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.profiles;
+
+import org.junit.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import static org.junit.Assert.assertEquals;
+
+public class SpringProfilesTest {
+
+    @Test
+    public void shouldGetDefaultBean() {
+        System.setProperty("spring.profiles.active", "");
+        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
+                "org.glassfish.jersey.server.spring.profiles");
+        assertEquals("default", context.getBean(TestService.class).test());
+    }
+
+    @Test
+    public void shouldGetDevProfileBean() {
+        System.setProperty("spring.profiles.active", "dev");
+        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
+                "org.glassfish.jersey.server.spring.profiles");
+        assertEquals("dev", context.getBean(TestService.class).test());
+    }
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringRequestResource.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringRequestResource.java
new file mode 100644
index 0000000..11f8bf7
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/SpringRequestResource.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.profiles;
+
+import javax.inject.Singleton;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+
+@Singleton
+@Path("spring-resource")
+@Service
+public class SpringRequestResource {
+
+    @Autowired
+    private TestService testService;
+
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String getGoodbye() {
+        return testService.test();
+    }
+
+}
diff --git a/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/TestService.java b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/TestService.java
new file mode 100644
index 0000000..045d3e2
--- /dev/null
+++ b/ext/spring4/src/test/java/org/glassfish/jersey/server/spring/profiles/TestService.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014, 2018 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.server.spring.profiles;
+
+public interface TestService {
+
+    String test();
+}
diff --git a/ext/spring4/src/test/resources/jersey-spring-aspect4j-applicationContext.xml b/ext/spring4/src/test/resources/jersey-spring-aspect4j-applicationContext.xml
new file mode 100644
index 0000000..c80c155
--- /dev/null
+++ b/ext/spring4/src/test/resources/jersey-spring-aspect4j-applicationContext.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (c) 2013, 2018 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
+
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+    http://www.springframework.org/schema/aop
+    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+    <aop:aspectj-autoproxy/>
+
+    <context:component-scan base-package="org.glassfish.jersey.server.spring"/>
+
+    <bean id="someAspect" class="org.glassfish.jersey.server.spring.aspect4j.TestAspect"/>
+</beans>