Skip to content

fix(codegen): JTA·JPA 트랜잭션 마법사가 선언되지 않은 체크박스로 tx:advice·aop:config 생성을 막는 문제 수정 - #154

Merged
eGovFrameSupport merged 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/tx-wizard-advice-guard
Sep 18, 2026
Merged

eGovFrameSupport merged 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/tx-wizard-advice-guard

Conversation

@wantaekchoi

@wantaekchoi wantaekchoi commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

수정 사유 Reason for modification

  • 버그수정 Bug fixes
  • 기능개선 Enhancements
  • 기능추가 Adding features
  • 기타 Others

수정된 소스 내용 Modified source

eGovFrameTemplates/transaction 의 jta.vm·jpa.vm 은 tx:advice 와 aop:config 블록 전체를 #if(${chkConfigurationalTransactionManagement}) 로 감쌉니다. 그런데 그 이름의 컴포넌트를 선언하는 마법사는 transaction.xml 뿐입니다.

$ git grep -n 'chkConfigurationalTransactionManagement' origin/main -- egovframework.dev.imp.codegen.template.templates/eGovFrameTemplates/transaction
origin/main:egovframework.dev.imp.codegen.template.templates/eGovFrameTemplates/transaction/jpa.vm:18:#if(${chkConfigurationalTransactionManagement})
origin/main:egovframework.dev.imp.codegen.template.templates/eGovFrameTemplates/transaction/jta.vm:24:#if(${chkConfigurationalTransactionManagement})
origin/main:egovframework.dev.imp.codegen.template.templates/eGovFrameTemplates/transaction/transaction-java.vm:28:#if(${chkConfigurationalTransactionManagement})
origin/main:egovframework.dev.imp.codegen.template.templates/eGovFrameTemplates/transaction/transaction-java.vm:50:#if(${chkConfigurationalTransactionManagement})
origin/main:egovframework.dev.imp.codegen.template.templates/eGovFrameTemplates/transaction/transaction.vm:20:#if(${chkConfigurationalTransactionManagement})
origin/main:egovframework.dev.imp.codegen.template.templates/eGovFrameTemplates/transaction/transaction.xml:29:				<checkbox name="chkConfigurationalTransactionManagement"
origin/main:egovframework.dev.imp.codegen.template.templates/eGovFrameTemplates/transaction/transaction.xml:42:			condition="$chkConfigurationalTransactionManagement">

Velocity 컨텍스트를 채우는 경로는 마법사 컴포넌트와 마법사 XML 의 <variables> 섹션인데, 이 저장소에는 <variables> 를 쓰는 마법사가 없습니다. 그래서 jta·jpa 쪽 참조는 항상 미정의이고 두 블록은 렌더되지 않습니다. transaction 은 같은 파일이 체크박스를 선언하고 2쪽 페이지를 그 값으로 묶어 정상 동작합니다.

jta.xml·jpa.xml 의 2쪽 Configurational Transaction Management 페이지에는 그 condition 이 없습니다. 페이지가 언제나 마법사에 들어가므로 그 안의 PointCut Name·PointCut Expression·Advice Name·Method Name 값도 언제나 컨텍스트에 실립니다. 그런데 Configuration Type 을 XML 로 고르면 그 값이 결과 파일에 하나도 남지 않습니다.

JTA 는 jta.xml 에 chkAnnotationTransactionManagement 가 선언돼 있어 <tx:annotation-driven> 은 지금도 생성됩니다. 손실되는 것은 2쪽에서 필수로 받은 PointCut·Advice 입력입니다. JPA 는 두 체크박스가 모두 미선언이라 생성된 파일에 tx:·aop: 요소가 하나도 없고 jpa.vm 이 선언한 두 네임스페이스가 미사용으로 남습니다.

같은 마법사의 Java Config 분기는 같은 입력을 조건 없이 씁니다.

jta-java.vm:62:    @Bean(name = "${txtAdviceName}")
jta-java.vm:100:		txMethods.put("${txtMethodName}", txAttribute);
jta-java.vm:111:		pointcut.setExpression("${txtPointCutExpression}");
jpa-java.vm:67:    @Bean(name = "${txtAdviceName}")
jpa-java.vm:94:		txMethods.put("${txtMethodName}", txAttribute);
jpa-java.vm:105:		pointcut.setExpression("${txtPointCutExpression}");

egovframework.dev.imp.templates 에 남아 있는 같은 템플릿의 이전 사본에도 이 게이트가 없습니다 — 그 트리의 src/main/resources/eGovFrameTemplates/transaction/jta.vm 은 22행 aop:config·27행 tx:advice, jpa.vm 은 18행 tx:advice·24행 aop:config 를 조건 없이 두고 있습니다. 게이트만 들어오고 체크박스가 따라오지 않은 것으로 보입니다.

AS-IS (jta.vm, jpa.vm)

#if(${chkConfigurationalTransactionManagement})
	<!-- AOP 설정 - 트랜잭션 관리 및 포인트컷 설정 -->
	<tx:advice id="${txtAdviceName}" transaction-manager="${txtTransactionName}">
[...]
	</aop:config>
#end

TO-BE

	<!-- AOP 설정 - 트랜잭션 관리 및 포인트컷 설정 -->
	<tx:advice id="${txtAdviceName}" transaction-manager="${txtTransactionName}">
[...]
	</aop:config>

jta.xml·jpa.xml 에 체크박스를 선언하고 2쪽 페이지에 condition 을 다는 방향도 생각했습니다. 그러나 위 Java Config 분기가 그 값을 무조건 쓰기 때문에 체크를 끈 사용자에게는 @Bean(name = "") 이 생성됩니다. transaction 쌍은 정본 트리의 transaction-java.vm 28·50행이 같은 변수로 함께 묶여 있어 성립하지만 jta·jpa 는 그렇지 않습니다. 그래서 XML 분기의 #if·#end 만 걷어내 형제 Java 출력 및 이전 사본과 결과를 맞췄습니다.

영향 범위

정본 트리 jpa.vm 46행의 #if(${chkAnnotationTransactionManagement}) 는 그대로 두었습니다. 이 게이트는 걷어낸 쪽과 형제 근거가 반대입니다 — jta-java.vm 30행이 @EnableTransactionManagement 를 같은 체크박스로 감싸므로 조건부가 선례이고, 정작 짝인 jpa-java.vm 33행은 조건 없이 둡니다. 게이트를 걷어내는 쪽과 jpa.xml 에 체크박스를 더하는 쪽 중 어느 것이 맞는지 이 비대칭만으로는 정해지지 않아 이번 diff 에 섞지 않았습니다.

jpa.xml 이 required="false" value="Exception" 으로 받는 txtRollbackFor 도 게이트인 chkRollbackFor 가 미선언이라 tx:method 에 rollback-for 가 붙지 않습니다. 선택 속성이라 이번 변경만으로 생성되는 설정은 유효하고, 이것도 체크박스를 더해야 하는 별개 사안입니다.

egovframework.dev.imp.templates 의 사본은 위와 같이 이 게이트가 없어 고칠 것이 없습니다.

JUnit 테스트 JUnit tests

  • JUnit 테스트 JUnit tests
  • 수동 테스트 Manual testing

이 플러그인 트리에는 테스트 소스가 없어 저장소가 함께 싣는 egovframework.dev.imp.codegen.template/lib/velocity-1.4.jar 로 템플릿을 직접 렌더해 확인했습니다. 컨텍스트는 손으로 적지 않고 해당 마법사 XML 의 컴포넌트에서 뽑습니다. egovframework.dev.imp.templates 의 TemplateCodeGenTest 는 그 모듈 안의 사본을 골든파일과 대조하므로 이 변경을 덮지 않고, 이 트리에 전례가 없는 검사라 하네스는 커밋에 넣지 않았습니다.

가설: chkConfigurationalTransactionManagement 는 두 마법사의 컨텍스트에 존재하지 않으므로 두 블록은 어떤 입력으로도 렌더되지 않는다.

eGovFrameTemplates/transaction 에서 vm 이 참조하는 변수에서 xml 이 선언하는 변수를 빼면 확인됩니다(Java 불필요).

$ for w in jta jpa transaction; do
>   grep -o '\${*[A-Za-z][A-Za-z0-9_]*' $w.vm | tr -d '${' | sort -u > /tmp/v
>   { grep -o 'name="[A-Za-z0-9_]*"' $w.xml | sed 's/name="//;s/"//'
>     grep -o '\[\[CHECK\][A-Za-z0-9_]*' $w.xml | sed 's/\[\[CHECK\]//'; } | sort -u > /tmp/d
>   echo "$w: $(comm -23 /tmp/v /tmp/d | tr '\n' ' ')"
> done
jta: chkConfigurationalTransactionManagement 
jpa: chkAnnotationTransactionManagement chkConfigurationalTransactionManagement chkNoRollbackFor chkReadOnly chkRollbackFor chkTimeout txtNoRollbackFor txtTimeout 
transaction: 

정상 동작하는 transaction 만 차집합이 비어 있습니다. 수정 후 같은 명령의 출력입니다.

jta: 
jpa: chkAnnotationTransactionManagement chkNoRollbackFor chkReadOnly chkRollbackFor chkTimeout txtNoRollbackFor txtTimeout 
transaction: 

수정 전 렌더 결과입니다. 컨텍스트 키 목록에 chkConfigurationalTransactionManagement 가 없고 tx:advice·aop:config 가 출력에 나타나지 않습니다.

$ ./run.sh jta.xml jta.vm
# wizard      : jta.xml
# template    : jta.vm
# context keys: 22 [chkAnnotationTransactionManagement, chkNoRollbackFor, chkReadOnly, chkRollbackFor, chkTimeout, cmbIsolation, cmbJTAImplementationType, cmbPropagation, rdoConfigType, txtAdviceName, txtClassName, txtConfigPackage, txtFileName, txtGlobalTimeout, txtMethodName, txtNoRollbackFor, txtPath, txtPointCutExpression, txtPointCutName, txtRollbackFor, txtTimeout, txtTransactionName]
[...]
	<bean id="tansactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
		<property name="userTransaction" ref="userTransaction"></property>
		<property name="transactionManager" ref="atomikosTransactionManager"></property>
	</bean>


	<tx:annotation-driven transaction-manager="tansactionManager" proxy-target-class="true" />

</beans>

---------------- assertions ----------------
  FAIL rendered output contains [tx:advice]
  FAIL rendered output contains [aop:config]
  FAIL rendered output contains [txAdvice]
  FAIL rendered output contains [requiredTx]
  FAIL rendered output contains [execution(* egovframework.com..*Impl.*(..)) or execution(* org.egovframe.rte.fdl.excel.impl.*Impl.*(..))]
RESULT: FAIL
EXIT=1

$ ./run.sh jpa.xml jpa.vm
[...]
---------------- assertions ----------------
  FAIL rendered output contains [tx:advice]
  FAIL rendered output contains [aop:config]
  FAIL rendered output contains [txAdvice]
  FAIL rendered output contains [requiredTx]
  FAIL rendered output contains [execution(* egovframework.sample..*Impl.*(..))]
RESULT: FAIL
EXIT=1

수정 후 같은 입력의 렌더 결과입니다.

$ ./run.sh jta.xml jta.vm
[...]
	<!-- AOP 설정 - 트랜잭션 관리 및 포인트컷 설정 -->
	<tx:advice id="txAdvice" transaction-manager="tansactionManager">
		<tx:attributes>
			<tx:method name="*"
				rollback-for="Exception"
				propagation="REQUIRED"
				isolation="DEFAULT" />
		</tx:attributes>
	</tx:advice>

	<aop:config proxy-target-class="true">
		<aop:pointcut id="requiredTx" expression="execution(* egovframework.com..*Impl.*(..)) or execution(* org.egovframe.rte.fdl.excel.impl.*Impl.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="requiredTx" />
	</aop:config>

	<tx:annotation-driven transaction-manager="tansactionManager" proxy-target-class="true" />

</beans>

---------------- assertions ----------------
  ok   rendered output contains [tx:advice]
  ok   rendered output contains [aop:config]
  ok   rendered output contains [txAdvice]
  ok   rendered output contains [requiredTx]
  ok   rendered output contains [execution(* egovframework.com..*Impl.*(..)) or execution(* org.egovframe.rte.fdl.excel.impl.*Impl.*(..))]
RESULT: PASS
EXIT=0

$ ./run.sh jpa.xml jpa.vm
[...]
---------------- assertions ----------------
  ok   rendered output contains [tx:advice]
  ok   rendered output contains [aop:config]
  ok   rendered output contains [txAdvice]
  ok   rendered output contains [requiredTx]
  ok   rendered output contains [execution(* egovframework.sample..*Impl.*(..))]
RESULT: PASS
EXIT=0

테스트 브라우저 Test Browser

  • Chrome
  • Firefox
  • Edge
  • Safari
  • Opera
  • Internet Explorer
  • 기타 Others

이클립스 플러그인의 코드 생성 템플릿이라 브라우저 테스트는 하지 않았습니다.

테스트 스크린샷 또는 캡처 영상 Test screenshots or captured video

화면 변경이 없어 위 출력으로 대신합니다.

…dvice·aop:config 를 막던 문제 수정

jta.vm 과 jpa.vm 은 두 블록을 #if(${chkConfigurationalTransactionManagement}) 로 감싸는데
그 이름의 컴포넌트가 jta.xml·jpa.xml 에 없다. VelocityContext 를 채우는 경로는 마법사
컴포넌트와 마법사 XML 의 <variables> 섹션인데 이 저장소에는 <variables> 를 쓰는 마법사가
없어 이 참조는 항상 미정의다. 같은 이름을 쓰는 transaction.xml 은 이 체크박스를
value="true" 로 선언한다.

두 마법사의 2쪽 페이지는 condition 없이 항상 열려 PointCut Expression·Advice Name 값이
언제나 컨텍스트에 실리는데, XML 을 고르면 그 값이 출력에 하나도 남지 않는다. JPA 는
chkAnnotationTransactionManagement 도 선언돼 있지 않아 트랜잭션 설정이 통째로 비어 나온다.
형제인 jta-java.vm·jpa-java.vm 과 egovframework.dev.imp.templates 의 이전 사본은 두 블록을
조건 없이 렌더하므로, XML 분기의 #if·#end 만 걷어낸다.
@eGovFrameSupport
eGovFrameSupport merged commit a16cdb7 into eGovFramework:main Sep 18, 2026
1 check passed
@wantaekchoi
wantaekchoi deleted the fix/tx-wizard-advice-guard branch September 18, 2026 05:57
swanpark8538 added a commit that referenced this pull request Sep 18, 2026
…체크박스를 선언

jpa.vm 은 tx:annotation-driven 을 chkAnnotationTransactionManagement 로, tx:method 의
rollback-for 를 chkRollbackFor 로 감싸지만 jpa.xml 은 둘 다 선언하지 않아 XML 출력에서
두 설정이 항상 빠졌다. 형제인 jta.xml 은 첫 페이지에 체크박스를 두고 rollback-for 를
[[CHECK]chkRollbackFor:true] 체크 텍스트필드로 받는다.

jta 와 같은 방식으로 jpa.xml 에 두 체크박스를 선언한다(기본값 켬). Java 분기 jpa-java.vm 은
같은 값을 조건 없이 쓰고 있었으므로, 체크를 끈 사용자에게도 XML 과 같은 결과가 나오도록
@EnableTransactionManagement 와 rollback 규칙을 jta-java.vm 과 같은 #if 로 감싼다.

Refs: #154
swanpark8538 added a commit that referenced this pull request Sep 18, 2026
egovframework.dev.imp.templates 의 eGovFrameTemplates 사본은 플러그인 원본과 57개
파일이 어긋나 있어 #153·#154 와 그 후속 jpa.xml 수정도 반영되지 않았다. ant/build.xml 과
같은 규칙(사본 삭제 후 복사, model 전체와 NamingUtils)으로 사본을 다시 채운다. Java 5개는
저작권 헤더만 바뀐다.

사본이 바뀌면 TemplateCodeGenTest·CrudCodeGenTest 의 골든파일이 옛 출력이라 28건이
깨지므로 같은 입력으로 다시 생성한 결과로 교체한다. 템플릿에 새로 생긴 변수와 jta·jpa 가
새로 선언한 체크박스는 마법사 기본값을 값 파일에 추가해 미해석 참조가 남지 않게 했다.

플러그인에서 사라진 템플릿을 가리키던 테스트 5건은 9d3f8d5 와 같은 기준으로 정리한다.
jeus.vm → jndiDatasource.vm, transaction/datasource.vm → transaction.vm,
dailyRollingFile.vm → timeBasedRollingFile.vm 으로 마법사가 실제로 쓰는 템플릿에 맞추고,
대응 템플릿이 없는 egovDb·egovJdbc 어펜더 테스트는 골든·값 파일과 함께 제거한다.
대소문자만 다르던 DailyRollingFile.properties·jndiDataSource.xm 도 테스트가 참조하는
이름으로 맞춘다.

Refs: #153, #154
@swanpark8538

Copy link
Copy Markdown
Collaborator

Velocity 템플릿 오류 수정 감사합니다.

PR Review 과정에서 유사한 다른 오류를 발견하여
추가 작업을 진행했습니다.
Ref: 2f5fbde

전자정부 표준프레임워크에 기여해 주셔서 감사합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants