Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullPointerException when extending controller classes with multiple parameterized types #953

Closed
woemler opened this issue Sep 8, 2015 · 8 comments
Labels
Milestone

Comments

@woemler
Copy link

woemler commented Sep 8, 2015

I have an abstract base controller class that is parameterized in much the same way as Spring Data PagingAndSortingRepository, with multiple subclasses that extend it. I have noticed when running unit tests that if SpringFox attempts to document a controller class with more than one parametrized type will always result in a NullPointerException, regardless of whether the second parameterized type is even used in the class:

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:94)
    at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:170)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:110)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:200)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:259)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:261)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:219)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.NullPointerException
    at springfox.documentation.schema.WildcardType.wildcardMatch(WildcardType.java:60)
    at springfox.documentation.schema.AlternateTypeRule.appliesTo(AlternateTypeRule.java:65)
    at springfox.documentation.spi.schema.AlternateTypeProvider$1.apply(AlternateTypeProvider.java:57)
    at springfox.documentation.spi.schema.AlternateTypeProvider$1.apply(AlternateTypeProvider.java:54)
    at com.google.common.collect.Iterators$7.computeNext(Iterators.java:647)
    at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143)
    at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138)
    at com.google.common.collect.Iterators.tryFind(Iterators.java:747)
    at com.google.common.collect.Iterables.tryFind(Iterables.java:675)
    at com.google.common.collect.FluentIterable.firstMatch(FluentIterable.java:197)
    at springfox.documentation.spi.schema.AlternateTypeProvider.alternateFor(AlternateTypeProvider.java:41)
    at springfox.documentation.spi.service.contexts.RequestMappingContext.alternateFor(RequestMappingContext.java:118)
    at springfox.documentation.spring.web.readers.operation.OperationModelsProvider.collectFromReturnType(OperationModelsProvider.java:70)
    at springfox.documentation.spring.web.readers.operation.OperationModelsProvider.apply(OperationModelsProvider.java:59)
    at springfox.documentation.spring.web.plugins.DocumentationPluginsManager.modelContexts(DocumentationPluginsManager.java:129)
    at springfox.documentation.spring.web.scanners.ApiModelReader.read(ApiModelReader.java:62)
    at springfox.documentation.spring.web.scanners.ApiListingScanner.scan(ApiListingScanner.java:91)
    at springfox.documentation.spring.web.scanners.ApiDocumentationScanner.scan(ApiDocumentationScanner.java:67)
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.scanDocumentation(DocumentationPluginsBootstrapper.java:102)
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.onApplicationEvent(DocumentationPluginsBootstrapper.java:88)
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.onApplicationEvent(DocumentationPluginsBootstrapper.java:51)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:151)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:773)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:483)
    at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:133)
    at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:60)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68)
    at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86)
    ... 28 more

The exception will occur, regardless of the types used. Replacing the parameterization with concrete types will make this error go away.

@dilipkrish
Copy link
Member

Hmm might be a bug :) thanks for reporting. I'll take a look

@woemler
Copy link
Author

woemler commented Dec 11, 2015

It looks like this issue still persists in Springfox 2.3.0. Did the fix for this not get included in the new release? To illustrate, creating an abstract controller defined as MyController<T> and then extending it will work just fine, but if the controller is defined as MyController<T, ID>, the above error gets thrown during initialization.

@dilipkrish
Copy link
Member

May not have been fixed completely? need to investigate

@dilipkrish
Copy link
Member

@woemler It seems to work as expected. Closing this issue with a proving test

@woemler
Copy link
Author

woemler commented Dec 29, 2015

@dilipkrish: Thanks, I'll take a look.

@dilipkrish dilipkrish modified the milestones: 2.4.0, 2.3.1 Jan 4, 2016
@elennick
Copy link

@dilipkrish fyi i ran into this exact same exception using 2.3.1... I am also using an abstract base class that has multiple generic parameters like so:

public class BaseController<T extends ResourceSupport, E extends BaseModel> {

I had a method like so:

    @ApiOperation(value = "Delete a resource", notes = "Deletes an existing resource.")
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public HttpEntity deleteResource(@ApiParam(value = "UUID", required = true) @PathVariable UUID id) {
        //some code
        return new ResponseEntity(NO_CONTENT);
    }

The above code generated the same or similar exception as to what was posted above. I was able to fix the issue by more strictly typing the return value like so:

    @ApiOperation(value = "Delete a resource", notes = "Deletes an existing resource.")
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public HttpEntity<T> deleteResource(@ApiParam(value = "UUID", required = true) @PathVariable UUID id) {
        //some code
        return new ResponseEntity<>(NO_CONTENT);
    }

Anyhow, I wanted to post this here before making a new issue for it to make sure this was actually different issue. Here is the exact trace I was encountering before fixing it:

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:183)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:123)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:230)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:249)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
    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.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at org.testng.junit.JUnit4TestRunner.start(JUnit4TestRunner.java:81)
    at org.testng.junit.JUnit4TestRunner.run(JUnit4TestRunner.java:69)
    at org.testng.TestRunner$1.run(TestRunner.java:697)
    at org.testng.TestRunner.runJUnitWorkers(TestRunner.java:1004)
    at org.testng.TestRunner.privateRunJUnit(TestRunner.java:728)
    at org.testng.TestRunner.run(TestRunner.java:629)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)
    at org.testng.SuiteRunner.run(SuiteRunner.java:268)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1244)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1169)
    at org.testng.TestNG.run(TestNG.java:1064)
    at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:115)
    at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:212)
    at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:108)
    at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:111)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
Caused by: java.lang.NullPointerException: null
    at springfox.documentation.schema.WildcardType.wildcardMatch(WildcardType.java:59)
    at springfox.documentation.schema.AlternateTypeRule.appliesTo(AlternateTypeRule.java:66)
    at springfox.documentation.spi.schema.AlternateTypeProvider$1.apply(AlternateTypeProvider.java:57)
    at springfox.documentation.spi.schema.AlternateTypeProvider$1.apply(AlternateTypeProvider.java:54)
    at com.google.common.collect.Iterators$7.computeNext(Iterators.java:652)
    at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143)
    at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138)
    at com.google.common.collect.Iterators.tryFind(Iterators.java:752)
    at com.google.common.collect.Iterables.tryFind(Iterables.java:675)
    at com.google.common.collect.FluentIterable.firstMatch(FluentIterable.java:236)
    at springfox.documentation.spi.schema.AlternateTypeProvider.alternateFor(AlternateTypeProvider.java:42)
    at springfox.documentation.spi.service.contexts.RequestMappingContext.alternateFor(RequestMappingContext.java:118)
    at springfox.documentation.spring.web.readers.operation.OperationModelsProvider.collectFromReturnType(OperationModelsProvider.java:69)
    at springfox.documentation.spring.web.readers.operation.OperationModelsProvider.apply(OperationModelsProvider.java:58)
    at springfox.documentation.spring.web.plugins.DocumentationPluginsManager.modelContexts(DocumentationPluginsManager.java:129)
    at springfox.documentation.spring.web.scanners.ApiModelReader.read(ApiModelReader.java:63)
    at springfox.documentation.spring.web.scanners.ApiListingScanner.scan(ApiListingScanner.java:88)
    at springfox.documentation.spring.web.scanners.ApiDocumentationScanner.scan(ApiDocumentationScanner.java:69)
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.scanDocumentation(DocumentationPluginsBootstrapper.java:101)
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.onApplicationEvent(DocumentationPluginsBootstrapper.java:87)
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.onApplicationEvent(DocumentationPluginsBootstrapper.java:50)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:380)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:334)
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:854)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:540)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752)
    at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:347)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:295)
    at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:183)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:123)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:230)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:249)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
    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.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at org.testng.junit.JUnit4TestRunner.start(JUnit4TestRunner.java:81)
    at org.testng.junit.JUnit4TestRunner.run(JUnit4TestRunner.java:69)
    at org.testng.TestRunner$1.run(TestRunner.java:697)
    at org.testng.TestRunner.runJUnitWorkers(TestRunner.java:1004)
    at org.testng.TestRunner.privateRunJUnit(TestRunner.java:728)
    at org.testng.TestRunner.run(TestRunner.java:629)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)
    at org.testng.SuiteRunner.run(SuiteRunner.java:268)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1244)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1169)
    at org.testng.TestNG.run(TestNG.java:1064)
    at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:115)
    at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:212)
    at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:108)
    at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:111)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)

@woemler
Copy link
Author

woemler commented Jan 25, 2016

@elennick : Thanks for posting this. I meant to comment back here after testing, but I ran into the same problem/solution as you. My code still was not working with version 2.3.1, but then I noticed that changing my return type from HttpEntity to HttpEntity<?> fixed the issue. I learned my lesson about ambiguous object declaration.

@dilipkrish
Copy link
Member

👍 @elennick Will research the fix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants