RESTful Web services emerged as an easy to use alternative to the SOAP and WSDL style Web services. Due to their simplicity RESTful Web services continue the gain high adoption among many Web 2.0 service providers.
SAP NetWeaver CE 7.20 does not provide out of the box support for REST services, but many 3dt party tools can be used for developing and deploying such services on SAP NetWeaver.
This article will show how to start developing RESTful Web services using SAP NetWeaver CE and Apache CXF.
Apache CXF is a popular open source services framework. Among the many other supported standards is JAX-RS (Java API for RESTful Web Services) that standardizes the way RESTful services can be developed in Java.
To be able to develop and execute RESTful Web services you need to create a new Software Component that wraps the CXF JAX-RS implementation.
| Public Part | Entities |
|---|---|
| api | jsr311-api-1.0.jar |
| archives | *(all jar files) |
This step is optional if you don't plan to reuse the JAX-RS software component.
Open the Development Infrastructure perspective, select the JAX-RS SC and choose Export... from the context menu. Choose to build all three contained DCs and click Next. On the second page of the wizard select the target file name and location.
This step is optional if you are not reusing the JAX-RS software component.
Open the Development Infrastructure perspective, select your development configuration and choose Import SC from the context menu.
After having the JAX-RS libraries in the workspace, the development of a RESTfull service is relatively easy.
Create a Web Application DC and a wrapping Enterprise Application DC. In both DCs add dependency to jax-rs/ear from the JAX-RS SC.Accept all proposed settings.
The application will contain two classes - one data object and one service. Bellow you can find the sample source code.
The data object:
package com.mycompany.rest;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Customer")
public class CustomerData {
private String id;
private String name;
public CustomerData() {
}
public CustomerData(String id, String name) {
super();
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}The service:
package com.mycompany.rest;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Response.Status;
@Path("/customer")
public class CustomerService {
private Map<String, CustomerData> customers;
public CustomerService() {
customers = new HashMap<String, CustomerData>();
}
@GET
@Path("{id}")
@Produces({"text/xml", "application/json"})
public Response getCustomer(@PathParam("id") String id) {
CustomerData customer = customers.get(id);
if (customer != null) {
return Response.ok().entity(customer).build();
}
return Response.status(Status.NOT_FOUND).entity("Customer with id " + id + " was not found!").build();
}
@POST
@Consumes({"application/json", "text/xml"})
public Response createCustomer(@Context UriInfo uriInfo, CustomerData customer) {
String id = String.valueOf(System.currentTimeMillis());
customer.setId(id);
customers.put(id, customer);
URI uri = uriInfo.getRequestUriBuilder().path(id).build();
return Response.created(uri).build();
}
@PUT
@Path("{id}")
@Consumes({"application/json", "text/xml"})
public Response updateCustomer(@PathParam("id") String id, CustomerData customer) {
CustomerData existingCustomer = customers.get(id);
if (existingCustomer != null) {
existingCustomer.setName(customer.getName());
return Response.noContent().build();
}
return Response.status(Status.NOT_FOUND).entity("Customer with id " + id + " was not found!").build();
}
@DELETE
@Path("{id}")
public Response deleteCustomer(@PathParam("id") String id) {
CustomerData customer = customers.remove(id);
if (customer != null) {
return Response.noContent().build();
}
return Response.status(Status.NOT_FOUND).entity("Customer with id " + id + " was not found!").build();
}
}The last step before deployment is to configure the CXF servlet instance that will intercept all RESTfull calls to your application. Open the web deployment descriptor web.xml and configure Apache CXF for your application. Add the entries bellow after the welcome-file-list section.
<servlet>
<servlet-name>RestfulApp</servlet-name>
<servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet
<!-- Specify here all REST services classes. Multiple entries can be separated with space.
<init-param>
<param-name>jaxrs.serviceClasses</param-name>
<param-value>com.mycompany.rest.CustomerService</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>RestfulApp</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>Before deploying the RESTfull application ensure that jax-rs/ear is deployed on your server.
The application can be tested with any of the REST clients around today or you can even write your own.
There are even add-ons and plug-ins for some web browsers.
Bellow you can see screenshots from the execution using "Simple REST Client" (see Resources section).
A key point for any RESTful service is its' resource URL – it uniquely identifies the underlying entity and is used for all entity operations except create. Let's take a look at a sample resource URL:
http://myserver:50000/vendor~appname/rest/customer/123
Here http://myserver:50000/vendor~appname/+ is the URL of the web application and usually depends on the web development component vendor and name.
“rest” is the path inside the application which is assigned to the REST servlet. This value was specified in the web.xml deployment descriptor above – see the servlet-name section
“customer” is the name of the RESTful service as specified by the @Path annotation in the CustomerService class.
The remaining part of the URL constitutes the unique resource identifier.
Entity creation in REST is mapped to HTTP POST. To create an entity instance, you specify POST for HTTP method, "Content-Type: application/json" and supply the actual message data (in this case in JSON format) - {Customer: {name: "John Smith"}}.
After a successful execution, the server will return HTTP status 201 CREATED and an HTTP header named location. The value of this header is a direct link to the entity - it is actually the POST method url with the addition of the entity key (the customer's id in this case).
Reading an entity in REST corresponds to the HTTP GET method. The location header value from the previous step is used to for reading the existing entity. The data format depends on the Accept HTTP header – in the example bellow text/xml is used and data is returned as xml. To use JSON instead, set the header value to application/json.
HTTP PUT is used to update an existing entity. Set the “Content-Type” HTTP header to indicate the data format and fill in the data itself. Use HTTP GET to check the update operation results.
Deleting an entity is simple – just use HTTP DELETE

tsvetan.stoyanov is a senior developer in the area of SOA Foundation.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 4246 | |
| 3365 | |
| 2605 | |
| 2153 | |
| 1983 | |
| 1257 | |
| 1164 | |
| 1122 | |
| 1100 |