REST type gives you a lot of flexibility. This is how to create the server and the corresponding client using Apache CXF.
Prerequisites
You should have installed:- Sun Java 6
- Maven 3
Creating a REST based Webservice
1) On Maven pom.xml please include:<packaging>war</packaging> <properties> <cxf.version>2.6.0</cxf.version> <spring.version>3.0.5.RELEASE</spring.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>${cxf.version}</version> <scope>runtime</scope> </dependency> <!-- REST based WS: Required libraries during compile time since Java 6 doesn't include REST specification libraries. --> <dependency> <groupId>org.apache.servicemix.specs</groupId> <artifactId>org.apache.servicemix.specs.jsr311-api-1.1</artifactId> <version>1.6.0</version> </dependency> <dependency> <groupId>org.apache.servicemix.specs</groupId> <artifactId>org.apache.servicemix.specs.jaxb-api-2.1</artifactId> <version>1.6.0</version> </dependency> <!-- REST based WS: Required libraries. In OSGi environment, these may be provided --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <version>${cxf.version}</version> <scope>runtime</scope> </dependency> </dependencies>
2) Create an interface defining a webservice
The primary annotations for SOAP based WS are: @Path, @Produces and a group defining the REST methods (@POST, @PUT, etc)
import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @Path("/calculator") // REST based WS: Path of this resource (or service) @Produces({"application/xml", "application/json"}) // REST based WS: Response format public interface CalculatorService { @POST // REST based WS: Called using POST method @Path("/sum") // REST based WS: Path of a sub resource public int sum( @FormParam(value = "a") // REST based WS: Define a form parameter (http://uri.com/sum?a=2) int a, @FormParam(value = "b") int b); @POST @Path("/algorithm/{code}") public Data process( @PathParam("code") // REST based WS: This argument is taken from a path String dCode, Data dData); }
3) Add XML annotations for complex object
Default constructor is mandatory!!!
@XmlRootElement(name = "data") public class Data { @XmlElement(name = "entry") public CollectiongetEntries() { return entries; } public void setEntries(Collection entries) { this.entries = entries; } }
@XmlRootElement public class FieldEntry { // Create setter getter methods for 'field' and 'value' }
4) Create the implementation
public class MyCalculatorServiceImpl implements CalculatorService
5) Create Spring context files
Inside resources directory (src/main/resources) create context files:
5.1) META-INF/spring/application-context.xml
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="calculatorService" class="michsan.research.cxf.wsserver.impl.MyCalculatorServiceImpl" /> </beans>
5.2) META-INF/spring/ws-context.xml (Watch for namespace!)
<?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:p="http://www.springframework.org/schema/p" 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/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml" /> <!-- REST based WS and SOAP based WS: Required --> <import resource="classpath:META-INF/cxf/cxf-extension-*.xml" /> <!-- if (Simple Web Application) { --> <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> <!-- } --> <!-- REST based WS: Root context --> <jaxrs:server id="wsServiceRoot" address="/rest"> <jaxrs:serviceBeans> <ref bean="calculatorService" /> </jaxrs:serviceBeans> <jaxrs:extensionMappings> <entry key="xml" value="application/xml" /> <entry key="json" value="application/json" /> </jaxrs:extensionMappings> </jaxrs:server> </beans>
6) Create web.xml file
In src/main/webapp/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>CXF Calculator Service</display-name> <description>Learning how to create CXF Webservice server</description> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:META-INF/spring/*-context.xml</param-value> </context-param> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>cxfServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>cxfServlet</servlet-name> <url-pattern>/ws/*</url-pattern> </servlet-mapping> </web-app>
7) Deploy (or mvn tomcat:run)
8) See it running in http://localhost:8080/cxf-ws-server/ws
Consuming the REST based Webservice
1) On Maven pom.xml<dependencies> <dependency> <artifactId>cxf-rt-frontend-jaxrs</artifactId> <groupId>org.apache.cxf</groupId> <version>2.6.0</version> </dependency> </dependencies>
2) Understand how to invoke the service.
Usually the service provider gives you a page describing how to use the service. If this is the case: Data sent and received is in the following format
<data> <entry> <field>name</field> <value>JACK</value> </entry> <entry> <field>cif</field> <value>343434</value> </entry> </data>Next, you must use complex object Data (see previous post)
3) On static main:
Given that center of all REST services is on http://localhost:8080/cxf-ws-server/ws/rest and the exact REST resource is on calculator/algorithm/{NAME_OF_ALGORITHM} using POST method and XML format, then in main method:
String baseUri = "http://localhost:8080/cxf-ws-server/ws/rest"; WebClient client = WebClient.create(baseUri); client.accept("application/xml"); // Service 1 ------------------------------ client.reset().path("calculator/sum"); Form form = new Form(); form.set("a", 4); form.set("b", 9); Response response = client.form(form); if (response.getStatus() == 200) { // OK InputStream inStream = (InputStream) response.getEntity(); BufferedReader reader = new BufferedReader(new InputStreamReader( inStream)); System.out.println(reader.readLine()); reader.close(); } // Service 2 ------------------------------ client.reset().path("calculator/algorithm/INTEGRAL"); Data requestData = new Data(); requestData.add("arg1", "5"); requestData.add("arg2", "8"); Data responseData = client.post(requestData, Data.class); // Print a response value System.out.println(responseData.getEntries().iterator().next().getValue());For testing the WS: http://niftybits.wordpress.com/2009/08/26/recipe-unit-testing-apache-cxf-restful-services/
2 comments:
Sehari-hari saya bekerja sebagai SPG menjual produk kosmetik terbaik di indonesia. Di sela waktu kerja saya browsing dengan hape untuk berkunjung ke berbagai blog. Saya mendapatkan banyak manfaat dan tambahan pengetahuan dengan membaca artikel seperti di blog ini. Trimakasih sudah berbagi.
Post a Comment