Response and Resources

Back

Loading concept...

๐Ÿ• RESTful Web Services: Response and Resources

The Pizza Delivery Story

Imagine you run a magical pizza delivery service. Customers call you (send requests), and you need to:

  • Package the pizza properly (Entity Providers)
  • Speak their language (Content Negotiation)
  • Handle complaints gracefully (Exception Mappers)
  • Build the delivery box (Response Building)
  • Fix mistakes when things go wrong (REST Error Handling)
  • Manage multiple shops (Sub-Resources)
  • Call other pizza shops for help (Client API)

Letโ€™s learn how Jakarta EE helps you run this pizza empire! ๐Ÿš€


๐ŸŽ Entity Providers: The Packaging Masters

What Are They?

Entity Providers are like gift wrappers. They take your pizza (Java object) and wrap it nicely for delivery (JSON, XML).

There are two types:

  • MessageBodyWriter โ†’ Wraps your gift (Java โ†’ JSON)
  • MessageBodyReader โ†’ Unwraps a gift (JSON โ†’ Java)

Simple Example

Think of it like this:

  • Customer orders online โ†’ You get JSON text
  • Your system needs a Pizza object
  • MessageBodyReader transforms text into a pizza!
@Provider
@Produces("application/json")
public class PizzaWriter
    implements MessageBodyWriter<Pizza> {

    @Override
    public void writeTo(Pizza pizza, ...) {
        // Turn pizza into JSON text
        String json = "{\"name\":\""
            + pizza.getName() + "\"}";
        outputStream.write(json.getBytes());
    }
}

The Magic Flow

graph TD A["Java Pizza Object"] --> B["MessageBodyWriter"] B --> C["JSON Text"] C --> D["Sent to Customer"] E["JSON from Customer"] --> F["MessageBodyReader"] F --> G["Java Pizza Object"]

When to Use Custom Providers

โœ… Special data formats (not just JSON/XML) โœ… Need extra processing (compression, encryption) โœ… Working with legacy systems


๐Ÿ—ฃ๏ธ Content Negotiation: Speaking Their Language

What Is It?

Your customer calls and says โ€œI speak French!โ€ Content Negotiation is how you figure out which language to respond in.

In REST, customers ask for specific formats:

  • โ€œGive me JSON!โ€ โ†’ Accept: application/json
  • โ€œGive me XML!โ€ โ†’ Accept: application/xml

How It Works

@GET
@Path("/menu")
@Produces({"application/json",
           "application/xml"})
public List<Pizza> getMenu() {
    return pizzaService.getAllPizzas();
}

The server checks the customerโ€™s Accept header and picks the best match!

The Decision Flow

graph TD A["Customer Request"] --> B{Accept Header?} B -->|application/json| C["Return JSON"] B -->|application/xml| D["Return XML"] B -->|No Preference| E["Use Default"]

Consuming Content

For incoming data, use @Consumes:

@POST
@Path("/order")
@Consumes("application/json")
@Produces("application/json")
public Pizza createOrder(Pizza pizza) {
    return pizzaService.save(pizza);
}

This says: โ€œI understand JSON orders and reply in JSON too!โ€


โš ๏ธ Exception Mappers: The Complaint Department

What Are They?

Sometimes things go wrong. A customer orders a pizza that doesnโ€™t exist! Exception Mappers are your complaint handlers โ€” they turn ugly errors into friendly messages.

The Problem Without Mappers

Without them, customers see scary error pages with technical jargon. Not good! ๐Ÿ˜ฑ

The Solution

@Provider
public class PizzaNotFoundMapper
    implements ExceptionMapper<PizzaNotFound> {

    @Override
    public Response toResponse(
        PizzaNotFound ex) {

        return Response
            .status(404)
            .entity("Sorry! That pizza " +
                    "doesn't exist.")
            .build();
    }
}

How It Works

graph TD A["Error Happens!"] --> B["ExceptionMapper"] B --> C["Creates Nice Response"] C --> D["Customer Gets Friendly Message"]

Real-World Tips

โœ… Create mappers for common exceptions โœ… Return proper HTTP status codes โœ… Include helpful error messages โœ… Log errors for debugging


๐Ÿ—๏ธ Response Building: Crafting Perfect Deliveries

What Is Response Building?

Itโ€™s like packing a delivery box with:

  • The pizza (entity body)
  • A receipt (status code)
  • Special notes (headers)

The Response Class

@GET
@Path("/pizza/{id}")
public Response getPizza(@PathParam("id") int id) {
    Pizza pizza = service.find(id);

    if (pizza == null) {
        return Response
            .status(Response.Status.NOT_FOUND)
            .build();
    }

    return Response
        .ok(pizza)
        .header("X-Pizza-Hot", "true")
        .build();
}

Common Response Builders

Method Status Code Use Case
ok() 200 Success!
created(uri) 201 New resource made
noContent() 204 Success, nothing to return
notFound() 404 Doesnโ€™t exist

Building with Headers

return Response
    .ok(pizza)
    .type(MediaType.APPLICATION_JSON)
    .header("Cache-Control", "max-age=3600")
    .lastModified(pizza.getUpdatedAt())
    .build();

๐Ÿ› ๏ธ REST Error Handling: Fixing Problems Gracefully

Why Proper Error Handling?

Bad error handling = frustrated customers Good error handling = happy customers who understand what went wrong

Best Practice: Error Response Structure

public class ErrorResponse {
    private int code;
    private String message;
    private String details;

    // Constructor and getters
}

Handling Different Errors

@Provider
public class GenericExceptionMapper
    implements ExceptionMapper<Exception> {

    @Override
    public Response toResponse(Exception ex) {

        ErrorResponse error = new ErrorResponse(
            500,
            "Something went wrong!",
            ex.getMessage()
        );

        return Response
            .status(500)
            .entity(error)
            .type(MediaType.APPLICATION_JSON)
            .build();
    }
}

HTTP Status Code Cheat Sheet

graph TD A["Status Codes"] --> B["2xx Success"] A --> C["4xx Client Error"] A --> D["5xx Server Error"] B --> E["200 OK, 201 Created"] C --> F["400 Bad Request"] C --> G["404 Not Found"] D --> H["500 Internal Error"]

๐Ÿข REST Sub-Resources: Managing Multiple Shops

What Are Sub-Resources?

Imagine your pizza empire has many locations. Each location has its own menu. Sub-Resources help organize this!

/shops/{shopId}/pizzas/{pizzaId}

Itโ€™s like folders inside folders!

How to Create Sub-Resources

Step 1: Parent Resource

@Path("/shops")
public class ShopResource {

    @Path("/{shopId}/pizzas")
    public PizzaSubResource getPizzas(
        @PathParam("shopId") int shopId) {

        return new PizzaSubResource(shopId);
    }
}

Step 2: Sub-Resource Class

public class PizzaSubResource {
    private int shopId;

    public PizzaSubResource(int shopId) {
        this.shopId = shopId;
    }

    @GET
    @Produces("application/json")
    public List<Pizza> getAll() {
        return service.getPizzasByShop(shopId);
    }

    @GET
    @Path("/{pizzaId}")
    public Pizza getOne(
        @PathParam("pizzaId") int id) {
        return service.getPizza(shopId, id);
    }
}

The Structure

graph TD A["/shops"] --> B["/shops/1"] B --> C["/shops/1/pizzas"] C --> D["/shops/1/pizzas/42"]

๐Ÿ“ž Client API: Calling Other Services

What Is It?

Sometimes your pizza shop needs to call another service โ€” maybe to check ingredient prices or order supplies. The JAX-RS Client API is your phone line to other REST services!

Creating a Client

// Step 1: Create the client
Client client = ClientBuilder.newClient();

// Step 2: Target a URL
WebTarget target = client
    .target("https://api.ingredients.com")
    .path("/cheese/prices");

// Step 3: Make the call
Response response = target
    .request(MediaType.APPLICATION_JSON)
    .get();

// Step 4: Read the response
CheesePrice price = response
    .readEntity(CheesePrice.class);

// Step 5: Clean up
client.close();

Different HTTP Methods

// GET
target.request().get();

// POST with body
target.request()
    .post(Entity.json(newOrder));

// PUT
target.request()
    .put(Entity.json(updatedOrder));

// DELETE
target.request().delete();

Adding Headers

Response response = target
    .request()
    .header("Authorization", "Bearer token123")
    .header("X-Custom-Header", "value")
    .get();

Async Calls

Donโ€™t want to wait? Make it async!

Future<Response> future = target
    .request()
    .async()
    .get();

// Do other stuff...

// Then get the result when ready
Response response = future.get();

๐ŸŽฏ Quick Summary

Concept What It Does Pizza Analogy
Entity Providers Convert objects โ†” formats Gift wrapping
Content Negotiation Choose response format Speaking customerโ€™s language
Exception Mappers Handle errors gracefully Complaint department
Response Building Construct HTTP responses Packing delivery boxes
Error Handling Manage failures Fixing mistakes
Sub-Resources Organize nested URLs Multiple shop locations
Client API Call other services Phone line to suppliers

๐ŸŒŸ You Did It!

You now understand how Jakarta EE handles REST responses and resources! Think of yourself as the master pizza delivery manager who knows:

  • โœ… How to package orders (Entity Providers)
  • โœ… How to speak any language (Content Negotiation)
  • โœ… How to handle complaints (Exception Mappers)
  • โœ… How to build perfect deliveries (Response Building)
  • โœ… How to fix problems (Error Handling)
  • โœ… How to manage multiple locations (Sub-Resources)
  • โœ… How to call other services (Client API)

Youโ€™re ready to build amazing REST APIs! ๐Ÿš€๐Ÿ•

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.