DataBase 연동(WAS 또는 Webapplication에서 생성한 DB connection 사용 및 transaction 처리)

외부 connection 사용하기

difingo는 mashup.msh 에  DataBase 등의 외부 연결 정보를 입력 하고 이를 기반으로 동작 합니다.
하지만 프로젝트의 성격에 따라 WAS 또는 web application에서 생성한 connection을 사용해야 하는 경우가 발생 하고 이번 장에서는 이런 경우 적용 할 수 있는 방법에 대해 기술 합니다.
구조
difingo에서 외부의 DataBase connection을 사용하는 방법으로는 "ExternalDataSourceProvider" 인터페이스를 구현 하여 이를 XIServiceController에 인자로 넘겨 주면 동작 하게 됩니다. 

이때 difingo  내부에서는 mashup.msh 에 정의된 이름을 인자로 "ExternalDataSourceProvider.getDataSource" 메소드를 인자로 호출 하며 호출 결과가 
"javax.sql.DataSource"일 경우 해당 DataSource 의  "getConnection" 메소드를 호출 하여 반환된 "java.sql.Connection"을 사용하게 됩니다.

DB Connection을 사용하는 우선 순위를 정리 하면 다음과 같습니다.
1. ExternalDataSourceProvider
2. mashup.msh

 보통의 경우 ExternalDataSourceProvider를 정의 하지 않았을 경우  mashup.msh 에 정의한 정보가 사용됩니다.


transaction 정책은 ExternalDataSourceProvider와 mashup.msh에 정의 하는 방법 모두 동일합니다.

소스코드

ExternalDataSource를 XIServiceController 에 설정 하는 코드는 아래와 같습니다.

XIServiceController x = new XIServiceController();
		
MyExternalDataSourceProvider exp = new MyExternalDataSourceProvider();

DataSource ds1;
DataSource ds2;
try
{	
	InitialContext initialContext = new InitialContext();
	ds1 = (DataSource) initialContext.lookup("java:comp/env/DS_DEVPACK");
    ds2 = (DataSource) initialContext.lookup("java:comp/env/DS_DEVPACK_MARIA");			
	exp.setDS_DEVPACK(ds1);
	exp.setDS_DEVPACK_MARIA(ds2);
	x.setExternalDataSourceProvider(exp);
} catch (NamingException e) {
			
}

위의 코드는 Servlet의 경우 init 메소드 또는 Spring의 경우 ApplicationContextAware와 같이 초기에 한번 실행 되는 영역에서 선언합니다.

아래의 코드는 ExternalDataSourceProvider 구현 예제 입니다.

아래와 같이 mashup.msh에 정의된 datasource 이름이 
"DS_DEVPACK" 과 "DS_DEVPACK_MARIA" 일 경우 구현되는 ExternalDataSourceProvider.getDataSource() 메소드에서 정의된 이름에 해당하는 javax.sql.DataSource를 반환 하도록 구현합니다.

class MyExternalDataSourceProvider implements ExternalDataSourceProvider
{

	
		DataSource DS_DEVPACK;
		
		DataSource DS_DEVPACK_MARIA;
		
		public DataSource getDS_DEVPACK() {
			return DS_DEVPACK;
		}
		
		public void setDS_DEVPACK(DataSource dS_DEVPACK) {
			DS_DEVPACK = dS_DEVPACK;
		}
		
		public void setDS_DEVPACK_MARIA(DataSource DS_DEVPACK_MARIA) {
			DS_DEVPACK_MARIA = DS_DEVPACK_MARIA;
		}
		
		@Override
		public Object getDataSource(String arg0) {
			
			
			if(arg0.equals("DS_DEVPACK")) {
				return DS_DEVPACK;
			} 
			else if(arg0.equals("DS_DEVPACK_MARIA")) {
				return DS_DEVPACK_MARIA;
			}
			else
			{
				return null;
			}
			
			
		}
		
}

Commit & Rollback 처리

difingo의 경우 engine에서 transactino 즉 commit & rollback은 자동 처리 됩니다.
commit과 rollback이 실행되는 경우는 아래와 같습니다.
       commit
            - 정상적으로 서비스가 동작 되었다고 판단 되는 경우.
      rollback
            - 서비스가 비정상 실행 되었다고 판단 하는 경우.
                    - Exception이 발생 하는 경우.
                    - 서비스 결과에서 ErrorCode 파라미터가 존재 하며 값이 음수인 경우.


하지만 서비스의 특성 상 commit과 rollback을 서비스 내에서 처리 해야 할 경우에 아래의 코드를
User method 기능을 이용하여 개발자가 직접 commit과 rollback을 수행 할 수 있습니다.
try {
      // datasource의 이름을 이용하여 Db Connection을 획득 합니다.
      Connection conn = getConnection("DataSource 이름");  
      // 획득한 connection은 wrapper로 씌워져 있어서 
      // Wrapper에서 orgin connection을 얻기 위해 type casting 후 
      // connection 객체를 획득 합니다.
  	  DbcpConnectionWrapper wrapper = (DbcpConnectionWrapper)conn; 
 	  Connection originConnection = wrapper.getConnection();
      // 이후 아래와 같이 commit과 rollback을 수행 하실 수 있습니다.
 	  //originConnection.commit(); 
	  //originConnection.rollback();
	} catch (InvalidDataSourceException e) {
			throw new AutomationFailException( e.getMessage() , e);
	} catch (SQLException e) {
		    throw new AutomationFailException( e.getMessage() , e);
	}