swagger-api / swagger-api/swagger-codegen
Problem with Context injection in jersey 2
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
The issue that I am hitting is that in the environment that I am using the injection with the constructor that is annotated with @Context does not seem to be working properly...
public class PodManagersApi {
private final PodManagersApiService delegate;
public PodManagersApi(@Context ServletConfig servletContext) {
PodManagersApiService delegate = null;
The underlying problem is captured in the posting below ...
https://stackoverflow.com/questions/37683765/jersey-constructor-injection-with-context-not-working
Swagger-codegen version
2.22.3
It originated with the change at..
https://github.com/swagger-api/swagger-codegen/pull/5662
Swagger declaration file content or url
`
Command line used for generation
lang = "jaxrs"
library = "jersey2"
....
doLast {
def swaggerIn =
new File("${project.projectDir}/${project.swagger.swaggersDir}/${project.swagger.swaggerFile}")
def swaggerOut =
new File("${project.buildDir}/${project.swagger.outputLocation}")
swaggerOut.mkdirs()
def config = new CodegenConfigurator()
config.setInputSpec(swaggerIn.path)
config.setOutputDir(swaggerOut.path)
config.setLang(project.swagger.lang.toString())
config.setLibrary(project.swagger.library.toString())
config.setAdditionalProperties([
'sourceFolder' : 'src/main/java'.toString(),
'groupId' : (project.swagger.swaggerGroupId ?: project.group).toString(),
'artifactId' : (project.swagger.swaggerArtifactId ?: project.name).toString(),
'artifactVersion': (project.swagger.swaggerArtifactVersion ?: project.version).toString(),
'invokerPackage' : (project.swagger.packageName + '.client').toString(),
'modelPackage' : (project.swagger.packageName + '.model').toString(),
'apiPackage' : (project.swagger.packageName + '.api').toString()//,
// TODO: broken in 2.2.2 of code gen
//'dateLibrary' : 'java8'.toString()
])
new DefaultGenerator().opts(config.toClientOptInput()).generate()
Steps to reproduce
Create a war from the above and deploy it. curl the target and you will get an exception of the kind..
WARNING: The following warnings have been detected: WARNING: Unknown HK2 failure detected:
MultiException stack 1 of 1
org.jboss.weld.exceptions.CreationException: WELD-001530: Cannot produce an instance of class com.oracle.fa.lcm.rest.fasaasmgr.api.PodManagersApi.
at org.jboss.weld.injection.producer.NonProducibleInjectionTarget.produce(NonProducibleInjectionTarget.java:79)
at org.glassfish.jersey.ext.cdi1x.internal.AbstractCdiBeanHk2Factory$2.getInstance(AbstractCdiBeanHk2Factory.java:139)
at org.glassfish.jersey.ext.cdi1x.internal.AbstractCdiBeanHk2Factory._provide(AbstractCdiBeanHk2Factory.java:91)
at org.glassfish.jersey.ext.cdi1x.internal.GenericCdiBeanHk2Factory.provide(GenericCdiBeanHk2Factory.java:63)
at org.jvnet.hk2.internal.FactoryCreator.create(FactoryCreator.java:153)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:487)
at org.jvnet.hk2.internal.PerLookupContext.findOrCreate(PerLookupContext.java:70)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2022)
at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:774)
at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:737)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:707)
at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:172)
at org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:284)
at org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:74)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:109)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:92)
at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:61)
at org.glassfish.jersey.process.internal.Stages.process(Stages.java:197)
at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:318)`
Related issues/PRs
Suggest a fix/enhancement
The following changes seemed to resolve the issue when made manually...
@Context
private ServletConfig servletContext;
@PostConstruct
private void initDelegate() {
java.util.logging.Logger.getGlobal().severe("POSTCONSTRUCT!!!!!!!!!");
FooManagersApiService delegate = null;
if (servletContext != null) {
String implClass = servletContext.getInitParameter("FooManagersApi.implementation");
if (implClass != null && !"".equals(implClass.trim())) {
try {
delegate = (FooManagersApiService) Class.forName(implClass).newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
if (delegate == null) {
delegate = FooManagersApiServiceFactory.getFooManagersApi();
}
this.delegate = delegate;
}
Alternatively, I was wondering if it might make sense to just use direct injection as an option..
As in....
public class PodManagersApi {
@Inject
private final PodManagersApiService delegate;
Then adding...
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2017-12-04T17:38:39.050-05:00")
@Contract
public abstract class FooManagersApiService {
public abstract Response getAllFooManagers(SecurityContext securityContext) throws NotFoundException;
}
and...
@javax.annotation.Generated(value = "io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2017-12-04T17:38:39.050-05:00")
@Service
public class FooManagersApiServiceImpl extends FooManagersApiService {
@Override
public Response getAllFooManagers(SecurityContext securityContext) throws NotFoundException {
This would make it really easy to override or use qualifiers without having to modify any source code or even descriptors..
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the failure using the shown jaxrs and jersey2 CodegenConfigurator settings, then inspect the generated PodManagersApi constructor and the JavaJerseyServerCodegen output. Compare the failing constructor-based @Context injection with the field-injection and @PostConstruct example; done means the generated WAR deploys and the request no longer produces the Weld CreationException.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, backend, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100