Blogs
같은 이름을 가진 input 객체를 사용하지 않는다.
Tags: input, 배열

input 객체 배열을 이용하여 쉽게 for 문장을 구성하려 하였으나 같은 폼이

여러번 출력될 시에 배열만큼 재 생성되어 의도 하지 않은 두배의 input

객체가 출력 되는 것을 볼 수 있다.

 

이에 대한 대안으로는 인풋 객체 이름을 inputName1, inputName2, inputName3

등과 같이 순차적인 숫자등을 붙여주고 객체에 접근할때 해당 이름 문자열을 검색

하여 접근하도록 한다.

ex )
for (var i = 1; i < 4; i++) {
    document.forms[0].all["inputName" + i].value
}

Average (0 Votes)
폼 엑티비티 작성시 내부 폼을 사용 할 수 없다.
Tags: form, 폼

폼 엑티비티 작성시 필요에 의해 폼을 삽입하여 폼 내부 인풋들을 접근하려

하였으나 해당 접근이 되지 않았다.

 

문제점 .

폼 이름을 regForm 이라 가정 하였을 경우document.regForm 을 활용하면

일반 테스트에서는 별 문제가 없으나 실제 활용부분에서는 찾을 수 없는 객체로 된다.

 

대안.

내부에 자동 생성 되는 폼을 이용하도록 한다.

폼을 새로 작성하지 말고 인풋 객체만 생성하여

document.forms[0].input객체 < 이 같은 방법을 활용하면 쉽게 접근이 가능하다.

Average (0 Votes)
MS SQL server 포트 변경
Tags: mssql 포트 변경

기본 포트는 1433이다

그런데 방화벽에 걸려서 보통 바로 접속이 안될 것이다.

그럼 이 포트를 허용해주던가

아니면 1434로 변경하는 방법이 있는데

포트 변경하는 방법은 

1. SQL SERVER 구성관리자 실행

2. 네트워크 구성 -> 프로토콜 -> TCP/IP -> 프로토콜 탭( 사용 : 예) -> IP 탭 (활성: 예, TCP 포트:1434)

3. SQL Native Client 구성 -> 클라이언트 프로토콜 ->TCP/IP-> 기본포트:1434 -> 사용: 예

이렇게 셋팅하면 원격 접속이 된다.
 

Average (0 Votes)
MS SQL server XA 설정하기
Tags: sql xa

1. JTA 프로시저 최신 버전을 받아서 mssql 서버에다가 설치한다.(sqljdbc.dll,instjdbc.sql)
C:\Program Files\Microsoft SQL Server\80\Tools\binn 폴더에 카피
C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn 폴더에 카피

2. instjdbc.sql 스크립트를 이용하여 MS SQL server manageement studio에서 프로시저 실행

3. 레지스트에 sqljdbc.dll등록
regedit실행해서 XADLL로 검색 -> 이름:sqljdbc.dll , 값: C:\Program Files\Microsoft SQL Server\80\Tools\binn\sqljdbc.dll 추가

4.구성요소 서비스(제어판->관리도구)->구성요소 서비스 ->'내 컴퓨터' 오른쪽 마우스 클릭 -> 속성 ->MDDTC->보안구성->XA 트랜젝션사용 체크->컴퓨터 리부팅

5.서비스(제어판-> 관리도구) ->distributed transaction coodinator 시작

6. JDBC 프로바이더 : com.ibm.websphere.jdbcx.sqlserver.SQLServerDataSource

7. 데이타 소스 추가 옵션 : selectMethod = cursor , enable2Phase= true로 셋팅

8. XA로 접속할 모든 DB서버에 셋팅되어 있어야 함.
 

* 고생해서 알게 된 아~~~~~~~~주 값진 정보임.

 

Average (0 Votes)
mssql & webshere XA 설정
Tags: 2pc, mssql, xa

제목 : 웹스피어 컨테이너에서 트랜잭션관리가 안되느거 같아요..
글쓴이: 검은바다(guest) 2004/11/27 11:59:40 조회수:445 줄수:25
 
자바개발자입니다.
현재 개발환경은 JBuilder+WebSphere5.1입니다.
구조는 action-delegate-stateless세션빈-CMP2.0이고
세션빈에서 DAO1을 호출하고 그 결과값으로 다시 또다른 DAO2를 호출해서 그 결과값을
CMP1과 CMP2 저장하는구조입니다.
ejb-jar.xml에 트랜잭션 속성은 <trans-attribute>Required</trans-attribute>로
잡혀있습니다. 현재 잡혀있는 상태입니다.
    <container-transaction id="MethodTransaction_1100669768593">
      <method id="MethodElement_1100669768603">
        <ejb-name>RequestFirstMaster</ejb-name>
        <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
    </container-transaction>


물론 호출하는 delegate쪽은 트랜잭션이 없는상태이고요.
그런데 세션빈에서 DAO1을 호출한 후 DAO2를 호출할때 아래와 같은에러가 발생합니다.
DAO나 CMP를 호출할때마다 jndi를 사용하여 세션빈 생성 및 DAO를 생성하고있고요.

에러내용 : 
TransactionIm E WTRN0062E: 1 단계 성능만 있는 여러 자원을 사용하려는 
잘못된 시도가 글로벌 트랜잭션 내에서 발생했습니다.

제목 : Re: E WTRN0062E: 1 단계 성능만 있는 여러 자원을 ...
글쓴이: 이원영(javaservice) 2004/11/28 14:05:36 조회수:273 줄수:28
 
위 에러 메세지는 1 phase-commit 자원, 즉, non-XA JDBC Datasource를 하나 이상 사용하여
단일의 J2EE Transaction boundary내에서 사용하려는 잘못된 시도를 하였다는 뜻입니다.
마치, 두개의 서로다른 Database가 있는데, 그 두개의 Database를 단일 Transaction으로
묶기 위해서는 반드시 2 phase-commit을 지원하는 XA-JDBC Driver를 사용하여야 하는데,
non-XA JDBC Driver를 사용하였다는 것과 같은 뜻이지요.

만약, 정말 하나 이상의 Database를 Access하시고 있다면, 그 JDBC Driver는 2 phase-commit을
지원하는 XA JDBC Driver를 사용하셨어야 했습니다.

반면, 현재 단 하나의 Database만 접속하고 있음에도 불구하고, 위와 같은 상황이 벌어지고
있다면, JNDI lookup 할 때, 그 JDBC URL 및 user/password 가 완전히 동일해야 합니다.

1. Resource에 대한 Local-Reference를 사용하고 있나요?
  즉, ctx.lookup("jdbc/realdb") 은 Global JNDI name를 직접호출하는 것으로 (그다지)
  바람직하지 않으며, ctx.lookup("java:comp/env/jdbc/mydb") 와 같이 호출하는 것이
  local reference를 등록하여 호출하는 격인데, 이렇게 하려면 WAR마다, 그리고 각각의
  EJB마다 자원등록에서 Datasource에 대한 Local-Reference로 jdbc/mydb를 이름으로하고
  JNDI name는 jdbc/realdb로 하여 Deploy시에 매칭되도록 하여야 합니다.

  Servlet도 JDBC 를 access하고 EJB도 JDBC Access가 있다면, Local-Reference의 이름과
  user/passwd는 완전히 동일하여야 하고, ctx.lookup("java:comp/env/jdbc/mydb")와 같이
  완전이 동일해야, 같은 DB에 대한 Resource로 인식하여 위와 같은 에러메세지가 나타나지
  않게 됩니다. 
2.또한 그 Datasource는 default인 "Shareable" 이어야 합니다.

PS: 설명이 부족한 듯 한데, 누가 부연설명 좀 해 주세요.

자바서비스넷 이원영

 

 

mssql에서는 2pc지원을 위한 xa DataResource설정을 위해서 드라이버를 따로 받을 필요가 없다 기본적으로 MSSQL JDBC Driver jar파일들 3개  (msbase.jar, mssqlserver.jar, msutil.jar)  를 받아서 사용하면 다 포함되어있다.

파라미터 설정 방법

* 필수
url = jdbc:microsoft:sqlserver://127.0.0.1:1433;user=mes;password=sames
(아래 설명되는 prarmeter들을 계속 ;로 구분하여 추가해도 무방함)

selectMethod = cursor | direct

user = DB_ID

password = DB_PASSWORD

databaseName = DB_INSTANCE_NAME

serverName = DB_HOST_NAME 또는 IP
(Windows가 가끔 IP로 지정한경우 5초딜레이가 발생할 수 있음.. 가급적 hosts파일에 등록하시고 host명으로 사용하시길)

driverClassName = com.microsoft.jdbcx.sqlserver.SQLServerDataSource

factory = com.microsoft.jdbcx.sqlserver.SQLServerDataSourceFactorys

*XA 관련 필수
disable2Phase = true | false 
(false일 경우 위 selectMethod는 cursor로 하셔야함)

* 옵션
portNumber = 1433
(기본포트 1433이며, 생략하시면 당연히 기본포트 사용합니다.)
 

 

 

 

Average (0 Votes)
Accessibillity 설정
Tags: accessibillity

정의된 프로세스들 중에서 admin 계정으로 들어가지 않은 경우 보이지 않는 프로세스들이 있다.

이것은 프로세스의 종류에 따라 볼수 있는 권한을 나눠 놓았기 때문에 누구에게는 보여지고 누구에게는 보여지지 않는것이다.

간단히 말해서 영업부에서 할일이 생산부 업무에 보여질 필요가 없기에 이런 기능이 있는 것이다.

 

 Accessibillity 설정은 프로세스만 하는것이 아니라 폴더, 폼 모두에 설정할 수 있다.

일반적으로 실제 사용되는것은 프로세스고 그 프로세스는 특정 폴더에 위치하기 때문에 폴더와 프로세스에만 설정을 한다.

 

그럼 예를 통해 설정 방법에 대해 알아 보겠다.

먼저 프로세스 메니저 화면으로 들어간다.

좌측 상단에 프로세스 데피니션들이 나열되어 있을 것이다.

여기서 설정하고자 하는 폴더중 제일 상위 폴더인 'Test'폴더에 가서 우클릭을 한다.

여러 메뉴가 나오는데 그중 'Accessibillity'를 클릭한다.

우측 화면이 변환되고 우상단에 보면 세개의 버튼이 보이는데 그 중 'ADD'버튼을 클릭한다.

 그럼 Add Accessibillity 팝업창이 뜨고 상단에 설정 조건 3가지 'View','Running','Edit'가 보이고 아래 ',그룹','롤''유저'를 선택하는 화면이 나온다.

View=보기 권한 설정

Runnign=실행 권한 설정

Edit=편집 권한 설정

3가지중 폴더를 볼 수 있도록 'View'을 선택하고, 그룹에 'uEngine'을 선택하고, 롤에 'Guest'를 선택한다.

선택 완료후 Insert 버튼을 누르면 권한 설정이 완료 된다.

설정하고자 하는 프로세스가 있으면 위와 같은 방법으로 하면 되고 궈한에서 'Running'을 주어야 실행이 가능하다.

 

 

 

Average (0 Votes)
uEngine에서의 Exception처리
Tags: exception, exception handling, handling, uengineexception, 예외사항 처리, 예외처리

유엔진에서 발생하는 예외사항에 대해선 크게  두 가지 분류로 구분하여 핸들링 해야 한다.

1. Designe Time 에서의 예외사항

프로세스 디자이너를 사용하여 프로세스를 정의할 때 각 액티비티나 프로세스에 반드시 필요한 속성일 경우에 Validation 로직을 거쳐서 속성이 설정되지 않았을 경우 설정하도록 유도해야 함.

예를 들어 HumanActivity에서 담당역할과 WIH에 대한 속성이 설정 안되있을경우 오류메세지를 보여주어야 함. 이에 대한 코드는 다음과 같다. 

 public ValidationContext validate(Map options) {
  ValidationContext vc = super.validate(options);
  
  if(getRole()==null)
   vc.add(getActivityLabel() + "Role is not specified");
  
  if(getTool()==null)
   vc.addWarning(getActivityLabel() + "Tool is not specified");
   
  return vc;
 }

 

 2. Run Time 에서의 예외사항

프로세스가 실행되어 진행하던 도중에 필요한 정보가 제대로 입력되지 않았을 경우에 발생하는 예외사항에 대한 처리 방법이다 . TroubleTicket 프로세스의 예에서 장애 사항 보고뒤 메니저에 의해서 장애를 처리할 처리담당자를 지정하게 되는데 이 메니저가 담당자를 지정하지 않고 해당 단계를 완료처리하게 되면 그 다음 단계인 장애 처리 에서의 업무를 수행할 실 사용자에 대한 정보를 찾을 수 없게 된다. 이 때 엔진에서 사용자가 이해할수 있는 내용으로 예외사항에 대한 메세지를 보여주어야 한다.

Run time에러에 대한 처리 방법은 HumanActivity.java에서 많은 예를 볼 수 있는데 대표적으로 앞에서 예들었던 특정 Role에 대한 실사용자 정보가 없을 때의 예외 처리방법은 다음의 코드와 같다.

RoleMapping roleMapping = null;
  try{
   roleMapping = getActualMapping(instance);
   
   UEngineException actualWorkerNotBound = new UEngineException("Actual worker for '"+ getRole() +"' isn't bound yet");
   actualWorkerNotBound.setActivity(this);
   actualWorkerNotBound.setInstance(instance);
   if(roleMapping==null) throw actualWorkerNotBound;
   if(roleMapping.getEndpoint()==null) throw actualWorkerNotBound;
   if(roleMapping.getEndpoint().trim().length()==0) throw actualWorkerNotBound;
  }catch(Exception e){
   
   //if(getRole().getRoleResolutionContext()==null)
   throw e;
  }

다른 예로는

RoleMapping roleMapping = null;
  
  try{
   roleMapping = getRole().getMapping(instance, getTracingTag());
  }catch(Exception e){
   throw new UEngineException("Couldn't get the actual user for the role [" + getName() + "] since: \n" + e.getMessage(), e);
  }

특히 runtime에서의 예외사항 처리를 제대로 해서 일반 사용자에게 시스템 오류로 착각하지 않도록 해야되겠음...

Average (0 Votes)
포탈 메뉴에 프로세스 실행 연결하기
Tags: 아이프레임, 프로세스실행

유엔진 홈페이지 '지원 및 QnA' 탭 아래 '문의접수'메뉴를 클릭하면 프로세스가 바로 실행 된다.

이처럼 포탈 메뉴에서 바로 프로세스를 연결하는 방법을 알아보겠다.

 

1. 먼저 사용할 프로세스를 만든다.(이미 만들어 놓은것도 상관 없다.)

2. 그다음 프로세스를 연결하고자 하는 포틀릿 페이지를 하나 생성한다.(탭 메뉴가 포틀릿 형태면 그대로 사용하여도 된다.)

3. 우측 상단에 메뉴중 '포틀릿추가' 메뉴를 선택한 다음 '샘플'폴더 아래 있는 '아이프레임'을 추가한다.

4. 추가된 아이프레임 설정 메뉴를 선택한다.

5. 설정화면 제일 상단에 보면 '소스 URL' 이 있는데 이곳에

/html/uengine-web/processparticipant/initiateForm.jsp?alias=     

를 복사하여 넣고 그 뒤에 앞서 만들어 놓은 프로세스의 alias 값을 입력한다.

ex) /html/uengine-web/processparticipant/initiateForm.jsp?alias=p_ocp

6. 아래 html 속성 부분은 아이프레임 창 크기를 설정하는 것으로 높이가 300으로 되어 있는데 600정도로 설정하면 전체 부분이 나온다.

7. 저장을 하면 모든 설정이 완료 된다.

 

Average (0 Votes)
Dojo에서의 Grid 사용법
Tags: dojo, grid, json, table, 그리드, 도조, 제이슨, 테이블

Dojo에서 Grid를 사용하는 법...

Dojo에서는 Grid는 HTML의 table과 같이 사용할 수 있으며 또한 엑셀 형식과 같이도 사용이 가능하다. 

<그림> Grid의 기본 구성

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
 <style type="text/css">
  @import "../dojo/dojo/resources/dojo.css";
  @import "../dojo/dijit/tests/css/dijitTests.css";
  
  @import "../dojo/dojox/grid/_grid/soriaGrid.css";
        @import "..dojo/dijit/themes/soria/soria.css";
 </style>

 <script type="text/javascript" src="../dojo/dojo/dojo.js"
  djConfig="parseOnLoad: true, isDebug: false, defaultTestTheme: 'soria'"></script>
 <script type="text/javascript" src="../dojo/dijit/tests/_testCommon.js"></script>
    <style> 
        /* NOTE: for a full screen layout, must set body size equal to the viewport. */
        html, body { height: 100%; width: 100%; margin: 0; padding: 0; }
    </style>
    <script type="text/javascript">
        dojo.require("dojo.parser");
        dojo.require("dijit.Declaration");
        dojo.require("dijit.layout.LayoutContainer");
        dojo.require("dijit.layout.ContentPane");
        
        dojo.require("dojo.data.ItemFileReadStore");
        dojo.require("dojox.grid.Grid");
        dojo.require("dojox.grid._data.model");
        var view1 = {
                        cells: [
                                {name: 'User', field: "name"},
                                {name: 'Jikname', width: "50em", field: "jikname"},
                                {name: 'E-mail', width: "50em", field: "email"}
                          ]
                };
                // a grid layout is an array of views.
                var layout = [ view1 ];
     </script>
</head>
<body class="soria">

<div dojoType="dojo.data.ItemFileReadStore" jsId="organizationUserStore" url="organizationUserListJson.jsp"></div>
 <div dojoType="dojox.grid.data.DojoData" jsId="model" rowsPerPage="20" store="organizationUserStore" query="{ name: '*' }"></div>
 <div id="grid" dojoType="dojox.Grid" model="model" structure="layout"></div>

</body>
</html>

 

1. Grid를 사용하기 위해서 dojox.grid.Grid, dojox.grid._data.model 를 선언한다.

2. Grid의 셀 구조를 스크립트로 작성한다. 이때 "name" 속성은 Grid의 각 셀의 타이틀이 됨으로 반드시 필요한다. 그리고 field 는 Json 파일로 부터 읽어 올 인자를 입력하면 된다.

3. 마지막으로 div를 통해 DojoData의 모델을 선언하고 속성으로 페이지당 row의 수와 json을 읽어올 store 를 정의한다. 그리고 "dojox.Grid의 model 속성에는 앞에서 선언한 DojoData의 ID 값을 선언한다.

Average (0 Votes)
로그인 유저 정보 서버로 넘기는 방법
Tags: genericcontext_curr_logged_rolemapping, login

유저가 로그인을 하고 서버로 로그인 정보를 보내야 한다.

그런데 유엔진에서는 기본적으로 로그인 메커니즘을 위한 API는 제공하지 않는다.

그리고 standalone의 loginForm.jsp와 login.jsp를 보면 쿼리로 유저 정보를 단순 비교하고

로그인이 승인이 되면 아래 두 로직에 의해서 서버와 웹단으로 로그인 유저 정보를 보내게 된다.

/uengine-web/wih/wihDefaultTemplate/submit.jsp 중에서...

RoleMapping loggedRoleMapping = RoleMapping.create();
loggedRoleMapping.setEndpoint("JB");
Map genericContext = new HashMap();
genericContext.put(HumanActivity.GENERICCONTEXT_CURR_LOGGED_ROLEMAPPING, loggedRoleMapping);
pm.setGenericContext(genericContext);


그리고 웹단에서는 session에 로그인 유저 정보들을 담아서 들고 다니게 된다.

/uengine-web/login.jsp 중에서...

session.setAttribute("loggedUserId", decode(request.getParameter("userId")));
session.setAttribute("loggedUserFullName", EMPNAME);
session.setAttribute("loggedUserIsAdmin",  ISADMIN);
session.setAttribute("loggedUserJikName",  JIKNAME);
session.setAttribute("loggedUserEmail",    EMAIL);
session.setAttribute("loggedUserPartCode", PARTCODE);

그래서 session이 종료가 되면 로그인을 다시 해야한다.

 

Average (0 Votes)
lep44 버전과 standalone jsp 통합 방안

uengine3.0_lep44에서 제일 두드러진 면은 jsp들의 업그레이드였다.

lep44에서 제공하는 style을 이용해서 유저에게 좀 더 친숙한 화면을 제공하는데

이번에 standalone버전에서 그 기능들을 옮기는 작업을 지행중이다.

그런데 기존 jsp에서 lep44의 api들을 많이 사용하고 있기 때문에 그대로 이용하기에는 무리가 있어서

버전별로 wrapper를 만드는걸로 결정을 하였다.

uegnine_properties에 WebCustomManager.class 프로퍼티를 추가하여 wrapper를 등록하면된다.

지금 제공되는 lep44용은 org.uengine.processmanager.web.Liferay44WebCustomManager가 추가되고

standalone 버전에는 org.uengine.processmanager.web.DefaultWebCustomManager가 제공된다.

Average (0 Votes)
Dojo 에서 트리 추가
Tags: dojo, json, tree, 도조, 제이슨, 트리

Dojo 로 트리를 추가하기 위해선 Dojo의 "Dijit.Tree" 라이브러리를 사용한다. 

트리를 추가하기 위한 페이지에서 "dijit.Tree" 를 선언하고 트리에서 사용할 데이터 구조인 Json 파일을 생성하고 트리 추가된 페이지에 선언한다.

    <script type="text/javascript">
        dojo.require("dojo.parser");
        dojo.require("dijit.Declaration");
        dojo.require("dijit.layout.LayoutContainer");
        dojo.require("dijit.layout.AccordionContainer");
        dojo.require("dijit.Tree");
        dojo.require("dijit.Menu");
        dojo.require("dojo.data.ItemFileWriteStore");
     </script>
</head>
<body class="soria">
<div dojoType="dojo.data.ItemFileWriteStore" jsId="organizationUserStore" url="organizationUserListJson.jsp"></div>
<div dojoType="dojo.data.ItemFileWriteStore" jsId="organizationGroupStore" url="organizationGroupListJson.jsp"></div>
<div dojoType="dojo.data.ItemFileWriteStore" jsId="organizationRoleStore" url="organizationRoleListJson.jsp"></div>

 Json 파일의 예

<%@include file="../common/header.jsp"%>
<
%@include file="../common/getLoggedUser.jsp"%>

<%@ page import="org.uengine.util.dao.*, java.sql.*,javax.sql.*,javax.naming.*" %>

<%
 String EMPCODE = null;
 String EMPNAME = null;
 String JIKNAME = null;
 String EMAIL = null;
 String PARTCODE = null;
 String PARTNAME = null;
 
 int authenticationCondition = 0 ;
 
 Connection      conn = null;
 Statement   stmt  = null;
 ResultSet   rs   = null;
 ResultSet  userRs = null;
 StringBuffer  partSql  = new StringBuffer();
 StringBuffer userSql  = new StringBuffer();
 
 StringWriter sw = new StringWriter();
 PrintWriter spw = new PrintWriter(sw);
 
 spw.println("{ identifier: 'id',");
    spw.println("  label: 'name',");
    spw.println("  items: [");
 
 try {
  conn = DefaultConnectionFactory.create().getConnection();
  stmt = conn.createStatement();
  
  partSql.setLength(0);
  partSql.append(" select P.GLOBALCOM, P.PARTCODE, P.PARTNAME");
  partSql.append(" from PARTTABLE P");
  rs = stmt.executeQuery(partSql.toString());
  
  while(rs.next()){
   PARTCODE = rs.getString("PARTCODE") == null ? "" : rs.getString("PARTCODE");
   PARTNAME = rs.getString("PARTNAME") == null ? "" : rs.getString("PARTNAME");
   
   userSql.setLength(0);
   userSql.append(" select E.EMPCODE,E.ISADMIN,E.EMPNAME,E.JIKNAME,E.EMAIL");
   userSql.append(" from EMPTABLE E where E.PARTCODE='" + PARTCODE + "'");
   userRs = stmt.executeQuery(userSql.toString());
   
   spw.print("{ type:'main', id:'" + PARTCODE + "', name:'" + PARTNAME + "'");
   spw.print(", children:[");
   String tempElement = "";
   while(userRs.next()){
    EMPCODE = userRs.getString("EMPCODE") == null ? "" : userRs.getString("EMPCODE");
    EMPNAME = userRs.getString("EMPNAME") == null ? "" : userRs.getString("EMPNAME");
    JIKNAME = userRs.getString("JIKNAME") == null ? "" : userRs.getString("JIKNAME");
    EMAIL = userRs.getString("EMAIL") == null ? "" : userRs.getString("EMAIL");
    spw.print("{_reference:'" + EMPCODE + "'}");
    tempElement = tempElement
       + "{ type:'user', id:'" + EMPCODE + "', name:'" + EMPNAME + "',jikname:'"+ JIKNAME +"',email:'"+ EMAIL +"'}";
    if(!userRs.isLast()){
     spw.print(",");
     tempElement = tempElement + ",";
    }    
   }
   userRs.close();
   spw.print("]}");
   if(!tempElement.equals("")){
    spw.print(",");
    spw.println(tempElement);
   }
   
   if(!rs.isLast()){
    spw.print(","); 
   }
  }
  rs.close();
 } finally {
  if (stmt != null)
   try {
    stmt.close();
   } catch (Exception e) {
   }
  if (conn != null)
   try {
    conn.close();
   } catch (Exception e) {
   }
 }
 spw.print("]}");
%>
<%=sw.toString()%>

 Json 의 출력결과

(유엔진의 회원관리 기능을 예로 설명하면 회원관리 트리에 그룹폴더가 생성하고 그룹폴더를 열었을 때 그룹에 속해있는 회원리스트가 뿌려진다. 그렇게 하기 위해선 아래의 Json 출력 결과 처럼 "type: main" 이 그룹의 폴더가 되고 이 그룹에 속해있는 회원의 ID 값을 가지는 "_reference"를 children으로 등록한다.)

{ identifier: 'id',
  label: 'name',
  items: [
 { type:'main', id:'DEV', name:'Development', children:[{_reference:'JB'},{_reference:'JJY'}]},
 { type:'user', id:'JB', name:'Joe Bloggs',jikname:'',email:''},
 { type:'user', id:'JJY', name:'JJY',jikname:'',email:''}
 ]
}

 

여기까지 진행이 되었으면 실제 트리가 뿌려질 부분에 Div를 통해 트리를 선언하는데 아래의 소스에서 처럼 트리를 위한 div 속성에 store는 트리를 그리기 위한 Json 파일, childrenAttr는 폴더가 가지는 children 정보가 있는 Item속성(Json 파일 출력샘플에서 설명했음), query에서는 폴더로 구성될 노드의 "type" 등의 정보를 입력한다.

<div dojoType="dijit.layout.AccordionPane" title="<%=GlobalContext.getLocalizedMessageForWeb("user_manage",loggedUserLocale,"User manage") %>">
   <div dojoType="dijit.Tree" id="userList" store="organizationUserStore" childrenAttr="children" query="{type:'main'}" label="<%=GlobalContext.getLocalizedMessageForWeb("user",loggedUserLocale,"User") %>">
    <script type="dojo/method" event="onClick" args="item">
    </script>
   </div>
   
  </div>
  <div dojoType="dijit.layout.AccordionPane" title="<%=GlobalContext.getLocalizedMessageForWeb("group_manage", loggedUserLocale, "Group manage") %>">
   <div dojoType="dijit.Tree" id="groupList" store="organizationGroupStore" childrenAttr="children" query="{type:'main'}" label="<%=GlobalContext.getLocalizedMessageForWeb("group",loggedUserLocale,"Group") %>">
    <script type="dojo/method" event="onClick" args="item">
    </script>
   </div>
  </div>
  <div dojoType="dijit.layout.AccordionPane" title="<%=GlobalContext.getLocalizedMessageForWeb("role_manage", loggedUserLocale, "Role manage") %>">
   <div dojoType="dijit.Tree" id="roleList" store="organizationRoleStore" childrenAttr="children" query="{type:'main'}" label="<%=GlobalContext.getLocalizedMessageForWeb("role",loggedUserLocale,"Role") %>">
    <script type="dojo/method" event="onClick" args="item">
    </script>
   </div>
  </div>

 위의 소스로 적용된 트리의 모습

Average (0 Votes)
SCORM 이란?

 

SCORM 이란?

SCORM(Sharable Content Object Relation Model)
우리말로 단지 해석하면 공유 콘텐츠 객체 관계 모델 이며, 좀더 알아듣게 설명하자면 '콘텐츠의 공유를 위한 관계 모델'이라고 할 수 있다.
즉, 콘텐츠의 표준을 정하여 공유를 하자는 것이 큰 핵심이다.
SCORM은 미국 국방성 산하에 있는 ADL Initiative에서 1999년 4월 처음 시작되었다.
SCORM 버전 1.0을 2000년 1월에 발표한 이후 현재 SCORM 2004(버전 1.3)을 발표한 상태에 있고 현재 대부분의 컨텐츠 들은 이 표준을 따르고 있다.

SCORM의 구성요소

SCORM 스펙은 크게 4개의 책으로 이루어져 있다.  Overview, CAM, RTE, S&N 이렇게 4권이다.


1. Overview

Overview는 말 그대로 전체 내용을 대략적으로 설명해 놓은 것으로 스펙에서 분량이 가장 적지만, 전체적인 흐름을 볼 수 있는 중요한 부분이다.

2. CAM (Contents Aggregation Model)

콘텐츠 통합 모델을 설명하고 있는 부분으로 SCORM에 중요한 용어가 나온다.
Manifest, SCO, ASSET, Aggregation, Metadata...등 이 나오며 이중 필수적으로 이해하고 넘어가야 하는 부분은 Manifest 파일과 Metadata 부분이다.
이 두가지는 SCORM 콘텐츠에 포함되는 정보로서 콘텐츠를 개발할 때 넣어주어야 하는 것이다.  
Manifest란 책의 목차와 같은 구성으로 된 파일로 SCORM의 목차 라고 이해하는게 쉬울 것이다. IMS 기관의 규격을 따라서 파일명이 'Imsmanifest.xml'이다.
Metadata란 데이터를 설명하는 데이터를 의미하는 것으로 위 각각의 목차에 대한 세부설명이 필요할 경우, 활용하면 된다.

3. RTE(Run-Time Environment)

실행환경으로 콘텐츠에서 학습진도율이나, 학습시간등을 처리할 때 콘텐츠에 대해 처리해야 하는 정보를 정리하고, 이것을 처리하도록 시스템에 제공 하는것이다.
처리해야 하는 정보를 XML 형태로 정리했으며 CMI Data Model이라고 부른다.

4. S&N(Sequencing & Navigation)

SCORM 2004에 새롭게 등장한 개념으로 학습자가 콘텐츠를 학습할때 한번에 한 과정을 처음부터 끝까지 할 수도 있겠지만 그렇지 않는 경우도 많이 있을것이다.
이 때, 전에 학습한 부분까지 정보가 있어 다음 학습시 그 위치로 이동되어 교육이 진행되어야 한다. 그리고 시험 결과에 따라 재학습이나 반복학습이 되도록 유도하는를 하는데
이러한 것을 '시퀀싱'이라 하며 시퀀싱에 따라서 이동하는 것을 '네비게이션'이라 한다.

 

Average (0 Votes)
uEngine standalone에서 mssql 연동하기
Tags: mssql

 

uEngine standalone 은 기본적으로 was와 db가 탑재되어 릴리즈가 된다.

was: tomcat 5.5 , db: hsql database

그런데 hsql은 데모용으로 사용 가능하지만 프로덕션 하기에는 무리가 있가 있기 때문에 보통 프로젝트를 하게 되면 다른 데이타베이스를 사용하게 되는데 한 예로 MSSQL서버를 연결하는 방법을 설명하겠다.

사전 준비

MSSQL 설치, uEngine_stanalone.jar

1. 데이타 베이스 셋팅

uEngine_stanalone.jar을 압축을 풀고 uengine_standalone\src\resources\sqls\mysql 디렉토리를 보면

MSSQL SQL 스크립트 파일이 있다. 이것을 가지고 uEnginDB를 셋팅해 준다.

2. uengine.properties 설정파일

uengine_standalone\was\webapps\uengine-web\WEB-INF\classes\org\uengine 디렉토리에 uengine.properties 설정 파일이 있다. 이 파일을 열어서 mssql daofactory를 선언해준다

ex) daofactory.class=org.uengine.persistence.dao.MSSQLDAOFactory

3. tomcat의 server.xml

uengine_standalone\was\conf 디렉토리에 server.xml 파일이 있다. 이 파일을 열어서 JNDI resources를 선언한다.

ex)

<Resource
      name="java:/uEngineDS"
      type="javax.sql.DataSource"
      driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
      url="jdbc:sqlserver://127.0.0.1:1434;DatabaseName=uenginedb"
      username="sa"
      password="1234"
      maxIdle="30"
      maxWait="10000"
      maxActive="100"/>

 이와 같은 방법으로 다른 데이타베이스와 연동을 할 수가 있다.

가끔 table script 파일이 업데이트가 안되어 셋팅 후 에러가 날 경우가 있는데 hsql script 파일을 열어서 비교를 해보도록 한다.

Average (0 Votes)
spring에서 rmi 통신
Tags: rmi, spring

spring에서 rmi 통신을 위해서는 server측과 client측에 ApplicationContext.xml 을 설정해야한다.

* 먼저 서버 측에서 해야 할일

1 . web.xml에 설정을 하는데 was 실행과 동시에 rmi 서버 실행

 <context-param id="context-param_1">
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /config/spring/applicationContext-*.xml
  </param-value>
 </context-param>
 
 <listener id="listener_1">
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>

2. ApplicationContext.xml에 서버 bean 선언

 <bean id="rmiExporter" class="org.springframework.remoting.rmi.RmiServiceExporter">
   <property name="serviceName" value="uEngineProcessManagerService"/>
   <property name="service" ref="processManagerService"/>
   <property name="serviceInterface" value="org.uengine.processmanager.ProcessManagerRemote"/>
   <property name="registryPort" value="1099"/>
  </bean>

3. 콘솔에서 rmiregistry를 실행한다.

* 클라이언트 측에서 해야하는 것.  

1. ApplicationContext.xml 에서 서버측 커넥션을 가져오기 위한 bean 선언

<bean id="rmiUengineProcessManagerService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> 
   <property name="serviceUrl" value="rmi://192.168.10.103:1099/uEngineProcessManagerService"/>
    <property name="serviceInterface" value="org.uengine.processmanager.ProcessManagerRemote"/>
  </bean>

 * 참고해야 할것은 spring에서 원격 rmi는 트랜젝션을 자동으로 묶어주지 않는 다는것을 명심해야 한다.

Average (0 Votes)