技术开发 频道

Eclipse环境下的OpenSocial开发

  Shindig 服务器端 SPI 扩展

  Shindig 作为 OpenSocial 规范的引用实现,提供了 SPI 的扩展能力,允许你把数据适配到 Shindig 容器中去。你的这些数据也许存在于诸如 My SQL/Oracle 的关系数据库,或者是以 JSON 格式存储的静态文件,无论哪种存储,你都可能通过 Shindig SPI 将它们适配到 Shindig, 从而使这些数据公布在 OpenSocial 平台上。

  图 4. Shindig SPI 扩展

Shindig 服务器端 SPI 扩展

  如图 4 所示,你的应用需要实现 ActivityService, PersonService, AppDataService 三个接口,利用诸如 JDBC/Hibernate 等机制把数据提供给 Shindig。

  接下来,本文将通过一个例子,实现 PersonService 接口向 Shindig 提供 People/Friends 相关的 OpenSocial 数据。

  清单 1 是 SocialTestJsonPersonService类的实现。

  清单 1. SocialTestJsonPersonService Class

public class SocialTestJsonPersonService implements PersonService {
  
private static final String PEOPLE_TABLE = "people";
  
private static final String FRIEND_LINK_TABLE = "friendLinks";
  
private JSONObject db;
  
private BeanConverter converter;
       ……
  
public Future<RestfulCollection<Person>> getPeople(Set<UserId>
             userIds,GroupId groupId, CollectionOptions options, Set
<String> fields,
      SecurityToken token)
throws ProtocolException {
    List
<Person> result = Lists.newArrayList();
    
try {
      
//Read people data from JSON table.
      JSONArray people = db.getJSONArray(PEOPLE_TABLE);
      Set
<String> idSet = getIdSet(userIds, groupId, token);

      
for (int i = 0; i < people.length(); i++) {
        JSONObject person
= people.getJSONObject(i);
        
if (!idSet.contains(person.get(Person.Field.ID.toString()))) {
          
continue;
        }
        
// Add group support later
        Person personObj = filterFields(person, fields, Person.class);
        result.add(personObj);
      }

      
if (GroupId.Type.self == groupId.getType() && result.isEmpty()) {
        
throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST,
            
"Person not found");
      }
      
int totalSize = result.size();
      
return ImmediateFuture.newInstance(new RestfulCollection<Person>(
          result, options.getFirst(), totalSize, options.getMax()));
    }
catch (JSONException je) {
      
throw new ProtocolException(
          HttpServletResponse.SC_INTERNAL_SERVER_ERROR, je
              .getMessage(), je);
    }
  }

  
public Future<Person> getPerson(UserId id, Set<String> fields,
      SecurityToken token)
throws ProtocolException {
    
try {
      
//Read people data from JSON table.
      JSONArray people = db.getJSONArray(PEOPLE_TABLE);
      
for (int i = 0; i < people.length(); i++) {
        JSONObject person
= people.getJSONObject(i);
        
if (id != null
            
&& person.get(Person.Field.ID.toString()).equals(
                id.getUserId(token))) {
          Person personObj
= filterFields(person, fields,
              Person.
class);
          
return ImmediateFuture.newInstance(personObj);
        }
      }
      
throw new ProtocolException(HttpServletResponse.SC_BAD_REQUEST,
          
"Person not found");
    }
catch (JSONException je) {
      
throw new ProtocolException(
          HttpServletResponse.SC_INTERNAL_SERVER_ERROR, je
              .getMessage(), je);
    }
  }
        ……
}

  从清单 1 可以看到,SocialTestJsonPersonService 实现了 PersonService 两个接口方法 getPeople 及其 getPerson。getPeople 根据传入参数 userIds,返回相应于该 ID 列表的用户列表,而 getPerson 根据传入参数 id,返回相应于该 ID 的用户。

  注意,Shindig 依赖 Guice 做动态的依赖注入 (dependency Injection),我们需要在 org.apache.shindig.social.sample.SampleModule 里指示 Guice 把 PersonService 绑定到 SocialTestJsonPersonService 实现,如清单 2 所示:

  清单 2. SampleModule Class

public class SampleModule extends SocialApiGuiceModule {

  @Override
  protected void configure() {
    super.configure();
    
    bind(String.
class).annotatedWith(Names.named("shindig.canonical.json.db"))
        .toInstance(
"sampledata/canonicaldb.json");
    
    bind(String.
class).annotatedWith(Names.named("shindig.socialtest.json.db"))
    .toInstance(
"sampledata/socialtestdb.json");
    
    
    bind(ActivityService.
class).to(JsonDbOpensocialService.class);
    bind(AppDataService.
class).to(JsonDbOpensocialService.class);
    
//bind(PersonService.class).to(JsonDbOpensocialService.class);
    bind(PersonService.
class).to(SocialTestJsonPersonService.class);
    
    bind(MessageService.
class).to(JsonDbOpensocialService.class);
    
    bind(OAuthDataStore.
class).to(SampleOAuthDataStore.class);


    
// We do this so that jsecurity realms can get access to the jsondbservice singleton
    requestStaticInjection(SampleRealm.
class);
  }
  ……
}

  从清单 2 中,还可以看到,标记为"shindig.socialtest.json.db"的字符串绑定到了"sampledata/socialtestdb.json", socialtestdb.json 是我们示例中的 JSON 数据文件,用来保存 People 数据。在 SocialTestJsonPersonService 的实现中,db.getJSONArray(PEOPLE_TABLE) 就是从该 JSON 文件获取所有的 People 数据。

  在下一节,我们给出客户端实现,来消费 socialtestdb.json 中的 Social 数据。

0
相关文章