REST Advanced Topics

Loading concept...

REST Advanced Topics: The Superpowers of Your API 🚀

Imagine your REST API is a pizza delivery shop. So far, you’ve learned how to take orders and deliver pizzas. But now? You’re about to unlock the superpowers that make your shop legendary—live tracking, special packaging, faster deliveries, and VIP menus!


🌊 Server-Sent Events (SSE): The Live News Channel

What Is It?

Think of Server-Sent Events like a radio station. You tune in once, and music keeps flowing to you—no need to keep asking “What’s next?”

In regular REST, the client asks → server answers. That’s like calling the pizza shop every minute: “Is my order ready?” Annoying, right?

With SSE, the server pushes updates to you automatically. The pizza shop calls YOU when your order is ready!

How It Works

@GET
@Path("/updates")
@Produces(MediaType.SERVER_SENT_EVENTS)
public void getUpdates(
    @Context SseEventSink sink,
    @Context Sse sse) {

    // Send message to client
    sink.send(sse.newEvent("Order received!"));
    sink.send(sse.newEvent("Pizza in oven!"));
    sink.send(sse.newEvent("Out for delivery!"));
}

Why Use It?

  • Live dashboards (stock prices, sports scores)
  • Notifications (new messages, alerts)
  • Progress tracking (file uploads, order status)

Key Point đź’ˇ

SSE is one-way: server → client. For two-way chat, you’d use WebSockets. But for live updates? SSE is simpler!


🛡️ Filters and Interceptors: The Security Guards & Editors

What Are They?

Imagine every pizza order passes through two checkpoints:

  1. Security Guard (Filter): Checks if you’re allowed to order. Do you have an account? Is your payment valid?

  2. Editor (Interceptor): Adjusts the order or wraps the pizza nicely. Maybe adds a napkin or corrects the address.

Filters: The Gatekeepers

Filters work on requests and responses. They run BEFORE your code (request filter) or AFTER (response filter).

@Provider
public class AuthFilter
    implements ContainerRequestFilter {

    @Override
    public void filter(
        ContainerRequestContext ctx) {

        String token = ctx.getHeaderString(
            "Authorization");

        if (token == null) {
            ctx.abortWith(
                Response.status(401).build());
        }
    }
}

Interceptors: The Content Editors

Interceptors work on the message body—they can read, modify, or wrap it.

@Provider
public class LoggingInterceptor
    implements ReaderInterceptor {

    @Override
    public Object aroundReadFrom(
        ReaderInterceptorContext ctx)
        throws IOException {

        // Log before reading
        System.out.println("Reading body...");

        // Continue normal processing
        return ctx.proceed();
    }
}

When to Use Which?

Use Case Use This
Check auth tokens Filter
Log requests Filter
Compress response Interceptor
Encrypt body Interceptor

đź’‰ Context Injection: Getting the Right Tools

What Is It?

Imagine you’re a chef. Sometimes you need a knife, sometimes a spoon. Context Injection gives you the right tool when you need it—automatically!

In Jakarta EE, the @Context annotation injects useful information about the current request.

What Can You Inject?

@Path("/order")
public class OrderResource {

    @Context
    private HttpServletRequest request;

    @Context
    private HttpHeaders headers;

    @Context
    private UriInfo uriInfo;

    @Context
    private SecurityContext security;

    @GET
    public String getOrder() {
        // Get client's IP address
        String ip = request.getRemoteAddr();

        // Get a specific header
        String auth = headers
            .getHeaderString("Authorization");

        // Get the full URL
        String url = uriInfo
            .getAbsolutePath().toString();

        return "Request from: " + ip;
    }
}

Common Context Objects

Object What It Gives You
HttpHeaders All request headers
UriInfo URL, path, query params
SecurityContext Who’s logged in
Request HTTP method info
Providers Other JAX-RS providers

⚡ Async REST Processing: Don’t Make Customers Wait!

The Problem

Imagine ordering pizza, and the cashier makes you wait at the counter while they bake it. The line behind you grows… people get angry!

Synchronous = You wait. Server waits. Everyone waits.

The Solution

With Async Processing, the server says: “Got it! I’ll call you when it’s ready!” Then it helps the next customer.

@GET
@Path("/slow-operation")
public void slowOperation(
    @Suspended AsyncResponse response) {

    // Handle in background thread
    CompletableFuture.runAsync(() -> {
        try {
            // Simulate slow work (5 seconds)
            Thread.sleep(5000);

            // Send response when ready
            response.resume("Done!");

        } catch (Exception e) {
            response.resume(e);
        }
    });

    // Method returns immediately!
    // Server is free to handle other requests
}

Setting Timeouts

Don’t let customers wait forever:

@GET
public void getData(
    @Suspended AsyncResponse response) {

    // Give up after 30 seconds
    response.setTimeout(30, TimeUnit.SECONDS);

    response.setTimeoutHandler(ar ->
        ar.resume(Response
            .status(503)
            .entity("Try again later")
            .build()));
}

Why Use Async?

  • Long database queries
  • Calling external APIs
  • File processing
  • Any slow operation!

📦 Multipart Form Data: Sending Files and More

What Is It?

Regular forms send text. But what if you want to upload a profile picture AND your name together? That’s where Multipart comes in!

Think of it like a gift box with compartments—one section for the photo, another for the card.

Receiving File Uploads

@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
    @FormDataParam("file")
    InputStream fileStream,

    @FormDataParam("file")
    FormDataContentDisposition fileDetail,

    @FormDataParam("description")
    String description) {

    String fileName = fileDetail.getFileName();

    // Save the file
    saveFile(fileStream, fileName);

    return Response.ok(
        "Uploaded: " + fileName).build();
}

The HTML Form

<form method="POST"
      enctype="multipart/form-data"
      action="/api/upload">

    <input type="file" name="file">
    <input type="text" name="description">
    <button type="submit">Upload</button>
</form>

Key Points đź’ˇ

  • Use @Consumes(MediaType.MULTIPART_FORM_DATA)
  • Each part has a name (like “file” or “description”)
  • Files come as InputStream
  • Metadata comes in FormDataContentDisposition

🔢 API Versioning: Old Friends & New Friends

The Problem

Your pizza shop becomes famous! You add new menu items. But some old customers only know the old menu. How do you serve both?

API Versioning lets you run multiple versions side by side!

Strategy 1: URL Path Versioning (Most Common)

@Path("/v1/pizza")
public class PizzaResourceV1 {
    @GET
    public String getPizza() {
        return "Classic Margherita";
    }
}

@Path("/v2/pizza")
public class PizzaResourceV2 {
    @GET
    public PizzaDTO getPizza() {
        return new PizzaDTO(
            "Margherita",
            12.99,
            List.of("cheese", "tomato"));
    }
}

Clients call: /api/v1/pizza or /api/v2/pizza

Strategy 2: Header Versioning

@Path("/pizza")
public class PizzaResource {

    @GET
    public Response getPizza(
        @HeaderParam("API-Version")
        String version) {

        if ("2".equals(version)) {
            return Response.ok(
                new PizzaDTO(...)).build();
        }

        // Default to v1
        return Response.ok(
            "Classic Margherita").build();
    }
}

Clients send header: API-Version: 2

Strategy 3: Query Parameter

@GET
public Response getPizza(
    @QueryParam("version")
    @DefaultValue("1")
    String version) {

    // Handle based on version
}

Clients call: /pizza?version=2

Which Should You Use?

Strategy Pros Cons
URL Path Clear, cacheable URL changes
Header Clean URLs Less visible
Query Easy to test Messy URLs

Tip: URL path versioning is the most common and easiest to understand!


đź”— HATEOAS: The Self-Guiding API

What Is HATEOAS?

Hypermedia As The Engine Of Application State

That’s a mouthful! Let’s simplify:

Imagine you’re in a video game. After defeating a monster, the game shows you buttons: “Go to Shop”, “Next Level”, “Save Game”. You don’t need a manual—the game TELLS you what you can do next!

HATEOAS makes your API work the same way. The response includes links to related actions.

Without HATEOAS (Old Way)

{
    "orderId": 123,
    "status": "preparing",
    "total": 29.99
}

The client must know the API structure to do anything else.

With HATEOAS (Smart Way)

{
    "orderId": 123,
    "status": "preparing",
    "total": 29.99,
    "_links": {
        "self": "/orders/123",
        "cancel": "/orders/123/cancel",
        "track": "/orders/123/tracking",
        "payment": "/payments/order/123"
    }
}

Now the client KNOWS what’s possible! They can cancel, track, or pay—without reading documentation.

Building HATEOAS Responses

@GET
@Path("/{id}")
public Response getOrder(
    @PathParam("id") Long id,
    @Context UriInfo uriInfo) {

    Order order = findOrder(id);

    // Build links
    URI self = uriInfo
        .getAbsolutePathBuilder()
        .build();

    URI cancel = uriInfo
        .getBaseUriBuilder()
        .path("orders/{id}/cancel")
        .build(id);

    // Create response with links
    Map<String, Object> response =
        new HashMap<>();
    response.put("order", order);
    response.put("_links", Map.of(
        "self", self.toString(),
        "cancel", cancel.toString()
    ));

    return Response.ok(response).build();
}

Why HATEOAS Matters

  • Self-documenting API
  • Discoverable actions
  • Flexible evolution (change URLs without breaking clients)
  • Reduced coupling between client and server

🎯 Putting It All Together

Let’s see how these superpowers work in a real pizza ordering system:

graph TD A["📱 Client Request"] --> B{🛡️ Auth Filter} B -->|Invalid| C["❌ 401 Unauthorized"] B -->|Valid| D["📦 Interceptor&lt;br&gt;Log &amp; Validate"] D --> E["💉 Context Injection&lt;br&gt;Get User Info"] E --> F{📋 Route} F -->|Upload Photo| G["📸 Multipart&lt;br&gt;Handle File"] F -->|Get Updates| H["🌊 SSE&lt;br&gt;Stream Events"] F -->|Long Query| I["⚡ Async&lt;br&gt;Background Work"] G --> J["🔗 HATEOAS Response"] H --> J I --> J J --> K["🔢 Version&lt;br&gt;v1 or v2 format"] K --> L["✅ Client Receives"]

📝 Quick Summary

Feature What It Does Pizza Shop Analogy
SSE Server pushes live updates Shop calls YOU when ready
Filters Check requests before/after Security guard at door
Interceptors Modify message body Gift wrapper for pizza
Context Injection Get request info automatically Chef gets right tools
Async Handle slow tasks without blocking Take order, bake later
Multipart Send files + data together Box with compartments
Versioning Run multiple API versions Old menu + new menu
HATEOAS Include action links in response “What’s next?” buttons

🚀 You Did It!

You’ve just unlocked the advanced superpowers of REST APIs! These aren’t just fancy features—they’re the tools that separate a basic API from a professional, production-ready service.

Remember:

  • SSE for live updates
  • Filters for security and logging
  • Interceptors for body transformation
  • Context for request information
  • Async for slow operations
  • Multipart for file uploads
  • Versioning for evolution
  • HATEOAS for self-describing APIs

Now go build something amazing! 🎉

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Interactive Preview

Interactive - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Interactive - Premium Content

Please sign in to view this interactive content and start learning.

Upgrade to Premium to unlock full access to all interactive content.

Stay Tuned!

Interactive content is coming soon.

Cheatsheet Preview

Cheatsheet - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Cheatsheet - Premium Content

Please sign in to view this cheatsheet and start learning.

Upgrade to Premium to unlock full access to all cheatsheets.

Stay Tuned!

Cheatsheet is coming soon.

Quiz Preview

Quiz - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Quiz - Premium Content

Please sign in to view this quiz and test your knowledge.

Upgrade to Premium to unlock full access to all quizzes.

Stay Tuned!

Quiz is coming soon.

Flashcard Preview

Flashcard - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Flashcard - Premium Content

Please sign in to view flashcards and reinforce your learning.

Upgrade to Premium to unlock full access to all flashcards.

Stay Tuned!

Flashcards are coming soon.