Skip to content

Unsupported bean type: UNRESOLVED_TYPE_VARIABLE, K When using generics #9674

@Cryptorious

Description

@Cryptorious

Hey,

I'm trying my first Quarkus application and are moving from Spring to Quarkus.

In Spring I gererated an helper library where I defined an generic standardservice.

The Service class looks like this:

@Service
public abstract class AbstractService<M extends AbstractModel<K>, K extends Serializable, R extends JpaRepository<M, K>> {

    protected R repository;

    public AbstractService() {

    }

    public Optional<M> get(K id) {
        return repository.findById(id);
    }

    public Optional<M> exists(M model) {
        return repository.findOne(Example.of(model));
    }

    public List<M> getAll() {
        return repository.findAll();
    }

    public M addNew(M newModel) {
        return repository.saveAndFlush(newModel);
    }

    public boolean delete(K id) {
        try {
            repository.deleteById(id);
            return true;
        } catch (Exception ex) {
            return false;
        }
    }

    public Optional<M> update(M updateModel) {

        Optional<M> mOptional = repository.findById(updateModel.getId());

        if (mOptional.isPresent())
            repository.saveAndFlush(updateModel);

        return mOptional;
    }

}

The model class looks like this:

@Getter
@Setter
@MappedSuperclass
@NoArgsConstructor
@AllArgsConstructor
public abstract class AbstractModel<K extends Serializable> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private K id;
}

This is the controller:

@Slf4j
@RestController
@RequestMapping("service.api.name")
public abstract class AbstractController<M extends AbstractModel<K>, S extends AbstractService<M, K, R>, K extends Serializable, AMA extends AbstractModelAssembler<M, K>, R extends JpaRepository<M, K>> {

    @Value("service.api.name")
    protected String apiName;

    protected S service;

    protected AMA assembler;

    public AbstractController() {

    }

    @GetMapping("/{id}")
    @ResponseBody
    public Response get(@Context UriInfo uriInfo, @PathVariable(value = "id") K id) {

        Optional<M> optionalModel = service.get(id);

        if (optionalModel.isPresent()) {
            return assembler.singleObject(uriInfo, optionalModel.get(), Response.Status.OK);
        } else {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
    }

    @GetMapping("/getall")
    @ResponseBody
    public Response getall(@Context UriInfo uriInfo) {
        return assembler.collection(uriInfo, service.getAll(), Response.Status.OK);
    }

    @PostMapping("/addNew")
    @ResponseBody
    public Response addNew(@Context UriInfo uriInfo, @RequestBody M newModel) {

        Optional<M> tmpModel = service.exists(newModel);

        if (tmpModel.isPresent()) {
            return assembler.singleObject(uriInfo, tmpModel.get(), Response.Status.SEE_OTHER);
        } else {
            M model = service.addNew(newModel);
            return assembler.singleObject(uriInfo, model, Response.Status.CREATED);
        }
    }

    @DeleteMapping("/{id}")
    @ResponseBody
    public Response delete(@PathVariable(value = "id") K id) {
        if (service.delete(id))
            return Response.noContent().build();
        else
            return Response.status(Response.Status.NOT_FOUND).build();
    }

    @PutMapping("/update")
    @ResponseBody
    public Response update(@Context UriInfo uriInfo, @RequestBody M updateModel) {

        Optional<M> mOptional = service.update(updateModel);

        if (mOptional.isPresent()) {
            return assembler.singleObject(uriInfo, mOptional.get(), Response.Status.OK);
        } else {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
    }

}

and this is my Assembler:

@Component
public abstract class AbstractModelAssembler<M extends AbstractModel<K>, K extends Serializable> {

  @Value("service.api.name")
  protected String apiName;

  public Response singleObject(@Context UriInfo uriInfo, M model, Response.Status status) {

    List<Link> links = initLinks(model, uriInfo);

    GenericEntity<M> genericEntity =
        new GenericEntity<>(model) {
        };

    Link self = Link.fromUriBuilder(uriInfo.getAbsolutePathBuilder())
        .rel("self").build();

    return Response.status(status).entity(genericEntity).links(self).build();
  }

  public Response collection(@Context UriInfo uriInfo, List<M> models, Response.Status status) {

    List<Link> links = new ArrayList<>();
    models.forEach(m -> links.addAll(initLinks(m, uriInfo)));

    GenericEntity<List<M>> genericEntity =
        new GenericEntity<>(models) {
        };

    Link self = Link.fromUriBuilder(uriInfo.getAbsolutePathBuilder())
        .rel("self").build();

    return Response.status(status).entity(genericEntity).links(self).build();
  }

  private List<Link> initLinks(M model, UriInfo uriInfo) {
    UriBuilder uriBuilder = uriInfo.getRequestUriBuilder();
    uriBuilder = uriBuilder.path(model.getId().toString());
    Link.Builder linkBuilder = Link.fromUriBuilder(uriBuilder);
    Link selfLink = linkBuilder.rel("self").build();//.toString().replace("${application.api.name}", apiName);
    return Arrays.asList(selfLink);
    //model.setLinks(Arrays.asList(selfLink));
  }
}

When trying to build the native executable, I get this message:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  9.984 s
[INFO] Finished at: 2020-05-29T10:52:22+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:1.5.0.Final:build (default) on project QuarkusTemplatePlugin: Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[ERROR] 	[error]: Build step io.quarkus.arc.deployment.ArcProcessor#generateResources threw an exception: java.lang.IllegalArgumentException: Unsupported bean type: UNRESOLVED_TYPE_VARIABLE, K
[ERROR] 	at io.quarkus.arc.processor.Types.getTypeHandle(Types.java:141)
[ERROR] 	at io.quarkus.arc.processor.Types.getTypeHandle(Types.java:91)
[ERROR] 	at io.quarkus.arc.processor.Types.getTypeHandle(Types.java:77)
[ERROR] 	at io.quarkus.arc.processor.Types.getTypeHandle(Types.java:91)
[ERROR] 	at io.quarkus.arc.processor.BeanGenerator.initConstructor(BeanGenerator.java:657)
[ERROR] 	at io.quarkus.arc.processor.BeanGenerator.createConstructor(BeanGenerator.java:555)
[ERROR] 	at io.quarkus.arc.processor.BeanGenerator.generateClassBean(BeanGenerator.java:297)
[ERROR] 	at io.quarkus.arc.processor.BeanGenerator.generate(BeanGenerator.java:116)
[ERROR] 	at io.quarkus.arc.processor.BeanProcessor.generateResources(BeanProcessor.java:199)
[ERROR] 	at io.quarkus.arc.deployment.ArcProcessor.generateResources(ArcProcessor.java:393)
[ERROR] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR] 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR] 	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[ERROR] 	at io.quarkus.deployment.ExtensionLoader$2.execute(ExtensionLoader.java:932)
[ERROR] 	at io.quarkus.builder.BuildContext.run(BuildContext.java:277)
[ERROR] 	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
[ERROR] 	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2046)
[ERROR] 	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1578)
[ERROR] 	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1452)
[ERROR] 	at java.base/java.lang.Thread.run(Thread.java:834)
[ERROR] 	at org.jboss.threads.JBossThread.run(JBossThread.java:479)
[ERROR] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

Am I missing something inside my code or is this a limitation of Quarkus? In Spring I can compile and use it inside services.

Metadata

Metadata

Assignees

Labels

area/arcIssue related to ARC (dependency injection)area/springIssues relating to the Spring integration

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions