Ignored Implementation Of A Generated Resource Interface
ID |
java.quarkus_panache_resource_implemented |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Java |
Tags |
quarkus, reliability, rest |
Description
REST-with-Panache turns a resource interface into a complete JAX-RS resource at build time: it generates the class, implements the standard create / read / update / delete / list operations, and registers the result.
The generator does not check whether an implementation already exists. It emits its own and wires that into the application. A class written by hand to implement the same interface is therefore never instantiated and never called — the methods look like the running code and are not.
This rule reports a concrete class whose implements clause names an interface that itself extends
a Panache resource base interface.
Rationale
public interface PeopleResource extends PanacheEntityResource<Person, Long> {
}
public class PeopleResourceImpl implements PeopleResource { // never runs
@Override
public Person get(Long id) {
auditLog.record("read", id); // the audit entry is never written
return Person.findById(id);
}
}
Everything in PeopleResourceImpl is dead: the override, the audit call, any validation added
later. Because the endpoint still answers — served by the generated class — the defect does not
show up as a failure, only as behaviour that silently never happens.
Remediation
Delete the implementation class and put the custom behaviour on the interface as a default
method. The generator keeps default methods and adds only the operations that are missing.
public interface PeopleResource extends PanacheEntityResource<Person, Long> {
@GET
@Path("/name/{name}")
@Produces("application/json")
default List<Person> findByName(@PathParam("name") String name) {
return Person.find("name = :name", Collections.singletonMap("name", name)).list();
}
}
Configuration
| Property | Default | Description |
|---|---|---|
|
|
Simple names of the framework base interfaces whose subinterfaces receive a generated implementation. Matched on the simple name, since a supertype is recorded fully qualified only when an import resolved it. |
Limitations
The implemented interface is declared in another file, so the rule resolves it through the project-wide type model. When that model has no entry for the interface — a third-party interface, or a scan in which the model was not built — the rule stays silent rather than guess. Abstract classes are also skipped: an abstract class cannot stand in for the generated implementation.