Hot questions for Spring Boot Jersey

Top 10 Java Open Source / Spring / Spring Boot Jersey

Question:

I am trying to setup a spring boot app with Jersey. The Rest API is working fine however the view (jsp) is getting rendered as is as plain text on browser. I tried including jstl in my dependencies , once I include it ; server starts returning blank response.

Please let me know what am I missing here .

Code Structure:

Below is my code:

JerseyConfig.java

package com.example.jersey.configuration;

import javax.ws.rs.ApplicationPath;

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.mvc.jsp.JspMvcFeature;
import org.springframework.stereotype.Component;

import com.example.jersey.controller.HelloController;
import com.example.jersey.controller.HelloJSPController;

@Component
@ApplicationPath("/jersey")
public class JerseyConfig extends ResourceConfig
{
    public JerseyConfig()
    {
        property(JspMvcFeature.TEMPLATE_BASE_PATH, "/WEB-INF/jsp");
        register(JspMvcFeature.class);
        register(HelloController.class);
        register(HelloJSPController.class);

    }
}

HelloController.java

package com.example.jersey.controller;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.springframework.stereotype.Component;

@Component
@Path("/hello")
public class HelloController {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "Hello Jersey with Spring boot";
    }
}

HelloJSPController

package com.example.jersey.controller;

import javax.inject.Singleton;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.server.mvc.Viewable;
import org.springframework.stereotype.Component;

@Component
@Singleton
@Path("/helloJSP")
public class HelloJSPController {

    @GET
    @Produces(MediaType.TEXT_HTML)
    public Viewable getIt(@Context final ServletContext context) {

        return new Viewable("/index");
    }
}

SpringJerseyApplication.java

package com.example.jersey;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringJerseyApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringJerseyApplication.class, args);
    }
}

application.properties

spring.jersey.servlet.load-on-startup=1
spring.jersey.type=filter
logging.level.root=INFO

index.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  <html>

  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Hello Jsp .</title>
  </head>

  <body>
    Hello JSP
  </body>

  </html>

Answer:

Changing the spring boot version to 1.5.12 makes the JSP working for me. Something is probably broken with spring boot 2.0.1 Below is the pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <groupId>com.example</groupId>
    <artifactId>spring-jersey</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-jersey</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jersey</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-mvc-jsp</artifactId>
            <version>2.25.1</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

Question:

I have a problem with Jersey 2.26 and Spring Boot 2.

I added a factory to inject @Context variable into methods, but it does it twice, first before the method and then again after the method:

@GET
@Path("/user-entitlements")
public Set<String> getUserEntitlements(@Context User user) {
    return service.getUserEntitlements(user);
}

I have a factory that creates those users:

public class UserFactory implements Factory<User> {

    private final User user;

    @Inject
    public UserFactory(HttpServletRequest request, RequestIdentityService requestIdentityService) {
        String userName = requestIdentityService.getCurrentUser(request);
        user = new User(userName);
    }

    @Override
    public User provide() {
        return user;
    }

    @Override
    public void dispose(User instance) {
    }
}

And in jersey configuration I register this factory:

    register(
        new AbstractBinder() {
            @Override
            public void configure() {
                bindFactory(UserFactory.class)
                    .to(User.class)
                    .in(RequestScoped.class);
            }
        }
    );

It worked fine previously, but after I upgraded the application to jersey 2.26 and spring boot 2, it stopped working and throws exception:

java.lang.IllegalStateException: Proxiable context org.glassfish.jersey.inject.hk2.RequestContext@3a94c454 findOrCreate returned a null for descriptor SystemDescriptor(
    implementation=org.glassfish.jersey.inject.hk2.SupplierFactoryBridge
    contracts={javax.servlet.http.HttpServletRequest}
    scope=org.glassfish.jersey.process.internal.RequestScoped
    qualifiers={}
    descriptorType=PROVIDE_METHOD
    descriptorVisibility=NORMAL
    metadata=
    rank=0
    loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2@464366a8
    proxiable=true
    proxyForSameScope=false
    analysisName=null
    id=20
    locatorId=0
    identityHashCode=1360647282
    reified=true) and handle ServiceHandle(SystemDescriptor(
    implementation=com.rest.UserFactory
    contracts={org.glassfish.hk2.api.Factory}
    scope=org.glassfish.hk2.api.PerLookup
    qualifiers={}
    descriptorType=CLASS
    descriptorVisibility=NORMAL
    metadata=
    rank=0
    loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2@33335025
    proxiable=null
    proxyForSameScope=null
    analysisName=null
    id=172
    locatorId=0
    identityHashCode=790201459
    reified=true),1915928862)

The exception shows up because UserFactory is called twice. First it is called before the getUserEntitlements is called, to inject the User. But after the method returns, it is called again (and this time it gets a HttpRequest implementation that doesn't allow some operations).

Why it could be called twice? As if I would asked it to enchance both the request and response.


Answer:

The problem is that in new Jersey they moved away from hk2 into an abstraction layer above it, and made the code Java 8 aware (because it is an implementation of Java EE 8 - https://jersey.github.io/release-notes/2.26.html).

So to fix it I had to:

  1. Import the correct AbstractBinder - org.glassfish.jersey.internal.inject.AbstractBinder(NOT the previous one from HK2 - org.glassfish.hk2.utilities.binding.AbstractBinder).

  2. Update the factory to implement Supplier<User> instead of Factory<User>.

After that changes everything works as previously, factory is called only once.

Question:

I am getting 403 Forbidden from rest api which is using Spring Security's JDBC Authentication.

I have written simple restful api using Jersey with Spring boot and tried to implement Spring Security with inMemoryAuthentication() method and that works fine. But when i switch to jdbcAuthentication() method, I get 403 forbidden as i hit service with valid credentials from postman. I don't get where i did wrong.

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    DataSource dataSource; 

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http.csrf().disable()
        .httpBasic()
        .and()
        .authorizeRequests()
        .antMatchers("/jersey/**").hasRole("USER")
        .antMatchers("/console/**").permitAll()
        .and()
        .headers().frameOptions().disable();
        //.anyRequest().permitAll();
    }
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        auth.jdbcAuthentication().dataSource(dataSource)
        .authoritiesByUsernameQuery("select USERNAME, ROLE from EMPLOYEE where USERNAME=?")
        .usersByUsernameQuery("select USERNAME, PASSWORD , 1 as enabled from EMPLOYEE where USERNAME=?");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

data.sql

INSERT INTO EMPLOYEE VALUES ('lalit','$2a$10$TV//Fu/4UwMTIqnPbkahqeMNjrrF1YQT1MdEwNDvaHurH5wR7ZLnm','USER');

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jersey</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>

UPDATE

error log:

2019-05-24 19:46:21.703 DEBUG 11724 --- [nio-8088-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@f9c70a69: Principal: org.springframework.security.core.userdetails.User@61fa502: Username: lalit; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: USER
2019-05-24 19:46:21.706 DEBUG 11724 --- [nio-8088-exec-2] o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@4a78101b, returned: -1
2019-05-24 19:46:21.713 DEBUG 11724 --- [nio-8088-exec-2] o.s.s.w.a.ExceptionTranslationFilter     : Access is denied (user is not anonymous); delegating to AccessDeniedHandler

org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
...

This is what i get when I hit service along with valid credentials.

HTTP Status 403 – Forbidden


Answer:

You are getting 403 Forbidden because Spring Security might have found a different role in the DB than the role "ROLE_USER", while accessing any mapping having /jersey/.

Also have a look at the configuration below. It's probably the password encoder than needs to be added.

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

    auth.jdbcAuthentication()
            .dataSource(dataSource)
            .passwordEncoder(passwordEncoder())
            .authoritiesByUsernameQuery("select USERNAME, ROLE from EMPLOYEE where USERNAME=?")
            .usersByUsernameQuery("select USERNAME, PASSWORD , 1 as enabled from EMPLOYEE where USERNAME=?");
}

UPDATE

Save the role in DB as "ROLE_USER" instead of "USER"

As your error log says that the credentials are previously authenticated, you need to remove cookies of your browser before trying to login again, or just open a new incognito tab.

Question:

I want to retrieve the pdf (Stored as BLOB) from Database using jersey api I am using mybatis as data base framework . I am able to download the pdf but the problem is i get the input stream as database to which i save it as file and then pass that it in Response but i don't want to save that file in server , i want file directly to be downloaded to user .

Current Process :

DATABASE-------> input stream-----> File -----------> add to response ----->user downloads it

         retrieving        making file  passing file          user downloads

What i want :

DATABASE---------->input stream------------> add to response -------> user downloads it

         retrieving         passing file              user downloads

I want remove File making in server as data is confidential

Resource interface

@GET
@Path("v1/download/{id}")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile(@PathParam("id") int id) throws IOException, SQLException;

Resource Impl

@Override
public Response downloadFile(int id) throws IOException, SQLException {
    // TODO Auto-generated method stub
    File file = fileUploadService.downloadFile(id);

    ResponseBuilder response = Response.ok(file);
    response.header("Content-Disposition", "attachment;filename=aman.pdf");
    return response.build();
}

Service method

@Override
public File downloadFile(int id) throws IOException {
    // TODO Auto-generated method stub
    File fil=new File("src/main/resources/Sample.pdf");
    FileUploadModel fm =mapper.downloadFile(id);
    InputStream inputStream = fm.getDaFile();
    outputStream = new FileOutputStream(fil);
    int read = 0;
    byte[] bytes = new byte[102400000];

    while ((read = inputStream.read(bytes)) != -1) {
        outputStream.write(bytes, 0, read);
    }
    return fil;
}

This code is working but i want to remove making of file on server side i.e i want to remove File fil=new File("src/main/resources/Sample.pdf"), this operation which is in service method .

Thanks in advance.


Answer:

Instead of using File, use ByteArrayOutputStream and write to it. Then return the result as a byte[] which you can pass to your Response.ok(content).

Didn't test this, but something like this:

public byte[] downloadFile(int id) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    FileUploadModel fm =mapper.downloadFile(id);
    InputStream inputStream = fm.getDaFile();
    int read = 0;
    byte[] bytes = new byte[1024];

    while ((read = inputStream.read(bytes)) != -1) {
        out.write(bytes, 0, read);
    }
    return out.toByteArray();
}

Also, that's a lot of bytes to allocate to an array. You can experiment with what works for you, but something like 1024 would likely be totally sufficient.

You'll probably also want to add another header to your response for Content-Type.

Question:

I have a resource in my Jersey REST api that has a private instance variable:

@Path("test")
public class TestResource implements ServletContextListener
{
    private String someString;

    @GET
    public void test()
    {
        System.out.println("someString " + someString);
    }

    @Override
    public void contextDestroyed(ServletContextEvent ctxt) {
        System.out.println("Destroying context");
    }

    @Override
    public void contextInitialized(ServletContextEvent ctxt) {
        System.out.println("TestResource initialized!");

        someString = "SET";
        System.out.println("someString has been set. someString: " + someString);
    }
}

On server startup/restart the instance variable someString is initialized during contextInitialized() and is correctly printed out. However when I set a GET request to http://localhost:8080/myapp/api/test (i.e. invoke the test() method above) the variable someString is null.

How can I prevent that?


Answer:

From the JAX-RS specification:

By default a new resource class instance is created for each request to that resource.

So, any state you set on your resource class instance is meaningless, since the instance is never used again. If you want to persist a value, place it in the ServletContext’s attributes:

// All classes in the web app share a ServletContext, so attribute names
// need to start with package names to prevent collisions.
private static final String SOME_ATTRIBUTE = TestResource.class.getName() + ".someAttribute";

@Override
public void contextInitialized(ServletContextEvent ctxt) {
    System.out.println("TestResource initialized!");

    String someString = "SET";
    System.out.println("someString has been set. someString: " + someString);

    ctxt.getServletContext().setAttribute(SOME_ATTRIBUTE, someString);
}

@GET
public void test(@Context ServletContext context) {
    System.out.println("someString " + context.getAttribute(SOME_ATTRIBUTE));
}

Storing values in static fields will require you to implement thread safety and will not work in a distributed production environment.

Question:

I am trying to write some integration tests for an application that uses Jersey with some Spring DI. Tests always come back as a 500 with no real explaination. Grizzly appears to start ok and boots up my hibernate connections just fine. Here is the error trace along with all of relevant files sans the class under test. I think it may be an issue with Grizzly and the configuration but I cant find anything that seems to work including switching to a webappcontext.

javax.ws.rs.InternalServerErrorException: HTTP 500 Request failed.
    at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1032)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:819)
    at org.glassfish.jersey.client.JerseyInvocation.access$700(JerseyInvocation.java:92)
    at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:701)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:697)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:420)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:316)
    at com.heapo.test.intergration.resources.UserResourceTest.test_getUser(UserResourceTest.java:25)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Test Class

package com.sample.test.intergration.resources;

import static org.junit.Assert.assertEquals;

import javax.ws.rs.core.Application;

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.sample.models.User;
import com.sample.rest.config.SampleApplication;
import com.sample.spring.config.SpringSecurityConfig;


public class UserResourceTest extends JerseyTest {

    @Test
    public void test_getUser() {
        final User hello = target("user/1")
                                .request()
                                .header("Authorization", "BEARER xxx")
                            .get(User.class);
   }

   @Override
   protected Application configure() {
       enable(TestProperties.LOG_TRAFFIC);
       enable(TestProperties.DUMP_ENTITY);

        ResourceConfig rc = new ProgramProApplication();
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringSecurityConfig.class);
        rc.property("contextConfig", ctx);

        return rc;
    }
}

Web.xml - works - Application runs fine under Tomcat and I can access the entire API via postman.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <display-name>Sample API</display-name>
    <servlet>
        <servlet-name>Sample API</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
             <param-name>javax.ws.rs.Application</param-name>
             <param-value>com.sample.rest.config.SampleApplication</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
        </init-param>        
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Sample API</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.sample.spring.config.SpringSecurityConfig</param-value>
    </context-param>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

Pom.xml

<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/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>sample-api</groupId>
      <artifactId>sample-api</artifactId>
      <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>sample-api Maven Webapp</name>
  <url>http://maven.apache.org</url>
    <properties>
        <jersey.version>2.23.2</jersey.version>
        <jersey.scope>compile</jersey.scope>
        <spring.version>4.1.0.RELEASE</spring.version>
        <hibernate.version>5.2.2.Final</hibernate.version>
        <mysql.version>5.1.37</mysql.version>
    </properties>
    <dependencies>
        <!-- Jersey core Servlet 2.x implementation -->
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>${jersey.version}</version>
            <scope>${jersey.scope}</scope>
        </dependency>

        <!-- Jersey JSON Jackson (2.x) entity providers support module -->
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>${jersey.version}</version>
            <scope>${jersey.scope}</scope>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-multipart</artifactId>
            <version>${jersey.version}</version>
            <scope>${jersey.scope}</scope>
        </dependency>

        <!-- Jersey extension module providing support for Spring 3 integration -->
        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-spring3</artifactId>
            <version>${jersey.version}</version>
            <scope>${jersey.scope}</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.glassfish.hk2.external</groupId>
                    <artifactId>bean-validator</artifactId>
                </exclusion>            
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Spring Framework-4.x -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- Hibernate Core 4.2.x -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.4.Final</version>      
        </dependency>

        <!-- MySql-Connector -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <!-- Hibernate c3p0 connection pool -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.4</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.5.0-b01</version>
        </dependency>       
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.5</version>
        </dependency>   

        <!-- TEST DEPENDENCIES -->
        <!-- Dependency for JUnit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!-- Dependency for Mockito -->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.10.19</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.test-framework</groupId>
            <artifactId>jersey-test-framework-core</artifactId>
            <version>${jersey.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.test-framework.providers</groupId>
            <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
            <version>${jersey.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-grizzly2-http</artifactId>
            <version>${jersey.version}</version>
            <scope>test</scope>         
        </dependency>
    </dependencies>
  <build>
    <finalName>sample-api</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>    
  </build>
</project>

Answer:

After several days of trial and error with almost no documentation and piecing together from other examples there were out of date, this is what finally worked for me. Hopefully it will help somebody else.

Test Class

package com.sample.test.intergration.resources;

import static org.junit.Assert.assertEquals;

import javax.ws.rs.core.Application;

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.sample.models.User;
import com.sample.rest.config.SampleApplication;
import com.sample.spring.config.SpringSecurityConfig;


public class UserResourceTest extends JerseyTest {

    @Test
    public void test_getUser() {
        final User hello = target("user/1")
                            .request()
                            .header("Authorization", "BEARER xxx")
                            .get(User.class);
   }

    @Override
    protected DeploymentContext configureDeployment() {
        return ServletDeploymentContext
                .forServlet(new ServletContainer(configureRC()))
                .addListener(ContextLoaderListener.class)
                .contextParam(ContextLoader.CONFIG_LOCATION_PARAM, SpringSecurityConfig.class.getPackage().getName())
                .contextParam(ContextLoader.CONTEXT_CLASS_PARAM, AnnotationConfigWebApplicationContext.class.getName())
                .addFilter(DelegatingFilterProxy.class, "springSecurityFilterChain")
                .build();       
    }   

    @Override
    protected TestContainerFactory getTestContainerFactory() {
        return new GrizzlyWebTestContainerFactory();
    }       
}