読者です 読者をやめる 読者になる 読者になる

sandbox

Scala, Android, Architecture, Management, Service Design あたりを主戦場としております

Apache Jackrabbit の OCM (Object Content Mapping) を使ってみる

jcr java

ブログ放置だったけど、JCR 回りをこれから定期的に調べていく。

Jackrabbit の用意

今回は、jackrabbit-webapp を Tomcat にデプロイして、
Remote で接続出来るようにした。

クライアントからはこんな感じで接続。
※サンプルそのまま

import javax.jcr.Repository;
import org.apache.jackrabbit.rmi.repository.RMIRemoteRepository;

Repository repo = new RMIRemoteRepository("//localhost/jackrabbit.repository");

モデルクラスの作成、マッピング

まずは、シンプルに単純なプロパティと、親子関係をもつクラスを定義。

public class Parent{
    private String path;
    private String title;
    private Date created;
    private List<Child> kids;

    //... getter, setter
}

public class Child{
    private String title;
}

これから、実際にどのようにマッピングするかの定義を記載するのだけど、
OCM ではアノテーションと、XML ファイルの 2 通りが用意されている。
それぞれこんな感じで指定する。

アノテーションバージョン
public class Parent{
    @Field(path=true) private String path;
    @Field private String title;
    @Field(jcrName="jcr:created") private Date created;
    @Collection(elementClassName=Child.class, collectionConverter=NTCollectionConverterImpl.class)
    private List<Child> kids;

    //... getter, setter
}
XML ファイルバージョン
<?xml version="1.0" encoding="UTF-8"?>
<jackrabbit-ocm>
  <class-descriptor className="dev.jcr.test.models.Parent" discriminator="false">
        <field-descriptor fieldName="path" path="true" />
    <field-descriptor fieldName="title" jcrName="title" />
    <field-descriptor fieldName="created" jcrName="jcr:created" />
    <collection-descriptor fieldName="kids" proxy="false"
      elementClassName="dev.jcr.test.models.Child"
      collectionConverter="org.apache.jackrabbit.ocm.manager.collectionconverter.impl.NTCollectionConverterImpl" />
  </class-descriptor>
  
  <class-descriptor className="dev.jcr.test.models.Child" discriminator="false">
    <field-descriptor fieldName="title" jcrName="title" />
  </class-descriptor>
</jackrabbit-ocm>

では、実行してみる

Session s = null;
try{
    Repository repo = new RMIRemoteRepository("//localhost/jackrabbit.repository");
    s = repo.login(new SimpleCredentials("test","test".toCharArray()));
     
    String[] mappingFiles = {"./src/main/java/config/simple-mapping.xml"};
    ObjectContentManager ocm = new ObjectContentManagerImpl(s, mappingFiles);
     
    Parent p = new Parent();
    p.setPath("/test");
    p.setTitle("hoge");
    p.setCreated(new Date());
     
    List<Child> kids = new ArrayList<Child>();
    for(int i : new int[]{1,2,3}){
        Child c = new Child();
        c.setTitle("fuga" + i);
        kids.add(c);
    }
    p.setKids(kids);
     
    ocm.insert(p);
    ocm.save();
     
    dump(s);
     
}catch(LoginException e){
    e.printStackTrace();
}catch(RepositoryException e){
    e.printStackTrace();
}finally{
    if(s!=null && s.isLive()){
        s.logout();
    }
}

実行結果

----- test-----
Path: /test
Name: test
title: hoge {String}
jcr:created: java.util.GregorianCalendar[time=1202203337796,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset=32400000,dstSavings=0,useDaylight=false,transitions=10,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2008,MONTH=1,WEEK_OF_YEAR=6,WEEK_OF_MONTH=2,DAY_OF_MONTH=5,DAY_OF_YEAR=36,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=6,HOUR_OF_DAY=18,MINUTE=22,SECOND=17,MILLISECOND=796,ZONE_OFFSET=32400000,DST_OFFSET=0] {Date}
jcr:primaryType: nt:unstructured {Name}
  ----- collection-element-----
  Path: /test/collection-element
  Name: collection-element
  title: fuga1 {String}
  jcr:primaryType: nt:unstructured {Name}
  ----- collection-element-----
  Path: /test/collection-element[2]
  Name: collection-element
  title: fuga2 {String}
  jcr:primaryType: nt:unstructured {Name}
  ----- collection-element-----
  Path: /test/collection-element[3]
  Name: collection-element
  title: fuga3 {String}
  jcr:primaryType: nt:unstructured {Name}


この例では、XML ファイルを読み込んで実行した。
めちゃくちゃ簡単!

まぁ、検証したものが単純過ぎるから、これからもう少し複雑なクラスとか、
バージョニング回りなども含めて、仕様とかソースコード見ながら追ってみる予定。

感想

まだまだ検証が必要だけど、JCR も OCM も結構使えるかも。
少なくとも今構想しているアプリは、RDB よりデータモデル的に適用しやすいかな。

後は、まだ JCR ベースのデータモデルの設計指針みたいのが分かってないから、
その辺を調べないと。