После длительного перерыва, рассмотрим как реализовать с помощью Apache Camel простейший REST-сервис. Реализовать подобное с помощью Apache Camel можно навскидку 3-мя способами. Мне как раз был необходим сервис по хранению и управлению настройками в формате key=value. REST необходим чтобы в дальнейшем сделать на AngularJS страницу для управления настройками.
Итак Apache Camel предоставляет следующие возможности для реализации REST сервиса
CXF Bean Component и CXFRS Component очень похожи друг на друга, и строятся на основе отдельного java-bean помеченного специальными аннотациями, и отличаются лишь обвязкой и инициализацией.Лично меня привлек CXF Bean Component который поддерживает из коробки одновременно два стандарта JAXRS, JAXWS. Что позволяет управлять выводом XML-JSON, плюс есть возможность использовать разработанный код для реализации SOAP WebService.
Сам код на Apache Camel очень лаконичен:
Детали скрываются в реализации ItemRestService. Ниже я опишу полную последовательность разработки
Сам сервис я попытался сделать захватывающим разные аспекты связывания данных.
Общий путь к REST-сервису:
http://localhost:8787/example
GET http://localhost:8787/example/getAllItem
GET http://localhost:8787/example/getItem/{key}
PUT http://localhost:8787/example/updateItem
PUT http://localhost:8787/example/addItem
DELETE http://localhost:8787/example/removeItem/{key}
getAllItem- GET запрос без параметров
getItem/{key}- GET запрос с запросе указывающий имя получаемого свойства
updateItem - PUT запрос обновления свойства. В теле запроса передается JSON
addItem - PUT запрос добавления свойства. В теле запроса передается JSON
removeItem/{key} - DELETE запрос на удаление свойства.
Изначально, для прозрачной работы с данными нам понадобится модель данных. У меня она предоставлена в виде XSD-схемы.
На основе который мы сгенерируем JAXB классы. Именно знакомый нам JAXB отвечает за "marshaling" из разных форматов. На самом деле, без этого этапа можно запросто обойтись. XSD-схема далее применяться не будет. Конечно можно разработать нужные классы вручную, но в таком подходе сервис получается стройнее, и появляется возможность в дальнейшем переработать его в SOAP Webservice.
После генерации имеем следующие классы:
На их основе разработаем интерфейс нашего сервиса:
Итак Apache Camel предоставляет следующие возможности для реализации REST сервиса
CXF Bean Component и CXFRS Component очень похожи друг на друга, и строятся на основе отдельного java-bean помеченного специальными аннотациями, и отличаются лишь обвязкой и инициализацией.Лично меня привлек CXF Bean Component который поддерживает из коробки одновременно два стандарта JAXRS, JAXWS. Что позволяет управлять выводом XML-JSON, плюс есть возможность использовать разработанный код для реализации SOAP WebService.
Сам код на Apache Camel очень лаконичен:
<?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:camel="http://camel.apache.org/schema/spring"
xmlns:osgi="http://www.springframework.org/schema/osgi" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.bssys.*" />
<bean id="itemRestService" class="com.bssys.rest_service.ItemRestService" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="jetty:http://localhost:8787?matchOnUriPrefix=true" />
<to uri="cxfbean:itemRestService" />
</route>
</camelContext>
</beans>
Детали скрываются в реализации ItemRestService. Ниже я опишу полную последовательность разработки
Сам сервис я попытался сделать захватывающим разные аспекты связывания данных.
Общий путь к REST-сервису:
http://localhost:8787/example
GET http://localhost:8787/example/getAllItem
GET http://localhost:8787/example/getItem/{key}
PUT http://localhost:8787/example/updateItem
PUT http://localhost:8787/example/addItem
DELETE http://localhost:8787/example/removeItem/{key}
getAllItem- GET запрос без параметров
getItem/{key}- GET запрос с запросе указывающий имя получаемого свойства
updateItem - PUT запрос обновления свойства. В теле запроса передается JSON
addItem - PUT запрос добавления свойства. В теле запроса передается JSON
removeItem/{key} - DELETE запрос на удаление свойства.
Изначально, для прозрачной работы с данными нам понадобится модель данных. У меня она предоставлена в виде XSD-схемы.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://bssys.com/item"
xmlns:tns="http://bssys.com/item" elementFormDefault="qualified">
<xsd:element name="itemRequest" type="tns:itemRequest"/>
<xsd:element name="itemResponse" type="tns:itemResponse"/>
<xsd:complexType name="item">
<xsd:sequence>
<xsd:element name="key" type="xsd:string"/>
<xsd:element name="value" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="itemRequest">
<xsd:sequence>
<xsd:element name="item" type="tns:item"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="itemResponse">
<xsd:sequence>
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded" type="tns:item"/>
<xsd:element name="errorMessage" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
На основе который мы сгенерируем JAXB классы. Именно знакомый нам JAXB отвечает за "marshaling" из разных форматов. На самом деле, без этого этапа можно запросто обойтись. XSD-схема далее применяться не будет. Конечно можно разработать нужные классы вручную, но в таком подходе сервис получается стройнее, и появляется возможность в дальнейшем переработать его в SOAP Webservice.
После генерации имеем следующие классы:
- Item
- ItemRequest
- ItemResponse
- ObjectFactory
На их основе разработаем интерфейс нашего сервиса:
package com.bssys.service;
import org.springframework.stereotype.Service;
import com.bssys.jaxb.model.ItemRequest;
import com.bssys.jaxb.model.ItemResponse;
@Service
public interface ItemService {
public ItemResponse addItem(ItemRequest request);
public ItemResponse updateItem(ItemRequest request);
public ItemResponse getItem(String key);
public ItemResponse getAllItem();
public ItemResponse removeItem(String key);
public ItemRequest stubRequest();
}
Слой DAO:
package com.bssys.dao;
import java.util.List;
import org.springframework.stereotype.Service;
import com.bssys.jaxb.model.Item;
@Service
public interface ItemManagerDao {
public Item getItem(String name);
public void deleteItem(String name);
public List- getAllItems();
public void insertItem(Item item);
public void updateItem(Item item);
}
Далее простейшая реализация "in memory":
package com.bssys.dao;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import com.bssys.jaxb.model.Item;
@Component
public class ItemManagerMemoryDao implements ItemManagerDao {
private List- items = new ArrayList
- ();
@Override
public Item getItem(String name) {
// TODO Auto-generated method stub
for (Item item: items){
String key = item.getKey();
if (key.equals(name)){
return item;
}
}
throw new RuntimeException("Item Not Found: " + name);
}
@Override
public List
- getAllItems() {
// TODO Auto-generated method stub
return items;
}
@Override
public void insertItem(Item item) {
// TODO Auto-generated method stub
items.add(item);
}
@Override
public void updateItem(Item item) {
// TODO Auto-generated method stub
Item storeItem = getItem(item.getKey());
storeItem.setValue(item.getValue());
}
@Override
public void deleteItem(String name) {
// TODO Auto-generated method stub
Item storeItem = getItem(name);
items.remove(storeItem);
}
}
И сам REST-сервис:
package com.bssys.rest_service;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import org.springframework.beans.factory.annotation.Autowired;
import com.bssys.dao.ItemManagerMemoryDao;
import com.bssys.jaxb.model.Item;
import com.bssys.jaxb.model.ItemRequest;
import com.bssys.jaxb.model.ItemResponse;
import com.bssys.service.ItemService;
@Path("/example")
public class ItemRestService implements ItemService{
@Autowired
private ItemManagerMemoryDao dao;
@PUT
@Path("addItem")
@Consumes("application/json")
@Produces("application/json")
public ItemResponse addItem(ItemRequest request) {
// TODO Auto-generated method stub
ItemResponse userResponse = new ItemResponse();
try{
dao.insertItem(request.getItem());
userResponse.setErrorMessage("Ok");
}catch(Exception e){
userResponse.setErrorMessage("Error: "+e.getMessage());
}
return userResponse;
}
@PUT
@Path("updateItem")
@Consumes("application/json")
@Produces("application/json")
public ItemResponse updateItem(ItemRequest request) {
// TODO Auto-generated method stub
ItemResponse userResponse = new ItemResponse();
try{
dao.updateItem(request.getItem());
userResponse.setErrorMessage("Ok");
}catch(Exception e){
userResponse.setErrorMessage("Error: "+e.getMessage());
}
return userResponse;
}
@GET
@Path("getItem/{key}")
@Produces("application/json")
public ItemResponse getItem(@PathParam("key") String key) {
// TODO Auto-generated method stub
ItemResponse userResponse = new ItemResponse();
try{
Item item = dao.getItem(key);
userResponse.getItem().add(item);
userResponse.setErrorMessage("Ok");
}catch(Exception e){
userResponse.setErrorMessage("Error: "+e.getMessage());
}
return userResponse;
}
@GET
@Path("getAllItem")
@Produces("application/json")
public ItemResponse getAllItem() {
// TODO Auto-generated method stub
ItemResponse userResponse = new ItemResponse();
try{
List- allItems = dao.getAllItems();
List
- item = userResponse.getItem();
item.addAll(allItems);
userResponse.setErrorMessage("Ok");
}catch(Exception e){
userResponse.setErrorMessage("Error: "+e.getMessage());
}
return userResponse;
}
@DELETE
@Path("removeItem/{key}")
@Consumes("application/json")
@Produces("application/json")
public ItemResponse removeItem(@PathParam("key") String key) {
// TODO Auto-generated method stub
ItemResponse userResponse = new ItemResponse();
try{
dao.deleteItem(key);
userResponse.setErrorMessage("Ok");
}catch(Exception e){
userResponse.setErrorMessage("Error: "+e.getMessage());
}
return userResponse;
}
@Override
@GET
@Path("stubRequest")
@Produces("application/json")
public ItemRequest stubRequest() {
// TODO Auto-generated method stub
ItemRequest itemRequest = new ItemRequest();
Item item = new Item();
item.setKey("key");
item.setValue("value");
itemRequest.setItem(item);
return itemRequest;
}
}
Все это собирается как OSGI-модуль готовый к развертыванию в ServiceMi. Исходники на BitBucket https://Hibernate2009@bitbucket.org/Hibernate2009/restful-with-apache-camel.git
Комментариев нет:
Отправить комментарий