weblogic session persistence 설정하기

웹로직에서 웹애플리케이션을 개발하고 배포를 하는 과정에서 재배포 혹은 서버 점검에 따라 인스턴스를 재기동할 경우 사용자 세션이 끊기는 현상이 발생합니다.

이에 대하여 웹로직 배치 기술자 조정을 통해 세션을 유지하는 방법을 찾아보고 글 남깁니다.

보통 세션 퍼시스턴스의 설정은 클러스터 환경에서 서로 다른 서버간 세션 공유에 활용되는 것이 많으리라 생각됩니다.

아래 설정은 단일 서버에서 파일에 세션 상태를 기록하여 세션을 유지하는 예제입니다.

<?xml version='1.0' encoding='UTF-8'?>
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <session-descriptor>
    <persistent-store-type>file</persistent-store-type>
  </session-descriptor>

</weblogic-web-app>

세션에 사용자 정의 클래스를 넣을 경우, 해당 클래스를 serializable을 구현하도록 해야 합니다. 그렇지 않을 경우, 세션은 유지되나 해당 세션 애트리뷰트를 참조할 수 없습니다.

그리고 해당 출처는 아래와 같습니다.

http://download.oracle.com/docs/cd/E13222_01/wls/docs81/webapp/sessions.html
위 문서에 설명이 나오며, weblogic.xml 파일 실제 구조는 아래 URL에서 참조하였습니다.

http://cheese.springnote.com/pages/4542851

netsh를 통한 ip주소 세팅 스크립트

리눅스에서는 이미 네트워크 설정에 프로필(?) 기능이 있어서, 노트북과 같이 이동하는 장비에서 IP설정(IPv6에서는 달라지겠지만)을 기록해 두는 기능이 있습니다.

저와 같이 여러 사이트를 방문하는 엔지니어에게는 IP주소 세팅이 업무의 시작이라 할 수 있습니다.

보통은 ipchanger같은 툴을 통해서 프로필 기능과 비슷하게 활용하고 계실 것입니다.
( 저는 ip를 메모해두고 윈도우 자체네트워크 설정으로 일일이 입력합니다만.. )

netsh 명령을 통해서 프로필 기능과 비슷한 시도를 해보았습니다.

아래 명령을 쉘스크립트로 작성하여 사용하는 방법입니다.

@echo off
set INTERFACE="eth0"
set IPADDRESS=192.168.20.10
set NETMASK=255.255.255.0
set GATEWAY=192.168.20.254
set PRIDNS=168.126.63.1
set SECDNS=168.126.63.2

netsh ^
interface ip ^
set address ^
name=%INTERFACE% ^
source=static ^
addr=%IPADDRESS% ^
mask=%NETMASK% ^
gateway=%GATEWAY% ^
gwmetric=0

netsh ^
interface ip ^
set dns name=%INTERFACE% ^
source=static ^
addr=%PRIDNS% ^
register=NONE

netsh ^
interface ip ^
add dns ^
name=%INTERFACE% ^
addr=%SECDNS% ^
index=2

netsh interface ip show config name=%INTERFACE%

pause

아래는 ini컨피그를 사용하는 확장판.

@setlocal enableextensions enabledelayedexpansion
@echo off
@rem change below configurable parameters.
set INTERFACE="eth0"
set file=ipaddress.ini
set DHCPKEY=DHCP
set IPADDRESSKEY=IPADDRESS
set NETMASKKEY=NETMASK
set GATEWAYKEY=GATEWAY

set IPADDRESS=
set NETMASK=
set GATEWAY=
set DHCP=
set PRIDNS=168.126.63.1
set SECDNS=168.126.63.2

set currarea=
set i=0
for /f "delims=" %%a in (!file!) do (
    set ln=%%a
    if "x!ln:~0,1!"=="x[" (
        set /a i=!i!+1
        set currarea=!ln!
        echo !i!. !currarea!
    )
)

set /a i=0

set /p choose=Choose profile : 

for /f "delims=" %%a in (!file!) do (
    set ln=%%a
    if "x!ln:~0,1!"=="x[" (
        set /a i=!i!+1
    ) else (
        for /f "tokens=1,2 delims==" %%b in ("!ln!") do (
            set currkey=%%b
            set currval=%%c
            if "x!choose!"=="x!i!" (
                if "x!currkey!"=="x!DHCPKEY!" (
                    set DHCP=!currval!
                )
                if "x!currkey!"=="x!IPADDRESSKEY!" (
                    set IPADDRESS=!currval!
                )
                if "x!currkey!"=="x!NETMASKKEY!" (
                    set NETMASK=!currval!
                )
                if "x!currkey!"=="x!GATEWAYKEY!" (
                    set GATEWAY=!currval!
                )
            )
        )
    )
)

if "x!DHCP!"=="x" ( 
    netsh ^
    interface ip ^
    set address ^
    name=%INTERFACE% ^
    source=static ^
    addr=%IPADDRESS% ^
    mask=%NETMASK% ^
    gateway=%GATEWAY% ^
    gwmetric=0
) else (
    netsh ^
    interface ip ^
    set address ^
    name=%INTERFACE% ^
    source=dhcp
)

netsh ^
interface ip ^
set dns name=%INTERFACE% ^
source=static ^
addr=%PRIDNS% ^
register=NONE

netsh ^
interface ip ^
add dns ^
name=%INTERFACE% ^
addr=%SECDNS% ^
index=2

netsh interface ip show config name=%INTERFACE%

pause

endlocal
[DHCP]
DHCP=yes

[회사]
IPADDRESS=192.168.20.18
NETMASK=255.255.255.0
GATEWAY=192.168.20.254

[집]
IPADDRESS=192.168.10.18
NETMASK=255.255.255.0
GATEWAY=192.168.10.254

웹로직의 보편적인 웹개발상의 디버그

웹로직을 사용하면서, 에러의 원인을 쉽게 찾을 수 없을 때, 원인을 추적하는 방법을 나열해 봅니다.

dispatcher forward 사용시 해당 리소스가 없을 경우 추적하기.( 알 수 없는 404 에러 )

웹개발 프레임워크를 사용할 때 주로 개발하는 형태가, controller를 작성하여 비즈니스 로직을 수행한 후, 사용자에게 보여질 페이지(JSP)로 RequestDispatcher.forward 하는 형태이리라 생각됩니다. ( 물론 다른 형태도 많겠지만, RequestDispatcher.forward 하는 형태를 가정한 상황으로 글을 씁니다. )

아래는 그렇게 사용한 java servlet 예제입니다.

RequestDispatcher rd = null;
rd = request.getRequestDispatcher("/main.jsp");
rd.forward(request, response);

이 경우 만약 main.jsp 파일이 존재하지 않는다면, 웹로직은 404 에러 페이지만 출력할 뿐입니다. 그러면 사용자는 호출한 URL이 존재하지 않는 것인지 forward 대상 페이지가 없는 것인지 알 수 없습니다.

tomcat 이나 다른 WAS의 경우는 주로 위 처리에 대한 에러가 로그파일 혹은 웹브라우저에 추적이 가능한 정보를 제공하는데, 웹로직은 404 에러코드만 줄 뿐 추가정보를 제공하지 않았습니다. ( 제 경험 )

이에 추적정보를 찾는 방법을 알았기에 공유합니다.

  1. 해당 서버를 선택합니다.
  2. 디버그 탭을 선택합니다.
  3. weblogic 항목을 펼칩니다.
  4. servlet 항목을 펼칩니다.
  5. DebugURLResolution 항목에 체크표합니다.
  6. 사용 버튼을 눌러 활성화 합니다.

위 과정을 거치면 아래와 같은 로그를 발견할 수 있습니다. 서버의 logs/서버명.log 파일에 기록됩니다.

####<2011. 6. 17 오후 4시 41분 10초 KST> <Debug> <URLResolution> <whity> <AdminServer> <[ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <> <1308296470912> <BEA-000000> <ServletContext@465470[app:test module:test path:/test spec-version:null]: resolving request with relUri: /main.jsp>
####<2011. 6. 17 오후 4시 41분 10초 KST> <Debug> <URLResolution> <whity> <AdminServer> <[ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <> <> <1308296470912> <BEA-000000> <ServletContext@465470[app:test module:test path:/test spec-version:null]: getResourceAsSource() couldn't find source for : /main.jsp>

위 로그 마지막 줄을 통해서 main.jsp 파일을 찾을 수 없다는 내용을 확인할 수 있습니다.

JDeveloper + WebLogic 환경에서 Remote Debugging 사용하기.

JDeveloper와 WebLogic을 사용하는 개발환경에서 Integrated Server를 쓰지 않고, 테스트 혹은 운용서버에 배포후 Remote Debugging을 하는 방법을 간략히 소개합니다.

1. 대상 서버의 Remote Debugging JVM 옵션 세팅.

먼저 JVM에서 Remote Debugging을 받아들이기 위한 설정을 추가합니다.
아래 세팅을 서버의 구동 스크립트에 포함되도록 합니다.
( 저는 편의상 개발서버의 .profile을 사용하고 있습니다. nodemanager 등을 사용중인 경우에는 콘솔에서 세팅 가능하겠습니다. )

# JDK 1.4 이하 기본 형태
# -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=[port]
# JDK 1.5 이상 기본 형태
# -agentlib:jdwp=transport=dt_socket,server=y,address=[port]
JAVA_OPTIONS=$JAVA_OPTIONS\
"-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=4000,server=y,suspend=n"

2. 대상 서버의 Tunneling 설정.

weblogic 콘솔에서 대상 서버의 Protocols탭에 Enable Tunneling.을 체크합니다.

3. JDeveloper에서 대상 프로젝트에 Remote Debugging 설정.

개발중인 프로젝트에 Remote Debugging을 세팅하는 과정입니다.

  1. ‘Project Properties’에서 ‘Run/Debug/Profile’ 선택.
  2. ‘Run Configurations’에서 복제 혹은 기존 것을 편집.
  3. ‘Launch Settings’에서 ‘Remote Debugging’ 체크.
  4. ‘Tool Settings’ – ‘Debugger’ – ‘Remote’에 아래 설정 추가.
    • Protocol : Attach to JPDA
    • Host : 해당서버 주소
    • Port : 4000 1항에서 설정.

4. Remote Debugging 시작.

프로젝트에서 ‘Start Remote Debugger’를 선택하면, 브레이크포인트 등 원하는 디버깅을 수행할 수 있습니다.

PKCS12 인증서를 Java keystore에 넣기.

PKCS12 인증서를 Java keystore에 넣기.

JDK1.5까지는 제공되지 않았던 기능으로 보이는데, JDK1.6에서는 keytool 명령으로 pkcs12인증서(*.p12)를 java keystore에 넣는 것이 가능하도록 바뀌었습니다.

keytool \
-importkeystore \
-srckeystore cert.p12 \
-destkeystore keystore.jks \
-srcstoretype pkcs12 \
-deststoretype jks \
-srcalias mycert \
-destalias mycert

브라우저에서 제공하는 기능(javascript)으로 전자서명하기.

브라우저에서 제공하는 기능(javascript)으로 전자서명하기.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="ko-KR">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>전자서명 테스트</title>
  <script language="javascript" type="text/javascript" src="js/sign.js"></script>
</head>
<body>
  <h2>전자서명 테스트</h2>
  <form name="form0" action="#">
    서명을 위한 원문<br />
    <textarea id="plain" type="text" name="plain"></textarea><br />
    <input type="button" onclick="document.getElementById('signed_msg').value = signDigest(document.getElementById('plain').value);" value="전자서명" /><br />
    <hr />
    전자서명문<br />
    <textarea id="signed_msg"></textarea>
  </form>
</body>
</html>

위에 포함된. sign.js 파일

function signDigest(text) {
    if ( window.event ) {
        window.event.cancelBubble = true;
    }

    var dest = sign(text); //TODO
    //alert(dest);
    return dest;
}

// CAPICOM constants
var CAPICOM_STORE_OPEN_READ_ONLY = 0;
var CAPICOM_CURRENT_USER_STORE = 2;
var CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0;
var CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY = 6;
var CAPICOM_CERTIFICATE_FIND_TIME_VALID = 9;
var CAPICOM_CERTIFICATE_FIND_KEY_USAGE = 12;
var CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE = 0x00000080;
var CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0;
var CAPICOM_INFO_SUBJECT_SIMPLE_NAME = 0;
var CAPICOM_ENCODE_BASE64 = 0;
var CAPICOM_E_CANCELLED = -2138568446;
var CERT_KEY_SPEC_PROP_ID = 6;

function IsCAPICOMInstalled() {
    if ( typeof(oCAPICOM) == 'object' ) {
        if( ( oCAPICOM.object != null ) ) {
            // We found CAPICOM!
            return true;
        }
    }
}

function FindCertificateByHash() {
    try {
        // instantiate the CAPICOM objects
        var MyStore = new ActiveXObject('CAPICOM.Store');
        // open the current users personal certificate store
        MyStore.Open(CAPICOM_CURRENT_USER_STORE, 'My', CAPICOM_STORE_OPEN_READ_ONLY);

        // find all of the certificates that have the specified hash
        var FilteredCertificates = MyStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, strUserCertigicateThumbprint);

        var Signer = new ActiveXObject('CAPICOM.Signer');
        Signer.Certificate = FilteredCertificates.Item(1);
        return Signer;

        // Clean Up
        MyStore = null;
        FilteredCertificates = null;
    } catch ( e ) {
        if (e.number != CAPICOM_E_CANCELLED) {
            return new ActiveXObject('CAPICOM.Signer');
        }
    }
}

function sign(src) {
    if ( window.crypto && window.crypto.signText ) {
        return sign_NS(src);
    }

    return sign_IE(src);
}

function sign_NS(src) {
    var s = crypto.signText(src, 'ask' );
    return s;
}

function sign_IE(src) {
    try {
        // instantiate the CAPICOM objects
        var SignedData = new ActiveXObject('CAPICOM.SignedData');
        var TimeAttribute = new ActiveXObject('CAPICOM.Attribute');

        // Set the data that we want to sign
        SignedData.Content = src;
        var Signer = FindCertificateByHash();

        // Set the time in which we are applying the signature
        var Today = new Date();
        TimeAttribute.Name = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;
        TimeAttribute.Value = Today.getVarDate();
        Today = null;
        Signer.AuthenticatedAttributes.Add(TimeAttribute);

        // Do the Sign operation
        var szSignature = SignedData.Sign(Signer, true, CAPICOM_ENCODE_BASE64);
        return szSignature;
    } catch ( e ) {
        if (e.number != CAPICOM_E_CANCELLED) {
            alert('An error occurred when attempting to sign the content, the errot was: ' + e.description);
        }
    }
    return '';
}

위 함수를 사용하면 PKCS#7 으로 인코딩된 전자서명문을 생성할 수 있으며, 서버에서는 bouncy castle라이브러리 등을 통해서 검증을 할 수 있습니다.

crypto.signText 문법

Syntax
crypto.signText
   (text, selectionStyle [, authority1 [, ... authorityN]])

Parameters
text
    A string evaluating to the text you want a user to sign.
selectionStyle
    A string evaluating to either of the following:
        * ask specifies that a dialog box will present a user with a list of possible certificates.
        * auto specifies that Navigator automatically selects a certificate from authority1 through authorityN.
authority1... authorityN
    Optional strings evaluating to Certificate Authorities accepted by the server using the signed text.

weblogic nodemanager 명령 요약

weblogic nodemanager 에 접속하여 명령을 하는 것에 대한 간단한 요약.

telnet 접속의 경우.

telnet wls.dgkim.net 5555
DOMAIN #도메인명#
USER weblogic
PASS #패스워드#
SERVER #서버#
KILL # 종료시.
START # 시작시.

ssl 접속의 경우.

openssl s_client -connect wls.dgkim.net:5556
DOMAIN #도메인명#
USER weblogic
PASS #패스워드#
SERVER #서버#
KILL # 종료시.
START # 시작시.

현재 사용중인 메일(+웹메일)의 기술적 지원사항.

현재 제가 사용하는 메일의 기술적 지원 사항을 나열해 봅니다.

메일

기본적인 메일 서버로서의 고려사항.

1. SMTP/SMTP with SSL : 사용가능. 단, 현재 IP주소를 ISP의 가정용(?) 대역이라 일부 메일 서버에서는 차단될 수 있습니다.
2. POP3/POP3 with SSL : POP3는 제공하는 기능의 한계로 인해 사용하지 않습니다.
3. IMAP/IMAP with SSL : IMAP with SSL로 기본적으로 접근하여 사용합니다.
4. Authentication : LDAP 연동하여 계정인증을 하고 있습니다.
5. Accounting : LDAP에 연계하여 사용하면 좋을 것이나, 현재는 unix 계정에 연계하여 메일을 받고 있습니다. ( 혹, 바꿨나 기억나지 않네요. )
6. Mail box : 편지함의 경우 개인 받은 편지함의 경우 수동으로 생성하며, 한번 생성후 자신의 편지함은 본인이 생성 및 삭제 가능합니다.
7. Mailbox sharing : 개인의 받은편지함 및 개인이 생성한 편지함에 대하여 편지함 단위로 개별 사용자에 대한 권한을 줄 수 있습니다. 단, 사용자가 관리하는 인터페이스는 없고, unix 명령으로만 해봤습니다.
8. group mail : 메일링 리스트와 같은 group mail은 unix에서 임의로 생성하여 사용하는 것은 가능하나, 관리가 편리한 메일링 프로그램과 연계는 하지 않았습니다.
9. SPAM Filter : 현재 서버측 스팸필터는 사용하지 않습니다. 클라이언트에서 thunderbird에서 제공하는 스팸 필터를 사용하고 있습니다.

웹메일과 소소한 기능

웹메일에서 기능으로 중시여기는 것들.

1. Authentication : LDAP백엔드를 사용하며, Web form 인증을 사용합니다.
2. 메일서버 선택 : 메일 백엔드 서버는 현재 웹메일 관리 페이지에서 지정할 수 있으며, 지정된 서버목록에서 사용자가 선택하여 로그인 가능합니다. ( 당연히, 메일서버는 IMAP 등으로 연계됩니다. )
3. 주소 : 주소록프로그램과 연계되어 사용되며, 주소록은 LDAP 백엔드를 사용하여 사용중입니다. 메일 작성시 이름을 입력하여 자동으로 주소와 연계하는 것은 가능하나, 한글에 대해서는 기대되는 성능을 내지 못합니다.
4. HTML 메일 : 자체 HTML에디터(html+css+javascript)를 제공하며 사용자가 선택하여 사용가능합니다.
5. SMIME 메일 : 개인 인증서를 통해서 SMIME 서명 및 암호화 메일을 발송할 수 있습니다. LDAP에 사용자 인증서를 등록한 경우, 메일 작성시 캐시에 없을 경우 LDAP에 자동으로 접근하여 인증서를 가져옵니다.
6. PGP 메일 : PGP 가능하나 현재 PGP 키를 잘 사용하지 않고 있습니다.
7. SPAM Filter : 자동화된 스팸 차단 기능은 사용하지 않으며, blacklist등을 통해서 filtering은 가능합니다.
8. Filtering : 개인이 보인의 메일 필터 규칙을 추가하여 사용 가능합니다.
9. 찾기 : 찾기 인터페이스를 통해서 검색은 가능하나, 한글이나 첨부파일에 대한 검색은 잘 안되리라 생각되며, 웹메일의 검색 기능보다는 thunderbird와 같은 클라이언트 프로그램에서 주로 검색합니다.
10. RSVP : 자체 캘린더를 제공하며, RSVP 초대 메일에 대한 연계 기능을 제공합니다.
11. 대용량 메일 : 첨부파일이 대용량인 경우 서버에 파일을 저장하고 링크를 보내는 대용량 메일 기능을 제공합니다.
12. 첨부파일 지원 : zip 첨부파일의 경우 자체 압축해제를 통해 웹으로 zip파일에 포함된 파일 목록을 볼 수 있습니다. 단, 한글 파일명에 대해서는 제대로 동작하지 않습니다.
13. 납치태그 : 기본적으로 메일보기에서는 plain text형태로 보여주며, html 메시지의 경우 이미지 차단이나 납치태그에 대한 차단이 기본적으로 제공됩니다.
14. 드래그앤드롭 파일업로드 : 메일작성시 아직은 드래그앤드롭으로 파일첨부가 불가능합니다.

ps. 이 글은 제가 생각하기에 필요하다고 느끼는 것에 대하여 간추려 올린 것입니다. 추가적으로 필요하다고 생각되는 것이 있으시면, 주저 없이 코멘트 달아 주십시오.

WLST로 DataSource 생성하기.

이번에 웹로직으로 웹프로젝트를 하면서, JDBC 정보를 프로그램에 녹여볼 생각을 했습니다.

예전에 Oracle WAS의 경우 Oracle WAS Deployment Descriptor중 data-sources.xml을 활용하여 애플리케이션 배포에 JDBC정보를 넣어 배포를 했었는데, 웹로직은 약간 달랐습니다.( 그리고 웹로직의 버저닝을 사용하니 뭔가 좀 더 달라지는 듯 했습니다. )

그래서, 애플리케이션 소스에는 넣지 못하더라도, 배포 가능한 소스로 해보고자 방법을 찾던 중 WLST를 사용하는 방법의 예제를 찾았습니다.

그래서 그 방법으로 하기로 하고 아래와 같은 스크립트로 한번에 DataSource를 생성하였습니다.

import sys
from java.lang import System

# function definition BEGIN

# defining addJDBC function
def addJDBC(obj, servers):
    print("")
    print("*** Creating JDBC  ")
    
    # Create the Connection Pool.  The system resource will have
    # generated name of 'PoolName'+"-jdbc"
    
    myResourceName = obj["PoolName"]
    print("Here is the Resource Name: " + myResourceName)
    
    jdbcSystemResource = create(myResourceName,"JDBCSystemResource")
    myFile = jdbcSystemResource.getDescriptorFileName()
    print ("HERE IS THE JDBC FILE NAME: " + myFile)
    
    jdbcResource = jdbcSystemResource.getJDBCResource()
    jdbcResource.setName(obj["PoolName"])
    
    # Create the DataSource Params
    dpBean = jdbcResource.getJDBCDataSourceParams()
    myName=obj["JNDIName"]
    dpBean.setJNDINames([myName])
    
    # Create the Driver Params
    drBean = jdbcResource.getJDBCDriverParams()
    drBean.setPassword(obj["Password"])
    drBean.setUrl(obj["URLName"])
    drBean.setDriverName(obj["DriverName"])
    
    propBean = drBean.getProperties()
    driverProps = Properties()
    driverProps.setProperty("user",obj["UserName"])
    
    e = driverProps.propertyNames()
    while e.hasMoreElements() :
        propName = e.nextElement()
        myBean = propBean.createProperty(propName)
        myBean.setValue(driverProps.getProperty(propName))
        print myBean
        
        # Create the ConnectionPool Params
        ppBean = jdbcResource.getJDBCConnectionPoolParams()
        
        ppBean.setInitialCapacity(int(obj["InitialCapacity"]))
        ppBean.setMaxCapacity(int(obj["MaxCapacity"]))
        ppBean.setCapacityIncrement(int(obj["CapacityIncrement"]))
        
        if not obj["ShrinkPeriodMinutes"] == None:
            ppBean.setShrinkFrequencySeconds(int(obj["ShrinkPeriodMinutes"]))
        if not obj["TestTableName"] == None:
            ppBean.setTestConnectionsOnReserve(1)
            ppBean.setTestTableName(obj["TestTableName"])
        if not obj["LoginDelaySeconds"] == None:
            ppBean.setLoginDelaySeconds(int(obj["LoginDelaySeconds"]))

        # Adding KeepXaConnTillTxComplete to help with in-doubt transactions.
        xaParams = jdbcResource.getJDBCXAParams()
        xaParams.setKeepXaConnTillTxComplete(1)

        # Add Target
        
        for servername in servers:
            jdbcSystemResource.addTarget(getMBean("/Servers/" + servername))

# function definition END


print "@@@ Starting the script ..."


url = 't3://localhost:7001'
usr = 'weblogic'
password = 'welcome'
servernames = ['AdminServer', 'SSO1', 'SSO2']

connect(usr,password, url)

for servername in servernames:
    servermb=getMBean("Servers/" + servername)
    if servermb is None:
       print '@@@ No server MBean found'
       exit()

edit()
startEdit()

DB1 = {
    'PoolName' : 'DataSource for DGKIM',
    'JNDIName' : 'jdbc/dgkim',
    'Password' : 'password',
    'URLName' : 'jdbc:oracle:thin:@db.dgkim.net:1521:DGKIM',
    'DriverName' : 'oracle.jdbc.OracleDriver',
    'UserName' : 'dgkim',
    'InitialCapacity' : '20',
    'MaxCapacity' : '100',
    'CapacityIncrement' : '10',
    'ShrinkPeriodMinutes' : None,
    'TestTableName' : 'DUAL',
    'LoginDelaySeconds' : None
}

addJDBC(DB1, servernames)

save()
activate(block="true")

exit()

저는 프로젝트 특성상 하나의 DB가 아닌 여러개의 DB를 사용하게 됩니다. 위 예제에서는 DB1이란 것을 사용했지만, 실제로는 8개의 DB에 접속하는 프로그램을 작성했습니다.

그래서 위 코드를 만들고, 개발 서버냐 운용 서버냐에 따라 url과 servernames를 수정하여 한번에 데이터 소스를 작성해서 편리했습니다.

스마트폰 사용기

아이폰이란 스마트폰을 쓴지 몇개월이 되었습니다.(4월 30일)

스마트폰으로 많이 편리해진 점도 있지만.

타인에 비해 PC 의존적인 부분은 많이 못 벗어난 듯합니다.

1. 메일

IMAP 메일을 쓰므로 PC와 같은 뷰를 가지고 확인할 수 있는 것은 강점입니다. 하지만 작은 자판(터치)으로 인해 메일 발송은 거의 하지 않습니다.(이건 다른 사용자도 비슷한 부분이 있다고 생각합니다.)
POP3를 쓰는 분 보단 편하게 쓰고 있지요.

2. 연락처

다른 분들은 PC의 Outlook이나 예전 일반폰의 싱크 기능을 활용하시고, 내장 주소록을 많이 쓰시리라 생각합니다만, 전 내장 연락처에는 전혀 레코드가 없습니다.
단, 스마트폰이란 장점(?)으로 LDAP주소록을 사용하고 있습니다.
이로 인한 단점으로 한글의 특징인 자음 검색이 되지 않고, 주소록 등록은 PC에서만 하고 있습니다.(제 스마트폰이 LDAP주소록에 대한 등록을 지원하지 않아서… 단, 웹브라우저로 주소록을 등록하는 것은 가능하지요.)

3. 일정

일정 기능의 경우는 개인차도 있으리라 생각됩니다만, 전 대부분 일정을 기록하고 있습니다. 그런데, 스마트폰 자체의 일정을 사용하고, Outlook과 같은 PC버전에 싱크를 맞추는 것이 아닌. 예전부터 사용하던 웹캘린더를 스마트폰에서 구독만 하는 형태로 사용하고 있습니다.
이건. 저와 같이 부서 일정을 확인하는 사람에겐 유용한 기능이기도 합니다.(전 부서원들의 일정을 웹에 싱크하도록하고, 스마트폰(및 PC)으로 구독하여 일정을 확인하고 있습니다.)

4. TODO 및 메모

TODO의 경우 제 스마트폰에는 기본적으로 제공하지 않아 활용하지 못하고 있습니다. 하지만, PC에서도 TODO 목록의 경우는 제대로 감당하지 못했습니다. 메모의 경우는 간략한 기록만 스마트폰에 기록하며 항목을 10개 미만만 둡니다.
메모의 경우 제가 PC에서 사용하는 Tomboy에 많은 기록을 두고 있습니다.
Android의 경우 Tomboy 가 있는 것 같은데, 제 폰에는 없어서 아쉽지만 웹으로 보는 것만으로 만족하고 있습니다.

이상 위 내용은 스마트 폰에서 가장 기본적으로 제공해야할 기능으로 생각하는 것에 대한 내용입니다.

5. 소셜네트워킹

현재, twitter, facebook 을 사용하고 있고, 점차 소셜 서비스는 늘려가고 있습니다.( 최근에 four square 시작) 소셜 서비스를 통해서 인터넷 사람들의 소식을 들을 수 있고, 뉴스 제공자를 통해서 뉴스도 빠르게 접할 수 있어 좋습니다.( 소셜 서비스에서 뉴스를 접하고서는 뉴스 제공자 앱은 잘 쓰지 않게 된 것도 있습니다. )

6. 인터넷

스마트폰이 널리 퍼지면서 가장 좋은 점은 무선데이터를 저렴하고 빠르게 사용할 수 있는 점입니다. 그로 인해 저는 짬짬 인터넷을 둘러 보기도 하고, 블로그도 관리하는 등 인터넷 사용량이 꽤나 많은 편입니다. ( 물론 일반 인터넷 서핑보다는 앞서 열거된 서비스에 사용되는 데이터량이 더 많을 수도 있습니다. )

7. 위치 기반 서비스

스마트폰에 GPS가 포함되어 지도 검색 기능으로 간략한 네비게이션이 가능하고, 스마트폰이 아닌 분에게는 지도를 캡쳐하여 대략적인 위치 안내도 가능하게 되었습니다.

etc. podcast, 게임, 웹사이트앱, 날씨 등

제 스마트폰에는 자체 기본적으로 podcast를 들을 수 있게 되어 있습니다. 아직은 스마트폰에서 바로 podcast를 받지는 않고 PC에서 받아 듣지만, 꾸준히 듣고 있습니다.
게임은 잠시 시간죽이기 용으로는 좋은듯합니다.
그리고, 웹사이트 혹은 웹사이트 정보를 활용하는 앱등은 웹에 일일이 방문하여 정보를 찾는 것보다 편리하여 몇가지 쓰고 있습니다.
날씨도 간혹 참조는 합니다. ( 맞지 않는 경우가 있다보니 문제도 있지만. )


이 외에 다양한 기능이 있는데, 제가 쓰지 않는 기능은 다음과 같습니다.

인터넷뱅킹

현재도 몇몇 인터넷뱅킹은 공인인증서가 있어야 뱅킹이 가능한 것으로 보입니다. 조만간 공인인증서 없이 인터넷뱅킹이 가능한 은행으로 주거래은행을 바꾸고 나서나 사용할 예정입니다.

비디오

제 폰에는 자체 Youtube앱이 있지만, 3G 망을 주로 쓰다보니, 거의 대부분의 youtube동영상은 볼일이 없습니다. 그리고, 예전 피쳐폰에 있던 DMB도 관심이 없고, 일반적인 방송에는 관심이 없어 비디오를 볼일은 없습니다.
단, 영화를 받아 볼 수 있는 서비스가 있다면 좋을 것 같습니다. ( 배터리가 문제지만 )

기타

예전의 PIMS 혹은 다이어리 들이 제공하던 장식적인 기능들은 전혀 사용하지 않고 있습니다.
보안카드 관리용 앱이 있던데, 받아보지도 않았지만 OTP를 선호하여 의미 없어 보입니다.
가계부 앱도 있으리라 생각합니다만, PC버전을 몇년간 써온지라 아직도 PC에서 기록하고, 폰에는 잠시(하루지출) 정도의 기록만 임시로 기록합니다.