Java Integration

Java integration patterns with zero-dependency core client and Spring Boot configuration.

Copy these patterns into your project to integrate gkCAPTCHA server-side verification.

Installation

Core Client

build.gradle.kts
// Gradle (Kotlin DSL)
dependencies {
    implementation("sa.gatekeeper:gkcaptcha-java:0.1.0")
}
pom.xml
<!-- Maven -->
<dependency>
    <groupId>sa.gatekeeper</groupId>
    <artifactId>gkcaptcha-java</artifactId>
    <version>0.1.0</version>
</dependency>

Spring Boot Starter

build.gradle.kts
// Spring Boot starter — Gradle (Kotlin DSL)
dependencies {
    implementation("sa.gatekeeper:gkcaptcha-spring-boot-starter:0.1.0")
}

Quick Start

Application.java
import sa.gatekeeper.*;

// Build the client once and reuse it (thread-safe)
GkCaptchaConfig config = GkCaptchaConfig.builder()
    .secretKey(System.getenv("GKCAPTCHA_SECRET_KEY"))
    .siteKey(System.getenv("GKCAPTCHA_SITE_KEY"))
    .build();

GkCaptchaClient client = new GkCaptchaClient(config);

// Synchronous verification
VerifyTokenResponse result = client.verifyToken(captchaToken);
if (!result.success()) {
    throw new ForbiddenException("CAPTCHA verification failed: " + result.error());
}

// Asynchronous verification
client.verifyTokenAsync(captchaToken)
    .thenAccept(r -> {
        if (!r.success()) throw new CompletionException(new ForbiddenException("CAPTCHA failed"));
    });

Spring Boot Integration

Spring Boot Configuration

application.yml
# application.yml
gkcaptcha:
  secret-key: ${GKCAPTCHA_SECRET_KEY}
  site-key: ${GKCAPTCHA_SITE_KEY}
  api-url: https://gkcaptcha.gatekeeper.sa  # optional, default
  timeout: 5s                     # optional, default
  max-retries: 1                  # optional, default
  fail-closed: false              # optional, default (fail-open)

@RequireCaptcha Annotation

Apply to any controller method. Reads the token from the gk-captcha-token form field or X-Gk-Captcha-Token header.

AuthController.java
import org.springframework.web.bind.annotation.*;
import sa.gatekeeper.spring.RequireCaptcha;

@RestController
public class AuthController {

    @PostMapping("/login")
    @RequireCaptcha
    public ResponseEntity<?> login(@RequestBody LoginRequest req) {
        // CAPTCHA has already been verified by the aspect
        return ResponseEntity.ok().build();
    }
}

Route-Level Filter

application.yml
# application.yml — route-level filter
gkcaptcha:
  secret-key: ${GKCAPTCHA_SECRET_KEY}
  site-key: ${GKCAPTCHA_SITE_KEY}
  filter:
    enabled: true
    url-patterns:
      - /api/submit
      - /login
      - /register

Error Handling

By default (fail-open), if the gkCAPTCHA API is unreachable after retries, the client returns a synthetic success response with failOpen() == true. Set failClosed(true) to throw GkCaptchaException instead.

افتراضيًا (فتح عند الفشل)، إذا كانت واجهة gkCAPTCHA غير متاحة، يُرجع العميل استجابة نجاح اصطناعية. لتغيير هذا السلوك استخدم failClosed(true).

ErrorHandling.java
VerifyTokenResponse result = client.verifyToken(token);
if (result.failOpen()) {
    log.warn("gkCAPTCHA API unreachable - request allowed through (fail-open)");
}

// To enforce fail-closed:
GkCaptchaConfig config = GkCaptchaConfig.builder()
    .secretKey("...")
    .siteKey("...")
    .failClosed(true)  // throws GkCaptchaException("NETWORK_ERROR") on API failure
    .build();

Environment Variables

VariableRequiredDescription
GKCAPTCHA_SECRET_KEYYesSecret key from gatekeeper.sa dashboard
GKCAPTCHA_SITE_KEYYesSite key from gatekeeper.sa dashboard
GKCAPTCHA_API_URLNoOverride API URL (default: https://gkcaptcha.gatekeeper.sa)