不支持的 bean 类型:UNRESOLVED_TYPE_VARIABLE,K 在使用泛型时

huangapple 未分类评论49阅读模式
英文:

Unsupported bean type: UNRESOLVED_TYPE_VARIABLE, K When using generics

问题

我正在尝试我的第一个Quarkus应用程序,并且正在从Spring迁移到Quarkus。

在Spring中,我生成了一个帮助程序库,其中我定义了一个通用的“标准服务”。

Service类如下所示:

public abstract class AbstractService<M extends AbstractModel, 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;
}
}

模型类如下所示:

@Getter
@Setter
@MappedSuperclass
@NoArgsConstructor
@AllArgsConstructor
public abstract class AbstractModel {

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

这是控制器:

@Slf4j
@RestController
@RequestMapping("service.api.name")
public abstract class AbstractController<M extends AbstractModel, 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();
    }
}
}

这是我的Assembler:

@Component
public abstract class AbstractModelAssembler<M extends AbstractModel, 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<>() {
    };

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 models, Response.Status status) {

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

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

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();
return Arrays.asList(selfLink);
}
}

尝试构建本机可执行文件时,我收到了以下消息:

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

英文:

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:

public abstract class AbstractService&lt;M extends AbstractModel, K extends Serializable, R extends JpaRepository&lt;M, K&gt;&gt; {

protected R repository;

public AbstractService() {

}

public Optional&lt;M&gt; get(K id) {
    return repository.findById(id);
}

public Optional&lt;M&gt; exists(M model) {
    return repository.findOne(Example.of(model));
}

public List&lt;M&gt; 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&lt;M&gt; update(M updateModel) {

    Optional&lt;M&gt; 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 {

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

This is the controller:

@Slf4j
@RestController
@RequestMapping(&quot;service.api.name&quot;)
public abstract class AbstractController&lt;M extends AbstractModel, S extends AbstractService&lt;M, K, R&gt;, K extends Serializable, AMA extends AbstractModelAssembler&lt;M, K&gt;, R extends JpaRepository&lt;M, K&gt;&gt; {

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

protected S service;

protected AMA assembler;

public AbstractController() {

}

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

    Optional&lt;M&gt; 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(&quot;/getall&quot;)
@ResponseBody
public Response getall(@Context UriInfo uriInfo) {
    return assembler.collection(uriInfo, service.getAll(), Response.Status.OK);
}

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

    Optional&lt;M&gt; 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(&quot;/{id}&quot;)
@ResponseBody
public Response delete(@PathVariable(value = &quot;id&quot;) K id) {
    if (service.delete(id))
        return Response.noContent().build();
    else
        return Response.status(Response.Status.NOT_FOUND).build();
}

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

    Optional&lt;M&gt; 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&lt;M extends AbstractModel, K extends Serializable&gt; {

@value(&quot;service.api.name&quot;)
protected String apiName;

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

List&lt;Link&gt; links = initLinks(model, uriInfo);

GenericEntity&lt;M&gt; genericEntity =
    new GenericEntity&lt;&gt;(model) {
    };

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

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

public Response collection(@context UriInfo uriInfo, List models, Response.Status status) {

List&lt;Link&gt; links = new ArrayList&lt;&gt;();
models.forEach(m -&gt; links.addAll(initLinks(m, uriInfo)));

GenericEntity&lt;List&lt;M&gt;&gt; genericEntity =
    new GenericEntity&lt;&gt;(models) {
    };

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

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

private List 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(&quot;self&quot;).build();//.toString().replace(&quot;${application.api.name}&quot;, 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.

答案1

得分: 0

在使用Quarkus的本机模式时的经验法则是:每个类/bean需要使用的每种类型都必须事先考虑到。也就是说,AbstractModel 没有为 K 声明类型。这甚至在JVM模式下都无法编译通过,更不用说本机模式了。

英文:

Rule of thumb when working with native mode in Quarkus: every type that the class/bean needs to use must be accounted for upfront. That said, AbstractModel is missing the type declaration for K. This won't even compile in JVM mode, let alone native.

huangapple
  • 本文由 发表于 2020年5月29日 17:17:22
  • 转载请务必保留本文链接:https://java.coder-hub.com/62082537.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定