Chaturmind
LearnDSASystem DesignInterview PrepDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth
  • Java Interview Prep

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Java Interview Prep: 8+ Years (Senior & Lead)

Expert Core Java

  • Tricky Java Output, Operators & OOP Edge Cases — Interview Questions
  • Tricky Exceptions, Memory & Keyword Questions — Interview Questions
  • Classic Java Language Questions, Senior-Grade Answers — Interview Questions
  • Classic Collections, Threads & JDK APIs, Senior-Grade Answers — Interview Questions
  • Reflection, Dynamic Proxies, final & Modern OOP Design — Interview Questions

JVM Internals & Performance

  • Class Loading, Bytecode & Object Layout — Interview Questions
  • JIT Compilation & Runtime Optimisations — Interview Questions
  • Garbage Collectors Deep Dive — Interview Questions
  • JVM Tuning, GC Logs & Memory Footprint — Interview Questions
  • Memory Leaks, OutOfMemoryErrors & Profiling Tools — Interview Questions
  • Modules, Agents & Advanced JVM APIs — Interview Questions

Collections & Concurrency at Scale

  • Collections Internals & Complexity — Interview Questions
  • Iterators, Comparators & Ordering Contracts — Interview Questions
  • Concurrent Collections, Queues & Lock-Free Structures — Interview Questions
  • Threads, Executors & ForkJoin Internals — Interview Questions
  • Locks, Atomics, CAS & Synchronizers — Interview Questions
  • Java Memory Model, volatile, Fences & ThreadLocal — Interview Questions
  • Deadlock, Livelock, Starvation & Concurrent Design — Interview Questions
  • CompletableFuture, Parallel Streams & Non-Blocking I/O — Interview Questions

Modern Java (8 to 21+)

  • Lambdas & Functional Interfaces Internals — Interview Questions
  • Streams & Collectors Deep Dive — Interview Questions
  • Optional & Interface Default/Static Methods — Interview Questions
  • Java 9–25 Features & Virtual Threads — Interview Questions

Design Patterns, SOLID & Clean Code

  • Design Pattern Trade-offs & Combinations — Interview Questions
  • SOLID, Clean Code & Anti-Patterns — Interview Questions

Spring & Spring Boot Internals

  • IoC, Dependency Injection & Bean Lifecycle Internals — Interview Questions
  • Spring AOP, Proxies & @Async Internals — Interview Questions
  • Spring Configuration, Auto-Configuration & Custom Starters — Interview Questions
  • Spring MVC & REST Internals, Exception Frameworks — Interview Questions
  • Spring Security Advanced Internals — Interview Questions
  • Spring WebFlux, Reactor & R2DBC — Interview Questions
  • Spring Cloud, Observability & Distributed Tracing — Interview Questions
  • Spring Boot 3, Native Images & Production Scenarios — Interview Questions

JPA, Hibernate & Databases at Scale

  • Spring Data JPA — Queries, Projections, Custom Repositories & Locking — Interview Questions
  • JPA Entity Mapping, Associations & Cascades — Interview Questions
  • JPQL vs Native Queries in Depth — Interview Questions
  • Hibernate Caching — First-Level, Second-Level & Query Cache — Interview Questions
  • Lazy vs Eager Loading, LazyInitializationException & N+1 — Interview Questions
  • JPA Transactions, Propagation, Isolation & Dirty Checking — Interview Questions
  • SQL vs NoSQL, Indexing & Query Tuning — Interview Questions
  • Database Scaling, Replication, Pooling & Consistency Models — Interview Questions
  • Redis, Search, Time-Series, CDC & Transactional Data Modelling — Interview Questions

Testing Strategy & API Design

  • Spring Boot Test Slices, Context & Test Strategy — Interview Questions
  • Testing Web, Persistence, Security, Async & Messaging in Spring Boot — Interview Questions
  • JUnit 5 & Mockito, Advanced — Interview Questions
  • MockMvc, WebTestClient & Testcontainers in Depth — Interview Questions
  • REST Principles, Status Codes & Resource Design — Interview Questions
  • OpenAPI, Validation Errors, API Versioning & GraphQL — Interview Questions

Build, DevOps & Cloud

  • Maven & Gradle at Scale — Interview Questions
  • Git, CI/CD Pipelines & Release Safety — Interview Questions
  • Docker & Kubernetes for Java Engineers — Interview Questions
  • Quality Gates, Artifact Repositories & Secrets Management — Interview Questions
  • AWS Deployment & Scaling for Spring Boot — Interview Questions
  • Multi-Cloud Deployment, High Availability, Cost & Cloud Troubleshooting — Interview Questions

Kafka & Messaging

  • Kafka Internals & Delivery Semantics — Interview Questions
  • Spring Kafka — Error Handling, DLQs, Schemas & Operations — Interview Questions
  • RabbitMQ, JMS & Messaging Models — Interview Questions

Microservices & Architecture

  • Distributed Systems Fundamentals — CAP, Consistency, Availability & SLOs — Interview Questions
  • DDD, Hexagonal Architecture & Service Boundaries — Interview Questions
  • Event-Driven Architecture, CQRS, Event Sourcing, Sharding & Idempotency — Interview Questions
  • Rate Limiting, Resilience, Caching at Scale & Chaos Engineering — Interview Questions
  • Files, Documents & Internationalisation in Java Backends — Interview Questions
  • WebSockets, Schedulers, Notifications & Real-Time Pipelines — Interview Questions

System Design Scenarios

  • Booking Systems, CRS, Inventory & Concurrency Control — Interview Questions
  • Dynamic Pricing & Rule Engines — Interview Questions
  • Partner Integrations — OTA Sync, Retries, Webhooks, Reconciliation & Bulk Data — Interview Questions
  • Designing Caches & Rate Limiters — Interview Questions
  • Event-Driven Architecture, Kafka at Scale, IoT & Real-Time Pipelines — Interview Questions
  • Observability, Logging, Alerting & Audit Systems — Interview Questions
  • Multi-Tenant SaaS, Identity & Platform Services — Interview Questions
  • Search, Notifications, Chat, Fraud Detection & Workflows — Interview Questions
  • Extreme Scale, 99.99% Availability, DR & Project Deep-Dive Stories — Interview Questions

Security for Senior Engineers

  • Tokens, OAuth2 PKCE, Web Attacks & API Security — Interview Questions
  • TLS, mTLS, Zero Trust, Secrets, DDoS & Privacy Compliance — Interview Questions

Leadership & Behavioural

  • Leadership Style, Motivation & Team Health — Interview Questions
  • Delivery, Planning & Decisions Under Uncertainty — Interview Questions
  • Problem Solving, Growth & Career Stories — Interview Questions
  • Stakeholder Communication, Ethics & Compliance — Interview Questions
  • Mentoring, Knowledge Sharing & Code Reviews — Interview Questions
  • Agile & Scrum Practices for Senior Engineers — Interview Questions
  • Architecture Decision-Making — Interview Questions
  • Conflict Resolution & Difficult Conversations — Interview Questions
Chaturmind
← Java Interview Prep: 8+ Years (Senior & Lead)

Expert Core Java

  • Tricky Java Output, Operators & OOP Edge Cases — Interview Questions
  • Tricky Exceptions, Memory & Keyword Questions — Interview Questions
  • Classic Java Language Questions, Senior-Grade Answers — Interview Questions
  • Classic Collections, Threads & JDK APIs, Senior-Grade Answers — Interview Questions
  • Reflection, Dynamic Proxies, final & Modern OOP Design — Interview Questions

JVM Internals & Performance

  • Class Loading, Bytecode & Object Layout — Interview Questions
  • JIT Compilation & Runtime Optimisations — Interview Questions
  • Garbage Collectors Deep Dive — Interview Questions
  • JVM Tuning, GC Logs & Memory Footprint — Interview Questions
  • Memory Leaks, OutOfMemoryErrors & Profiling Tools — Interview Questions
  • Modules, Agents & Advanced JVM APIs — Interview Questions

Collections & Concurrency at Scale

  • Collections Internals & Complexity — Interview Questions
  • Iterators, Comparators & Ordering Contracts — Interview Questions
  • Concurrent Collections, Queues & Lock-Free Structures — Interview Questions
  • Threads, Executors & ForkJoin Internals — Interview Questions
  • Locks, Atomics, CAS & Synchronizers — Interview Questions
  • Java Memory Model, volatile, Fences & ThreadLocal — Interview Questions
  • Deadlock, Livelock, Starvation & Concurrent Design — Interview Questions
  • CompletableFuture, Parallel Streams & Non-Blocking I/O — Interview Questions

Modern Java (8 to 21+)

  • Lambdas & Functional Interfaces Internals — Interview Questions
  • Streams & Collectors Deep Dive — Interview Questions
  • Optional & Interface Default/Static Methods — Interview Questions
  • Java 9–25 Features & Virtual Threads — Interview Questions

Design Patterns, SOLID & Clean Code

  • Design Pattern Trade-offs & Combinations — Interview Questions
  • SOLID, Clean Code & Anti-Patterns — Interview Questions

Spring & Spring Boot Internals

  • IoC, Dependency Injection & Bean Lifecycle Internals — Interview Questions
  • Spring AOP, Proxies & @Async Internals — Interview Questions
  • Spring Configuration, Auto-Configuration & Custom Starters — Interview Questions
  • Spring MVC & REST Internals, Exception Frameworks — Interview Questions
  • Spring Security Advanced Internals — Interview Questions
  • Spring WebFlux, Reactor & R2DBC — Interview Questions
  • Spring Cloud, Observability & Distributed Tracing — Interview Questions
  • Spring Boot 3, Native Images & Production Scenarios — Interview Questions

JPA, Hibernate & Databases at Scale

  • Spring Data JPA — Queries, Projections, Custom Repositories & Locking — Interview Questions
  • JPA Entity Mapping, Associations & Cascades — Interview Questions
  • JPQL vs Native Queries in Depth — Interview Questions
  • Hibernate Caching — First-Level, Second-Level & Query Cache — Interview Questions
  • Lazy vs Eager Loading, LazyInitializationException & N+1 — Interview Questions
  • JPA Transactions, Propagation, Isolation & Dirty Checking — Interview Questions
  • SQL vs NoSQL, Indexing & Query Tuning — Interview Questions
  • Database Scaling, Replication, Pooling & Consistency Models — Interview Questions
  • Redis, Search, Time-Series, CDC & Transactional Data Modelling — Interview Questions

Testing Strategy & API Design

  • Spring Boot Test Slices, Context & Test Strategy — Interview Questions
  • Testing Web, Persistence, Security, Async & Messaging in Spring Boot — Interview Questions
  • JUnit 5 & Mockito, Advanced — Interview Questions
  • MockMvc, WebTestClient & Testcontainers in Depth — Interview Questions
  • REST Principles, Status Codes & Resource Design — Interview Questions
  • OpenAPI, Validation Errors, API Versioning & GraphQL — Interview Questions

Build, DevOps & Cloud

  • Maven & Gradle at Scale — Interview Questions
  • Git, CI/CD Pipelines & Release Safety — Interview Questions
  • Docker & Kubernetes for Java Engineers — Interview Questions
  • Quality Gates, Artifact Repositories & Secrets Management — Interview Questions
  • AWS Deployment & Scaling for Spring Boot — Interview Questions
  • Multi-Cloud Deployment, High Availability, Cost & Cloud Troubleshooting — Interview Questions

Kafka & Messaging

  • Kafka Internals & Delivery Semantics — Interview Questions
  • Spring Kafka — Error Handling, DLQs, Schemas & Operations — Interview Questions
  • RabbitMQ, JMS & Messaging Models — Interview Questions

Microservices & Architecture

  • Distributed Systems Fundamentals — CAP, Consistency, Availability & SLOs — Interview Questions
  • DDD, Hexagonal Architecture & Service Boundaries — Interview Questions
  • Event-Driven Architecture, CQRS, Event Sourcing, Sharding & Idempotency — Interview Questions
  • Rate Limiting, Resilience, Caching at Scale & Chaos Engineering — Interview Questions
  • Files, Documents & Internationalisation in Java Backends — Interview Questions
  • WebSockets, Schedulers, Notifications & Real-Time Pipelines — Interview Questions

System Design Scenarios

  • Booking Systems, CRS, Inventory & Concurrency Control — Interview Questions
  • Dynamic Pricing & Rule Engines — Interview Questions
  • Partner Integrations — OTA Sync, Retries, Webhooks, Reconciliation & Bulk Data — Interview Questions
  • Designing Caches & Rate Limiters — Interview Questions
  • Event-Driven Architecture, Kafka at Scale, IoT & Real-Time Pipelines — Interview Questions
  • Observability, Logging, Alerting & Audit Systems — Interview Questions
  • Multi-Tenant SaaS, Identity & Platform Services — Interview Questions
  • Search, Notifications, Chat, Fraud Detection & Workflows — Interview Questions
  • Extreme Scale, 99.99% Availability, DR & Project Deep-Dive Stories — Interview Questions

Security for Senior Engineers

  • Tokens, OAuth2 PKCE, Web Attacks & API Security — Interview Questions
  • TLS, mTLS, Zero Trust, Secrets, DDoS & Privacy Compliance — Interview Questions

Leadership & Behavioural

  • Leadership Style, Motivation & Team Health — Interview Questions
  • Delivery, Planning & Decisions Under Uncertainty — Interview Questions
  • Problem Solving, Growth & Career Stories — Interview Questions
  • Stakeholder Communication, Ethics & Compliance — Interview Questions
  • Mentoring, Knowledge Sharing & Code Reviews — Interview Questions
  • Agile & Scrum Practices for Senior Engineers — Interview Questions
  • Architecture Decision-Making — Interview Questions
  • Conflict Resolution & Difficult Conversations — Interview Questions
HomeLearnJava Interview PrepJava Interview Prep: 8+ Years (Senior & Lead)Testing Strategy & API Design
✓ FreeAdvanced· 14 min read

OpenAPI, Validation Errors, API Versioning & GraphQL — Interview Questions

Documenting file uploads, pagination and examples in OpenAPI, @ApiResponse/@ApiOperation vs springdoc's @Operation, serving Swagger UI, hiding endpoints, annotations vs YAML-first specs, versioning OpenAPI docs, contract testing and conformance checks; handling validation exceptions, custom error formats, business exceptions with HTTP semantics, MethodArgumentNotValidException, @Valid vs @Validated, validation groups, nested constraint violations, not leaking internals; versioning strategies and preferences, backward compatibility, graceful deprecation, multiple versions with routes, content-negotiation versioning, detecting outdated clients, evolving without breaking consumers; and GraphQL — implementing, securing, and REST vs GraphQL.

Published September 25, 2026


How to use this lesson

API contracts are long-lived promises. Show:

  • that the documentation is generated from, or validated against, the implementation;
  • that errors are consistent and safe;
  • that versioning is a last resort, after backward-compatible evolution.

Q1. How do you generate and serve Swagger UI in Spring Boot? What are @ApiResponse and @ApiOperation?

Short answer:

  • springdoc-openapi (org.springdoc:springdoc-openapi-starter-webmvc-ui, or the -webflux-ui variant) is the current choice for Spring Boot 3. It scans the controllers at runtime, and serves:

    • /v3/api-docs (the OpenAPI 3 JSON or YAML);
    • /swagger-ui.html.

    Configure it with springdoc.* properties, and group APIs with GroupedOpenApi. Springfox is dead (it doesn't support Boot 3).

  • The annotations:

    • @ApiOperation/@ApiResponse (with @ApiParam) are Swagger 2 / Springfox annotations (io.swagger.annotations);
    • in OpenAPI 3 (swagger-core v3, used by springdoc), the equivalents are @Operation(summary, description), @ApiResponse(responseCode, description, content), @Parameter, @Schema, @Tag and @SecurityRequirement. They enrich the generated spec with descriptions, error responses, examples and security.
@Operation(summary = "Create order", description = "Idempotent via Idempotency-Key header")
@ApiResponse(responseCode = "201", description = "Created")
@ApiResponse(responseCode = "409", description = "Duplicate idempotency key with different payload",
             content = @Content(mediaType = "application/problem+json", schema = @Schema(implementation = ProblemDetail.class)))
@PostMapping("/orders")
ResponseEntity<OrderDto> create(@Valid @RequestBody CreateOrderRequest req, @RequestHeader("Idempotency-Key") String key) { ... }

Q2. How do you document a file-upload API, paginated endpoints, and request or response examples in OpenAPI?

Short answer:

  • File upload: requestBody with content: multipart/form-data, and a schema with type: string, format: binary for the file part, plus the other fields. In springdoc, use @RequestPart MultipartFile file (detected automatically), and @Schema for the metadata parts. Document the size limits and allowed types in the descriptions.
  • Pagination:
    • document the query parameters (page, size, sort, or cursor/limit), with defaults and maximums (@ParameterObject Pageable in springdoc);
    • define a response envelope schema (items, nextCursor, totalElements), or document the Link headers;
    • use reusable components (#/components/schemas/PageOfOrderDto).
  • Examples: @ExampleObjects on @Content (several named examples: a success and each error case), or example values on @Schema fields. In YAML-first specs, use examples: per media type. Keep the examples realistic and valid: they drive mocks and SDK documentation.

Q3. How do you hide certain endpoints from Swagger?

Short answer:

  • @Hidden (on a controller or method) or @Operation(hidden = true);
  • path or package filters: springdoc.paths-to-exclude=/internal/** and springdoc.packages-to-scan;
  • GroupedOpenApi, which exposes only public groups;
  • disable the documentation in production entirely: springdoc.api-docs.enabled=false and springdoc.swagger-ui.enabled=false, or protect them behind authentication.

Hiding isn't securing. Internal endpoints still need authorisation and network restrictions.

Q4. What are the pros and cons of annotation-generated specs vs YAML-first (design-first) OpenAPI?

Short answer:

  • Code-first (annotations plus generation):
    • Pros: the spec can't drift from the code, it's easy to start, and developers stay in Java.
    • Cons: the spec quality depends on annotation discipline; controllers get cluttered; the design happens after implementation; it's harder for non-Java consumers to review early; and there's accidental exposure of internal model details.
  • Design-first (YAML spec as the source of truth):
    • Pros: a consumer-driven design reviewed before coding; generated server interfaces and clients (OpenAPI Generator); parallel mocking; clean, reviewable diffs; linting with Spectral; easy breaking-change detection.
    • Cons: generator quirks, and a build step. You must verify that the implementation conforms (generated interfaces help: the build breaks if the code doesn't match).

Many organisations use design-first for public or shared APIs, and code-first for internal ones, with conformance checks either way.

Q5. How do you version OpenAPI documents for different API versions? What are the implications of versioning in the docs?

Short answer:

  • One spec per major version (openapi-v1.yaml, openapi-v2.yaml) with info.version set, served at separate URLs (/v3/api-docs/v1, through springdoc GroupedOpenApi per version path), and published in a developer portal with a changelog.
  • The implications:
    • you maintain parallel docs and SDKs;
    • deprecations are marked with deprecated: true on operations or fields, plus sunset dates;
    • breaking-change detection in CI (openapi-diff, oasdiff breaking) compares against the last released spec;
    • examples and tests for each supported version.
  • info.version tracks the document's own version (it can be semantic-versioned, with minor additive changes), separately from the major API version in the URL.

Q6. How can Swagger/OpenAPI help with contract testing? How do you verify that the implementation matches the spec?

Short answer:

  • Validate the requests and responses against the spec in tests: Atlassian swagger-request-validator (with MockMvc or RestAssured integration), openapi4j, or openapi-spec-validator wrappers. That fails the test if a response has undocumented fields or wrong types or statuses.
  • Generate code from the spec: server interfaces (the build fails if controllers don't implement them) and clients for consumers.
  • Schemathesis or Dredd: property-based fuzzing of the running API from the spec (it finds 500s and schema violations).
  • Breaking-change checks in CI (oasdiff).
  • Consumer-driven contracts (Pact, Spring Cloud Contract) complement spec validation, by verifying the specific interactions consumers rely on.
  • Mock servers from the spec (Prism) let consumers test against the contract.

Q7. How do you handle validation exceptions in a REST controller? How does Spring handle MethodArgumentNotValidException?

Short answer:

  • The flow: @Valid @RequestBody → the RequestResponseBodyMethodProcessor validates → on failure it throws MethodArgumentNotValidException (with a BindingResult). For @RequestParam/@PathVariable constraints with method validation (Spring 6.1+), it's HandlerMethodValidationException; for @Validated services, ConstraintViolationException.
  • Default handling: ResponseEntityExceptionHandler (or Boot's default error handling) returns 400. With spring.mvc.problemdetails.enabled=true, you get a ProblemDetail body.
  • The best practice: a @RestControllerAdvice (extending ResponseEntityExceptionHandler) that overrides handleMethodArgumentNotValid, and returns structured field errors, consistently, for all three exception types.

Q8. How do you send validation errors in a structured JSON format? How do you customise error response formats?

Short answer: Use Problem Details, plus an errors array:

{
  "type": "https://api.shop.example/problems/validation",
  "title": "Validation failed",
  "status": 400,
  "detail": "2 fields are invalid",
  "instance": "/api/orders",
  "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
  "errors": [
    { "field": "lines[0].quantity", "code": "Positive", "message": "must be greater than 0", "rejectedValue": -1 },
    { "field": "shippingAddress.postcode", "code": "Pattern", "message": "invalid postcode" }
  ]
}
  • Customise it by overriding the handlers in ResponseEntityExceptionHandler, setting ProblemDetail properties (setProperty("errors", …)), using the type URIs for documentation, and internationalising the messages (MessageSource, ValidationMessages.properties).
  • For consistency across services, put the advice and the error model in a shared starter.
  • Avoid echoing sensitive rejectedValues (passwords, card numbers).

Q9. How do you handle a custom business exception with HTTP semantics?

Short answer:

  • In the domain: throw semantic exceptions (InsufficientStockException, OrderAlreadyShippedException) with error codes, and with no HTTP knowledge.
  • At the edge: the @RestControllerAdvice maps them to statuses: not found → 404, conflict or state → 409, business-rule violation → 422, forbidden action → 403, a dependency down → 503 (with Retry-After).
  • The body is Problem Details with a stable type/code, a human detail, and actionable data (for example availableQuantity).
  • Alternatives: a base exception carrying an HttpStatus-agnostic category, which the advice maps; or ErrorResponseException/ResponseStatusException for web-layer-specific errors.
  • Log 4xx at INFO or WARN, and 5xx at ERROR, with the trace ID.

Q10. What's the difference between @Valid and @Validated?

Short answer:

  • @Valid (Jakarta Bean Validation): triggers validation of the annotated argument or return value, and cascades into nested objects and collection elements. It has no groups.
  • @Validated (Spring):
    • on a method argument, it validates it, with validation groups (@Validated(OnCreate.class));
    • on a class, it enables method-level validation of parameters and return values (through an AOP proxy, MethodValidationPostProcessor), which is useful on services and configuration properties.

Use @Valid on request bodies and nested fields, and @Validated when you need groups, or service or @ConfigurationProperties validation.

Q11. How do you apply conditional validation with groups? How do you handle constraint violations in nested objects?

Short answer:

  • Groups: marker interfaces (OnCreate, OnUpdate) on the constraints (@Null(groups = OnCreate.class) Long id, @NotNull(groups = OnUpdate.class) Long id), with the group chosen at the entry point: @Validated(OnCreate.class) @RequestBody OrderDto dto. @GroupSequence orders cheap validations before expensive ones. For complex conditions (field B required when A = X), use a class-level custom constraint, which is clearer than juggling groups. Many teams prefer separate request DTOs per operation (CreateOrderRequest, UpdateOrderRequest), avoiding groups altogether.
  • Nested objects: put @Valid on the nested field, or on the container elements (List<@Valid OrderLineDto> lines), so validation cascades. Violations report property paths (lines[1].quantity, address.postcode), which your error mapper exposes as the field. Without @Valid on the nested field, nested constraints are silently skipped.

Q12. How do you avoid leaking internal details in exception messages?

Short answer:

  • A catch-all handler returns a generic 500 message ("Unexpected error"), with a trace or correlation ID. Log the full exception server-side.
  • Never return stack traces, SQL, class or package names, file paths, internal hostnames, or framework messages. Configure server.error.include-stacktrace=never, include-message=never (the defaults) and include-binding-errors carefully.
  • Map the known exceptions to curated messages. Validation messages should come from your message bundle, not echo raw input.
  • Use uniform responses for authentication failures (don't reveal whether the username or the password was wrong), and 404 instead of 403 for resources whose existence is sensitive.
  • Review the logs too: mask personal data and secrets in the exception messages that get logged.

Q13. What versioning strategies exist? Which do you prefer, and why? How do you implement content negotiation for versioning?

Short answer:

  • The strategies:
    • a URI path: /api/v1/orders. Explicit, easy to route, cache and document, and the most common. The purist criticism is that a URI should identify a resource, not a version.
    • a custom header: X-API-Version: 2 or API-Version. Clean URIs, but less visible, and harder to test in a browser and to cache (needs Vary).
    • a query parameter: ?version=2. Simple, but it mixes versioning into resource queries.
    • media type (content negotiation): Accept: application/vnd.shop.order.v2+json. It's RESTful (it versions the representation), and supports per-resource evolution, but it's complex for clients and tooling.
  • My usual preference: a URI major version for public APIs (clarity, gateway routing, documentation), plus additive, backward-compatible evolution within a version. Header or media-type versioning suits sophisticated clients, or hypermedia APIs.
  • Content-negotiation implementation in Spring: @GetMapping(value = "/orders/{id}", produces = "application/vnd.shop.order.v1+json") and produces = "…v2+json" on two handler methods (or one handler plus version-specific serialisers). Return Content-Type accordingly, and add Vary: Accept for caches. Spring Framework 7 adds first-class API versioning support (configurable resolvers: header, path, query, media type).

Q14. How do you support backward compatibility, and design APIs that evolve without breaking consumers?

Short answer:

  • Additive changes only within a version:
    • add optional fields, new endpoints, new optional parameters;
    • never remove or rename fields, change their types or meanings, or make optional inputs required.
  • Tolerant readers: clients ignore unknown fields (Jackson FAIL_ON_UNKNOWN_PROPERTIES=false), and servers accept old request shapes.
  • Enums: document that new values may appear, and have clients handle unknown values gracefully.
  • Defaults for new inputs. Expand/contract for renames (add the new field, populate both, deprecate the old one, remove it in the next major version).
  • Consumer-driven contract tests (Pact) and spec diff checks in CI catch breaking changes before release.
  • Feature flags or capability discovery, instead of branching versions.
  • Introduce a new major version only for genuinely breaking changes, and run the versions side by side.

Q15. How would you deprecate an old API version gracefully? How do you detect clients using an outdated version?

Short answer:

  • Announce it early: docs, changelog, and emails to the registered API consumers, with a timeline (for example, 6–12 months).
  • Signal it in responses: the Deprecation header (RFC 9745), the Sunset header (RFC 8594) with the removal date, and a Link to the migration guide. Mark the operations deprecated: true in OpenAPI.
  • Measure usage: metrics per version and per client ID (API keys or OAuth client IDs, User-Agent), and gateway analytics. That's how you detect the outdated clients: tag the requests by version, and dashboard or alert on usage.
  • Contact the remaining consumers directly, and offer migration help or SDK updates.
  • Brownouts: scheduled temporary failures before shutdown, to surface forgotten clients.
  • Remove the version once usage reaches zero (or at the deadline), and keep returning 410 Gone with a migration link for a while.

Q16. Can you use Spring profiles or routes to support several API versions?

Short answer:

  • Routes (yes): different request mappings per version in the same application:

    • /api/v1/... and /api/v2/... controllers, sharing the service layer, with version-specific DTOs and mappers;
    • or gateway routing: Spring Cloud Gateway sends /v1/** to the legacy deployment, and /v2/** to the new one.

    This lets the versions coexist, and be deployed independently.

  • Profiles (no, as a versioning mechanism): profiles select configuration per deployment environment. A profile applies to the whole instance, so one instance can't serve v1 and v2 at the same time. You'd need separate deployments per version, which is better handled by explicit routing (and profiles make the version behaviour implicit and error-prone).

Q17. Is GraphQL a better alternative to versioning? How would you implement and secure GraphQL? REST vs GraphQL?

Short answer:

  • Versioning: GraphQL avoids many version bumps. Clients select exactly the fields they need, so adding fields never breaks anyone, and fields are deprecated in the schema (@deprecated(reason:)), with usage tracked per field. It's "continuous evolution", not a free pass: removing or changing fields is still breaking.

  • Implementation in Java: Spring for GraphQL (built on graphql-java):

    • a schema-first schema.graphqls;
    • @QueryMapping/@MutationMapping/@SchemaMapping controllers;
    • @BatchMapping or DataLoader to solve N+1 when resolving nested fields;
    • subscriptions over WebSocket;
    • testing with GraphQlTester.

    Netflix DGS is an alternative.

  • Securing GraphQL:

    • authentication on the single endpoint;
    • field-level or type-level authorisation (method security on the resolvers);
    • query depth and complexity limits, and query cost analysis;
    • timeouts, and pagination limits (Relay-style connections);
    • disable introspection in production (or restrict it);
    • persisted or allow-listed queries for public clients;
    • rate limiting by query cost, not just by request;
    • careful error masking (no internal exceptions in errors).
  • REST vs GraphQL:

    • REST: resource-oriented, HTTP caching built in, simple, great tooling, and a good fit for public, cacheable, CRUD-style APIs and service-to-service calls.
    • GraphQL: client-driven queries (no over- or under-fetching, one round trip for nested data), a strongly typed schema, and an excellent fit for BFFs and aggregation layers for several frontends (mobile and web) over many backend services. The costs: harder caching (POST requests, per-field), N+1 risks, query-cost security, file uploads, and operational complexity.

    Many companies use REST (or gRPC) internally, and GraphQL at the edge.

Follow-up questions this topic invites — and their answers

Q: What is Spectral? A: An open-source linter for OpenAPI and AsyncAPI documents, with rule sets (naming, pagination, error formats, security definitions). Run it in CI to enforce API style-guide consistency across teams.

Q: How do you document authentication in OpenAPI? A: Define components.securitySchemes (for example bearerAuth: {type: http, scheme: bearer, bearerFormat: JWT} or OAuth2 flows with scopes), and apply security globally or per operation. In springdoc: @SecurityScheme and @SecurityRequirement.

Q: What is AsyncAPI? A: An OpenAPI-like specification for event-driven APIs (Kafka topics, AMQP, WebSockets): channels, messages, schemas and bindings. It's used for documenting and generating code for asynchronous contracts.

Q: How do you stop clients from depending on undocumented fields? A: Return only the documented DTO fields (no entity serialisation), validate responses against the spec in tests, and use strict schemas (additionalProperties: false) in contract tests for your own outputs.

Previous

REST Principles, Status Codes & Resource Design — Interview Questions

Next

Maven & Gradle at Scale — Interview Questions

AI Tutor

Lesson: OpenAPI, Validation Errors, API Versioning & GraphQL — Interview Questions

Quick actions

AI responses can be inaccurate. Verify critical information.