Skip to content

Problem with Context injection in jersey 2 #7122

Open
@paclat

Description

@paclat
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..

#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..

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions