英文:
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<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;
}
}
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("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();
}
}
}
and this is my 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<>(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 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 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.
答案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.
专注分享java语言的经验与见解,让所有开发者获益!

评论