A web service is a
method of communication between multiple devices over the World Wide Web.
Using Web Services we
can publish application's functions to everyone.
In the web services world, REpresentational State Transfer (REST)
is a key design idiom that embraces a stateless client-server
architecture in which the web services are viewed as resources
and can be identified by their URLs.
This basic REST design principle establishes a one-to-one mapping between
create, read, update, and delete (CRUD)
operations and HTTP methods.
Required Software
Pre-requsite
Instructions assume that jdk,jboss,cxf is installed without any error.
Instructions
Click here to download source code of above example
- To create a resource on the server, use POST.
- To retrieve a resource, use GET.
- To change the state of a resource or to update it, use PUT.
- To remove or delete a resource, use DELETE.
- Developemnt
- Testing
- Create a dynamic web project in eclipse.
- Create a file name customer.xsd under /WEB-INF and use the following xml snippet.
- Generate Jaxb classes from customer.xsd using eclipse. After execution of above steps com.kaustuv.jaxrs.example.vo package will be created which contains three Jaxb generated classes. Address.java , Customer.java , ObjectFactory.
- Add @XmlRootElement to both jaxb generated classes. please have a look into following code snippets. Address.java
- Open web.xml under WEB-INF\web.xml and add following xml snippet
- Create a new package "com.kaustuv.jaxrs.example.service"
- create a new service interface name DemoCustomerService under package "com.kaustuv.jaxrs.example.service". Add following code snippet.
- Create DemoCustomerServiceImpl under package "com.kaustuv.jaxrs.example.service". Add following code snippet
- Create a xml file name global-beans.xml under WEB-INF/conf
- Create a xml name jaxrs-beans.xml under WEB-INF/conf
- Export and package this as war. Destination path %JBOSS_HOME%\server\default
- Open command prompt and go to directory %JBOSS_HOME\bin .
- Execute run.bat -c default -b 0.0.0.0
- click on our wadl url for our restful webservice project. http://localhost:8080/jaxrs-example/customerService?_wadl
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:complexType name="customer"> <xsd:sequence> <xsd:element name="address" type="address" /> <xsd:element name="customerId" type="xsd:long" /> <xsd:element name="customerName" type="xsd:string" /> <xsd:element name="phone" type="xsd:long" /> </xsd:sequence> </xsd:complexType> <xsd:complexType name="address"> <xsd:sequence> <xsd:element name="street" type="xsd:string" /> <xsd:element name="city" type="xsd:string" /> <xsd:element name="state" type="xsd:string" /> <xsd:element name="country" type="xsd:string" /> <xsd:element name="pincode" type="xsd:long" /> </xsd:sequence> </xsd:complexType> </xsd:schema>
package com.kaustuv.jaxrs.example.vo; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * <p>Java class for address complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * <complexType name="address"> * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> * <element name="street" type="{http://www.w3.org/2001/XMLSchema}string"/> * <element name="city" type="{http://www.w3.org/2001/XMLSchema}string"/> * <element name="state" type="{http://www.w3.org/2001/XMLSchema}string"/> * <element name="country" type="{http://www.w3.org/2001/XMLSchema}string"/> * <element name="pincode" type="{http://www.w3.org/2001/XMLSchema}long"/> * </sequence> * </restriction> * </complexContent> * </complexType> * </pre> * * */ @XmlRootElement(name="address") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "address", propOrder = { "street", "city", "state", "country", "pincode" }) public class Address { @XmlElement(required = true) protected String street; @XmlElement(required = true) protected String city; @XmlElement(required = true) protected String state; @XmlElement(required = true) protected String country; protected long pincode; /** * Gets the value of the street property. * * @return * possible object is * {@link String } * */ public String getStreet() { return street; } /** * Sets the value of the street property. * * @param value * allowed object is * {@link String } * */ public void setStreet(String value) { this.street = value; } /** * Gets the value of the city property. * * @return * possible object is * {@link String } * */ public String getCity() { return city; } /** * Sets the value of the city property. * * @param value * allowed object is * {@link String } * */ public void setCity(String value) { this.city = value; } /** * Gets the value of the state property. * * @return * possible object is * {@link String } * */ public String getState() { return state; } /** * Sets the value of the state property. * * @param value * allowed object is * {@link String } * */ public void setState(String value) { this.state = value; } /** * Gets the value of the country property. * * @return * possible object is * {@link String } * */ public String getCountry() { return country; } /** * Sets the value of the country property. * * @param value * allowed object is * {@link String } * */ public void setCountry(String value) { this.country = value; } /** * Gets the value of the pincode property. * */ public long getPincode() { return pincode; } /** * Sets the value of the pincode property. * */ public void setPincode(long value) { this.pincode = value; } }Customer.java
package com.kaustuv.jaxrs.example.vo; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * <p>Java class for customer complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * <complexType name="customer"> * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> * <element name="address" type="{}address"/> * <element name="customerId" type="{http://www.w3.org/2001/XMLSchema}long"/> * <element name="customerName" type="{http://www.w3.org/2001/XMLSchema}string"/> * <element name="phone" type="{http://www.w3.org/2001/XMLSchema}long"/> * </sequence> * </restriction> * </complexContent> * </complexType> * </pre> * * */ @XmlRootElement(name="customer") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "customer", propOrder = { "address", "customerId", "customerName", "phone" }) public class Customer { @XmlElement(required = true) protected Address address; protected long customerId; @XmlElement(required = true) protected String customerName; protected long phone; /** * Gets the value of the address property. * * @return * possible object is * {@link Address } * */ public Address getAddress() { return address; } /** * Sets the value of the address property. * * @param value * allowed object is * {@link Address } * */ public void setAddress(Address value) { this.address = value; } /** * Gets the value of the customerId property. * */ public long getCustomerId() { return customerId; } /** * Sets the value of the customerId property. * */ public void setCustomerId(long value) { this.customerId = value; } /** * Gets the value of the customerName property. * * @return * possible object is * {@link String } * */ public String getCustomerName() { return customerName; } /** * Sets the value of the customerName property. * * @param value * allowed object is * {@link String } * */ public void setCustomerName(String value) { this.customerName = value; } /** * Gets the value of the phone property. * */ public long getPhone() { return phone; } /** * Sets the value of the phone property. * */ public void setPhone(long value) { this.phone = value; } }ObjectFactory
package com.kaustuv.jaxrs.example.vo; import javax.xml.bind.annotation.XmlRegistry; /** * This object contains factory methods for each * Java content interface and Java element interface * generated in the com.kaustuv.jaxrs.example.vo package. * <p>An ObjectFactory allows you to programatically * construct new instances of the Java representation * for XML content. The Java representation of XML * content can consist of schema derived interfaces * and classes representing the binding of schema * type definitions, element declarations and model * groups. Factory methods for each of these are * provided in this class. * */ @XmlRegistry public class ObjectFactory { /** * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.kaustuv.jaxrs.example.vo * */ public ObjectFactory() { } /** * Create an instance of {@link Customer } * */ public Customer createCustomer() { return new Customer(); } /** * Create an instance of {@link Address } * */ public Address createAddress() { return new Address(); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>jaxrs-example</display-name> <servlet> <description>Apache CXF Endpoint</description> <display-name>cxf</display-name> <servlet-name>cxf</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cxf</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>60</session-timeout> </session-config> <context-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/conf/*beans.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
/** * * Copyright (c) Kaustuv Maji , 2013 * Repos - https://github.com/kaustuvmaji * Blog - http://kaustuvmaji.blogspot.in * */ package com.kaustuv.jaxrs.example.service; 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.QueryParam; import javax.ws.rs.core.Response; import com.kaustuv.jaxrs.example.vo.Customer; /** * This is rest services interface . * Methods * i. Add customer {@link #addCustomer(Customer)}. * ii. Get customer by customerId {@link #getCustomerById(long)}. * iii. Update customer {@link #updateCustomer(Customer)}. * iv. Delete customer {@link #deleteCustomer(long)}. * * @since 1.0 * @version 1.0 * * @author KMaji * */ public interface DemoCustomerService { /** * This method is used to demonstrate http method GET. * * @param custId will be accepted as Queryparam. * @return response */ @GET @Path("/getCustomerById") public Response getCustomerById(@QueryParam("custId") long custId); /** * This method is used to demonstrate http method POST. * @param customer * @return response */ @POST @Path("/addCustomer") public Response addCustomer(Customer customer); /** * This method is used to demonstrate Http method DELETE. * @param custId will be accepted as Queryparam. * @return response */ @DELETE @Path("/deleteCustomer") public Response deleteCustomer(@QueryParam("custId") long custId); /** * This method is to demonstrate http method PUT. * * @param customer * @return response */ @PUT @Path("/updateCustomer") public Response updateCustomer(Customer customer); }
/** | | Copyright (c) Kaustuv Maji , 2013 | | Please do not use source code in production. | Repos - https://github.com/kaustuvmaji | Blog - http://kaustuvmaji.blogspot.in */ package com.kaustuv.jaxrs.example.service; import java.util.HashMap; import java.util.Map; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.apache.log4j.Logger; import com.kaustuv.jaxrs.example.vo.Address; import com.kaustuv.jaxrs.example.vo.Customer; /** * This implementation class is to implement rest service interface. * Methods * -- Add customer {@link #addCustomer(Customer)}. * -- Get customer by customerId {@link #getCustomerById(long)}. * -- Update customer {@link #updateCustomer(Customer)}. * -- Delete customer {@link #deleteCustomer(long)}. * -- init {@link #init()}. * -- destory {@link #destroy()}. * * @since 1.0 * @version 1.0 * * @author KMaji * */ public class DemoCustomerServiceImpl implements DemoCustomerService { @Context UriInfo uriInfo; private final static String ACCESS_CONTROL_ALLOW_ORIGIN = "*"; private Logger log; private Map<Long, Customer> customers; public DemoCustomerServiceImpl() { log = Logger.getLogger(DemoCustomerServiceImpl.class); customers = new HashMap<Long, Customer>(); } public Response getCustomerById(long custId) { log.info("Executing getCustomerById operation"); if (!customers.containsKey(custId)) { return Response.status(Response.Status.BAD_REQUEST) .location(uriInfo.getAbsolutePath()) .entity("customer not found") .header("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN) .build(); } return Response.ok(uriInfo.getAbsolutePath()) .entity(customers.get(custId)) .header("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN) .build(); } public Response addCustomer(Customer customer) { log.info("Executing Add Customer operation"); if (customers.containsKey(customer.getCustomerId())) { return Response.status(Response.Status.BAD_REQUEST) .location(uriInfo.getAbsolutePath()) .entity("Exsisting customer found with same id.") .header("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN) .build(); } customers.put(customer.getCustomerId(), customer); log.info("Added new customer with customer id" + customer.getCustomerId()); return Response.ok(uriInfo.getAbsolutePath()) .entity(customer) .header("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN) .build(); } public Response deleteCustomer(long custId) { log.info("Executing Delete Customer operation"); if (!customers.containsKey(custId)) { return Response.status(Response.Status.BAD_REQUEST) .location(uriInfo.getAbsolutePath()) .entity("customer not found") .header("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN) .build(); } customers.remove(custId); log.info("Removed customer contains customerid " + custId); return Response.ok(uriInfo.getAbsolutePath()) .entity("Removed customer contains customerid " + custId) .header("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN) .build(); } public Response updateCustomer(Customer customer) { log.info("Executing update Customer operation"); if (!customers.containsKey(customer.getCustomerId())) { return Response.status(Response.Status.BAD_REQUEST) .location(uriInfo.getAbsolutePath()) .entity("customer not found") .header("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN) .build(); } customers.put(customer.getCustomerId(), customer); return Response.ok(uriInfo.getAbsolutePath()) .entity(customer) .header("Access-Control-Allow-Origin", ACCESS_CONTROL_ALLOW_ORIGIN) .build(); } /** * Init method is used to prepare data which we * will use for testing purpose. * usage of this method is defined in bean definition. */ public void init() { Customer cus1 = new Customer(); cus1.setCustomerId(1l); cus1.setCustomerName("Kaustuv Maji"); cus1.setPhone(9830098300l); Address add = new Address(); add.setStreet("saltlake"); add.setCity("kolkata"); add.setState("westbengal"); add.setCountry("India"); add.setPincode(700106); cus1.setAddress(add); customers.put(cus1.getCustomerId(), cus1); log.info("Added " + cus1.getCustomerName() + " into Customer info"); Customer cus2 = new Customer(); cus2.setCustomerId(2l); cus2.setCustomerName("customer 2"); customers.put(cus2.getCustomerId(), cus2); log.info("Added " + cus2.getCustomerName() + " into Customer info"); log.info("Customer info map contains " + customers.size() + " details"); } /** * destroy method is also used after our testing purpose is done. * usage of this method is defined in bean definition. */ public void destroy() { log.info("Cleaning up customers info map"); customers.clear(); } }
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd" default-lazy-init="false"> <import resource="classpath:META-INF/cxf/cxf*.xml" /> <!-- Cxf Jason provider --> <bean id="jsonProvider" class="org.apache.cxf.jaxrs.provider.JSONProvider"> <property name="dropRootElement" value="true" /> <property name="supportUnwrapped" value="true" /> </bean> <!-- Cxf Jaxb Provider --> <bean id="jaxbXmlProvider" class="org.apache.cxf.jaxrs.provider.JAXBElementProvider" /> <!-- Cxf Cors filter (cross domain purpose)--> <bean id="cors-filter" class="org.apache.cxf.jaxrs.cors.CrossOriginResourceSharingFilter"/> </beans>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:cxf="http://cxf.apache.org/core" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd" default-lazy-init="false"> <!-- Service --> <bean id="customerService" class="com.kaustuv.jaxrs.example.service.DemoCustomerServiceImpl" init-method="init" destroy-method="destroy" /> <!-- Jaxrs Server --> <jaxrs:server id="restserver" address="/customerService"> <!-- adding service bean --> <jaxrs:serviceBeans> <ref bean="customerService" /> </jaxrs:serviceBeans> <!-- adding media type provider --> <jaxrs:providers> <ref bean="jsonProvider" /> <ref bean="jaxbXmlProvider" /> <ref bean="cors-filter" /> </jaxrs:providers> <jaxrs:features> <cxf:logging/> </jaxrs:features> <!-- Keeping extention type --> <jaxrs:extensionMappings> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </jaxrs:extensionMappings> </jaxrs:server> </beans>
- Post Development testing
- open soap ui and create a new project using our wadl url. http://localhost:8080/jaxrs-example/customerService?_wadl Test Http GET Method
- Explore soap ui project name RestCustomerService. Select Request of service getCustomerById
- enter value of parameter custId in following example picture value is 2 . click on submit Test Http POST Method
- Explore soap ui project name RestCustomerService. Select Request of service addCustoer
- enter customer xml use following snippet and click on submit .
- Explore soap ui project name RestCustomerService. Select Request of service updateCustomer
- enter customer xml use following snippet and click on submit .
- Explore soap ui project name RestCustomerService. Select Request of service deleteCustomer
- enter value of parameter custId in following example picture value is 3 . click on submit .
<customer> <customerId>3</customerId> <customerName>testPost</customerName> <phoneNumber>9831098301</phoneNumber> <address> <street>saltlake</street> <city>kolkata</city> <state>westbengal</state> <country>India</country> <pincode>700064</pincode> </address> </customer>
Test Http PUT Method
<customer> <customerId>3</customerId> <customerName>testUpdate</customerName> <phoneNumber>9831098301</phoneNumber> <address> <street>saltlake</street> <city>kolkata</city> <state>westbengal</state> <country>India</country> <pincode>700064</pincode> </address> </customer>
Test Http DELETE Method
Click here to download source code of above example
Source Code
- References:
European Union laws require you to give European Union visitors information about cookies used on your blog. In many cases, these laws also require you to obtain consent.
As a courtesy, we have added a notice on your blog to explain Google's use of certain Blogger and Google cookies, including use of Google Analytics and AdSense cookies.
No comments:
Post a Comment