Spring Security를 이용해 로그인 페이지를 구현하다가 /favicon.ico 페이지로 리다이렉트 되는 현상을 경험했다. 이 문제의 원인은 Spring Security의 문서에서 찾을 수 있었다.

Spring Security의 ExceptionTranslationFilter의 역할 중 하나는 인증 단계 진입 전에 최초 사용자의 요청을 캐싱 하고 있다가 사용자 인증 절차가 필요하여 인증 페이지로 이동 후 인증에 성공할 경우 캐싱된 페이지로 리다이렉트 시켜 준다.


-- from http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#request-caching


원래대로라면 사용자가 최초 요청한 url에서 인증 페이지로 리다이렉트 되며 사용자가 요청한 url이 캐싱되어야 하지만 많은 브라우저가 사용자 요청과 동시에 /favicon.ico 을 찾으려고 한번 더 리퀘스트를 하게 되고, 이 때 /favicon.ico에 대한 권한이 없다면 최초 요청한 url에서의 리다이렉트가 아닌 /favicon.ico에 대한 리다이렉트 페이지로 접근하게 되는 현상이었다.


이 문제는 간단하게 아래 처럼 /favicon.ico 리소스에 대해 접근 제한을 해제하면 해결할 수 있었다.


<intercept-url pattern="/favicon.ico" access="ROLE_ANONYMOUS" />

Posted by 제리곰
,

기존의 Spring Framework기반의 Application을 개발하다 보면 꽤 많은 시간을 Application 설정하는데에 소비하곤 했다. 보통은 내게 익숙한 스타일의 설정이 아니어서이기도 하였고, 가끔은 그 설정이 잘못되어 수정하는데 시간을 보내기도 했다.


가끔은 library 의존성에 의해 설정 오류가 발생하기도 하였지만, 대부분의 경우 설정에 시간을 쏟은 원인은 동일한 Spring Application 설정을 하는 방법이 Xml기반, Annotation기반, 그리고 Java Configuration기반이 존재하기 때문이었다. 하나의 동일한 설정을 하기 위한 방법이 무궁무진하게 존재하여 프로젝트마다 다른 설정이 적용되는 경우도 있었고, 새로운 기술을 도입하기 위해 참고자료들을 찾아 적용해 보려 하는데 예제가 특정 형태의 환경설정만 사용하고 있어 다른 스타일로 변경하기 위한 시간을 쏟기도 했다. 가끔은 그 스타일 변환이 쉽게 되지 않아 스타일을 섞어서 사용하게 되었고, 그 경우 예상치 못한 side-effect를 발생시키기도 하였다.


이러한 점 때문에 Spring Application 설정에 대해 좀 더 자세히 찾아보기로 하였고, 그에 앞서 각각의 Application Configuration 방법의 장단점에 대해 정리한 포스팅이 있어 이를 간단히 소개하고자 한다. 



이하 내용은 http://www.javacodebook.com/2013/07/08/spring-book-chapter-5-application-configuration-simplified/ 에서 발췌함.


Configuration Type 장점 단점
XML
  • Class파일들과 설정을 분리할 수 있고, 관심사의 분리(Separation of concerns) 관점이 적용된다.
  • 설정을 한눈에 보기에 용이하다.
  • 간단한 설정 변경은 별도의 컴파일 없이도 적용 가능하다.
  • 오타가 발생했을 때 debugging이 어렵다.
    (역주: 최근의 IDE들은 잘 잡아주기도 한다.)
  • XML의 값 들은 모두 String형이기 때문에 type safe하지 않다. 또한 Java Context에서 이 값들을 적절한 Java type으로 변환하는 과정에 JVM에 부하가 생긴다.
Annotation-based
  • Java code로 설정을 하기 때문에 type safe하며, Spring이 빠르게 container를 설정하게 한다.
  • Annotation이 클래스(또는 메소드) 상단에 추가되면서 설정이 구성되기 때문에 클래스 파일만 보아도 어떤 스프링 설정이 적용된 클래스인지 한눈에 알 수 있다.
  • POJO 개념을 흐트러놓는다.
  • 설정이 변경될 경우 Application code 클래스 파일까지 수정해 주어야 한다.
  • 변경사항이 있을 경우 컴파일이 필요하다.
Java Configuration
  • Java code로 설정을 하기 때문에 type safe하며, Spring이 빠르게 container를 설정하게 한다.
  • 설정이 별도의 class file로 분리되어 관심사의 분리(separation of concerns) 관점이 적용된다.
  • Application Configuration을 나타내기 위해 Single resource 가 사용된다.
  • For systems which needs change constantly, configuration can change without changing the application code which is key for such systems.
  • 변경사항이 있을 경우 컴파일이 필요하다.

결론적으로 Java Configuration을 이용한 Spring Application 방법이 여느 다른 방법에 비해 단점이 적은 방법이다. 하지만 그렇다고 다른 방식의 설정 방법을 무시해버릴 수는 없다. (역주. 다른 설정방법에 대해 고려해야 하는 이유는 많은 legacy code들은 여전히 xml 또는 annotation기반의 설정을 이용하고 있고, 그리고 경우에 따라서는 각각의 설정 방법이 갖고 있는 장점을 살리는 설정도 효과적이기 때문일 것이다.)


'Spring Framework' 카테고리의 다른 글

[troubleshooting] Spring Security redirect to /favicon.ico  (0) 2015.01.21
Posted by 제리곰
,

본 포스팅은 아래의 포스트를 참조하여 작성되었습니다.

http://amitstechblog.wordpress.com/2011/05/20/spring-transactions-behavior-on-private-and-internal-methods/



스프링 트랜잭션의 기본 모드인 proxy 모드에서는 오직 외부로부터의 method 호출이 발생한 경우에만 method가 인터셉트 되어 트랜잭션 관리가 적용된다. 즉, 다시 말해서 오브젝트 내의 한 method가 동일 오브젝트 내의 다른 method를 호출할 경우에는 피 호출 method에 @Transactional 어노테이션이 명시되어 있더라도 실행시 트랜잭션이 스프링에 의해 관리되지 않는다.


-from reference document@spring.io , 발번역


Private Method에서의 @Transactional

스프링 트랜잭션의 기본 모드에서는 private method에 @Transactional 을 붙여 봐야 스프링이 트랜잭션을 관리해 주지 않습니다. 다시 말해, @Transactional annotation 을 non-public(public visibility가 아닌 protected, private, package) method에 적용할 경우 실행시 따로 에러가 발생하지는 않지만 트랜잭션 정책이 적용되지 않습니다. 만약 이러한 non-public method에 @Transactional을 적용하려 한다면 프록시 대신 AspectJ 방식을 고려해 봐야 합니다.


Internal Method에서의 @Transactional 


public visiblilty를 가진 method지만 object 내부의 다른 method에 의한 호출로 수행되는 경우에는 private method와 마찬가지로 @Transactional 정책이 적용되지 않습니다.




결론


위 내용을 간단히 요약하면 다음과 같습니다.

  1. @Transctional은 프록시 모드로 동작한다.
  2. 그래서 외부에서 오브젝트 내의 method에 들어갈때와 나올때 적용된다. 
  3. 오브젝트 내부 호출은 적용되지 않기 때문에 Private method, Internal called Method는 @Transactional에 의한 스프링 트랜잭션 관리가 되지 않는다.


Posted by 제리곰
,


본 포스팅은 아래의 내용을 대충 한글화 하는데 초점을 맞췄다.

https://blog.codecentric.de/en/2012/03/transactions-in-spring-batch-part-1-the-basics/

본문 내 모든 이미지는 위 링크에서 참조하였다.



Spring Batch에서 생각해야 할 Transaction 개념에 대해 정리해 본다.


일반적인 어플리케이션의 경우 사용자의 액션을 기준으로 하나의 액션에 하나의 트랜잭션을 생각하면 된다. 하지만 배치 어플리케이션의 경우에는 다량의 데이터를 처리하는 배치 전체 프로세스를 트랜잭션으로 묶게 되면 데이터베이스에 무리가 될 수 있기 때문에 중간에 작업 데이터에 대한 커밋이 일어나야 한다. 만약 배치를 재실행해야 하거나 수동으로 실행해야 하는 등의 기능이 제공되어야 할 경우에는 중간에 이미 커밋된 데이터에 대해 어떻게 처리해야 할지 생각해 봐야 한다.


이하 설명은 단일 쓰레드로 이루어진 Chunk Oriented Processing에 대해 진행한다.


Chunk Oriented Steps



Chunk Oriented Processing Step은 다음과 같다.

  1. ItemReader는 item이 없을 때 까지 하나씩 item을 어딘가에서 read 한다.
  2. ItemProcessor는 item 각각에 대해 특정 process를 진행한다.
  3. ItemWriter는 item list를 받아 어딘가로 write한다.

배치 프로세스는 Chunk 단위로 구분되며 이 Chunk단위로 하나의 트랜젝션이 형성된다. exception이 발생할 경우, 해당 Chunk는 롤백이 된다. 당연히 이전에 커밋한 Chunk는 완료된 상태가 유지된다. Chunk 단위는 CompletionPolicy에 의해 결정되며 그림 속의 1번과 같이 read 단계에서 CompletionPolicy 조건이 만족될 경우 item이 남아있더라도 하나의 Chunk 단위로 묶여 다음 단계인 process 단계로 넘어가게 된다.

CompletionPolicy는 다음과 같이 설정할 수 있다.

  • commit-interval 속성을 설정할 경우, SimpleCompletionPolicy가 적용되며, 지정한 갯수의 item이 chunk단위로 묶인다.
  • CompletionPolicy에 chunk-completion-policy 속성을 지정하여 추가로 커스터마이징 할 수도 있다.

Business data and batch job data



Spring Batch는 기본적으로 몇몇 table definition을 제공한다. 이 곳에는 배치 히스토리 관리나 배치 프로세스 재시작에 이용될 수 있는 job, step, 실행 context가 저장된다. 배치 프로세스 상에서 저장되는 부분은 위 그림에 표시되어 있다. 이러한 정보를 Business data가 들어있는 DB와는 다른 별도의 DB에 저장할 수 있지만, JtaTransactionManager, DataSources등을 따로 지정해줘야 하고, 각각의 DB에 연결해야 하는 성능상 이슈 등이 발생할 수 있으므로 보통 추천하지는 않는다.


A Failted Batch

배치가 실패했을 경우를 좀 더 자세히 살펴보면 다음과 같다.



Chunk 단위 내에서 exception이 발생할 경우 rollback이 발생하고 해당 step 및 해당 batch job은 fail상태로 기록된다. job data 기록부분은 별도의 transaction으로 묶여있기 때문에 기록이 가능하다. 만약 특정 exception의 경우 무시하고 진행하길 원할 경우 아래처럼 no-rollback-exception-class에 해당 exception을 등록해 주면 된다.


<batch:tasklet>
  <batch:chunk ... />
  <batch:no-rollback-exception-classes>
    <batch:include class="some.ignoreable.MyRuntimeException"/>
  </batch:no-rollback-exception-classes>
</batch:tasklet>


Transaction Attributes

각 transaction에 대해 지정할 수 있는 속성은 다음과 같다.

  • Propagation Type ( 기본 : REQUIRED)
  • Isolation Level ( 기본 : DEFAULT)
  • Timeout
<batch:tasklet>
  <batch:transaction-attributes isolation="READ_COMMITTED" propagation="REQUIRES_NEW" timeout="200"/>
  <batch:chunk reader="myItemReader" writer="myItemWriter" commit-interval="20"/>
</batch:tasklet>


Posted by 제리곰
,