RESTful Web Services

REST stands for Representational state transfer protocol. Restful web services are designed for resource intercommunication. REST APIs provide access to resources (data entities) via URL paths. To use a REST API, application will make a HTTP request and parse the response.

REST is an architectural style which is based on web-standards and the HTTP protocol. REST was first described by Roy Fielding in 2000. In a REST based architecture everything is a resource. A resource is accessed via a common interface based on the HTTP standard methods. In a REST based architecture you typically have a REST server which provides access to the resources and a REST client which accesses and modifies the REST resources. REST allows that resources have different representations, e.g., text, XML, JSON etc. The REST client can ask for a specific representation via the HTTP protocol (content negotiation).

HTTP methods:

The PUT, GET, POST and DELETE methods are typically used in REST based architectures. The following table gives an explanation of these operations.

GET: Defines a reading access of the resource without side-effects. The resource is never changed via a GET request, e.g., the request has no side effects (idempotent).

PUT: Creates a new resource. It must also be idempotent.

DELETE: Removes the resources. The operations are idempotent. They can get repeated without leading to different results

POST: Updates an existing resource or creates a new resource.

Java Implementation for Restful web services:

JAX-RS:

Java defines REST support via the Java Specification Request (JSR) 311. This specification is called JAX-RS (The Java API for RESTful Web Services). JAX-RS uses annotations to define the REST relevance of Java classes.

Jersey:

Jersey is the reference implementation for the JSR JAX-RS specification. The Jersey implementation provides a library to implement Restful web services in a Java servlet container. On the server side Jersey provides a servlet implementation which scans predefined classes to identify RESTful resources. In web.xml configuration file we register this servlet for web application. The Jersey implementation also provides a client library to communicate with RESTful web services.

RESTEasy:

RESTEasy is the JAX-RS implementation provided by JBoss project. We can use RESTEasy to create restful web services. RESTEasy provides tighter integration with the JBoss Application Server but we can deploy it on any servlet container.

Important JAX_RS Annotations:

AnnotationDescription
@PATH(your_path)Sets the path to base URL + /your_path. The base URL is based on your application name, the servlet and the URL pattern from the web.xml configuration file.
@POSTIndicates that the following method will answer to

an HTTP POST request.

@GETIndicates that the following method will answer to an HTTP GET request.
@PUTIndicates that the following method will answer to

an HTTP PUT request.

@DELETEIndicates that the following method will answer

to an HTTP DELETE request.

@Produces(MediaType.TEXT_PLAIN[, more-types])@Produces defines which MIME type is delivered by a method annotated with @GET. In the example text (“text/plain”) is produced. Other examples would be “application/xml” or “application/json”.
@PathParamUsed to inject values from the URL into a method

parameter. for example, we can inject the ID of

a resource into the method to get the

correct object.

@ConsumesThe @Consumes annotation is used to specify the MIME media types a REST resource can consume.

Code Snippet:

@Path("/customers")
 public class CustomerController {

@PUT
@Path(“/createCustomer”)
public String CreateCustomer(@QueryParam(“custNo”) int custNo,
@QueryParam(“custName”) String custName,
@QueryParam(“custCountry”) String custCountry) {

Customer customer = new Customer(custNo, custName, custCountry);
return “customer details created successfully”;
}

@GET
@Path(“/{custNo}”)
@Produces(MediaType.APPLICATION_JSON)
public Customer getCustomer(@PathParam(“custNo”) int custNo) {
Customer customer = new CustomersDao().getCustomerDetails(custNo);

return customer;
}

@POST
@Path(“/updateCustomer”)
public String updateCustomer(@QueryParam(“custNo”) int custNo,
@QueryParam(“custName”) String custName,
@QueryParam(“custCountry”) String custCountry) {
new CustomersDao().updateCustomerDetails(custNo, custName, custCountry);

return “customer details updated successfully”;

}

@Path(“/deleteCustomer”)
public String deleteCustomer(@QueryParam(“custNo”) int custNo) {
new CustomersDao().deleteCustomerDetails(custNo);

return “customer deleted successfully”;

}
}

Will have a Customer POJO class for above restful web service.

We should include Jersey implementation classes in web.xml file in our web project.

<servlet>
 <servlet-name>Jersey REST Service</servlet-name>
 <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
 <init-param>
 <param-name>jersey.config.server.provider.packages</param-name>
 <param-value>com.rest.ws.demo</param-value>
 </init-param>
 <init-param>
 <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
 <param-value>true</param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
 </servlet>

<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest</url-pattern>
</servlet-mapping>

Securing Restful web services:

We can secure RESTful Web Services using web.xml:

We have to define security constraint in deployment descriptor. Below code snippet gives an idea of defining the security constraint.

 <security-constraint>
 <web-resource-collection>
 <web-resource-name>ClientDataWS</web-resource-name>
 <url-pattern>/rest/customers/createCustomer</url-pattern>
 <url-pattern>/rest/customers/getCustomer</url-pattern>
 <http-method>PUT</http-method>
 <http-method>GET</http-method>
 </web-resource-collection>
 <auth-constraint>
 <role-name>admin</role-name>
 </auth-constraint>
 </security-constraint>

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>default</realm-name>
</login-config>

Using SecurityContext:

The javax.ws.rs.core.SecurityContext interface provides access to security-related information for a request. It enables to access the following security-related information:

  • security.Principal object containing the name of the user making the request.
  • Authentication types used to secure the resource, such as BASIC_AUTH and CLIENT_CERT_AUTH.

BASIC_AUTH:

This is a very basic authentication.this type of authentication checks whether client has given correct credentials or not.

CLIENT_CERT_AUTH: With client authentication, the web server authenticates the client by using the client’s public key certificate. Client authentication is a more secure method of authentication than either basic or form-based authentication. It uses SSL (HTTPS),to authenticate the client using the client’s public key certificate

  • Whether the authenticated user is included in a particular role.
  • Whether the request was made using a secure channel, such as HTTPS.

Here is a small example to use Securitycontext in our web services method.

@GET
 @Path("/getCustomer")
 @Produces(MediaType.APPLICATION_JSON)
 public Customer getCustomer(@Context SecurityContext sc,@QueryParam("custNo") int custNo) {

if (sc.isUserInRole(“admin”) && sc.isSecure()) {
Customer customer = new CustomersDao().getCustomerDetails(custNo);
return customer;
} else{
return null;
}
}

Using Java Security Annotations:

The javax.annotation.security package provides annotations to secure the resource. Following table describes annotations we can use to secure the RESTful Web services. By using these annotation we can restrict the accessibility of resources from users.

DeclareRolesDeclares roles.
DenyAllSpecifies that no security roles are allowed to invoke the specified methods.
PermitAllSpecifies that all security roles are allowed to invoke the specified methods.
RolesAllowedSpecifies the list of security roles that are allowed to invoke the methods in the application.
RunAsDefines the identity of the application during execution in a J2EE container.

A small code snippet for using the annotations:

@GET
 @Path("/getCustomer")
 @Produces(MediaType.APPLICATION_JSON)
 @RolesAllowed("ADMIN")
 public Customer getCustomer(@Context SecurityContext sc,
 @QueryParam("custNo") int custNo) {
 Customer customer = new CustomersDao().getCustomerDetails(custNo);

return customer;
}

In this example the users with admin role only able to access the method. Remaining users will get error saying “HTTP Status 403 – Access to the requested resource has been denied”.

We can use either annotation provided by javax.annotation.security to define the roles or we can declare in web.xml file. The user with that particular role only allowed to access the resource.

Author

  • Manasa Devineni

    Manasa Devineni works as Software Engineer with Trigent Software. She is an OCJP certified Java Developer Software Engineer having 3+ years of experience in JAVA/J2EE. Manasa has worked on Spring, Hibernate, Jasper Reports, GWT and Restful web services technologies. She is strongly interested to work on Web and Enterprise application projects.