@Path
|-Binding URIs
|-@Path Expressions
|-Template Parameters
|-Problems with Query Params
|-Benefits of @Path Expressions
|-Differences between the Query and Template Params
|-Regular Expressions
|-Matrix Parameters
|-Differences between the Query, Path and Matrix Params and when to use them
Sub Resource Locators
|-Full Dynamic Dispatching
Terminology in REST Resource
@Path:
@Path can have complex matching expressions so that you can be more specific on
what requests get bound to which incoming URIs. @Path can also be used on a Java
method as sort of an object factory for sub-resources of your application.
@Path("/order")
class OrderResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String track(@QueryParam("orderID") String orderID) {
return "status for orderID : " + orderID + " is : processed";
}
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getOrderDetails(@QueryParam("orderID") String orderID) {
return "ordered Date : " + new Date() + " no of products 2";
}
}
In the above code there is an ambiguity in modelling the resources bcz with one single
URI 2-methods has been matched JAX-RS will leads into an ambiguity. So in order to
avoid this ambiguity we need to go for Binding URI's.
Binding URI's:
The @javax.ws.rs.Path annotation in JAX-RS is used to define a URI matching pattern
for incoming HTTP requests. It can be placed upon a class or on one or more Java
methods as well to avoid the ambiguious URI's.
For a Java class to be eligible to receive any HTTP requests, the class must be
annotated with at least the @Path("/") expression. These types of classes are called
JAX-RS root resources.
To receive a request, a Java method must have at least an HTTP method annotation
like @javax.ws.rs.GET applied to it. This method is not required to have an @Path
annotation on it but if we want we can write/bind @Path at method level with one
more URI called as Binding URI.
@Path("/order")
class OrderResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getOrderDetails(@QueryParam("orderID") String orderID) {
return "ordered Date : " + new Date() + " no of products 2";
}
@Path("/track")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String track(@QueryParam("orderID") String orderID) {
return "status for orderID : " + orderID + " is : processed";
}
}
Here req by default maps to the getOrderDetails() method and if we send req with
additional URI then req's binds to the track().
http://localhost:8080/10.1BindingURIs/resources/order/track?orderID=121
Status for orderID : 121 is : processed
@Path Expressions:
@Path("/customers")
public class CustomerResource {
@GET
@Path("/details")
public String getCustomer(@QueryParam("id") int id) {
...
}
}
Access the Resource
http://localhost:8080/CustomerWeb/resources/customers/details?id=133
@Path("/customers")
public class CustomerResource {
@GET
@Path("/details/{id}")
public String getCustomer(@PathParam("id") int id) {
...
}
}
http://localhost:8080/CustomerWeb/resources/customers/details/333
The {id} expression represents a template parameter which is reserved position or
place holder as part of the req URI path hence these are also called as Path Params.
A template parameter is a named wildcard pattern embedded within the value of an
@Path annotation. It starts with an open brace, "{", continues with one or more
alphanumeric characters, and ends with a closed brace "}". The expression represents
one or more characters that are not the slash "/" character.
So now the client will sends the data as part of path of the URI without referring the
param names. For example of a GET will be matched as /customers/details/333
request would match getCustomer(), but a GET request /customers/details/333/444
would not match the path expression.
These template parameters can be embedded anywhere within an @Path declaration.
@Path("/customers")
public class CustomerResource {
@GET
@Path("details/{id}-{custname}")
public String getCustomer(@PathParam("id") int id,
@PathParam("custname") String custname) {
...
}
}
In our example, the URI is constructed with a customer’s id name, followed by a
hyphen, ending with the custname of the individual. So, the GET request
/customers/details/333 would no longer match to getCustomer(), but a GET req
/customers/details/333-dbreddy request would.
@Path("/customers/{id}")
public class CustomerResource {
@GET
@Path("/details/{custname}")
public String getCustomer(@PathParam("id") String id,
@PathParam("custname") String custname) {
...
}
}
Access the application (In ARC or Browser but it will not accessible in Eclipse browser):
http://localhost:8080/10.2.1TemplateParams/resources/
customers/333/details/dbreddy
Response:
Customer Details:
Name: dbreddy
Cust-id: 333
@Path("/airtelmobile")
public class AirtelMobileServiceActivatorResource {
/*
* Here \\d+ any no.of digits and and d{10} means only digits and that
* should be 10-digits only Here .* means any characters
*/
/*
* Here \\d{10} meant for to accept 10-digit mobileNo and .* meant for
* either prepaid or postpaid any thing as string
*/
/*
* Expression [789]{1}\\d{9} meaning is start with 7/8/9 which can occur
* only once and \\d{9} indicates 9-digits from range 0-9. so finally we
* will get 1+9=10 digit number
*/
@Path("/status/{mobileNo : [789]{1}\\d{9}}/{type : .*}")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getMobileNoStatus(@PathParam("mobileNo") long mobileNo,
@PathParam("type") String type) {
return "Status: Your " + type + " MobliNo : " + mobileNo
+ " will be activated in 24-hours";
}
}
Regular expressions are not limited in matching one segment of a URI it can be for
multiple segments as well.
Similarly we can implement any type of Regular Expressions as part of the RESTful
services as well bcz it has a support for Regular Expressions.
Advantages of Regular Expression in RESTful:
In RESTful services if we use Regular Expressions then these will make our resource
can be accessible if and only if proper data is matched otherwise it makes resource
not found so that we can avoid throwing Exceptions. That means it stops accessing
the resource if data format is not proper so that we can avoid accessing the resource
with wrong data.
Matrix Parameters:
Matrix parameters are name-value pairs embedded within the path of a URI string.
It is not a concept of java rather it is concept of Http protocol which is has been added
as part of Http 1.1
JAX-RS 1.1 doesn't had a support for Matric params but it has been added in JAX-RS
2.0
For example:
http://example.cars.com/mercedes/e55;color=black/2006
They come after a URI segment and are delimited by the “;” character. The matrix
parameter in this example comes after the URI segment e55. Its name is color and
its value is black. Matrix parameters are different than query parameters, as they
represent attributes of certain segments of the URI and are used for identification
purposes.
Query parameters, on the other hand, always come at the end of the URI and always
pertain to the full resource you are referencing.
Matrix parameters are ignored when matching incoming requests to JAX-RS resource
methods. It is actually illegal to specify matrix parameters within an @Path
expression.
For example:
@Path("/car-agent")
class CarAgent {
@Path("/search/{make}/{model}")
@GET
@Produces("text/plain")
public String search(@PathParam("make") String make,
@MatrixParam("year") int makeYear,
@PathParam("model") String model,
@MatrixParam("capacity") int seatCapacity,
@QueryParam("color") String color,
@QueryParam("price") float price) {
If we wanted to search car we can use Path params but if we search a Marathi of
vegnor or swift then we need that model year as 2006 model which is an additional
data then we can use Matrix params for this use case.
If we search for Marathi with swift then we wanted to search for capacity as 4 then
we can use Matrix params.
These can be attached to a specific part/segment of path as part of URI Like this we
send any no.of Matrix params as well.
Access the application:
http://localhost:8082/10.4MatrixParams/resources/car-
agent/search/maruthi;year=2006/swift;capacity=4?color=red&price=12000
Response:
Make : maruthi
Model : swift
SeatCapacity: 4
Color : red
Price : 12000.0
We can send all matrix params as well and we can some of them as well ncz Matrix
params are optional.
http://localhost:8082/10.4MatrixParams/resources/car-
agent/search/maruthi/swift?color=red
Response:
Make : maruthi
Model : swift
SeatCapacity: 0
Color : red
Price : 0.0
We should not send Matrix params after the Query params bcz Query Params always
to be last. If we send Matrix params after the Query params we will get un-expected
response and sometimes we cannot access the resource. Hence we need to send
Matrix params before the Query param and anywhere of part/segment of path of URI
that means order doesn't matters.
Example:
http://localhost:8082/10.4MatrixParams/resources/car-agent/search/maruthi/swift?
color=red;capacity=4&price=120000
Response:
Make : maruthi
Model : swift
SeatCapacity: 0
Color : red;capacity=4
Price : 120000.0
http://localhost:8080/10.4MatrixParams/resources/car-
agent/search/honda;year=2006/citi;capacity=4?color=red&price=12000
(Observe the order of Matrix params in URI)
Response:
Entered Model is: citi
Make : honda
SeatCapacity: 4
Year: 0
Color : red
Price : 12000.0
http://localhost:8080/10.4MatrixParams/resources/car-agent/search/maruthi/
citi;capacity=4;year=2006?color=red&price=12000
Response:
Entered Model is: citi
Make : maruthi
SeatCapacity: 4
Year: 2006
Color : red
Price : 12000.0
http://localhost:8080/10.4MatrixParams/resources/car-agent/
search/marutki/vegnor;capacity=4;year=2006?color=red&price=12000
Response:
make : maruthi
Model : vegnor
Year: 2006
Color : red
Price : 12000.0
http://localhost:8080/10.4MatrixParams/resources/car-
agent/search/marutki/swift;capacity=4;year=2006?color=red&price=12000
Response:
Make : marutki
Model : swift
SeatCapacity: 4
Color : red
Price : 12000.0
How many we can send the data as part of path of the URI?
We can send in 3-ways by using Query, Path and Matrix Params
Differences between the Query, Path and Matrix Params and when to use
them:
Irrespective of parans we can send the data as part of path of the URI.
1. Query and Matrix params are optional but Template params are mandatory.
2. Query params always can appear at end of the req URI. Template params can be
appear in anywhere of the URI and these params are mandatory. Matrix params can
be appear in where in the req of part of path of URI and before the Query params.
3. The Template params involves/influences the way of resolving the req bcz these
are mandatory but not by Query or Matrix params bcz they are optional.
4. The scope of the Matrix params is part/segment scope but not entire URI but the
Template params scope is of entire req URI level. The scope of Query param is also
entire req scope but scope is not make sense for Query params bcz these are always
can be appear at end of the req URI but scope make sense for Matrix and Template
bcz these can be passed in anywhere of the req.
5. We can send multi-values for an single param in case of Query and Matrix (in case
of multiple values it takes 1st values only) but we cannot send in case of Template
param.
Example:
http://localhost:8080/10.4MatrixParams/resources/car-agent/ search/maruthi
/citi;capacity=4;year=2009;year=2006?color=red&price=12000&price=9000
Response:
Entered Model is: citi
Make : maruthi
SeatCapacity: 4
Year: 2009
Color : red
Price : 12000.0
Note:
We cannot access multiple values for single param by using Matrix params.
Sub Resource Locators:
The JAX-RS has capability to statically bind URI patterns expressed through the @Path
annotation to a specific Java method. JAX-RS also allows us to dynamically dispatch
requests our-self through sub resource locators. Sub resource locators are Java
methods annotated with @Path, but with no HTTP method annotation, like @GET,
applied to them. This type of method can returns an object type or specific object
type, a JAX-RS annotated service that knows how to dispatch the remainder of the
request.
Let’s consider by expanding our courier business as JAX-RS service. Let’s say our
courier can be work in different ways based on the geographic regions like
domestic/national or international. We want to add this information to our URI
scheme.
@Path("/courier")
class CourierResource {
@Path("/domestic/{docID}")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getCourierStatus(@PathParam("docID") int docID) {
//docID means domestic courier ID
return "doc ID : " + docID + " status : in-transit";
}
@Path("/international/{awbNo}")
// awbNo means air way bill no
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getCourierStatus(@PathParam("awbNo") String awbNo) {
return "awbNo : " + awbNo + " status : unknown";
}
}
There is no problem with the code but it is difficult to maintain all the meta-data in an
single Resource class if we have more no.of Resource methods. Hence in order to
prevent cluttering code in single large Resource class we will go for Sub Resource
Locators.
@Path("/courier")
class CourierResource {
//Sub resource or Sub Resource Locate methods which will locates corresponding
resource methods.
@Path("/domestic")
public DomesticCourierSubResource locateDomesticServices() {
return new DomesticCourierSubResource();
}
@Path("/international")
public InternationalCourierSubResource locateInternationalServices() {
return new InternationalCourierSubResource();
}
}
@Singleton
class DomesticCourierSubResource {
public DomesticCourierSubResource() {
System.out.println("domestic()");
}
//Resource method
@Path("/{awbNo}")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getCourierStatus(@PathParam("awbNo") String awbNo) {
return "awbNo : " + awbNo + " status : in progress";
}
}
@Singleton
class InternationalCourierSubResource {
public InternationalCourierSubResource() {
System.out.println("international()");
}
//Resource method
@Path("/{docID}")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getCourierStatus(@PathParam("docID") int docID) {
return "doc ID : " + docID + " status : in-transit/in progress";
}
}
The CourierResource class is our root resource. It does not service any HTTP requests
directly. The root resource class CourierResource contains the sub-resource locator
method getCourierStatus() that returns a new resource class. If the path of the
request URL is "/courier/domestic" or "/courier/international" then first of all the root
resource will be matched, then the sub-resource locator will be matched and invoked,
which returns an instance of DomesticCourierSubResource or
InternationalCourierSubResource resource class obj. Sub-resource locators enable
reuse of resource classes. A method can be annotated with the @Path annotation with
empty path (@Path ("/") or @Path("/anything") that means "/domestic" etc) which
means that the sub resource locator is matched for the path of the enclosing resource.
The JAX-RS provider uses this DmesticCourierSubResource/
InternationalCourierSubResource instance to service the remainder of the request and
then takes that obj and calls the method on that class obj with which Http methods
the req has came.
http://localhost:8080/11SubresourceLocators/resource/courier/international/IN112
InternationalCourier: doc ID : IN112 status : in-transit
Dynamic Dispatching:
While our previous example does illustrate the concept of sub resource locators, it
does not show their full dynamic nature.
The CourierResource locator methods are retiring user class obj type but it can return
any instance of any class. At runtime, the JAX-RS provider will introspect this
instance’s class for resource methods that can handle the request.
The CourierResource classes returned by sub-resource locators is performed at
runtime thus it is possible to support polymorphism. A sub-resource locator may
return different sub-types depending on the request (for example a sub-resource
locator could return different sub-types dependent on the role /business need).
Instead of writing 2-locator methods for 2-user class obj our CourierResource class
method can have only one locator method which will return any java.lang.Object.
JAX-RS will introspect the instance returned to figure out how to dispatch the request.
For this example, if our courier is domestic, we will use our
DomesticCourierSubResource class to service the request. If our courier is
international, we will create and retun the InternationalCourierSubResource class obj
@Path("/courier")
public class CourierResource {
@Path("/{type}")
public Object locateServices(@PathParam("type") String type) {
if (type.equals("domestic")) {
return new DomesticCourierSubResource();
} else if (type.equals("international")) {
return new InternationalCourierSubResource();
}
return null;
}
}
If send req with /courier/domestic URI pattern then CourierResource lookup requests
routed to domestic would match so it creates DomesticCourierSubResource obj and
returns similarly we can have any Couriers but always return Object type only so that
we can avoid multiple locatotr methods and req will forwaded to corresponding
Resource dynamically based on the {type}.
Access the Resource:
http://localhost:8080/11.2DynamicDispatchingSubresourceLocators/resource/courie
r/domestic/DM112
DomesticCourier: awbNo : DM112 status : in progress
http://localhost:8080/11.2DynamicDispatchingSubresourceLocators/resource
/courier/international/IN112
InternationalCourier: doc ID : IN112 status : in-transit
Terminology:
Resource class:
A Java class that uses JAX-RS annotations to implement a corresponding Web
resource.
Root resource class:
A resource class annotated with @Path. Root resource classes provide the roots of the
resource class tree and provide access to sub-resources.
Request method designator:
A runtime annotation annotated with @HttpMethod. Used to identify the HTTP request
method to be handled by a resource method.
Resource method:
A method of a resource class annotated with a request method designator (@GET etc)
that is used to handle requests on the corresponding resource.
@Path(“/courier/{id}”)
class CourierResource {
// Resource method
@GET
public String getDetails(@PathParam(“id”) String id) {
}
}
Sub Resources:
Methods of a resource class that are annotated with @Path or either sub-resource
methods or sub-resource locators. Sub-resource methods handle a HTTP request
directly whilst (whilst means whereas) sub-resource locators return an object that will
handle a HTTP request.
Sub-resource method:
A method of a resource class that is used to handle requests on a sub-resource of the
corresponding resource. That means the method which is annotated with Request
method designator (@GET etc) and @Path is called as Sub-resource method.
@Path(“/courier/{id}”)
class CourierResource {
// Sub-Resource method
@GET
@Path(“/details”)
public String getDetails(@PathParam(“id”) String id) {
}
}
Sub-resource locator:
A method of a resource class that is used to locate sub-resources of the corresponding
resource.