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

Problem with Context injection in jersey 2 #7122

Open
paclat opened this issue Dec 6, 2017 · 5 comments
Open

Problem with Context injection in jersey 2 #7122

paclat opened this issue Dec 6, 2017 · 5 comments

Comments

@paclat
Copy link

paclat commented Dec 6, 2017

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

@wing328
Copy link
Contributor

wing328 commented Dec 7, 2017

My suggestion is to try the latest master (2.3.0). The SNAPSHOT version can be found in the README.

@funtastian
Copy link

any news on that issue? :)

@funtastian
Copy link

funtastian commented Jan 9, 2019

the second solution that @paclat suggested doesn't work (at least for me). Although, the first one does.
Here is the changed template:

`package {{package}};

import {{modelPackage}}.*;
import {{package}}.{{classname}}Service;
import {{package}}.factories.{{classname}}ServiceFactory;

import io.swagger.annotations.ApiParam;
import io.swagger.jaxrs.*;

{{#imports}}import {{import}};
{{/imports}}

import java.util.Map;
import java.util.List;
import {{package}}.NotFoundException;

import java.io.InputStream;

import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;

import javax.annotation.PostConstruct;
import javax.servlet.ServletConfig;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.;
{{#useBeanValidation}}
import javax.validation.constraints.
;
import javax.validation.Valid;
{{/useBeanValidation}}

{{#commonPath}}@path("/{{{commonPath}}}"){{/commonPath}}{{^commonPath}}@path(""){{/commonPath}}
{{#hasConsumes}}@consumes({ {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }){{/hasConsumes}}
{{#hasProduces}}@produces({ {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }){{/hasProduces}}
@io.swagger.annotations.Api(description = "the {{{baseName}}} API")
{{>generatedAnnotation}}
{{#operations}}
public class {{classname}} {
@context
private ServletConfig servletContext;
private {{classname}}Service delegate;

@PostConstruct
private void initDelegate() {
{{classname}}Service delegate = null;

  if (servletContext != null) {
     String implClass = servletContext.getInitParameter("{{classname}}.implementation");
     if (implClass != null && !"".equals(implClass.trim())) {
        try {
           delegate = ({{classname}}Service) Class.forName(implClass).newInstance();
        } catch (Exception e) {
           throw new RuntimeException(e);
        }
     } 
  }

  if (delegate == null) {
     delegate = {{classname}}ServiceFactory.get{{classname}}();
  }

  this.delegate = delegate;

}

{{#operation}}
@{{httpMethod}}
{{#subresourceOperation}}@path("{{{path}}}"){{/subresourceOperation}}
{{#hasConsumes}}@consumes({ {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} }){{/hasConsumes}}
{{#hasProduces}}@produces({ {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }){{/hasProduces}}
@io.swagger.annotations.ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}", response = {{{returnBaseType}}}.class{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}{{#hasAuthMethods}}, authorizations = {
{{#authMethods}}@io.swagger.annotations.Authorization(value = "{{name}}"{{#isOAuth}}, scopes = {
{{#scopes}}@io.swagger.annotations.AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{#hasMore}},
{{/hasMore}}{{/scopes}}
}{{/isOAuth}}){{#hasMore}},
{{/hasMore}}{{/authMethods}}
}{{/hasAuthMethods}}, tags={ {{#vendorExtensions.x-tags}}"{{tag}}",{{/vendorExtensions.x-tags}} })
@io.swagger.annotations.ApiResponses(value = { {{#responses}}
@io.swagger.annotations.ApiResponse(code = {{{code}}}, message = "{{{message}}}", response = {{{baseType}}}.class{{#containerType}}, responseContainer = "{{{containerType}}}"{{/containerType}}){{#hasMore}},
{{/hasMore}}{{/responses}} })
public Response {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}},{{/allParams}}@context SecurityContext securityContext)
throws NotFoundException {
return delegate.{{nickname}}({{#allParams}}{{#isFile}}{{paramName}}InputStream, {{paramName}}Detail{{/isFile}}{{^isFile}}{{paramName}}{{/isFile}},{{/allParams}}securityContext);
}
{{/operation}}
}
{{/operations}}
`

@rajeswarikolluri
Copy link

Is the issue resolved? Am using Codegen 3.0.5 , facing same issue mentioned with JAX-RS 2.0 , Weblogic 12.2.1.3 .

Sample application is working fine . It was tested on Tomcat Server. Only difference I see is in sample app class - at org.jvnet.hk2.internal.ClazzCreator is called instead of FactoryCreator.

@funtastian
Copy link

funtastian commented Jun 6, 2023

i recently updated the openAPI codeGen to version 6.5.0
This version doesn't have the issue anymore.
using glassfish 5.49.0

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

No branches or pull requests

4 participants