RESTful API @QueryParam vs @PathParam: What Works and What Doesn’t
RESTful API @QueryParam and @PathParam: What They Can and Can’t Be
In RESTful APIs, @QueryParam and @PathParam annotations are used to extract parameters from the URL. However, these parameters have certain constraints on their types and usage. Here’s an overview of what works, what doesn’t, and how to handle special cases.
Supported Types for @QueryParam and @PathParam
-
Primitive Types (Except
char
)- Supported:
int
,double
,boolean
, etc. - Example:
@GET @Path("/item/{id}") public String getItem(@PathParam("id") int id) { return "Item ID: " + id; }
- Supported:
-
Wrapper Classes for Primitives (Except
Character
)- Supported:
Integer
,Double
,Boolean
, etc. - Example:
@GET @Path("/user") public String getUser(@QueryParam("active") Boolean active) { return "Active Status: " + active; }
- Supported:
-
Classes with a Static
valueOf(String)
Method- If a class provides a static
valueOf(String)
method, it can be used as a parameter type. - Example:
public class CustomType { private final String value; public CustomType(String value) { this.value = value; } public static CustomType valueOf(String value) { return new CustomType(value); } } @GET @Path("/custom") public String getCustom(@QueryParam("type") CustomType type) { return "Custom Type: " + type; }
- If a class provides a static
-
Classes with a Constructor That Accepts a
String
- Classes with a single-parameter
String
constructor are valid. - Example:
public class Order { private final String orderId; public Order(String orderId) { this.orderId = orderId; } } @GET @Path("/order") public String getOrder(@QueryParam("id") Order order) { return "Order ID: " + order.getOrderId(); }
- Classes with a single-parameter
-
Collections (
List<T>
,Set<T>
,SortedSet<T>
)- If the parameter allows multiple values, collections can be used.
- Example:
@GET @Path("/tags") public String getTags(@QueryParam("tag") List<String> tags) { return "Tags: " + String.join(", ", tags); }
Unsupported Types
-
char
andCharacter
- These are not supported as parameters since they can’t reliably represent complex string values.
-
Complex Custom Objects Without
valueOf(String)
orString
Constructor- Classes must implement one of the supported mechanisms to be valid as parameters.
Using @DefaultValue
To handle optional parameters, you can use the @DefaultValue
annotation. This ensures a default value is assigned when the parameter is absent in the request.
Example:
@GET
@Path("/greet")
public String greet(@QueryParam("name") @DefaultValue("Guest") String name) {
return "Hello, " + name + "!";
}
Differences Between @QueryParam and @PathParam
Feature | @QueryParam | @PathParam |
---|---|---|
Usage | Extracts parameters from the query part of the URL. | Extracts parameters from the path part of the URL. |
Example URL | /items?type=electronics |
/items/electronics |
Syntax | @QueryParam("type") String type |
@PathParam("type") String type |
Optional Params | Can use @DefaultValue . |
Cannot use @DefaultValue . |
Best Practices
-
Validate Inputs:
- Always validate parameters to avoid security risks like injection attacks.
-
Use Specific Types:
- Prefer explicit data types to ensure proper deserialization and error handling.
-
Error Handling:
- Provide clear error messages for invalid parameters by using exception mappers or custom responses.
Conclusion
Understanding the constraints and capabilities of @QueryParam and @PathParam is essential for designing effective RESTful APIs. By adhering to these rules and leveraging features like @DefaultValue
, you can ensure robust and predictable API behavior.
Would you like code examples for specific use cases or deeper insights into error handling? 😊