이 카테고리에는 더 이상 글이 올라오지 않습니다.


별도의 개발 블로그를 열어 개발에 관련된 이야기는 블로그를 분리하였습니다.

만약 더 많은 개발 이야기가 보고 싶으시다면 아래 링크로 이동해 주세요.


link : Digital Blue Eye's dev-ops

#######################################################################################################



EJB에서 Transaction을 처리하다 보면 아래와 같은 Exception이 발생하는 경우가 있습니다.

java.sql.SQLException: Cannot call Connection.commit in distributed transaction.
Transaction Manager will commit the resource manager when the distributed transaction is committed.


저도 아직 명확히 어느 부분의 셋팅이 문제가 된 것인지 찾아내지는 못했습니다.
2년전 프로젝트 진행할 때에는 해당 Exception이 떨어지지 않았는데 올해 유지보수에 들어가기 위해 개발환경을 다시 맞추다 보니 발생하더군요.

우선 원인은 transaction이 두번 발생하기 때문입니다.
EJB Containner는 자체적으로 Transaction Controller(이하 EJB TC)를 가지고 있습니다. 대부분 EJB를 사용하실 때는 이 EJB TC를 의지하게 되는데요. 저희처럼 이 EJB TC를 신뢰하지 못하고 프로그램에서 Transaction 처리를 할 경우 문제가 발생합니다.

EJB TC에 의해 Transaction이 처리된 상태에서 프로그램에서 commit()을 호출하거나 AutoCommit 설정을 true로 설정할 경우 두번의 Transaction이 발생하게 되는 것이죠.


이 문제의 해결방법은 EJB Build Configure인 ejb-jar.xml을 수정하는 것입니다.

ejb-jar.xml의 아래 부분을 찾아가 붉은 글씨 부분을 "NotSupported"로 수정해 주시면 됩니다. 대부분 "Required" 설정을 사용하실 겁니다.

<assembly-descriptor>

	<container-transaction>
		<method>
			<ejb-name>SrmSegmentationEJB</ejb-name>
			<method-intf>Remote</method-intf>
			<method-name>*</method-name>
		</method>
		<trans-attribute>NotSupported</trans-attribute>
	</container-transaction>

</assembly-descriptor>

사실 EJB TC를 사용하지 않으면 EJB를 사용하는 의미가 없다는 이야기까지 나오고는 합니다.

현재의 수많은 발전된 Framework들의 Transaction Control은 매우 성능이 좋습니다.
하지만 수년전 EJB의 그것은 그렇지 않은 모양이더군요.



어쨋든 저 Exception에 대해서는 설명과 같이 대처하시면 되겠습니다...^^


  1. 복덩이 2009.10.19 10:49

    웹로직8에서는 같은 소스로 에러없이 실행되었는데, 웹로직10에서는 con.commit()에서 에러가 나네요. 운영이다 보니, 모든 소스에 관계된 일이라 난해한 상태이구요. 헌데, NotSupported로 바꾸고서 프로그램 내 소스에서도 setAutoCommit(flase);와 con.commit(); 부분을 모두 주석처리하고 테스트해봤습니다. 에러없이 진행되지만 데이터가 들어가지 않을꺼라 예상했는데 데이터가 들어갔더군요..NotSupported로 설정하면 프로그램단에서 트랜잭션 처리를 해야한다고 생각하는데, 그 부분을 주석처리 했으므로, insert가 되지 않아야 한다고 생각했었습니다. 어딘가에서 처리를 해주고 있을까요? 그래서 데이터가 들어간 것일까요? 갈수록 헤매네요...

    • Favicon of https://blog.sz21c.com BlogIcon 제피르 2009.10.19 12:54 신고

      안녕하세요...^^

      음.. 제가 전체 소스를 보지 않은 상태에서 정확히 말씀드리기는 어려울 것 같지만... 아마도....

      setAutoCommit(false);를 주석 처리하셨다면 기본으로 auto commit이 활성화가 될겁니다. 그에 따라 JDBC 드라이버 단계에서 자동으로 commit이 실행된 것으로 보이네요.

      JDBC 드라이버에 의해 connection이 생성되면 commit 옵션의 기본은 auto commit 상태입니다. 이 auto commit이란 상태가 프레임워크에게 transaction 처리를 위임한다는 의미가 아닌, transaction이 발생했을 때 즉시 처리한다는 의미가 되는 것이죠.

      예를 들어 하나의 method에서 여러가지 transaction이 발생한 경우(delete 후 insert 등) JDBC connection이 auto commit 상태라면, delete 후에 commit, 다시 insert 후에 commit으로 각 transaction에 따라 개별 commit이 발생하게 될 겁니다.

      따라서 transaction을 수동제어하시기 위해서는 connection object를 사용하시기 전에 setAutoCommit(false)로 auto commit 상태를 변경해 주셔야 합니다.

+ Recent posts