IllegalArgumentException with Spring AOP - spring

This problem was first reported as Spring issue #24248.
I'm building an application with Spring AOP and I'm using aspects to modify some of my business objects. When I'm starting my application I get the following stacktrace (only the root is shown):
java.lang.IllegalArgumentException: methods with same signature get() but incompatible return types: [interface main.DomainObjectInterfaceA, interface main.DomainObjectInterfaceB]
at sun.misc.ProxyGenerator.checkReturnTypes(ProxyGenerator.java:712)
at sun.misc.ProxyGenerator.generateClassFile(ProxyGenerator.java:461)
at sun.misc.ProxyGenerator.generateProxyClass(ProxyGenerator.java:339)
at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:639)
at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:557)
at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:230)
at java.lang.reflect.WeakCache.get(WeakCache.java:127)
at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:419)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:719)
at org.springframework.aop.framework.JdkDynamicAopProxy.getProxy(JdkDynamicAopProxy.java:123)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:473)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:355)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:304)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:439)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1712)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:581)
... 10 more
I extracted this in a minimal code snippet from my application to reproduce this stacktrace.
Remark by kriegaex: I created an MCVE and pushed it to a GitHub repo.
My domain model consists of three classes:
package main;
public interface DomainObjectInterfaceA {
}
package main;
public interface DomainObjectInterfaceB{
}
package main;
public class DomainObjectImplementation implements DomainObjectInterfaceA, DomainObjectInterfaceB {
private int fieldToModifyThroughAspect = 0;
public int getFieldToModifyThroughAspect() {
return fieldToModifyThroughAspect;
}
public void setFieldToModifyThroughAspect( int aFieldToModify ) {
fieldToModifyThroughAspect = aFieldToModify;
}
}
Furthermore I have the following two Spring components:
package main;
#Component
public class ComponentImplementation implements ComponentInterfaceA<DomainObjectImplementation>, ComponentInterfaceB<DomainObjectImplementation> {
public DomainObjectImplementation get() {
return new DomainObjectImplementation();
}
}
package main;
#org.aspectj.lang.annotation.Aspect
#Component
public class Aspect {
#Pointcut( "execution(public DomainObjectImplementation main.ComponentImplementation.*(..))" )
public void anyPublicOperation() {
}
#AfterReturning( pointcut = "anyPublicOperation()", returning = "aObject" )
public Object get( Object aObject ) {
DomainObjectImplementation returningObject = ( DomainObjectImplementation ) aObject;
returningObject.setFieldToModifyThroughAspect( 5);
return returningObject;
}
}
The crucial part in reproducing the issue are the following two generic interfaces which are implemented by ComponentImplementation:
package main;
public interface ComponentInterfaceA<T extends DomainObjectInterfaceA> {
T get();
}
package main;
public interface ComponentInterfaceB<T extends DomainObjectInterfaceB> {
T get();
}
The above two interfaces share a method with the same signature, but a different generic type. ComponentImplementation implements those two interfaces with a class that satisfies both of those generic arguments.
The last two required classes are of course the Main class and the Spring Config class which are declared below:
package main;
#Configuration
#EnableAspectJAutoProxy
#ComponentScan( basePackageClasses = Config.class )
public class Config {
}
package main;
public class Main {
public static void main( String[] args ) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( Config.class );
ComponentImplementation bean = context.getBean( ComponentImplementation.class );
DomainObjectImplementation domainObject = bean.get();
System.err.println("Aspect modified get method = " + ( domainObject.getFieldToModifyThroughAspect() == 5));
}
}
I also tried to configure EnableAspectJAutoProxy with proxyTargetClass = true, but then the same exception is thrown with a slightly different stacktrace (namely the JDK proxy vs the Cglib)
The complete dependencies list:
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aspectj/aspectjrt -->
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.4</version>
</dependency>
</dependencies>

Related

Override Spring-Boot's GsonAutoConfiguration with custom Gson

Is there a way to override the GsonAutoConfiguration in spring-boot?
I would like to add some typeAdapter to the gson instance.
Preferably using java configurations
I've added the following to the application.properties.
spring.http.converters.preferred-json-mapper=gson
and the following class
#Configuration
#ConditionalOnClass(Gson.class)
public class GsonConfig {
#Bean
public Gson gson() {
return new GsonBuilder()
.registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter())
.setPrettyPrinting().create();
}
}
I am also using Jersey in the mix as well.
So I've also have the following code, which also didn't work.
InternalApplication.java
import com.google.gson.GsonBuilder;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import org.immutables.gson.stream.GsonMessageBodyProvider;
import org.immutables.gson.stream.GsonProviderOptionsBuilder;
import org.joda.time.DateTime;
public class InternalApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(TestResource.class);
return classes;
}
#Override
public Set<Object> getSingletons() {
final Set<Object> singletons = new HashSet<>();
singletons.add(new GsonMessageBodyProvider(
new GsonProviderOptionsBuilder()
.gson(new GsonBuilder()
.registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter())
.setPrettyPrinting()
.create())
.lenient(true)
.build()
)
);
return singletons;
}
}
Since when does Gson have anything to with Jersey in Spring Boot? It doesn't. What you really want to do is first disable Jackson (which is the default provider). Then you can register your GsonMessageBodyProvider.
Basically all you need to do is exclude the Jackson provider from your Maven/Gradle dependencies, as the Jersey starter pulls it in
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</exclusion>
</exclusions>
</dependency>
And I'm not quite sure why you are using an Application class, as Spring Boot doesn't support that for its auto-configuration. You should be using a ResourceConfig class
#Component
#ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(TestResource.class);
register(new GsonMessageBodyProvider(...));
}
}

Spring Boot Aspect Autowiring

I have created an annotation to invoke a Spring AOP Aspect in a spring boot project. All works fine until I try to autowire a dependency into the Aspect: the autowiring doesn't happen.
I have read in various questions in stackoverflow that this is because the Aspect is not Spring managed. Apologies if this has been answered previously, but I have I have tried various solutions mentioned in stackoverflow including using #Configurable and implementing ApplicationContextAware.
What is the simplest change to make to get this to work?
I have created a simple example to illustrate the problem: the test passes if the dependency is created directly:
/**
* Aspect applying the annotation {#link LogDuration} to where ever it has been added, see {#link #logDuration(ProceedingJoinPoint, LogDuration)}.
*/
#Configurable
#Aspect
public class LogDurationAspect {
private static final Logger LOGGER = LogManager.getLogger( LogDurationAspect.class );
#Autowired
private TimeMeasurer timeMeasurer;// = new TimeMeasurer();
public LogDurationAspect() {
}
/** For any method with #LogDuration, no matter what the return type, name, or arguments are, call this method to log how long it takes. */
#Around("#annotation(annotation)")
public Object logDuration( ProceedingJoinPoint joinPoint , LogDuration annotation ) throws Throwable {
System.out.println( timeMeasurer );
final long startTime = timeMeasurer.now();
try{
final Object result = joinPoint.proceed();
final long duration = timeMeasurer.timeSince( startTime );
LOGGER.info( String.format( "%s returned %s took %d ms %.3f s" , annotation.value() , result , duration , 0.001 * duration ) );
return result;
}
catch ( Throwable t){
final long duration = timeMeasurer.timeSince( startTime );
LOGGER.error( String.format( "%s took %d ms %.3f s" , annotation.value() , duration , 0.001 * duration ) , t);
throw t;
}
}
}
/**
* Simple annotation which will log the duration of a method via {#link LogDurationAspect#logDuration(org.aspectj.lang.ProceedingJoinPoint, LogDuration)}.
*/
#Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
public #interface LogDuration {
String value();
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = LogDurationAspectITests.TestConfiguration.class )
public class LogDurationAspectITests {
#Autowired
private TestListener underTest;
#Rule
public OutputCapture outputCapture = new OutputCapture();
#Autowired
private TimeMeasurer timeMeasurer;
#Test
public void annotationWorks() {
// prove that scanning is working
assertThat( timeMeasurer , is( notNullValue( ) ) );
underTest.doIt( 1234 );
assertThat( outputCapture.toString() , containsString ( "doIt 1 2 3 returned 2468 took") );
}
#SpringBootApplication
#Configuration
public static class TestConfiguration {
}
}
#Component
public class TimeMeasurer{
/** #return milliseconds between now and start.*/
public long timeSince( long start ) {
return now( ) - start;
}
/** #return current time in milliseconds. */
public long now( ) {
return System.currentTimeMillis( );
}
}
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
And how to debug the aspect?
Thanks
Added a bean to the configuration class that uses Aspects.aspectOf
#SpringBootApplication
#Configuration
public static class TestConfiguration {
/**
* This is needed to get hold of the instance of the aspect which is created outside of the spring container,
* and make it available for autowiring.
*/
#Bean
LogDurationAspect logDurationAspect()
{
final LogDurationAspect aspect = Aspects.aspectOf(LogDurationAspect.class);
return aspect;
}
}

Cucumber + TestNG + SpringBoot

The runner class:
#CucumberOptions(plugin = "json:target/cucumber-report.json")
#Test(groups = "slow")
public class RunCukesTest extends AbstractTestNGCucumberTests {
}
The step definitions class :
#ContextConfiguration(loader=SpringApplicationContextLoader.class, classes = {Application.class,MarketDataServiceMockConfig.class})
#WebIntegrationTest({"server.port=0", "management.port=0"})
#TestExecutionListeners(inheritListeners = false, listeners = {
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class })
public class MyStepdefs extends AbstractTestNGCucumberTests {
private MockMvc mockMvc;
#Autowired
private FilterChainProxy filterChainProxy;
#Autowired
private WebApplicationContext wac;
#Before
public void setUp() {
wac = (EmbeddedWebApplicationContext) SpringApplication.run(Application.class);
}
}
The filterChainProxy and wac are not autowired, why ?
Thanks for your help.
In order to use Cucumber and Spring Test with TestNG instead of JUnit, all you need to do is extend AbstractTestNGSpringContextTests in your Step Definition, the rest of the code remains the same.
Full Code:
pom.xml
<!-- TestNG -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
</dependency>
<!-- Cucumber with TestNG -->
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-testng</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Spring Test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- Cucumber with Spring -->
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-spring</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
Test Executor
#CucumberOptions(plugin = "json:target/cucumber-report.json")
#Test(groups = "slow")
public class RunCukesTest extends AbstractTestNGCucumberTests {
}
Step Definition
#ContextConfiguration(loader=SpringApplicationContextLoader.class, classes = {Application.class,MarketDataServiceMockConfig.class})
#WebIntegrationTest({"server.port=0", "management.port=0"})
#TestExecutionListeners(inheritListeners = false, listeners = {
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class })
// Notice that the class extends AbstractTestNGSpringContextTests now
public class MyStepdefs extends AbstractTestNGSpringContextTests {
private MockMvc mockMvc;
#Autowired
private FilterChainProxy filterChainProxy;
#Autowired
private WebApplicationContext wac;
#Before
public void setUp() {
wac = (EmbeddedWebApplicationContext) SpringApplication.run(Application.class);
}
}
Cucumber and TestNG are both test frameworks. Cucumber is tool for BDD testing, TestNG is for unit/integration testing. I don't think it makes sense trying to integrate Cucumber with TestNG. It's like integrating JUnit with TestNG.
So if you want to execute Cucumber tests with Spring, there is module cucumber-spring.
You will have something like main Tests executor:
import org.junit.runner.RunWith;
import cucumber.junit.Cucumber;
#RunWith(Cucumber.class)
#CucumberOptions(format={"pretty", "html:target/cucumber"})
public class RunTests {
}
And you will define your steps in classes where you define your Spring context:
#ContextConfiguration(YourContext.class)
public class StepDefinitions {
#Autowired
private YourBean yourBean;
#Given("^your given line$")
public void givenLine() {
//...
}
#When("^your when line$")
public void whenLine() {
//...
}
#Then("^your then assertions$")
public void thenAssertions() {
//...
}
}
After running main class RunTests, it will try to find Gherkin files and match them with steps. Doesn't matter how are steps structured across your Java classes.
But I must warn you, Cucumber was designed in Ruby first, so some concepts may seem very weird to Java programmer. Sharing state between steps needs to be done via some class level variable. No duplicate steps are allowed. If you need to share state between steps defined in two different classes, you need to use some global objects.

Cannot run powermockrule with SpringJUnit4ClassRunner in spring boot project

I have a spring boot project that needs to test with spring test runner(so that I can get the real application context) and mock the static method.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes= MyApplication.class)
#PrepareForTest(StaticClass.class)
public class StaticClassTest {
#Rule
public PowerMockRule rule = new PowerMockRule();
#Autowired
HelloCmd hello;
#Test
public void testGetOne() {
mockStatic(StaticClass.class);
when(StaticClass.getNumber()).thenReturn(2);
System.out.println(hello.getNumber());
}
}
And I got following error message when run the test:
com.thoughtworks.xstream.converters.ConversionException: hello.hystrix.commands.HelloCmd$$EnhancerBySpringCGLIB$$a27be1be : hello.hystrix.commands.HelloCmd$$EnhancerBySpringCGLIB$$a27be1be
---- Debugging information ----
message : hello.hystrix.commands.HelloCmd$$EnhancerBySpringCGLIB$$a27be1be
cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
cause-message : hello.hystrix.commands.HelloCmd$$EnhancerBySpringCGLIB$$a27be1be
class : hello.hystrix.commands.StaticClassTest
required-type : hello.hystrix.commands.StaticClassTest
converter-type : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
path : /org.powermock.modules.junit4.rule.PowerMockStatement$1/outer-class/fNext/next/next/target/hello
line number : 15
class[1] : org.junit.internal.runners.statements.InvokeMethod
class[2] : org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks
class[3] : org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks
class[4] : org.powermock.modules.junit4.rule.PowerMockStatement
class[5] : org.powermock.modules.junit4.rule.PowerMockStatement$1
version : null
How to fix this? Thanks!
I found a fix from here link
to use PowerMockRunnerDelegate instead of PowerMockRule.
The updated test class would be:
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes= MyApplication.class)
#PrepareForTest(StaticClass.class)
public class StaticClassTest {
#Autowired
HelloCmd hello;
#Test
public void testGetOne() {
mockStatic(StaticClass.class);
when(StaticClass.getNumber()).thenReturn(2);
System.out.println(hello.getNumber());
}
}
Spring, camel & powermock unittest:
I had also same problem with PowerMockRule. I replaced it with following annotations
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
.
Also remove dependencies powermock-module-junit4-rule & powermock-classloading-xstream from Pom.xml and it works.
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { StaticClassTest.ContextConfig.class })
#PrepareForTest({ StaticClass.class })
#PowerMockIgnore("javax.management.*")
public class StaticClassTest extends DroolsHelper {
#Before
public void setup() {
PowerMockito.mockStatic(StaticClass.class);
}
#Produce(uri = "direct:start")
private ProducerTemplate template;
/**
*
* ContextConfig.
*/
#Configuration
#Import(AppConfig.class)
public static class ContextConfig extends SingleRouteCamelConfiguration
{
#Bean
#Override
public RouteBuilder route() {
return new RouteBuilder() {
#Override
public void configure() {
from("direct:start").to("kie:kieSessionType?action=insertBody");
}
};
}
}
#Test
public void test() {
PowerMockito.when(StaticClass.anyMethod(Matchers.any(TestClass.class)).thenReturn(false);
......assert.........
}
}
Use of PowerMockRule had been advised for a situation, when
To derive code coverage using Eclemma along with the use of PowerMockito API
It is a known bug that "Usage of PowerMockito along with Eclmemma gives 0% Coverage" because of ByteCode Manipulation Issues.
Thus,
use
#RunWith(PowerMockRunner.class) and
#PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
when Code Coverage is not the primary concern during JUnit Development. But that shouldn't be the case.
I needed to derive Code Coverage infromation for the Test cases defined for
Methods of type static, private, final
Classes with Access Modifier static, private, final
To declare Test Class inside #PrepareForTest
Hence I had to use PowermockRule.
I had to remove those previously mentioned annotations.
But somehow, usage of PowerMockRule is not working for me.
I added below mentioned artifacts
<!-- powermock-module-junit4-rule -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4-rule</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
<!-- powermock-classloading-xstream -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-classloading-xstream</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
<!-- powermock-classloading-base -->
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-classloading-base</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
Online advises also include "Bootstrapping using a Java agent"
Advise.

Making Aspectj work on a Spring servlet bean

I am trying to get an aspectprofiler working on a Jersey servlet registered in a spring project. The aspectprofiler is loaded, but don't notice when methods within the Jersey servlet are run.
#EnableAutoConfiguration
#Configuration
#EnableAspectJAutoProxy(proxyTargetClass = true)
public class App {
public static void main(final String[] args) {
final SpringApplicationBuilder sab = new SpringApplicationBuilder(ConsolidatedCustomerMasterApp.class);
sab.run(args);
}
#Bean
public ServletRegistrationBean jerseyServlet() {
final ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), "/*");
registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyInitialization.class.getName());
return registration;
}
#Bean
public AspectProfiler profiler() {
return new AspectProfiler();
}
}
...
public class JerseyInitialization extends ResourceConfig {
public JerseyInitialization() {
packages("com.example.package");
}
...
package com.example.package;
//imports
#Path("/test")
public class RestService {
#GET
#Path("test")
#Produces(MediaType.TEXT_PLAIN)
public String test() {
return "Something";
}
}
...
#Aspect
public class AspectProfiler {
private static final DefaultApplicationProfiler PROFILER = new DefaultApplicationProfiler(
Arrays.<ProfilerOperator> asList(
new StatsdProfilerOperator(),
new LoggingProfilerOperator())
);
private static final String REST_MATCHER =
"execution(* com.example.package..*.*(..))";
#Around(REST_MATCHER)
public Object around(final ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("test");
return PROFILER.around(joinPoint);
}
}
On top of making the Jersey resource classes Spring #Components (and #ComponentScaning for them), you also need to make the ResourceConfig a Spring #Component also. You can see in the Spring Boot JerseyAutoConfigurer that it autowires the ResourceConfig, which it uses for the ServletContainer registration.
One thing to also note is that it creates its own ServletRegistrationBean
public ServletRegistrationBean jerseyServletRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(
new ServletContainer(this.config), this.path);
addInitParameters(registration);
registration.setName("jerseyServlet");
return registration;
}
When you declare your own, you are overriding this one. You are not adding any special functionality that is not already provided, so just leave the default. Any Jersey specific configurations can be added in the application.properties file or through code configurations.
As for dependencies, I'll just assume you have all the right dependencies. The following are what I used to test
<!-- all 1.2.7.RELEASE -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
See Also:
spring-boot-sample-jersey - from project samples
ยง26.2 JAX-RS and Jersey - from Spring Boot docs

Resources