Skip to content
Back to skills

Java Advanced Coding Skill

ASecurity

Reusable skill module for Java coding. Covers Java 17/21 features, OOP principles with clear examples, Spring Boot 3.x patterns, Javadoc standards, and test generation with JUnit 5 + Mockito.

  • 3 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 5, 2026
developmentgojavabashsqlexpressspringtestinggitapidatabase

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 21 files and shows the line behind each finding

Scanned October 1, 2026

npx -y skills add sharmapuneet1510/awesome-prompts --skill skills --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Java Advanced Coding Skill?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Java Advanced Coding Skill
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/sharmapuneet1510-java-advanced-coding-skill/badge)](https://www.skillsdirectory.com/skills/sharmapuneet1510-java-advanced-coding-skill)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: Java Advanced Coding Skill
version: 2.1
description: >
  Reusable skill module for Java coding. Covers Java 17/21 features, OOP
  principles with clear examples, Spring Boot 3.x patterns, Javadoc standards,
  and test generation with JUnit 5 + Mockito.
applies_to: [java, spring-boot, maven, gradle]
---

# Java Advanced Coding Skill — v2.1

## Quick Card

> Read this card first. Load a section below only when the task needs it.

| | |
|---|---|
| **Use when** | Writing or reviewing Java 17/21 code, with or without Spring Boot |
| **Skip when** | Spring internals (AOP, WebFlux, Batch) — `spring_advanced_skill` |
| **Inputs** | Java version (§1 — detect first), build tool, existing conventions |
| **Produces** | Idiomatic Java with Javadoc and JUnit 5 tests |
| **Steps** | 1. Detect JDK and Spring Boot versions → 2. Model data (records, sealed types) → 3. Apply OOP pillars → 4. Javadoc → 5. Tests |
| **Done when** | §7 quality rules hold; tests in the same change |
| **Senior defaults** | Records for DTOs and value types · sealed interfaces + exhaustive `switch` for closed result types · virtual threads for blocking I/O on 21 (`spring.threads.virtual.enabled=true`) · constructor injection only · `Optional` for nullable returns, never `null` from public methods · JPQL named parameters, never concatenation |
| **Load on demand** | §1 version detection · §2 OOP in Java · §3 Java 17/21 features · §4 Spring Boot 3 · §5 Javadoc · §6 testing · §7 rules |
| **Run report** | `html_report_skill` — adds: Java features used, with version gates |
| **Pairs with** | `spring_advanced_skill`, `maven_skill`, `lombok_skill`, `logger_skill`, `test_skill` |

---

## 1. Version Detection First

Before writing any Java code, check what is installed:

```bash
java -version
mvn -version
```

Then match features to what is available:

| Java Version | Use These Features |
|-------------|-------------------|
| Java 11 | `var`, HTTP Client, `Optional`, lambda, streams |
| Java 17 (LTS) | All above + **records**, **sealed classes**, **text blocks**, switch expressions |
| Java 21 (LTS) | All above + **virtual threads** (`Thread.ofVirtual()`), **pattern matching for switch**, sequenced collections |

---

## 2. Four OOP Pillars — Applied in Java

### 2.1 Encapsulation — Control What Can Change

Keep fields private. Provide controlled access through methods.

```java
/**
 * Represents a customer's bank account.
 *
 * <p>Balance can only change through deposit() and withdraw().
 * Direct field access is not allowed outside this class.</p>
 */
public class BankAccount {

    /** The account owner's full name. Immutable after creation. */
    private final String ownerName;

    /** Current balance in the account currency. Modified only via transactions. */
    private double balance;

    /**
     * Creates a new bank account.
     *
     * @param ownerName     the full name of the account holder
     * @param initialBalance starting balance — must be zero or positive
     * @throws IllegalArgumentException if initialBalance is negative
     */
    public BankAccount(String ownerName, double initialBalance) {
        if (initialBalance < 0) {
            throw new IllegalArgumentException(
                "Initial balance cannot be negative. Got: " + initialBalance
            );
        }
        this.ownerName = ownerName;
        this.balance   = initialBalance;
    }

    /**
     * Deposits money into the account.
     *
     * @param amount amount to deposit — must be positive
     * @throws IllegalArgumentException if amount is zero or negative
     */
    public void deposit(double amount) {
        if (amount <= 0) {
            throw new IllegalArgumentException("Deposit must be positive. Got: " + amount);
        }
        this.balance += amount;
    }

    /** Returns the current balance. Callers can read it but not set it directly. */
    public double getBalance() {
        return balance;
    }

    /** Returns the account owner's name. */
    public String getOwnerName() {
        return ownerName;
    }
}
```

### 2.2 Abstraction — Define WHAT, Not HOW

Use interfaces to define the contract. Implementations provide the detail.

```java
/**
 * Defines how notifications are sent.
 *
 * <p>Any class that wants to send notifications should use this interface.
 * This means you can swap email for SMS or push without changing the callers.</p>
 */
public interface NotificationSender {

    /**
     * Sends a notification to the recipient.
     *
     * @param recipient the address to send to (email, phone number, device token)
     * @param subject   a short title for the notification
     * @param message   the full notification content
     * @return true if the notification was delivered successfully
     */
    boolean send(String recipient, String subject, String message);
}


/**
 * Sends notifications via email using JavaMail.
 *
 * <p>Implements {@link NotificationSender} for the email channel.</p>
 */
public class EmailNotificationSender implements NotificationSender {

    private final JavaMailSender mailSender;
    private final String fromAddress;

    /**
     * @param mailSender   the Spring Mail component to use for sending
     * @param fromAddress  the "From" email address for outbound messages
     */
    public EmailNotificationSender(JavaMailSender mailSender, String fromAddress) {
        this.mailSender  = mailSender;
        this.fromAddress = fromAddress;
    }

    @Override
    public boolean send(String recipient, String subject, String message) {
        SimpleMailMessage mail = new SimpleMailMessage();
        mail.setFrom(fromAddress);
        mail.setTo(recipient);
        mail.setSubject(subject);
        mail.setText(message);
        mailSender.send(mail);
        return true;
    }
}
```

### 2.3 Inheritance — Shared Behaviour, Specialised Differences

Use inheritance for true "is-a" relationships. Keep hierarchies shallow (max 2–3 levels).

```java
/**
 * Base class for all payment types processed by this system.
 *
 * <p>Holds the common fields (amount, currency, reference) and defines
 * the process() method that each payment type must implement.</p>
 */
public abstract class Payment {

    protected final double amount;
    protected final String currency;
    protected final String referenceId;

    /**
     * @param amount      the payment amount — must be positive
     * @param currency    the ISO 4217 currency code (e.g. "GBP")
     * @param referenceId a unique reference for this payment
     */
    protected Payment(double amount, String currency, String referenceId) {
        this.amount      = amount;
        this.currency    = currency;
        this.referenceId = referenceId;
    }

    /**
     * Processes this payment through its specific channel.
     *
     * @return a {@link PaymentResult} indicating success or failure with details
     */
    public abstract PaymentResult process();

    /** Returns the payment amount. */
    public double getAmount() { return amount; }

    /** Returns the ISO 4217 currency code. */
    public String getCurrency() { return currency; }
}


/**
 * Processes payments via a credit or debit card.
 *
 * <p>Extends {@link Payment} with card-specific fields and card gateway logic.</p>
 */
public class CardPayment extends Payment {

    private final String maskedCardNumber;   // e.g. "****-****-****-1234"
    private final String cardHolderName;

    /**
     * @param amount            payment amount
     * @param currency          ISO 4217 currency code
     * @param referenceId       unique payment reference
     * @param maskedCardNumber  last 4 digits shown (e.g. "****1234")
     * @param cardHolderName    name on the card
     */
    public CardPayment(double amount, String currency, String referenceId,
                       String maskedCardNumber, String cardHolderName) {
        super(amount, currency, referenceId);
        this.maskedCardNumber = maskedCardNumber;
        this.cardHolderName   = cardHolderName;
    }

    @Override
    public PaymentResult process() {
        // Card gateway integration logic goes here
        return PaymentResult.success(referenceId);
    }
}
```

### 2.4 Polymorphism — Write Code to the Interface

```java
/**
 * Sends a payment confirmation to the customer after a successful transaction.
 *
 * <p>This method works with any {@link NotificationSender} implementation.
 * You can pass an email sender, SMS sender, or push sender — this code
 * does not need to know which one.</p>
 *
 * @param sender    the notification channel to use
 * @param recipient the customer's contact address
 * @param payment   the payment that was just processed
 */
public void sendConfirmation(NotificationSender sender, String recipient, Payment payment) {
    String subject = "Payment confirmed — " + payment.getReferenceId();
    String message = String.format("Your payment of %.2f %s has been received.",
                                   payment.getAmount(), payment.getCurrency());
    sender.send(recipient, subject, message);
}
```

---

## 3. Java 17 / 21 Modern Features

### Records (Java 17+) — Immutable Data Carriers

Use records for request/response objects and value types. They are immutable by design.

```java
/**
 * Request object for creating a new customer order.
 *
 * <p>Uses a Java record — all fields are final, getters are auto-generated,
 * and equals/hashCode/toString are included for free.</p>
 *
 * @param customerId the ID of the customer placing the order — must be positive
 * @param items      list of items to include — must not be empty
 */
public record CreateOrderRequest(
    @NotNull Long customerId,
    @NotEmpty List<String> items
) {}
```

### Sealed Classes (Java 17+) — Controlled Hierarchies

Use sealed classes when you have a fixed set of subtypes:

```java
/**
 * Represents the result of a payment operation.
 *
 * <p>Can only be a {@link Success} or a {@link Failure} —
 * no other subtypes are allowed. This makes switch expressions exhaustive.</p>
 */
public sealed interface PaymentResult permits PaymentResult.Success, PaymentResult.Failure {

    /** Creates a successful result with the transaction ID. */
    static PaymentResult success(String transactionId) {
        return new Success(transactionId);
    }

    /** Creates a failure result with a human-readable reason. */
    static PaymentResult failure(String reason) {
        return new Failure(reason);
    }

    /** Returned when the payment was processed successfully. */
    record Success(String transactionId) implements PaymentResult {}

    /** Returned when the payment failed, with the reason why. */
    record Failure(String reason) implements PaymentResult {}
}

// Usage — switch is exhaustive, no default needed
String message = switch (result) {
    case PaymentResult.Success s -> "Payment " + s.transactionId() + " succeeded";
    case PaymentResult.Failure f -> "Payment failed: " + f.reason();
};
```

### Virtual Threads (Java 21+) — Simple Concurrency

```java
// Traditional thread pool — complex setup
ExecutorService executor = Executors.newFixedThreadPool(200);

// Virtual threads (Java 21) — simple, scales to millions
// In Spring Boot 3.2+, enable with: spring.threads.virtual.enabled=true
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();

// Or create a single virtual thread:
Thread.ofVirtual()
      .name("order-processor")
      .start(() -> processOrder(orderId));
```

---

## 4. Spring Boot 3.x Patterns

### Layered Architecture (Always Follow This)

```java
REST Controller   → Receives HTTP requests, calls Service, returns responses
Service Interface → Defines the business operations (what)
Service Impl      → Implements the business logic (how)
Repository        → Data access (Spring Data JPA interface)
Entity            → JPA entity (maps to a DB table)
DTO               → What goes in/out of the API (not the entity)
```

### Constructor Injection (Always)

```java
// ❌ WRONG — field injection makes testing harder and hides dependencies
@Service
public class OrderService {
    @Autowired
    private OrderRepository repository;
}

// ✅ CORRECT — constructor injection is explicit and testable
@Service
@RequiredArgsConstructor   // Lombok generates the constructor
public class OrderServiceImpl implements OrderService {

    private final OrderRepository repository;  // injected via constructor
}
```

### application.yml Recommended Defaults

```yaml
spring:
  jpa:
    open-in-view: false        # Prevents lazy loading outside transactions
    show-sql: false            # Only enable during development

  mvc:
    problemdetails:
      enabled: true            # Use RFC 9457 error format in responses

# Java 21 + Spring Boot 3.2+ — enable virtual threads for better throughput
spring:
  threads:
    virtual:
      enabled: true
```

---

## 5. Javadoc Standards

Every public class and method must have Javadoc. No exceptions.

```java
/**
 * [One-sentence summary of what this class is and what it does.]
 *
 * <p>[Optional: One paragraph of context — why does this class exist?
 * What problem does it solve? What are its key responsibilities?]</p>
 *
 * @author [Team or developer name]
 * @since  [Version or sprint when this was added]
 */
public class YourClass {

    /**
     * [One-sentence summary of what this method does.]
     *
     * <p>[Optional extra context for non-obvious logic.]</p>
     *
     * @param paramName [what it is, any constraints — e.g. "must not be null", "must be positive"]
     * @return          [what is returned and when]
     * @throws SomeException [when this exception is thrown and why]
     */
    public ReturnType methodName(ParamType paramName) { }
}
```

---

## 6. Testing Standards

### Unit Tests — JUnit 5 + Mockito

```java
/**
 * Unit tests for {@link OrderServiceImpl}.
 *
 * <p>Mocks are used for all dependencies. No Spring context or database
 * is loaded — these tests run in milliseconds.</p>
 */
@ExtendWith(MockitoExtension.class)
class OrderServiceImplTest {

    // ── Test naming: givenContext_whenAction_thenExpectedOutcome ──────────

    @Test
    @DisplayName("Given valid request, when createOrder, then saves and returns order")
    void givenValidRequest_whenCreateOrder_thenSavesAndReturnsOrder() {
        // Arrange — set up the world for this test
        ...
        // Act — call the method under test
        ...
        // Assert — verify the outcome
        ...
    }

    @ParameterizedTest
    @NullSource
    @ValueSource(longs = {0L, -1L, -100L})
    @DisplayName("Given invalid customer ID, when createOrder, then throws exception")
    void givenInvalidCustomerId_whenCreateOrder_thenThrowsException(Long customerId) {
        // Tests multiple bad inputs with one test method
    }
}
```

### Integration Tests — @SpringBootTest + Testcontainers

```java
/**
 * Integration test for the orders REST endpoint.
 *
 * <p>Starts the full Spring context and a real PostgreSQL database via
 * Testcontainers. Tests the complete request → response cycle.</p>
 */
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class OrderControllerIntegrationTest {

    @Test
    @DisplayName("POST /api/v1/orders — valid request should return HTTP 201")
    void givenValidRequest_whenPostOrder_thenReturns201() throws Exception {
        mockMvc.perform(post("/api/v1/orders")
                .contentType(MediaType.APPLICATION_JSON)
                .content("""
                    {
                        "customerId": 1,
                        "items": ["product-A", "product-B"]
                    }
                    """))
               .andExpect(status().isCreated())
               .andExpect(jsonPath("$.id").isNotEmpty())
               .andExpect(jsonPath("$.status").value("PENDING"));
    }
}
```

---

## 7. Code Quality Rules (Quick Reference)

| Rule | Detail |
|------|--------|
| Field injection | Never — use constructor injection |
| Magic numbers/strings | Use enums or named constants |
| Method length | ≤ 20 lines — extract to private helpers |
| Class length | ≤ 300 lines — split by responsibility |
| Exception swallowing | Never — always log or rethrow |
| Logging | SLF4J only — never `System.out.println` |
| Nulls | Use `Optional<T>` for nullable returns — never return `null` from public methods |
| SQL in strings | Use JPQL with named parameters — never concatenate |

Files in this skill

  • README.md10.2 KB
  • adr_skill.md8.4 KB
  • agent_skill_design_skill.md3.1 KB
  • apache_camel_skill.md15.5 KB
  • apache_pulsar_skill.md17.1 KB
  • ba_create_skill.md18.9 KB
  • backend_skill.md22.1 KB
  • code_documentation_skill.md13.4 KB
  • code_formatting_skill.md11.7 KB
  • code_health_skill.md9.8 KB
  • code_review_skill.md36.7 KB
  • context_builder_skill.md11.7 KB
  • current_tech_spec_skill.md6.3 KB
  • database_skill.md18.4 KB
  • debugging_skill.md3.4 KB
  • error_handling_skill.md18.4 KB
  • frontend_skill.md23.6 KB
  • java_advanced_skill.md15 KB
  • jira_html_report_skill.md15.5 KB
  • jira_incremental_spec_generator_skill.md19.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.