Olingo client的使用

原文来至:http://user.qzone.qq.com/974816077/2


上篇我们使用restFull来对OData service进行POST和PUT操作,麻烦的是我们必须要自己编写请求body. 如图:

 
<?xml version='1.0' encoding='utf-8'?>
< entry  xmlns = "http://www.w3.org/2005/Atom"
xmlns:m = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" 
xmlns:d = "http://schemas.microsoft.com/ado/2007/08/dataservices"
xml:base = "http://localhost:8080/odata2-jpa2/SemServiceServlet.svc/" >
< id >http://localhost:8080/odata2-jpa2/SemServiceServlet.svc/Departments(4) </ id >
< title  type = "text" >Departments </ title >
< updated >2014-10-17T15:15:57.071+08:00 </ updated >
< category  term = "odata2_jpa2.Department"  scheme = "http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
< link  href = "Departments(4)"  rel = "edit"  title = "Department" />
< content  type = "application/xml" >
< m:properties >
< d:Id >4 </ d:Id >
< d:Name > </ d:Name >
</ m:properties >
</ content >
</ entry >
 
这就是我们进行PUT更新Department时自己编写的请求body,相当麻烦,下面我们再介绍Olingo client 对这个请求头的封装与其使用方法:

client中创建Entity的源代码,这是创建Entity的主入口函数:
 
  public ODataEntry createEntry(Edm edm,  String serviceUri,  String contentType, 
       String entitySetName, Map < StringObject > data)  throws  Exception {
     String absolutUri  = createUri(serviceUri, entitySetName,  null);
     return writeEntity(edm, absolutUri, entitySetName, data, contentType, HTTP_METHOD_POST);
  }
  createUri ( serviceUri entitySetName null );实际上就是拼接新的url请求路径, serviceUri=" http://localhost:8080/odata2-jpa2/SemServiceServlet.svc ";  entitySetName=" Departments "; 拼接出新的url=" http://localhost:8080/odata2-jpa2/SemServiceServlet.svc/Departments ";
 
接下再看 
writeEntity ( edm absolutUri entitySetName data contentType HTTP_METHOD_POST );方法:
 
  private ODataEntry writeEntity(Edm edm, String absolutUri, String entitySetName, 
      Map<String, Object> data, String contentType, String httpMethod) 
      throws EdmException, MalformedURLException, IOException, EntityProviderException, URISyntaxException {

    HttpURLConnection connection = initializeConnection(absolutUri, contentType, httpMethod);

    EdmEntityContainer entityContainer = edm.getDefaultEntityContainer();
    EdmEntitySet entitySet = entityContainer.getEntitySet(entitySetName);
    URI rootUri = new URI(entitySetName);

    EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(rootUri).build();
    // serialize data into ODataResponse object
    ODataResponse response = EntityProvider.writeEntry(contentType, entitySet, data, properties);
    // get (http) entity which is for default Olingo implementation an InputStream
    Object entity = response.getEntity();
    if (entity instanceof InputStream) {
      byte[] buffer = streamToArray((InputStream) entity);
      // just for logging
      String content = new String(buffer);
      print(httpMethod + " request on uri '" + absolutUri + "' with content:\n  " + content + "\n");
      //
      connection.getOutputStream().write(buffer);
    }

    // if a entity is created (via POST request) the response body contains the new created entity
    ODataEntry entry = null;
    HttpStatusCodes statusCode = HttpStatusCodes.fromStatusCode(connection.getResponseCode());
    if(statusCode == HttpStatusCodes.CREATED) {
      // get the content as InputStream and de-serialize it into an ODataEntry object
      InputStream content = connection.getInputStream();
      content = logRawContent(httpMethod + " request on uri '" + absolutUri + "' with content:\n  ", content, "\n");
      entry = EntityProvider.readEntry(contentType,
          entitySet, content, EntityProviderReadProperties.init().build());
    }

    //
    connection.disconnect();

    return entry;
  }
 
 不难看出该方法是在封装POST的请求报文,同时封装了http对 absolutUri 的请求,最后检查POST请求处理结果,如果 statusCode == HttpStatusCodes.CREATED 说明POST请求成功,最后再读取response的写入流转换成ODataEntry对象返回,
整个POST请求就结束了.

PUT更新实体,入口方法 updateEntry :
 
  public  void updateEntry(Edm edm,  String serviceUri,  String contentType,  String entitySetName, 
       String id, Map < StringObject > data)  throws  Exception {
     String absolutUri  = createUri(serviceUri, entitySetName, id);
    writeEntity(edm, absolutUri, entitySetName, data, contentType, HTTP_METHOD_PUT);
  }
 
每个选项方法都需要一个 edm参数,这个参数就是?$metadata请求返回的实体数据模型对象,client中这样读取的:
 
 Edm edm  = clienApp.readEdm(serviceUrl);
  serviceUrl=" http://localhost:8080/odata2-jpa2/SemServiceServlet.svc ";底层会拼接成 http://localhost:8080/odata2-jpa2/SemServiceServlet.svc/$metadata的url请求. 如源代码:
 
public Edm readEdm( String serviceUrl)  throws IOException, ODataException {
    InputStream content  = execute(serviceUrl  + SEPARATOR  + METADATA, APPLICATION_XML, HTTP_METHOD_GET);
     return EntityProvider.readMetadata(content,  false);
  }
  SEPARATOR  ="/";
 
METADATA=" $metadata ";

updateEntry(Edm edm,  String  serviceUri,  String  contentType,  String  entitySetName,   String  id, Map < String Object >  data)方法中参数:
contentType=" application/atom+xml ";表示拼接一个atom-xml格式的请求报文



.






 
 

entitySetName="Departments";
id这里的id是我们要更新的id值
data是更新的实体数据,底层会拼接成一下形势的body:
 
< content  type = "application/xml" >
      < m:properties >
          < d:Id >5 </ d:Id >
      < d:Name > </ d:Name >
      </ m:properties >
   </ content >
 
 DELETE就很简单了,因为不需要传递body,只需要传递id就可以执行删除了,所有DELETE的入口方法是:
 
HttpStatusCodes statusCode  = clienApp.deleteEntry(serviceUrl,  "Departments""4");
 最终client会封装成url:http://localhost:8080/odata2-jpa2/SemServiceServlet.svc/Departments(4)的DELETE http请求方式.
 
 
   private  String createUri( String serviceUri,  String entitySetName,  String id) {
     return createUri(serviceUri, entitySetName, id,  null);
  }
   private  String createUri( String serviceUri,  String entitySetName,  String id,  String expand) {
     final  StringBuilder absolutUri  =  new  StringBuilder(serviceUri).append(SEPARATOR).append(entitySetName);
     if(id  !=  null) {
      absolutUri.append( "(").append(id).append( ")");
    }
     if(expand  !=  null) {
      absolutUri.append( "/?$expand=").append(expand);
    }
     return absolutUri.toString();
  }
 

下面是全部操作Olingo client的原代码,在main函数中有演示的方式调用,将该java文件拷贝到工程中就可以随意操作了:
 
package olingo.clien;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
import org.apache.olingo.odata2.api.edm.Edm;
import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
import org.apache.olingo.odata2.api.edm.EdmEntitySet;
import org.apache.olingo.odata2.api.edm.EdmException;
import org.apache.olingo.odata2.api.ep.EntityProvider;
import org.apache.olingo.odata2.api.ep.EntityProviderException;
import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
import org.apache.olingo.odata2.api.ep.feed.ODataDeltaFeed;
import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
import org.apache.olingo.odata2.api.exception.ODataException;
import org.apache.olingo.odata2.api.processor.ODataResponse;
/**
 * OlingoClienApp
 */
public  class OlingoClienApp {
   public  static  final  String HTTP_METHOD_PUT  =  "PUT";
   public  static  final  String HTTP_METHOD_POST  =  "POST";
   public  static  final  String HTTP_METHOD_GET  =  "GET";
   private  static  final  String HTTP_METHOD_DELETE  =  "DELETE";
   public  static  final  String HTTP_HEADER_CONTENT_TYPE  =  "Content-Type";
   public  static  final  String HTTP_HEADER_ACCEPT  =  "Accept";
   public  static  final  String APPLICATION_JSON  =  "application/json";
   public  static  final  String APPLICATION_XML  =  "application/xml";
   public  static  final  String APPLICATION_ATOM_XML  =  "application/atom+xml";
   public  static  final  String APPLICATION_FORM  =  "application/x-www-form-urlencoded";
   public  static  final  String METADATA  =  "$metadata";
   public  static  final  String INDEX  =  "/index.jsp";
   public  static  final  String SEPARATOR  =  "/";
   public  static  final  boolean PRINT_RAW_CONTENT  =  true;
  
  
   public  static  void main( String[] paras)  throws  Exception {
    OlingoClienApp clienApp  =  new OlingoClienApp();
     String serviceUrl  =  "http://localhost:8080/odata2-jpa2/SemServiceServlet.svc";
     String usedFormat  = APPLICATION_ATOM_XML;
//    String usedFormat = APPLICATION_JSON;
    print( "\n----- Generate sample data ------------------------------");
    clienApp.generateSampleData(serviceUrl);
    print( "\n----- Read Edm ------------------------------");
    Edm edm  = clienApp.readEdm(serviceUrl);
    print( "Read default EntityContainer: "  + edm.getDefaultEntityContainer().getName());
    print( "\n----- Read Feed ------------------------------");
    ODataFeed feed  = clienApp.readFeed(edm, serviceUrl, usedFormat,  "Manufacturers");
    print( "Read: "  + feed.getEntries().size()  +  " entries: ");
     for (ODataEntry entry : feed.getEntries()) {
      print( "##########");
      print( "Entry:\n"  + prettyPrint(entry));
      print( "##########");
    }
    print( "\n----- Read Entry ------------------------------");
    ODataEntry entry  = clienApp.readEntry(edm, serviceUrl, usedFormat,  "Manufacturers""'1'");
    print( "Single Entry:\n"  + prettyPrint(entry));
    Map < StringObject > data  =  new HashMap < StringObject >();
    data.put( "Id""123");
    data.put( "Name""MyCarManufacturer");
    data.put( "Founded"new Date());
     //
    Map < StringObject > address  =  new HashMap < StringObject >();
    address.put( "Street""Main");
    address.put( "ZipCode""42421");
    address.put( "City""Fairy City");
    address.put( "Country""FarFarAway");
    data.put( "Address", address);
     //
    print( "\n----- Read Entry with $expand  ------------------------------");
    ODataEntry entryExpanded  = clienApp.readEntry(edm, serviceUrl, usedFormat,  "Manufacturers""'1'""Cars");
    print( "Single Entry with expanded Cars relation:\n"  + prettyPrint(entryExpanded));
     //
     //
    print( "\n----- Create Entry ------------------------------");
    ODataEntry createdEntry  = clienApp.createEntry(edm, serviceUrl, usedFormat,  "Manufacturers", data);
    print( "Created Entry:\n"  + prettyPrint(createdEntry));
    print( "\n----- Update Entry ------------------------------");
    data.put( "Name""MyCarManufacturer Renamed");
    address.put( "Street""Main Street");
    clienApp.updateEntry(edm, serviceUrl, usedFormat,  "Manufacturers""'123'", data);
    ODataEntry updatedEntry  = clienApp.readEntry(edm, serviceUrl, usedFormat,  "Manufacturers""'123'");
    print( "Updated Entry successfully:\n"  + prettyPrint(updatedEntry));
     //
    print( "\n----- Delete Entry ------------------------------");
    HttpStatusCodes statusCode  = clienApp.deleteEntry(serviceUrl,  "Manufacturers""'123'");
    print( "Deletion of Entry was successfully: "  + statusCode.getStatusCode()  +  ": "  + statusCode.getInfo());
     try {
      print( "\n----- Verify Delete Entry ------------------------------");
      clienApp.readEntry(edm, serviceUrl, usedFormat,  "Manufacturers""'123'");
    }  catch( Exception e) {
      print(e.getMessage());
    }
  }
   private  static  void print( String content) {
     System.out.println(content);
  }
   private  static  String prettyPrint(ODataEntry createdEntry) {
     return prettyPrint(createdEntry.getProperties(),  0);
  }
   private  static  String prettyPrint(Map < StringObject > properties,  int level) {
     StringBuilder b  =  new  StringBuilder();
    Set <Entry < StringObject >> entries  = properties.entrySet();
     for (Entry < StringObject > entry : entries) {
      intend(b, level);
      b.append(entry.getKey()).append( ": ");
       Object value  = entry.getValue();
       if(value  instanceof Map) {
        value  = prettyPrint((Map < StringObject >)value, level +1);
        b.append(value).append( "\n");
      }  else  if(value  instanceof Calendar) {
        Calendar cal  = (Calendar) value;
        value  = SimpleDateFormat.getInstance().format(cal.getTime());
        b.append(value).append( "\n");
      }  else  if(value  instanceof ODataDeltaFeed) {
        ODataDeltaFeed feed  = (ODataDeltaFeed) value;
        List <ODataEntry > inlineEntries  =  feed.getEntries();
        b.append( "{");
         for (ODataEntry oDataEntry : inlineEntries) {
          value  = prettyPrint((Map < StringObject >)oDataEntry.getProperties(), level +1);
          b.append( "\n[\n").append(value).append( "\n],");
        }
        b.deleteCharAt(b.length() -1);
        intend(b, level);
        b.append( "}\n");
      }  else {
        b.append(value).append( "\n");
      }
    }
     // remove last line break
    b.deleteCharAt(b.length() -1);
     return b.toString();
  }
   private  static  void intend( StringBuilder builder,  int intendLevel) {
     for ( int i  =  0; i  < intendLevel; i ++) {
      builder.append( "  ");
    }
  }
   public  void generateSampleData( String serviceUrl)  throws MalformedURLException, IOException {
     String url  = serviceUrl.substring( 0, serviceUrl.lastIndexOf(SEPARATOR));
    HttpURLConnection connection  = initializeConnection(url  + INDEX, APPLICATION_FORM, HTTP_METHOD_POST);
     String content  =  "genSampleData=true";
    connection.getOutputStream().write(content.getBytes());
    print( "Generate response: "  + checkStatus(connection));
    connection.disconnect();
  }
   public Edm readEdm( String serviceUrl)  throws IOException, ODataException {
    InputStream content  = execute(serviceUrl  + SEPARATOR  + METADATA, APPLICATION_XML, HTTP_METHOD_GET);
     return EntityProvider.readMetadata(content,  false);
  }
   public ODataFeed readFeed(Edm edm,  String serviceUri,  String contentType,  String entitySetName)
       throws IOException, ODataException {
    EdmEntityContainer entityContainer  = edm.getDefaultEntityContainer();
     String absolutUri  = createUri(serviceUri, entitySetName,  null);
    InputStream content  = execute(absolutUri, contentType, HTTP_METHOD_GET);
     return EntityProvider.readFeed(contentType,
        entityContainer.getEntitySet(entitySetName),
        content,
        EntityProviderReadProperties.init().build());
  }
   public ODataEntry readEntry(Edm edm,  String serviceUri,  String contentType,  String entitySetName,  String keyValue)
       throws IOException, ODataException {
     return readEntry(edm, serviceUri, contentType, entitySetName, keyValue,  null);
  }
   public ODataEntry readEntry(Edm edm,  String serviceUri,  String contentType, 
       String entitySetName,  String keyValue,  String expandRelationName)
       throws IOException, ODataException {
     // working with the default entity container
    EdmEntityContainer entityContainer  = edm.getDefaultEntityContainer();
     // create absolute uri based on service uri, entity set name with its key property value and optional expanded relation name
     String absolutUri  = createUri(serviceUri, entitySetName, keyValue, expandRelationName);
    InputStream content  = execute(absolutUri, contentType, HTTP_METHOD_GET);
     return EntityProvider.readEntry(contentType,
        entityContainer.getEntitySet(entitySetName),
        content,
        EntityProviderReadProperties.init().build());
  }
   private InputStream logRawContent( String prefix, InputStream content,  String postfix)  throws IOException {
     if(PRINT_RAW_CONTENT) {
       byte[] buffer  = streamToArray(content);
      print(prefix  +  new  String(buffer)  + postfix);
       return  new ByteArrayInputStream(buffer);
    }
     return content;
  }
   private  byte[] streamToArray(InputStream stream)  throws IOException {
     byte[] result  =  new  byte[ 0];
     byte[] tmp  =  new  byte[ 8192];
     int readCount  = stream.read(tmp);
     while(readCount  >=  0) {
       byte[] innerTmp  =  new  byte[result.length  + readCount];
       System.arraycopy(result,  0, innerTmp,  0, result.length);
       System.arraycopy(tmp,  0, innerTmp, result.length, readCount);
      result  = innerTmp;
      readCount  = stream.read(tmp);
    }
    stream.close();
     return result;
  }
   public ODataEntry createEntry(Edm edm,  String serviceUri,  String contentType, 
       String entitySetName, Map < StringObject > data)  throws  Exception {
     String absolutUri  = createUri(serviceUri, entitySetName,  null);
     return writeEntity(edm, absolutUri, entitySetName, data, contentType, HTTP_METHOD_POST);
  }
   public  void updateEntry(Edm edm,  String serviceUri,  String contentType,  String entitySetName, 
       String id, Map < StringObject > data)  throws  Exception {
     String absolutUri  = createUri(serviceUri, entitySetName, id);
    writeEntity(edm, absolutUri, entitySetName, data, contentType, HTTP_METHOD_PUT);
  }
   public HttpStatusCodes deleteEntry( String serviceUri,  String entityName,  String id)  throws IOException {
     String absolutUri  = createUri(serviceUri, entityName, id);
    HttpURLConnection connection  = connect(absolutUri, APPLICATION_XML, HTTP_METHOD_DELETE);
     return HttpStatusCodes.fromStatusCode(connection.getResponseCode());
  }
   private ODataEntry writeEntity(Edm edm,  String absolutUri,  String entitySetName, 
      Map < StringObject > data,  String contentType,  String httpMethod) 
       throws EdmException, MalformedURLException, IOException, EntityProviderException, URISyntaxException {
    HttpURLConnection connection  = initializeConnection(absolutUri, contentType, httpMethod);
    EdmEntityContainer entityContainer  = edm.getDefaultEntityContainer();
    EdmEntitySet entitySet  = entityContainer.getEntitySet(entitySetName);
    URI rootUri  =  new URI(entitySetName);
    EntityProviderWriteProperties properties  = EntityProviderWriteProperties.serviceRoot(rootUri).build();
     // serialize data into ODataResponse object
    ODataResponse response  = EntityProvider.writeEntry(contentType, entitySet, data, properties);
     // get (http) entity which is for default Olingo implementation an InputStream
     Object entity  = response.getEntity();
     if (entity  instanceof InputStream) {
       byte[] buffer  = streamToArray((InputStream) entity);
       // just for logging
       String content  =  new  String(buffer);
      print(httpMethod  +  " request on uri '"  + absolutUri  +  "' with content:\n  "  + content  +  "\n");
       //
      connection.getOutputStream().write(buffer);
    }
     // if a entity is created (via POST request) the response body contains the new created entity
    ODataEntry entry  =  null;
    HttpStatusCodes statusCode  = HttpStatusCodes.fromStatusCode(connection.getResponseCode());
     if(statusCode  == HttpStatusCodes.CREATED) {
       // get the content as InputStream and de-serialize it into an ODataEntry object
      InputStream content  = connection.getInputStream();
      content  = logRawContent(httpMethod  +  " request on uri '"  + absolutUri  +  "' with content:\n  ", content,  "\n");
      entry  = EntityProvider.readEntry(contentType,
          entitySet, content, EntityProviderReadProperties.init().build());
    }
     //
    connection.disconnect();
     return entry;
  }
   private HttpStatusCodes checkStatus(HttpURLConnection connection)  throws IOException {
    HttpStatusCodes httpStatusCode  = HttpStatusCodes.fromStatusCode(connection.getResponseCode());
     if ( 400  <= httpStatusCode.getStatusCode()  && httpStatusCode.getStatusCode()  <=  599) {
       throw  new  RuntimeException( "Http Connection failed with status "  + httpStatusCode.getStatusCode()  +  " "  + httpStatusCode.toString());
    }
     return httpStatusCode;
  }
   private  String createUri( String serviceUri,  String entitySetName,  String id) {
     return createUri(serviceUri, entitySetName, id,  null);
  }
   private  String createUri( String serviceUri,  String entitySetName,  String id,  String expand) {
     final  StringBuilder absolutUri  =  new  StringBuilder(serviceUri).append(SEPARATOR).append(entitySetName);
     if(id  !=  null) {
      absolutUri.append( "(").append(id).append( ")");
    }
     if(expand  !=  null) {
      absolutUri.append( "/?$expand=").append(expand);
    }
     return absolutUri.toString();
  }
   private InputStream execute( String relativeUri,  String contentType,  String httpMethod)  throws IOException {
    HttpURLConnection connection  = initializeConnection(relativeUri, contentType, httpMethod);
    connection.connect();
    checkStatus(connection);
    InputStream content  = connection.getInputStream();
    content  = logRawContent(httpMethod  +  " request on uri '"  + relativeUri  +  "' with content:\n  ", content,  "\n");
     return content;
  }
   private HttpURLConnection connect( String relativeUri,  String contentType,  String httpMethod)  throws IOException {
    HttpURLConnection connection  = initializeConnection(relativeUri, contentType, httpMethod);
    connection.connect();
    checkStatus(connection);
     return connection;
  }
   private HttpURLConnection initializeConnection( String absolutUri,  String contentType,  String httpMethod)
       throws MalformedURLException, IOException {
    URL url  =  new URL(absolutUri);
    HttpURLConnection connection  = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod(httpMethod);
    connection.setRequestProperty(HTTP_HEADER_ACCEPT, contentType);
     if(HTTP_METHOD_POST.equals(httpMethod)  || HTTP_METHOD_PUT.equals(httpMethod)) {
      connection.setDoOutput( true);
      connection.setRequestProperty(HTTP_HEADER_CONTENT_TYPE, contentType);
    }
     return connection;
  }
}
 

基于OData请求处理插件,还有个data plugin也有和Olingo clien一样的实现,但data plugin是一个人写的,目前还有很多bug,不支持中文,返回OData协议定义的报文体excle不一定能解析.所以支持apache 的Olingo client吧.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值