Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ <h4>Compliant solution</h4>
<h2>Resources</h2>
<h3>Standards</h3>
<ul>
<li>CWE - <a href="https://cwe.mitre.org/data/definitions/547">CWE-547 - Use of Hard-coded, Security-relevant Constants</a></li>
<li>OWASP - <a href="https://owasp.org/Top10/A01_2021-Broken_Access_Control/">Top 10 2021 Category A1 - Broken Access Control</a></li>
<li>OWASP - <a href="https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure">Top 10 2017 Category A3 - Sensitive Data
Exposure</a></li>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
<p>This is an issue when a caching annotation designed to store method return values is applied to a method that returns no value (void). Since there
is no value to cache, the annotation serves no purpose and indicates a misunderstanding of the caching mechanism.</p>
<h2>Why is this an issue?</h2>
<p>Return value caching annotations are designed to cache the output of a method. When a method annotated for result caching is invoked, the framework computes a cache key and checks if the result has been previously cached. If found, the cached value is returned without executing the method body. If not found, the method executes and its return value is stored in the cache.</p>
<p>This caching mechanism fundamentally requires a return value to function. A <code>void</code> method, by definition, does not return a value - it only produces side effects. Since there is no value to cache or retrieve, applying result caching annotations to a void method is meaningless and will not provide any caching benefits.</p>
<p>Return value caching annotations are designed to cache the output of a method. When a method annotated for result caching is invoked, the framework
computes a cache key and checks if the result has been previously cached. If found, the cached value is returned without executing the method body. If
not found, the method executes and its return value is stored in the cache.</p>
<p>This caching mechanism fundamentally requires a return value to function. A <code>void</code> method, by definition, does not return a value - it
only produces side effects. Since there is no value to cache or retrieve, applying result caching annotations to a void method is meaningless and will
not provide any caching benefits.</p>
<p>This misuse typically indicates one of the following:</p>
<ul>
<li>A misunderstanding of how result caching works</li>
<li>An attempt to cache side effects, which is not supported by these annotations</li>
<li>A method that should be refactored to return a value if caching is truly needed</li>
</ul>
<p>Framework documentation explicitly states that result caching annotations cannot be used on methods returning <code>void</code>.</p>
<h2>What is the potential impact?</h2>
<h3>What is the potential impact?</h3>
<p>While this issue does not cause runtime errors or security vulnerabilities, it can lead to:</p>
<ul>
<li>Confusion about the intended behavior of the code</li>
Expand All @@ -17,7 +23,8 @@ <h2>What is the potential impact?</h2>
<li>Potential performance misconceptions if developers believe expensive operations are being cached when they are not</li>
</ul>
<h2>How to fix it</h2>
<p>Remove the <code>@CacheResult</code> annotation from the void method if caching is not needed, or refactor the method to return a value that can be meaningfully cached.</p>
<p>Remove the <code>@CacheResult</code> annotation from the void method if caching is not needed, or refactor the method to return a value that can be
meaningfully cached.</p>
<h3>Code examples</h3>
<h4>Noncompliant code example</h4>
<pre data-diff-id="1" data-diff-type="noncompliant">
Expand All @@ -39,6 +46,7 @@ <h4>Compliant solution</h4>
<h2>Resources</h2>
<h3>Documentation</h3>
<ul>
<li>Quarkus Cache Guide - <a href="https://quarkus.io/guides/cache">Official Quarkus documentation on application data caching, including proper usage of @CacheResult annotation</a></li>
<li>Quarkus @CacheResult Annotation Reference - <a href="https://quarkus.io/guides/cache#cacheresult">Detailed reference for the @CacheResult annotation, explicitly noting it cannot be used on void methods</a></li>
<li>Quarkus Cache Guide - <a href="https://quarkus.io/guides/cache">Application Data Caching</a></li>
<li>Quarkus @CacheResult Annotation Reference - <a href="https://quarkus.io/guides/cache#cacheresult">@CacheResult</a></li>
</ul>

Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant/Issue",
"constantCost": "5min"
"func": "Constant\/Issue",
"constantCost": "5 min"
},
"tags": [],
"tags": [
"api-design",
"confusing"
],
"defaultSeverity": "Minor",
"ruleSpecification": "RSPEC-8908",
"sqKey": "S8908",
Expand All @@ -16,6 +19,6 @@
"impacts": {
"MAINTAINABILITY": "LOW"
},
"attribute": "CLEAR"
"attribute": "CONVENTIONAL"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ <h4>Compliant solution</h4>
<pre data-diff-id="1" data-diff-type="compliant">
@ApplicationScoped
public class CustomKeyGen implements CacheKeyGenerator {
@Inject
ConfigService configService;
private final ConfigService configService;

CustomKeyGen(ConfigService configService) {
this.configService = configService;
}

@Override
public Object generate(Method method, Object... methodParams) {
Expand All @@ -71,12 +74,15 @@ <h4>Compliant solution</h4>
}
</pre>
<h2>Resources</h2>
<h3>Documentation</h3>
<ul>
<li>Quarkus CDI Reference - <a href="https://quarkus.io/guides/cdi-reference">Guide to using CDI (Contexts and Dependency Injection) in Quarkus
applications</a></li>
<li>Quarkus Caching Guide - Cache Key Generator - <a
href="https://quarkus.io/guides/cache#generating-a-cache-key-with-cachekeygenerator">Application Data Caching</a></li>
<li>Quarkus CDI Reference - <a href="https://quarkus.io/guides/cdi-reference">Contexts and Dependency Injection</a></li>
</ul>
<h3>Related rules</h3>
<ul>
<li>{rule:java:S2060} - Classes should not be coupled to their subclasses through constructors or static methods</li>
<li>{rule:java:S3306} - Constructor injection should be used instead of field injection</li>
</ul>

Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
<p>This rule raises an issue when an interface is designated as a mapper type but does not contain any methods designated as data access object
factory methods.</p>
<p>In Java, this specifically refers to interfaces annotated with <code>@Mapper</code> that lack methods annotated with <code>@DaoFactory</code>.</p>
<h2>Why is this an issue?</h2>
<p>In object-relational mapping frameworks that use code generation, a mapper interface serves as a factory for constructing Data Access Object (DAO) instances. This is a core design pattern of such libraries.</p>
<p>The mapper's sole purpose is to provide factory method declarations that create and return DAO beans. These factory methods enable dependency injection of DAOs throughout your application. Without any factory method declarations, the mapper interface:</p>
<p>In object-relational mapping frameworks that use code generation, a mapper interface serves as a factory for constructing Data Access Object (DAO)
instances. This is a core design pattern of such libraries.</p>
<p>The mapper’s sole purpose is to provide factory method declarations that create and return DAO beans. These factory methods enable dependency
injection of DAOs throughout your application. Without any factory method declarations, the mapper interface:</p>
<ul>
<li>Cannot construct any DAO instances</li>
<li>Provides no functionality to the application</li>
<li>Serves no purpose in the codebase</li>
</ul>
<p>The framework's code generation mechanism generates implementation code based on the factory method declarations present in the mapper interface. An empty mapper results in generated code that does nothing useful.</p>
<p>In the DataStax Object Mapper framework, the mapper interface uses the <code>@Mapper</code> annotation, and factory methods are declared using the <code>@DaoFactory</code> annotation. According to the Quarkus documentation: "If you intend to construct and inject a specific DAO bean in your own code, then you first must add a <code>@DaoFactory</code> method for it in a <code>@Mapper</code> interface."</p>
<p>The framework’s code generation mechanism generates implementation code based on the factory method declarations present in the mapper interface.
An empty mapper results in generated code that does nothing useful.</p>
<p>In the DataStax Object Mapper framework, the mapper interface uses the <code>@Mapper</code> annotation, and factory methods are declared using the
<code>@DaoFactory</code> annotation. According to the Quarkus documentation: "If you intend to construct and inject a specific DAO bean in your own
code, then you first must add a <code>@DaoFactory</code> method for it in a <code>@Mapper</code> interface."</p>
<h3>What is the potential impact?</h3>
<p>An interface marked for code generation without the expected factory methods creates unnecessary code that serves no purpose. This can:</p>
<ul>
Expand All @@ -17,7 +25,8 @@ <h3>What is the potential impact?</h3>
<li>Make the codebase harder to maintain</li>
</ul>
<h2>How to fix it</h2>
<p>Add at least one <code>@DaoFactory</code> method to the mapper interface. The method should return a DAO interface that is annotated with <code>@Dao</code>.</p>
<p>Add at least one <code>@DaoFactory</code> method to the mapper interface. The method should return a DAO interface that is annotated with
<code>@Dao</code>.</p>
<h3>Code examples</h3>
<h4>Noncompliant code example</h4>
<pre data-diff-id="1" data-diff-type="noncompliant">
Expand All @@ -37,6 +46,7 @@ <h4>Compliant solution</h4>
<h2>Resources</h2>
<h3>Documentation</h3>
<ul>
<li><a href="https://quarkus.io/guides/cassandra">Quarkus - Using the Cassandra Client</a> - Official Quarkus guide explaining the @Mapper and @DaoFactory pattern</li>
<li><a href="https://docs.datastax.com/en/developer/java-driver/latest/manual/mapper/">DataStax Object Mapper Documentation</a> - Comprehensive documentation for the DataStax Java Driver Object Mapper</li>
<li>Quarkus Guide - <a href="https://quarkus.io/guides/cassandra">Using the Cassandra Client</a></li>
<li>DataStax Documentation - <a href="https://docs.datastax.com/en/developer/java-driver/latest/manual/mapper/">DataStax Java Driver</a></li>
</ul>

Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
{
"title": "Interfaces annotated with \"@Mapper\" should contain at least one \"@DaoFactory\" method",
"type": "CODE_SMELL",
"code": {
"impacts": {
"MAINTAINABILITY": "MEDIUM"
},
"attribute": "CONVENTIONAL"
},
"status": "ready",
"remediation": {
"func": "Constant/Issue",
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"confusing"
"quarkus",
"orm",
"api"
],
"defaultSeverity": "Major",
"ruleSpecification": "RSPEC-8910",
"sqKey": "S8910",
"scope": "All"
"scope": "All",
"quickfix": "unknown",
"code": {
"impacts": {
"MAINTAINABILITY": "MEDIUM"
},
"attribute": "CONVENTIONAL"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,7 @@ <h4>Compliant solution</h4>
<h2>Resources</h2>
<h3>Documentation</h3>
<ul>
<li>Quarkus - Using a Credentials Provider - <a href="https://quarkus.io/guides/credentials-provider">Official Quarkus guide on implementing and
using credentials providers</a></li>
<li>Quarkus ArC - Unremovable Beans - <a href="https://quarkus.io/guides/cdi-reference#remove_unused_beans">Documentation on CDI bean removal and
the @Unremovable annotation</a></li>
<li>Quarkus Guide - <a href="https://quarkus.io/guides/credentials-provider">Using a Credentials Provider</a></li>
<li>Quarkus Guide - <a href="https://quarkus.io/guides/cdi-reference#remove_unused_beans">Removing Unused Beans</a></li>
</ul>

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"quickfix": "targeted",
"code": {
"impacts": {
"SECURITY": "MEDIUM",
"RELIABILITY": "HIGH"
},
"attribute": "COMPLETE"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<p>This rule raises an issue when a class implements an interface that extends one of the framework’s provided base resource interfaces for REST
endpoints with built-in database entity operations.</p>
<p>This rule raises an issue when a class implements an interface that extends one of the framework’s provided base resource interfaces.</p>
<p>In Java with Quarkus, these interfaces are specifically: <code>PanacheEntityResource</code>, <code>PanacheRepositoryResource</code>,
<code>PanacheMongoEntityResource</code>, and <code>PanacheMongoRepositoryResource</code>.</p>
<h2>Why is this an issue?</h2>
Expand Down Expand Up @@ -63,10 +62,6 @@ <h4>Compliant solution</h4>
<h2>Resources</h2>
<h3>Documentation</h3>
<ul>
<li>Quarkus - Generating Jakarta REST resources with Panache - <a href="https://quarkus.io/guides/rest-data-panache">Official Quarkus documentation
on REST Data with Panache, including how to properly use resource interfaces and add custom methods</a></li>
<li>Quarkus - Adding additional methods to the generated resource - <a
href="https://quarkus.io/guides/rest-data-panache#adding-additional-methods-to-the-generated-resource">Specific section on how to correctly add
custom methods using default interface methods</a></li>
<li>Quarkus Guide - <a href="https://quarkus.io/guides/rest-data-panache">Generating Jakarta REST resources with Panache</a></li>
</ul>

Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
"quickfix": "unknown",
"code": {
"impacts": {
"MAINTAINABILITY": "MEDIUM"
"RELIABILITY": "MEDIUM",
"MAINTAINABILITY": "LOW"
},
"attribute": "CLEAR"
"attribute": "COMPLETE"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ <h3>Documentation</h3>
<ul>
<li>Jakarta Persistence Specification - <a
href="https://jakarta.ee/specifications/persistence/3.1/jakarta-persistence-spec-3.1.html#a538">Relationship Mapping Defaults</a></li>
<li>Hibernate documentation - <a
href="https://docs.jboss.org/hibernate/orm/6.2/userguide/html_single/Hibernate_User_Guide.html#associations">Hibernate ORM User Guide -
<li>Hibernate documentation - <a href="https://docs.hibernate.org/stable/orm/userguide/html_single/#associations">Hibernate ORM User Guide -
Associations</a></li>
<li>Baeldung - <a href="https://www.baeldung.com/jpa-hibernate-associations">Understanding JPA/Hibernate Associations</a></li>
</ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,6 @@
"S8696",
"S8715",
"S8745",
"S8786",
"S8910"
"S8786"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void profile_is_registered_as_expected() {
BuiltInQualityProfilesDefinition.BuiltInQualityProfile actualProfile = profilesPerLanguages.get("java").get("Sonar agentic AI");
assertThat(actualProfile.isDefault()).isFalse();
assertThat(actualProfile.rules())
.hasSize(466)
.hasSize(465)
.extracting(BuiltInQualityProfilesDefinition.BuiltInActiveRule::ruleKey)
.doesNotContainAnyElementsOf(List.of(
"S101",
Expand Down
2 changes: 1 addition & 1 deletion sonarpedia.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"languages": [
"JAVA"
],
"latest-update": "2026-06-30T10:26:48.191927160Z",
"latest-update": "2026-07-06T12:46:45.971922719Z",
"options": {
"no-language-in-filenames": true,
"preserve-filenames": false
Expand Down
Loading