2

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 Answer 1

0

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.