실행방법 :
1. 파일을 다운로드 받는다(http://drop.io/datptht/asset/anotherlore-jar anotherLore.jar 약 30M)
2. 알집으로 열어서 webapps/ 디렉토리만 현재 디렉토리에 압축을 푼다.
현재 디렉토리에 다운 받은 jar 파일 하나와 webaspps 디렉토리가 있어야 한다.
현재 디렉토리
- anotherLore.jar
- webapps/
3. command 창에서 java -jar anotherLore.jar 로 실행(require JRE1.5 higher)한다. (jetty server가 기동한다.)
4. http://localhost:8080/board/ 로 접속한다.. 끝. -ㅅ- (중단하려면 Ctrl+c를 누른다.)
============== 4월 12일
1. noticeType은 versionable 시키지 않았기에 상관없지만 generalBoard는 versionable code로 되어 있었는데 버전을 3번 수정하는 PK 오류가 나는 걸 수정.
2. 불필요하게 nodeType을 매번 억세스 하는 걸 수정.
3. Property.Type에 virtualText, referenceType 추가.
예컨데 generalBoard의 2번째 Textarea는 VirtualText Type으로 되어 있는데 벨로시티 템플릿을 사용한다.
아래와 같이 입력/수정 할 경우..
$node.getUUIDString() <br/><br/>
#foreach($n in $node.getNodeByPath('/').getChildNode())
$n<br/>
#end
View 화면에서는 위의 템플릿이 적용된 다른 내용이 보이게 된다. $node는 현재 node를 가르키지만 이를 통해 모든 node를 억세스 가능하다.
4. 파일공유 사이트 바꿈.
=============== 4월 5일
AL은 DataStore를 확인할 수 있는 NodeTypeInfo, NodeInfo Page가 있고
AL로 만든 간단한 Sample Program인 Notice, GeneralBoard, Diagram 3가지가 있다.
AL은 게시판을 만들어 주는 어드민 모드 프로그램이 아니라 프로그램를 만드는 프로그램이다. 3가지의 다른 데이타 모델을 사용하는 샘플 프로그램은 모두 같은 인터페이스 모델로 저장이 된다.
모든 DataModel은 NodeType으로 쉽게 만들수 있다.
anotherLore.jar의 com.bleuji.lore.impl.board에 위의 3개의 샘플 프로그램 소스가 있는데 예를 들어 데이타 모델은 아래와 같이 만들면 된다.
private void initBoard(AnotherLore lore) throws RepositoryException {
UserSession session = lore.login(new TestCredential("admin"), "localhost");
globalStore = session.getGlobalStore();
NodeType objectType = globalStore.createNodeType(NodeType.NO_SUPERTYPE, "_object", new PropertyDefinition[0]);
Node root = session.createNode(Node.NO_PARENT, objectType, "/");
Node anonymousRoot = session.createNode(root, objectType, "anonymous");
// notice DataModel
NodeType noticeBoardType = globalStore.createNodeType(objectType, "notice_board", new PropertyDefinition[0]);
PropertyDefinition boardNo = createProperty(BOARDNO, Property.Type.LONG);
PropertyDefinition subject = createProperty(SUBJECT, Property.Type.STRING);
PropertyDefinition regUserId = createProperty(REGUSERID, Property.Type.STRING);
PropertyDefinition regDate = createProperty(REGDATE, Property.Type.DATE);
PropertyDefinition content = createProperty(CONTENT, Property.Type.STRING);
PropertyDefinition[] noticeProperties = new PropertyDefinition[] { boardNo, subject, regUserId, regDate, content };
NodeType noticeType = globalStore.createNodeType(objectType, "notice", noticeProperties);
noticeType.addPropertyConstraint(boardNo, new NumberConstraint());
noticeType.addPropertyConstraint(subject, new RangeByteLengthConstraint(1, 200));
noticeType.addPropertyConstraint(regUserId, new RequireConstraint());
noticeType.addPropertyConstraint(regDate, new RequireConstraint());
noticeBoardType.setMemberType(noticeType);
Node noticeBoardRootNode = session.createNode(root, noticeBoardType, "noticeboard");
// extend board Data Model
NodeType generalBoardType = globalStore.createNodeType(objectType, "general_board", new PropertyDefinition[0]);
NodeType articleType = globalStore.createNodeType(noticeType, "article", new PropertyDefinition[] { createProperty(ATTACH_FILE, Property.Type.BINARY),
createProperty(FORMET_TEXT, Property.Type.VIRTUAL_TEXT) });
articleType.addPropertyConstraint(boardNo, new NumberConstraint());
articleType.addPropertyConstraint(subject, new RangeByteLengthConstraint(1, 200));
articleType.addPropertyConstraint(regUserId, new RequireConstraint());
articleType.addPropertyConstraint(regDate, new RequireConstraint());
PropertyDefinition comment = createProperty(COMMENT, Property.Type.STRING);
NodeType commentType = globalStore.createNodeType(objectType, "comment", new PropertyDefinition[] { comment, regUserId, regDate });
commentType.addPropertyConstraint(comment, new RangeByteLengthConstraint(10, 4000));
commentType.addPropertyConstraint(regUserId, new RequireConstraint());
commentType.addPropertyConstraint(regDate, new RequireConstraint());
articleType.setMemberType(commentType);
Node generalBoardRootNode = session.createNode(root, generalBoardType, "generalboard");
generalBoardType.setMemberType(articleType);
// web note(diagram) Data Model
PropertyDefinition name = createProperty("name", Property.Type.STRING);
PropertyDefinition nextNoteNum = createProperty("nextNoteNum", Property.Type.INTEGER);
NodeType workspaceType = globalStore.createNodeType(objectType, "workspace_type", new PropertyDefinition[] { name, nextNoteNum });
workspaceType.addPropertyConstraint(name, new RequireConstraint());
workspaceType.addPropertyConstraint(nextNoteNum, new RequireConstraint());
PropertyDefinition note_content = createProperty("note_content", Property.Type.STRING);
NodeType noteType = globalStore.createNodeType(objectType, "note_type", new PropertyDefinition[] { note_content });
noteType.addPropertyConstraint(content, new RequireConstraint());
Node workspace = session.createNode(session.getNodeByPath("/"), workspaceType, "workspace");
session.save();
session.logout();
}
private PropertyDefinition createProperty(String pid, Property.Type requireType) throws RepositoryException {
return globalStore.createPropertyDefinition(pid, requireType);
}
} |
API는 가능한 jcr170과 비슷하게 하려고는 했지만 여러가지 자잘한 이유로 조금씩 변경했다.
예컨데
new RequireConstraint()라는 constraint는 실제로는 데이타베이스에
<configured-object>
<class-name>com.bleujin.lore.core.constraint.RequireConstraint</class-name>
</configured-object>
와 같은 XML 형태로 저장이 된다.
AL의 기본 모드는 인메모리에서 동작하게 되어 있다. 따라서
만약 오라클에 저장을 하고 싶으면
webapps/board/WEB-INF/default-config.xml 파일을 열어서
1. root.database-controller.database-manager 에 userId, userPassword, jdbcURL을 설정하고
(해당 아이디는 connect, resource 권한을 가지고 있어야 한다.)
2. root.license.startmode를 oracle:recreate로 바꿔주고 재시동하면 된다.
오라클을 DataStore로 사용했을 경우 root.license.startmode에는
oracle:recreate, oracle:reset, oracle:none 3가지를 적용할 수 있는데,
1) oracle:recreate는 시작할때 관련 테이블과 sequence를 모두 지우고(없으면 무시) 다시 테이블등의 세그먼트를 만든다.
2) oracle:reset 세그먼트를 다시 만들지는 않지만 테이블의 데이타는 모두 지우고 시작한다.
3) oracle:none 이미 오라클에 관련 테이블이 있다면 그냥 아무짓 안하고 시작한다.(이전에 저장했던 데이타가 남는다.)
처음 오라클 모드로 시작하는 거면 oracle:recreate로 시작한다. (가능한 쉬운 기동을 위해 과정을 단순하게 만들려고 했다.)
generalBoard를 통해 업데이트 되는 Binary형태의 Property는 root.file-repository-path를 수정하지 않으면 /another/data/property에 저장이 되고 파일정보만 AL에 저장된다.
실제 많은 사용자를 버티려면 TypeCache를 적용해야 하지만 NoCache JIT 상태로도 그럭저럭 빠른 속도를 보여준다. 나중에 자세한 성능 테스트 자료를 올리겠음.(국내에 30M 정도를 공유할 수 있는 쓸만한 웹하드 사이트가 없다는 걸 이 글 작성하면서 처음 알았다 -ㅅ-)