Apache Jackrabbit の OCM (Object Content Mapping) を使ってみる
ブログ放置だったけど、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 ベースのデータモデルの設計指針みたいのが分かってないから、
その辺を調べないと。