🏠 RESTful Web Services: URL Mapping & Parameters
The Postal System Analogy 📬
Imagine your web service is like a giant post office. Every letter (request) needs to reach the right desk (endpoint). The address on the envelope tells workers exactly where to deliver it and what extra info they need.
In Jakarta EE, JAX-RS annotations are your addressing system. They tell your application exactly where each request should go and what information to grab from it.
🛤️ Path Annotations: Naming Your Streets
What is @Path?
Think of @Path as giving a street name to your endpoint. Just like “123 Main Street” tells a mailman where to go, @Path("/users") tells your app: “Hey, any request for /users comes here!”
@Path("/users")
public class UserResource {
// All user-related stuff lives here
}
Nesting Paths
You can stack paths like building addresses:
- Building:
/users - Apartment:
/users/{id}
@Path("/users")
public class UserResource {
@Path("/{id}")
public User getUser() {
// Gets /users/123
}
}
🎯 Key Point: The full path becomes /users/{id} — like saying “Go to the Users building, then find apartment number {id}.”
🎬 HTTP Method Annotations: What Action to Take
When a letter arrives, the post office needs to know: Read it? Reply? Throw it away?
HTTP methods are your action instructions:
| Annotation | Action | Real-World Example |
|---|---|---|
@GET |
Read/Fetch | “Show me my profile” |
@POST |
Create new | “Register a new user” |
@PUT |
Replace entirely | “Update my whole profile” |
@PATCH |
Update partially | “Just change my email” |
@DELETE |
Remove | “Delete my account” |
Example: A Complete User Service
@Path("/users")
public class UserResource {
@GET
public List<User> getAllUsers() {
// Fetch all users
}
@POST
public User createUser(User user) {
// Create new user
}
@PUT
@Path("/{id}")
public User updateUser(User user) {
// Replace user completely
}
@DELETE
@Path("/{id}")
public void deleteUser() {
// Remove user
}
}
💡 Simple Rule:
GET= Give me infoPOST= Here’s something newPUT= Replace everythingDELETE= Throw it away
🎯 Path Parameters: The Apartment Number
What Are Path Parameters?
When you visit apartment 42 in a building, “42” is your path parameter. It’s part of the address itself.
URL: /users/42 → The 42 is a path parameter
@GET
@Path("/{userId}")
public User getUser(
@PathParam("userId") int userId
) {
// userId = 42
return findUser(userId);
}
Multiple Path Parameters
Like finding a book on shelf 3, row 7:
@GET
@Path("/{shelf}/{row}")
public Book getBook(
@PathParam("shelf") int shelf,
@PathParam("row") int row
) {
// /books/3/7 → shelf=3, row=7
return findBook(shelf, row);
}
🎯 Remember: Path parameters are required. No apartment number? Mail gets returned!
❓ Query Parameters: The Extra Notes
What Are Query Parameters?
Ever write “FRAGILE” or “Open immediately” on a package? Those are extra instructions — optional but helpful.
Query parameters come after ? in the URL:
/users?sort=name&limit=10
@GET
@Path("/users")
public List<User> getUsers(
@QueryParam("sort") String sortBy,
@QueryParam("limit") int limit
) {
// sort = "name", limit = 10
}
Default Values
What if someone forgets the note? Use defaults!
@GET
public List<User> getUsers(
@QueryParam("page")
@DefaultValue("1") int page,
@QueryParam("size")
@DefaultValue("20") int size
) {
// If no ?page=X, use page=1
}
💡 Key Difference:
- Path params = Required address
- Query params = Optional notes
📋 Header Parameters: The Invisible Stamps
What Are Header Parameters?
Headers are like invisible stamps on your envelope. The mailman sees them, but they’re not part of the address you write.
Common uses:
Authorization: Who’s sending this?Content-Type: What language is this in?Accept-Language: Reply in which language?
@GET
@Path("/profile")
public User getProfile(
@HeaderParam("Authorization")
String token,
@HeaderParam("Accept-Language")
String language
) {
// token = "Bearer abc123"
// language = "en-US"
}
🔒 Pro Tip: Sensitive data like passwords and tokens should always go in headers, never in the URL!
📝 Form Parameters: The Application Form
What Are Form Parameters?
When you fill out a paper form, each field has a name: “First Name”, “Email”, etc. Form parameters work the same way!
When a user submits an HTML form, the data arrives as form parameters.
<form method="POST">
<input name="username" type="text">
<input name="password" type="password">
<button type="submit">Login</button>
</form>
@POST
@Path("/login")
@Consumes("application/x-www-form-urlencoded")
public Response login(
@FormParam("username") String user,
@FormParam("password") String pass
) {
// user = what they typed
// pass = their password
}
📌 Important: Always use @Consumes("application/x-www-form-urlencoded") for form data!
🎒 Bean Parameters: The Organized Backpack
The Problem
What if you have 10 query parameters? Writing @QueryParam ten times is messy!
The Solution: Bean Parameters
Pack all parameters into one neat backpack (a Java class):
public class SearchFilters {
@QueryParam("keyword")
private String keyword;
@QueryParam("category")
private String category;
@QueryParam("minPrice")
@DefaultValue("0")
private double minPrice;
@QueryParam("maxPrice")
@DefaultValue("9999")
private double maxPrice;
// getters and setters...
}
Now your method stays clean:
@GET
@Path("/products")
public List<Product> search(
@BeanParam SearchFilters filters
) {
// All params neatly organized!
String keyword = filters.getKeyword();
}
Bean Params Can Hold Everything!
public class RequestContext {
@PathParam("userId")
private int userId;
@QueryParam("format")
private String format;
@HeaderParam("Authorization")
private String token;
}
🎯 One annotation to rule them all!
🗺️ Visual Summary
graph TD A["📬 HTTP Request"] --> B{URL Parsing} B --> C["🛤️ @Path<br/>Which endpoint?"] B --> D["🎬 @GET/@POST/etc<br/>What action?"] C --> E["🎯 @PathParam<br/>/users/{id}"] C --> F["❓ @QueryParam<br/>?sort=name"] A --> G["📋 @HeaderParam<br/>Authorization, etc"] A --> H["📝 @FormParam<br/>Form field data"] E --> I["🎒 @BeanParam<br/>Collect all params"] F --> I G --> I
🏆 Quick Reference Table
| Annotation | Where Data Lives | Example | Required? |
|---|---|---|---|
@Path |
URL path | /users |
Yes |
@PathParam |
In the path | /users/{id} |
Yes |
@QueryParam |
After ? |
?name=John |
No |
@HeaderParam |
HTTP headers | Authorization: Bearer... |
Depends |
@FormParam |
Form body | Username field | Depends |
@BeanParam |
Multiple sources | All above combined | No |
🎉 You Did It!
Now you understand how Jakarta EE routes requests like a well-organized post office:
- @Path = Street address (where to go)
- HTTP Methods = What to do when you get there
- @PathParam = Required parts of the address
- @QueryParam = Optional filters/preferences
- @HeaderParam = Hidden metadata
- @FormParam = Form submissions
- @BeanParam = Keep it all organized!
Go build something awesome! 🚀
