### Compliant setUp implementation Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2188.html This example demonstrates the correct approach by including an explicit call to super.setUp(). ```java public class MyClassTest extends MyAbstractTestCase { private MyClass myClass; @Override protected void setUp() throws Exception { super.setUp(); myClass = new MyClass(); } } ``` -------------------------------- ### Noncompliant setUp implementation Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2188.html This example shows an overriding setUp method that fails to call the parent implementation. ```java public class MyClassTest extends MyAbstractTestCase { private MyClass myClass; @Override protected void setUp() throws Exception { // Noncompliant myClass = new MyClass(); } } ``` -------------------------------- ### Noncompliant Switch Examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6208.html Examples showing redundant case branches that can be simplified. ```java // Switch Expression int i = switch (mode) { case "a": case "b": yield 1; default: yield 3; }; ``` ```java // Switch Statement switch (mode) { case "a": case "b": doSomething(); break; default: doSomethingElse(); } ``` -------------------------------- ### Compliant Assertion Examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2701.html These examples show the preferred way to perform assertions using specific methods. ```java assertTrue(something()); assertNotNull(something()); ``` -------------------------------- ### Compliant Implementation Examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S7180.html Examples showing the correct approach of moving @Cache* annotations to concrete class methods to ensure proper cache isolation. ```java @Service public class ExampleServiceImpl implements ExampleService { @Cacheable("exampleCache") @Override public String getData(String id) { // Implementation here } } ``` ```java public interface Zoo { Animal getMostPopularAnimal(); } public class SanDiegoZoo implements Zoo { @Override @Cacheable("sanDiegoPopAnimal") public Animal getMostPopularAnimal() { return new Lion(); } } public class RomeBioparc implements Zoo { @Override @Cacheable("romePopAnimal") public Animal getMostPopularAnimal() { return new Pantegana(); } } ``` -------------------------------- ### Example Usage (Compliant) Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5846.html Demonstrates the correct behavior of the compliant method with both multi-line and empty strings. ```java System.out.println(containsEmptyLines("a\n\nb")); // correctly prints 'true' System.out.println(containsEmptyLines("")); // also correctly prints 'true' ``` -------------------------------- ### Compliant Java Package and Directory Structure Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1598.html These compliant examples demonstrate correct Java package and directory structure alignment. The first example places the file in a path matching the package. The second example adjusts the package name to match the file path. ```java // file: src/main/com/foo/bar/Fubar.java package com.foo.bar; class Fubar { } ``` ```java // file: src/main/foo/Fubar.java package foo; class Fubar { } ``` -------------------------------- ### Compliant Java Code Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S4276.html This example demonstrates the preferred way to implement a supplier of integers using the specialized `IntSupplier` interface, avoiding auto-boxing. ```java public class Foo implements IntSupplier { @Override public int getAsInt() { // ... } } ``` -------------------------------- ### Sensitive Code Examples for Temporary File Access Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5443.html These examples demonstrate patterns that trigger the security rule, such as using hard-coded paths in /tmp or accessing environment variables for temporary directories. ```java new File("/tmp/myfile.txt"); // Sensitive Paths.get("/tmp/myfile.txt"); // Sensitive java.io.File.createTempFile("prefix", "suffix"); // Sensitive, will be in the default temporary-file directory. java.nio.file.Files.createTempDirectory("prefix"); // Sensitive, will be in the default temporary-file directory. Map env = System.getenv(); env.get("TMP"); // Sensitive ``` -------------------------------- ### SMT String Constraint Example Source: https://github.com/sonarsource/sonar-java/wiki/Checking-satisfiability-of-regular-expressions Models a regular expression as a set of constraints for an SMT solver. This example demonstrates how to represent regex components like 'a(?=.b)[^c]*' using SMTLIB format for string manipulation. ```smtlib (declare-fun s1 () String) (declare-fun s2 () String) (declare-fun s3 () String) (declare-fun s4 () String) (declare-fun s5 () String) (declare-fun s6 () String) (assert (and (str.in.re s5 re.all) (str.in.re s3 (str.to.re "a")) (str.in.re s1 (re.++ re.allchar (str.to.re "b"))) (str.prefixof s1 s2) (str.in.re s4 (re.* (re.inter re.allchar (re.comp (str.to.re "c"))))) (str.in.re s6 re.all) (= (str.++ s4 s6) s2))) (check.sat) ``` -------------------------------- ### Compliant Regex Solutions Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6397.html These examples demonstrate compliant regular expressions. This includes simplified versions of the noncompliant examples and cases with metacharacters used to avoid escaping. ```regex "abc" ``` ```regex "\\^" ``` ```regex "a\[\*\*]c" ``` -------------------------------- ### Example Usage (Noncompliant) Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5846.html Demonstrates the incorrect behavior of the noncompliant method with an empty string. ```java System.out.println(containsEmptyLines("a\n\nb")); // correctly prints 'true' System.out.println(containsEmptyLines("")); // incorrectly prints 'false' ``` -------------------------------- ### Noncompliant and Compliant Boolean Method Naming Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2047.html Examples of naming patterns for boolean methods. Methods starting with 'get' are flagged as noncompliant. ```java public boolean getFoo() { // Noncompliant // ... } public boolean getBar(Bar c) { // Noncompliant // ... } public boolean testForBar(Bar c) { // Compliant - The method does not start by 'get'. // ... } ``` ```java public boolean isFoo() { // ... } public boolean hasBar(Bar c) { // ... } public boolean testForBar(Bar c) { // ... } ``` -------------------------------- ### Build and Test Project Source: https://github.com/sonarsource/sonar-java/blob/master/README.md Execute this command from the project root to compile the plugin and run unit tests. ```bash mvn clean install ``` -------------------------------- ### Compliant: Record with Both Default and Equivalent 'get' Getter Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6211.html This example is compliant as it includes both the default getter 'name()' and a custom getter 'getName()' with the 'get' prefix. Crucially, the implementation of 'getName()' is equivalent to 'name()', preventing confusion. ```java record Person(String name, int age) { @Override public String name() { // Compliant return name.toUpperCase(Locale.ROOT); } public String getName() { // Compliant, equal to 'name()' return name.toUpperCase(Locale.ROOT); } } ``` -------------------------------- ### Compliant: Equivalent Getter with 'get' Prefix in Java Record Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6211.html This example is compliant because the custom getter method 'getName()' has the 'get' prefix but its implementation is equivalent to the default getter 'name()'. This is often done for backward compatibility. ```java record Person(String name, int age) { public String getName() { // Compliant, is equivalent to 'name()' return name; } } ``` -------------------------------- ### Compliant Solutions for Secure File Handling Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5443.html These examples show how to securely manage temporary files by specifying secure directories or explicitly setting file permissions. ```java new File("/myDirectory/myfile.txt"); // Compliant File.createTempFile("prefix", "suffix", new File("/mySecureDirectory")); // Compliant if(SystemUtils.IS_OS_UNIX) { FileAttribute> attr = PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------")); Files.createTempFile("prefix", "suffix", attr); // Compliant } else { File f = Files.createTempFile("prefix", "suffix").toFile(); // Compliant f.setReadable(true, true); f.setWritable(true, true); f.setExecutable(true, true); } ``` -------------------------------- ### Noncompliant Thread.start() usage in constructor Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2693.html This example demonstrates the prohibited pattern of starting a thread directly within a class constructor. ```java public class MyClass { Thread thread = null; public MyClass(Runnable runnable) { thread = new Thread(runnable); thread.start(); // Noncompliant } } ``` -------------------------------- ### Build the custom plugin with Maven Source: https://github.com/sonarsource/sonar-java/blob/master/docs/CUSTOM_RULES_101.md Use this command to compile the custom plugin project using the specified Maven configuration file. ```bash $ pwd /home/gandalf/workspace/sonar-java/docs/java-custom-rules-example $ mvn clean install -f pom_SQ_9_9_LTS.xml [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building SonarQube Java :: Documentation :: Custom Rules Example 1.0.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 8.762 s [INFO] Finished at: 2021-03-02T12:17:28+01:00 [INFO] ------------------------------------------------------------------------ ``` -------------------------------- ### Implement Plugin Entry Point in Java Source: https://context7.com/sonarsource/sonar-java/llms.txt The entry point class must implement org.sonar.api.Plugin and register server and batch extensions within the define method. ```java package org.sonar.samples.java; import org.sonar.api.Plugin; public class MyJavaRulesPlugin implements Plugin { @Override public void define(Context context) { // Server extensions - instantiated during server startup context.addExtension(MyJavaRulesDefinition.class); // Batch extensions - instantiated during code analysis context.addExtension(MyJavaFileCheckRegistrar.class); } } ``` -------------------------------- ### Noncompliant: Custom Getter with 'get' Prefix in Java Record Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6211.html This example shows a record with a custom getter method 'getName()' that overrides the default 'name()' getter. This is non-compliant because it introduces a 'get' prefixed method that behaves differently from the default, potentially confusing users. ```java record Person(String name, int age) { public String getName() { // Noncompliant return name.toUpperCase(Locale.ROOT); } } ``` -------------------------------- ### Comparable.compareTo implementation examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S4351.html Demonstrates the difference between an incorrect overload and a correct override when implementing the Comparable interface. ```java public class Foo { static class Bar implements Comparable { public int compareTo(Bar rhs) { return -1; } } static class FooBar extends Bar { public int compareTo(FooBar rhs) { // Noncompliant: Parameter should be of type Bar return 0; } } } ``` ```java public class Foo { static class Bar implements Comparable { public int compareTo(Bar rhs) { return -1; } } static class FooBar extends Bar { public int compareTo(Bar rhs) { return 0; } } } ``` -------------------------------- ### Implement `visitNode` for Method Analysis in SonarQube Source: https://github.com/sonarsource/sonar-java/blob/master/docs/CUSTOM_RULES_101.md Override the `visitNode` method to implement the logic for analyzing a visited node. This example shows the initial setup for handling `MethodTree`. ```java @Override public void visitNode(Tree tree) { } ``` -------------------------------- ### Compliant Initialization Alternatives Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1171.html Use static blocks, constructors, or factory methods to initialize collections cleanly. ```java class MyClass { private static final Map MY_MAP = new HashMap<>(); static { MY_MAP.put("a", "b"); // Compliant } } ``` ```java class MyClass { private static final Map MY_MAP = new HashMap<>(); public MyClass() { MY_MAP.put("a", "b"); // Compliant } } ``` ```java class MyClass { private static final Map MY_MAP = java.util.Map.of("a", "b"); // Compliant } ``` ```java class MyClass { private static final Map MY_MAP = com.google.common.collect.ImmutableMap.of("a", "b"); // Compliant } ``` -------------------------------- ### Noncompliant Java Indentation Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1120.html This example shows Java code with inconsistent indentation. The rule flags lines that do not start at the expected column based on the configured indent size. ```java class Foo { public int a; public int b; // Noncompliant, expected to start at column 4 ... public void doSomething() { if(something) { doSomethingElse(); // Noncompliant, expected to start at column 6 } // Noncompliant, expected to start at column 4 } } ``` -------------------------------- ### Compliant File Header and License Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1451.html This is an example of a compliant header that should be placed at the beginning of every source file. It includes ownership, copyright, and licensing information. ```java /* * SonarQube, open source software quality management tool. * Copyright (C) 2008-2013 SonarSource * mailto:contact AT sonarsource DOT com * * SonarQube is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * SonarQube is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ ``` -------------------------------- ### Noncompliant Java Test Method Name Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S3578.html This example shows a test method that does not adhere to the default naming convention. Ensure test method names start with 'test' followed by an uppercase letter. ```java @Test public void foo() { // Noncompliant //... } ``` -------------------------------- ### Compliant Solution: Using Customizable Parameters for File Paths Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1075.html This compliant solution shows how to use a customizable parameter obtained from a Configuration object to specify the file path. This improves portability and testability. ```java public class Foo { // Configuration is a class that returns customizable properties: it can be mocked to be injected during tests. private Configuration config; public Foo(Configuration myConfig) { this.config = myConfig; } public Collection listUsers() { // Find here the way to get the correct folder, in this case using the Configuration object String listingFolder = config.getProperty("myApplication.listingFolder"); // and use this parameter instead of the hard coded path File userList = new File(listingFolder, "users.txt"); // Compliant Collection users = parse(userList); return users; } } ``` -------------------------------- ### Noncompliant Java Comment Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S7476.html This code demonstrates comments that will be interpreted as JavaDoc in Java 23 and later, potentially causing migration issues. Ensure comments do not start with more than two slashes in older Java versions. ```java /// Some comment for the developers public abstract void foo(); //// public void foo(String s){} public void foo(){} ``` -------------------------------- ### Compliant Temporary Directory Creation Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5445.html This example uses the atomic Files.createTempDirectory method to ensure the directory is created securely. ```java import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; protected void Example() throws IOException { Path tempPath = Files.createTempDirectory(""); File tempDir = tempPath.toFile(); } ``` -------------------------------- ### Compliant: Custom Getter with Descriptive Name in Java Record Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6211.html This example shows a compliant approach where a custom getter method is named descriptively ('getNameUpperCase()') rather than using the 'get' prefix that clashes with the default getter convention. This avoids ambiguity. ```java record Person(String name, int age) { public String getNameUpperCase() { // Compliant return name.toUpperCase(Locale.ROOT); } } ``` -------------------------------- ### Noncompliant Temporary Directory Creation Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5445.html This example demonstrates an insecure approach where a file is created, deleted, and then recreated as a directory, creating a race condition window. ```java import java.io.File; import java.io.IOException; protected void Example() throws IOException { File tempDir; tempDir = File.createTempFile("", "."); tempDir.delete(); tempDir.mkdir(); // Noncompliant } ``` -------------------------------- ### Compliant Java 8 Date and Time API Usage Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2143.html Utilize the Java 8 Date and Time API for modern date and time handling. This example shows how to get the current date and time without components, and how to create a specific date. ```java LocalDate now = LocalDate.now(); // gets calendar date. no time component LocalTime now2 = LocalTime.now(); // gets current time. no date component LocalDate christmas = LocalDate.of(2020,12,25); ``` -------------------------------- ### Compliant Java Code: Brace Placement Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1106.html This example demonstrates the correct placement of opening curly braces at the beginning of a line, adhering to the coding standard. ```java public void myMethod { if(something) { executeTask(); } else { doSomethingElse(); } } ``` -------------------------------- ### Compliant RSA and EC Key Initialization Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S4426.html Examples of using recommended key sizes for RSA and secure NIST-approved curves for EC key generation. ```java import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; public static void main(String[] args) { try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); } catch (NoSuchAlgorithmException e) { // ... } } ``` ```java import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.InvalidAlgorithmParameterException; import java.security.spec.ECGenParameterSpec; public static void main(String[] args) { try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); ECGenParameterSpec ellipticCurveName = new ECGenParameterSpec("secp256r1"); keyPairGenerator.initialize(ellipticCurveName); } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { // ... } } ``` -------------------------------- ### Noncompliant test method example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5961.html Example of a test method exceeding the assertion limit of 2. ```java @Test void test() { // Refactor this method. assertEquals(1, f(1)); assertEquals(2, f(2)); assertEquals(3, g(1)); } ``` -------------------------------- ### Noncompliant Assertion Examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2970.html Examples of incomplete assertions in Fest and Mockito that fail to verify any behavior. ```java // Fest boolean result = performAction(); // let's now check that result value is true assertThat(result); // Noncompliant; nothing is actually checked, the test passes whether "result" is true or false // Mockito List mockedList = Mockito.mock(List.class); mockedList.add("one"); mockedList.clear(); // let's check that "add" and "clear" methods are actually called Mockito.verify(mockedList); // Noncompliant; nothing is checked here, oups no call is chained to verify() ``` -------------------------------- ### Interface Naming Convention Examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S114.html Demonstrates noncompliant and compliant interface naming based on the default regex pattern. ```java public interface myInterface {...} // Noncompliant ``` ```java public interface MyInterface {...} ``` -------------------------------- ### Compliant Constructor Injection in Java Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S3306.html This example demonstrates the recommended approach using constructor injection, ensuring dependencies are provided at instantiation and preventing NullPointerExceptions. ```java class MyComponent { private final MyCollaborator collaborator; @Inject public MyComponent(MyCollaborator collaborator) { Assert.notNull(collaborator, "MyCollaborator must not be null!"); this.collaborator = collaborator; } public void myBusinessMethod() { collaborator.doSomething(); } } ``` -------------------------------- ### Noncompliant Deprecation Examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1123.html Examples of incomplete deprecation missing either the annotation or the Javadoc tag. ```java class MyClass { @Deprecated public void foo1() { // Noncompliant: Add the missing @deprecated Javadoc tag. } /** * @deprecated */ public void foo2() { // Noncompliant: Add the missing @Deprecated annotation. } } ``` -------------------------------- ### Noncompliant Assertion Examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2701.html These examples demonstrate the use of literal values in generic assertion methods, which is discouraged. ```java Assert.assertTrue(true); // Noncompliant assertThat(null).isNull(); // Noncompliant assertEquals(true, something()); // Noncompliant assertNotEquals(null, something()); // Noncompliant ``` -------------------------------- ### Build the custom plugin Source: https://github.com/sonarsource/sonar-java/blob/master/docs/CUSTOM_RULES_101.md Commands to build the Maven project using specific or default POM files. ```bash mvn clean install -f pom_SQ_10_6_LATEST.xml ``` ```bash mvn clean install ``` -------------------------------- ### Compliant JUnit 5 Test Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5793.html Example of the same test class migrated to use JUnit 5 annotations. ```java package org.foo; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MyJUnit5Extension.class) class MyJUnit5Test { @BeforeAll static void beforeAll() { System.out.println("beforeAll"); } @AfterAll static void afterAll() { System.out.println("afterAll"); } @BeforeEach void beforeEach() { System.out.println("beforeEach"); } @AfterEach void afterEach() { System.out.println("afterEach"); } @Test void test1() { System.out.println("test1"); } @Test @Tag("SomeTests") void test2() { System.out.println("test2"); } @Test @Disabled("Requires fix of #42") void disabled() { System.out.println("ignored"); } } ``` -------------------------------- ### Build and Deploy Custom Plugin Source: https://context7.com/sonarsource/sonar-java/llms.txt Build the plugin JAR using Maven and deploy it to SonarQube's extensions directory. ```bash # Build the custom rules plugin cd docs/java-custom-rules-example mvn clean install -f pom_SQ_10_6_LATEST.xml # Copy the generated JAR to SonarQube extensions folder cp target/java-custom-rules-example-1.0.0-SNAPSHOT.jar \ $SONAR_HOME/extensions/plugins/ ``` -------------------------------- ### Define Message with Parameter Source: https://github.com/sonarsource/sonar-java/blob/master/its/plugin/projects/struts-1.3.9-lite/core/src/main/java/org/apache/struts/util/package.html Example of a properties file entry using a placeholder for parameter replacement. ```properties hi=Hello {0} ``` -------------------------------- ### Noncompliant Servlet Code Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1989.html This example shows a servlet method where an exception from InetAddress.getByName is not caught, which is a security risk. ```java public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { InetAddress addr = InetAddress.getByName(request.getRemoteAddr()); // Noncompliant //... } ``` -------------------------------- ### Compliant Constructor Initialization (Prologue) Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S8447.html Demonstrates initializing subclass fields in the constructor prologue before the super() call. ```java class Super { Super() { foo(); } void foo() { System.out.println("Base logic"); } } class Sub extends Super { final int x; Sub(int x) { this.x = x; // Compliant: x is initialized in the prologue before super() super(); } @Override void foo() { System.out.println(x); // Prints the expected value } } ``` -------------------------------- ### Noncompliant JUnit 4 Test Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5793.html Example of a test class using JUnit 4 annotations that are flagged for migration. ```java package org.foo; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @RunWith(MyJUnit4Runner.class) public class MyJUnit4Test { @BeforeClass public static void beforeAll() { System.out.println("beforeAll"); } @AfterClass public static void afterAll() { System.out.println("AfterAll"); } @Before public void beforeEach() { System.out.println("beforeEach"); } @After public void afterEach() { System.out.println("afterEach"); } @Test public void test1() throws Exception { System.out.println("test1"); } public interface SomeTests { /* category marker */ } @Test @Category(SomeTests.class) public void test2() throws Exception { System.out.println("test2"); } @Test @Ignore("Requires fix of #42") public void ignored() throws Exception { System.out.println("ignored"); } } ``` -------------------------------- ### JUnit Rule Usage Examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2924.html Examples showing a noncompliant test class with an unused rule and the compliant version after removal. ```java public class ProjectDefinitionTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); // Noncompliant @Test public void shouldSetKey() { ProjectDefinition def = ProjectDefinition.create(); def.setKey("mykey"); assertThat(def.getKey(), is("mykey")); } } ``` ```java public class ProjectDefinitionTest { @Test public void shouldSetKey() { ProjectDefinition def = ProjectDefinition.create(); def.setKey("mykey"); assertThat(def.getKey(), is("mykey")); } } ``` -------------------------------- ### Analyze Project with Maven Source: https://github.com/sonarsource/sonar-java/blob/master/java-checks-test-sources/README.md Use this command to analyze the project with a local SonarQube instance when running Maven. ```bash mvn clean install sonar:sonar -Panalyze-tests ``` -------------------------------- ### Noncompliant code example for empty files Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2309.html This example shows a file that contains no executable lines of code, which triggers the rule. ```java //package org.foo; // //public class Bar {} ``` -------------------------------- ### Password Hashing Salt Implementation Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2053.html Examples demonstrating the difference between insecure hard-coded salts and secure, randomly generated salts using PBEParameterSpec. ```java import javax.crypto.spec.PBEParameterSpec; public void hash() { byte[] salt = "salty".getBytes(); PBEParameterSpec cipherSpec = new PBEParameterSpec(salt, 10000); // Noncompliant } ``` ```java import java.security.SecureRandom; import javax.crypto.spec.PBEParameterSpec; public void hash() { SecureRandom random = new SecureRandom(); byte[] salt = new byte[16]; random.nextBytes(salt); PBEParameterSpec cipherSpec = new PBEParameterSpec(salt, 10000); } ``` -------------------------------- ### Compliant Control Structure Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S121.html Example showing the use of curly braces to ensure both statements are correctly scoped to the if condition. ```java if (condition) { executeSomething(); checkSomething(); } ``` -------------------------------- ### Noncompliant Utility Class Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1118.html This noncompliant code example shows a utility class that can be instantiated because it lacks a private constructor. ```java class StringUtils { // Noncompliant public static String concatenate(String s1, String s2) { return s1 + s2; } } ``` -------------------------------- ### Run Plugin Test (Community Edition) Source: https://github.com/sonarsource/sonar-java/blob/master/README.md Execute the Plugin Test suite to verify plugin features like metric calculation and coverage, focusing on community edition tests. Ensure MAVEN_HOME is set. ```shell mvn clean install -Pit-plugin -DcommunityEditionTestsOnly=true ``` -------------------------------- ### Compliant AWS SDK Java Client Initialization Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6242.html This code example demonstrates the compliant way to initialize an S3Client by explicitly setting the credentials provider using EnvironmentVariableCredentialsProvider. This avoids the automatic detection logic and improves startup performance. ```java S3Client.builder() .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())) .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build(); ``` -------------------------------- ### Noncompliant Nested If Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1066.html This noncompliant code example demonstrates unnecessary nesting within an if statement. It checks for a file and then its type. ```java if (file != null) { if (file.isFile() || file.isDirectory()) { // Noncompliant /* ... */ } } ``` -------------------------------- ### Run Plugin Test (Including Enterprise Edition) Source: https://github.com/sonarsource/sonar-java/blob/master/README.md Execute the Plugin Test suite, including tests that depend on the SonarQube Server Enterprise Edition. Ensure MAVEN_HOME is set. ```shell mvn clean install -Pit-plugin ``` -------------------------------- ### Noncompliant SpEL and property placeholder examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6857.html Examples of syntactically incorrect SpEL expressions and property placeholders that will cause runtime issues. ```java @Value("#{systemProperties\['user.region'}") // Noncompliant: unclosed "\[" private String region; @Value("#{'${listOfValues}' split(',')}") // Noncompliant: missing operator private List valuesList; @Value("#{T(java.lang.Math).random() \* 64h}") // Noncompliant: invalid number private Double randPercent; @Query("SELECT u FROM User u WHERE u.status = :#{#status+}") // Noncompliant: missing operand for "+" List findUsersByStatus(@Param("status") String status); @Value("${myapp.!prop}") // Noncompliant: property key contains an exclamation mark "!" private String myProperty; @Value("${my.property:#{1\*\*1}}") // Noncompliant: invalid SpEL expression "1\*\*1" private Integer myValue; ``` -------------------------------- ### Use AES Encryption in Java Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5547.html This example demonstrates the compliant way to initialize a Cipher using the AES algorithm with GCM mode and NoPadding, which are considered secure. ```java import javax.crypto.Cipher; import java.security.NoSuchAlgorithmException; import javax.crypto.NoSuchPaddingException; public static void main(String[] args) { try { Cipher aes = Cipher.getInstance("AES/GCM/NoPadding"); } catch(NoSuchAlgorithmException|NoSuchPaddingException e) { // ... } } ``` -------------------------------- ### Sensitive Code Example for Custom MessageDigest Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2257.html This example demonstrates the creation of a custom cryptographic algorithm by extending MessageDigest, which is flagged as insecure. ```java public class MyCryptographicAlgorithm extends MessageDigest { ... } ``` -------------------------------- ### Noncompliant Serializable Subclass Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2055.html An example where a subclass is serializable but the parent class lacks a no-argument constructor, causing serialization issues. ```java public class Fruit { // Noncompliant; this Raspberry's ancestor doesn't have a no-argument constructor // this rule raises an issue on the Raspberry class declaration public Fruit(String debugMessage) { LOG.debug(debugMessage); } } public class Raspberry extends Fruit implements Serializable { private static final long serialVersionUID = 1; private String variety; public Raspberry(String variety) { super("From Raspberry constructor"); this.variety = variety; } } ``` -------------------------------- ### Java Text Block Indentation Examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5664.html Demonstrates the difference between mixed whitespace indentation and consistent indentation in Java text blocks. ```java String textBlock = """ this is text block! !!!! """; ``` ```java String textBlock = """ this is text block! !!!! """; ``` -------------------------------- ### Noncompliant Control Structure Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S121.html Example showing a control structure without curly braces where the second statement is executed unconditionally. ```java if (condition) // Noncompliant executeSomething(); checkSomething(); ``` -------------------------------- ### Non-compliant AWS SDK Java Client Initialization Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6242.html This code example shows how to initialize an S3Client without explicitly setting the credentials provider, which can cause slower startup times due to automatic provider detection logic. ```java S3Client.builder() .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) .build(); ``` -------------------------------- ### Compliant Java code examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1116.html Examples showing the removal of redundant semicolons and the valid use of a semicolon as the unique statement of a loop. ```java void doSomething() {} void doSomethingElse() { System.out.println("Hello, world!"); // ... for (int i = 0; i < 3; i++) ; // Compliant if unique statement of a loop // ... } ``` -------------------------------- ### Database Connection Password Handling Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2115.html Examples demonstrating the insecure use of empty passwords versus the secure retrieval of passwords from system properties. ```java Connection conn = DriverManager.getConnection("jdbc:derby:memory:myDB;create=true", "login", ""); // Noncompliant ``` ```java String password = System.getProperty("database.password"); Connection conn = DriverManager.getConnection("jdbc:derby:memory:myDB;create=true", "login", password); ``` -------------------------------- ### Noncompliant Field Injection Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6813.html This example demonstrates the use of field injection, which is flagged as noncompliant because it allows objects to be instantiated in an invalid state. ```java public class SomeService { @Autowired private SomeDependency someDependency; // Noncompliant private String name = someDependency.getName(); // Will throw a NullPointerException } ``` -------------------------------- ### Noncompliant Class Initialization Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2390.html This example demonstrates a problematic pattern where a parent class references a subclass method during static field initialization. ```java class Parent { static int field1 = Child.method(); // Noncompliant static int field2 = 42; public static void main(String[] args) { System.out.println(Parent.field1); // will display "0" instead of "42" } } class Child extends Parent { static int method() { return Parent.field2; } } ``` -------------------------------- ### Get Fully Qualified Module Key Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/static/documentation.md New method to get the fully qualified module key. Requires Java 8.22 or later. ```java ModuleMetadataUtils#getFullyQualifiedModuleKey(@Nullable ProjectDefinition current) ``` -------------------------------- ### Compliant: Standard static main method in Java Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S8446.html This is the standard and recommended way to define an entry point for a Java application using a static main method. ```java public class LegacyApplication { // Compliant: Standard static entry point public static void main(String[] args) { System.out.println("Running standard static entry point."); } } ``` -------------------------------- ### Noncompliant Interface Caching Examples Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S7180.html Examples demonstrating the use of @Cacheable on interface methods, which is discouraged due to potential runtime issues and cache conflicts. ```java public interface ExampleService { @Cacheable("exampleCache") // Noncompliant: interface method is annotated with @Cacheable String getData(String id); } ``` ```java public interface Zoo { @Cacheable("popAnimal") //non compliant, interface method is annotated with @Cacheable Animal getMostPopularAnimal(); } public class SanDiegoZoo implements Zoo { @Override public Animal getMostPopularAnimal() { return new Lion(); } } public class RomeBioparc implements Zoo { @Override public Animal getMostPopularAnimal() { return new Pantegana(); } } ``` -------------------------------- ### Queueing Messages in Action Source: https://github.com/sonarsource/sonar-java/blob/master/its/plugin/projects/struts-1.3.9-lite/taglib/src/main/java/org/apache/struts/taglib/html/package.html Messages are often queued in the Action class. This example shows how to add both global messages and property-specific messages. ```java ActionMessages messages = new ActionMessages(); messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("userForm.insert", info.getUserName()); messages.add("activationDate", new ActionMessage("userForm.active", info.getSubscriptionLength()); ``` -------------------------------- ### Test Sonar-Scanner with Binaries Source: https://github.com/sonarsource/sonar-java/blob/master/java-checks-test-sources/README.md Configure and run sonar-scanner to test the Java Analyzer's behavior when binaries (dependencies and compiled classes) are provided. Requires a local SonarQube instance. ```bash sonar-scanner -Dproject.settings=sonar-project-with-binaries.properties ``` -------------------------------- ### Noncompliant Code Example: Banning java.lang.String Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S3688.html This example shows a noncompliant code snippet where `java.lang.String` is used, which is banned by the rule with the parameter `className:java.lang.String`. ```java String name; // Noncompliant ``` -------------------------------- ### Noncompliant code example for control characters Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2479.html Examples of string literals containing unescaped control characters or special Unicode whitespace that trigger the rule. ```java String tabInside = "A B"; // Noncompliant, contains a tabulation String zeroWidthSpaceInside = "foo​bar"; // Noncompliant, it contains a U+200B character inside char tab = ' '; ``` -------------------------------- ### Compliant Servlet Code Example with Exception Handling Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1989.html This compliant solution demonstrates how to use a try-catch block to handle potential exceptions, such as UnknownHostException, within a servlet method. ```java public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { InetAddress addr = InetAddress.getByName(request.getRemoteAddr()); //... } catch (UnknownHostException ex) { // Compliant //... } } ``` -------------------------------- ### Iterate Map Entries in Java Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S2864.html Demonstrates the difference between inefficient keySet iteration and efficient entrySet iteration. ```java public void doSomethingWithMap(Map map) { for (String key : map.keySet()) { // Noncompliant; for each key the value is retrieved Object value = map.get(key); // ... } } ``` ```java public void doSomethingWithMap(Map map) { for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); // ... } } ``` -------------------------------- ### Noncompliant Code Example with TODO Tag Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1135.html This example shows a function with an unattended TODO comment. Such tags should be addressed to ensure code completeness and maintainability. ```java void doSomething() { // TODO } ``` -------------------------------- ### Compliant TLS Version Configuration Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S4423.html This example demonstrates a compliant configuration using TLS v1.2, which is a secure and widely compatible choice. Always prefer secure TLS versions. ```java import okhttp3.ConnectionSpec; import okhttp3.TlsVersion; public static void main(String[] args) { new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .tlsVersions(TlsVersion.TLS_1_2) .build(); } ``` -------------------------------- ### Combined Property Reference Example Source: https://github.com/sonarsource/sonar-java/blob/master/its/plugin/projects/struts-1.3.9-lite/taglib/src/main/java/org/apache/struts/taglib/bean/package.html Demonstrates arbitrary nesting and indexing for complex property access. ```jsp foo.bar[0].baz[2] ``` -------------------------------- ### Noncompliant Java Code Example Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S4276.html This example shows a class implementing `Supplier`, which is less efficient due to auto-boxing. Prefer specialized interfaces when possible. ```java public class Foo implements Supplier { @Override public Integer get() { // ... } } ``` -------------------------------- ### Noncompliant Code Example: Unused Label Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1065.html This example shows a Java code snippet where a label 'outer' is declared but not used. Such labels can be considered dead code. ```java void foo() { outer: //label is not used. for(int i = 0; i<10; i++) { break; } } ``` -------------------------------- ### Implement Lazy Initialization Singleton in Java Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S6548.html Defers instance creation until requested, which is memory-efficient but not thread-safe in multi-threaded environments. ```java public class LazyInitializedSingleton { private static LazyInitializedSingleton instance; private LazyInitializedSingleton(){} public static LazyInitializedSingleton getInstance() { if (instance == null) { instance = new LazyInitializedSingleton(); } return instance; } } ``` -------------------------------- ### Avoid Calling Thread.run() on Subclasses Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S1217.html When extending Thread, calling run() directly on an instance does not start a new thread. Use start() for proper thread execution. ```java class ComputePrimesThread extends Thread { @Override public void run() { // ... } } new ComputePrimesThread().run(); // Noncompliant, does not start a thread ``` ```java class ComputePrimesThread extends Thread { @Override public void run() { // ... } } new ComputePrimesThread().start(); // Compliant ``` -------------------------------- ### Configure TilesServlet for Non-Struts Applications Source: https://github.com/sonarsource/sonar-java/blob/master/its/plugin/projects/struts-1.3.9-lite/tiles/src/main/java/org/apache/struts/tiles/package.html Use the provided TilesServlet in web.xml to initialize the definition factory without Struts. ```xml action org.apache.struts.tiles.TilesServlet definitions-config /WEB-INF/tiles-defs.xml definitions-parser-validate true ... ``` -------------------------------- ### Use @GetMapping Instead of @RequestMapping for GET Requests Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S4488.html Prefer using @GetMapping for GET requests in Spring. This improves code clarity and adheres to modern Spring practices. ```java @RequestMapping(path = "/greeting", method = RequestMethod.GET) // Noncompliant public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) { ... ``` ```java @GetMapping(path = "/greeting") // Compliant public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) { ... ``` -------------------------------- ### Transforming Class Files Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S7478.html Comparison between manual class building and the optimized transformClass approach. ```java public static void transformClassFile(Path path) throws IOException { ClassFile classFile = ClassFile.of(); ClassModel classModel = classFile.parse(path); byte[] newBytes = classFile.build( // Noncompliant classModel.thisClass().asSymbol(), classBuilder -> { for (ClassElement classElement : classModel) { if (!(classElement instanceof MethodModel methodModel && methodModel.methodName().stringValue().startsWith("debug"))) { classBuilder.with(classElement); } } }); Files.write(path, newBytes); } ``` ```java public static void transformClassFile(Path path) throws IOException { ClassFile classFile = ClassFile.of(); ClassModel classModel = classFile.parse(path); byte[] newBytes = classFile.transformClass( classModel, (classBuilder, classElement) -> { if (!(classElement instanceof MethodModel methodModel && methodModel.methodName().stringValue().startsWith("debug"))) { classBuilder.with(classElement); } }); Files.write(path, newBytes); } ``` -------------------------------- ### Noncompliant: Multiple Calls in Try-Catch Source: https://github.com/sonarsource/sonar-java/blob/master/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S5783.html This example demonstrates a non-compliant try-catch block for exception testing. Similar to the assertThrows example, it's ambiguous which method call is intended to throw the exception. ```java @Test public void testGTryCatchIdiom() { try { // Noncompliant g(f(1)); Assert.fail("Expected an IOException to be thrown"); } catch (IOException e) { // Test exception message... } } ```