[Spring] SessionStatus는 어떻게 동작할까?

JAVA/Spring|2020. 9. 8. 17:02

Spring MVC 에서 SessionStatus 라는것이 존재합니다.

(현재는 대부분의 서비스회사들이 Session을 사용하지 않기 때문에 사용하지 않는 회사들은 무의미 할수 있겠네요)

 

SessionStatus는 @SessionAttributes를 활용해 Session에 남긴 데이터를 정리하는데 활용을 하는 인터페이스 입니다.

(Controller에 args로 선언해두면 injection이 되며 정리는 setComplete() 를 통해 정리 flag를 세팅합니다.)

 

SessionStatus 에 setComplete()를 호출하게 되면 내부적으로 complete boolean을 세팅하게 되고

RequestMappingHandlerAdapter에서 modelFactory의 updateModel() 내부에서 대상 attribute들을 정리하게 됩니다.

 

여기서 @SessionAttributes이 등장하는데

 

@SessionAttributes는 names를 args로 받게 되고

지정된 names들에 대해서 model에 접근하면 기존 model 저장소가 아닌 Session 영역까지 확장되도록 도움을 줍니다.

 

 

model.addAttribute("dutch", "hello");

 

일반적으로 위 코드 처럼 "dutch" 라는 키로 model에 세팅하면

응답 이후 값이 삭제 됩니다.

 

하지만 컨트롤러 클래스 상단에  @SessionAttribues 를 세팅 후 사용한다면 동작이 변경되게 됩니다.

@RequestMapping("dutch")
@Controller
@SessionAttributes("dutch")
public class DutchController

@SessionAttributes선언 후 model.addAttribute 를 호출한다면 해당 key,value가 Session에 저장 되고,

다음 요청이 동일 세션으로 왔을때 session의 Key를 "dutch"로 조회하면 addAttribute값이 존재하는것을 볼 수 있습니다. 그리고 model을 통해 "dutch"를 조회했을때도 값이 존재하는것을 확인 할 수 있습니다.

 

주의해야할 사항은 해당 컨트롤러가 아닌, 다른 컨트롤러에서 모델에서 "dutch"으로 값을 얻으려 시도하면

값이 들어 있지 않습니다.

위의 컨트롤러의 경우에는 model에 "dutch" 에 해당하는 값을 줘! 라고 하면 @SessionAttributes가 설정되어있는 Key는 Session에서 값을 찾지만

@SessionAttributes("dutch") 가 달려있지 않은 컨트롤러에서 model에 ""dutch" 에 해당하는 값을 줘!" 라고 한다면

Session에서 찾는게 아니라 정말 model에서 찾기 때문에 값이 존재 하지 않습니다.

 

 

 

'JAVA > Spring' 카테고리의 다른 글

SpringBoot App에 외부 libs 추가  (0) 2023.11.19
[JPA] LockType  (0) 2020.07.23
[Spring] LifeCycle, SmartLifeCycle  (0) 2020.06.23
[MSA] sidecar 패턴  (0) 2020.01.13
[SpringConfig] Properties 암호화  (0) 2019.12.24

댓글()

[Spring] Spring Batch Tasklet

JAVA/SpringBatch|2020. 2. 25. 20:07

ETL이나 각종 기능들은 결국 Tasklet을 구현하여 제공하는 기능들이며

Tasklet은 execute(S,C) 메소드 만을 제공합니다.

 

/**
* Given the current context in the form of a step contribution, do whatever
* is necessary to process this unit inside a transaction. Implementations
* return {@link RepeatStatus#FINISHED} if finished. If not they return
* {@link RepeatStatus#CONTINUABLE}. On failure throws an exception.
* 
* @param contribution mutable state to be passed back to update the current
* step execution
* @param chunkContext attributes shared between invocations but not between
* restarts
* @return an {@link RepeatStatus} indicating whether processing is
* continuable. Returning {@code null} is interpreted as {@link RepeatStatus#FINISHED}
*
* @throws Exception thrown if error occurs during execution.
*/
@Nullable
RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception;

결국 리턴이 RepeatStatus.FINISHED(혹은 null) 로 리턴되면 마치게 되고 RepeatStatus.CONTINUABLE 의 경우에는 execute를 다시 호출하게 됩니다

(리턴값을 RepeatStatus.CONTINUABLE로 계속 반환하면 무한히 돌겠죠..)

 

 

Spring Batch에서 Tasklet을 imple하여 제공하고 있는 클래스 및 interface는 아래와 같습니다.

 

  • [I] Tasklet
    • [C] MethodInvokingTaskletAdapter : POJO 메소드 호출을 Step 시점에 호출하기위한 wraps 클래스
    • [C] CallableTaskletAdapter : Callable을 Step 시점에 호출하기 위한 wraps 클래스
    • [C] ChunkOrientedTasklet : ChunkProvider(SimpleChunkProvier 기준으로 ItemReader) , ChunkProcessor(SimpleChunkProcessor 기준으로 ItemProcessor, ItemWriter)를 활용하는 Tasklet(ETL)
    • [I] StoppableTasklet : (3.0부터) stop() 메소드를 구현하도록 하는 인터페이스며, 프레임워크에서 JobOperator.stop 시 해당 메소드를 불러줍니다.
      • [C] BatchletAdapter : (3.0부터) Batchlet을 지원하는 Tasklet Batchlet은 arg가 없는 process와 stop 메소드가 있는 interface 입니다.
      • [C] SystemCommandTasklet : Command(Java가 아닌 별도 프로그램을 실행한다던지)를 위한 Tasklet

 

 

'JAVA > SpringBatch' 카테고리의 다른 글

[SpringBatch] State  (0) 2020.03.25
[Spring] Spring Batch Reader Writer  (0) 2020.03.24
[Spring Batch] Flow & Step  (0) 2020.03.23
[Spring Batch] Job  (0) 2020.03.20
[Spring] Spring Batch Version History  (0) 2020.02.22

댓글()

[Spring] Spring Batch Version History

JAVA/SpringBatch|2020. 2. 22. 19:39

https://docs.spring.io/spring-batch/docs/3.0.9.RELEASE/reference/html/whatsNew.html

https://docs.spring.io/spring-batch/docs/4.2.x/reference/html/whatsnew.html#whatsNew

추후 각 버전별 주요 사항들을 조금씩 정리해보려고 합니다.

'JAVA > SpringBatch' 카테고리의 다른 글

[SpringBatch] State  (0) 2020.03.25
[Spring] Spring Batch Reader Writer  (0) 2020.03.24
[Spring Batch] Flow & Step  (0) 2020.03.23
[Spring Batch] Job  (0) 2020.03.20
[Spring] Spring Batch Tasklet  (0) 2020.02.25

댓글()

spring boot log level 변경(actuator)

JAVA/Spring|2019. 12. 19. 19:50

로그레벨 동적 반영을 위하여

Controller를 하나 만들어서 처리할까 하다 이미 구현된 기능이 있을지 해서 검색해보니

이기 해당 기능이 actuator를 이용하여 처리가 가능하도록 되어있었습니다.

 

먼저 actuator를 사용하기 위해 pom.xml 에 추가합니다.(메이븐 기준으로)

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

 

설정 없이는 /actuator 로 확인할수 있는것들이 없지만 'management.endpoints.web.exposure.include' 에 항목들을 추가하여 추가적인 기능들을 사용할 수 있습니다.

management.endpoints.web.exposure.include=loggers

#management.endpoints.web.exposure.include=httptrace,loggers,health,info,metrics

 

logger 설정 및 확인을 위해 필요한 내용은 loggers입니다.

 

위와같이 설정 후 기동하게되면

'/actuator/loggers' 를 통해 모든 로거들의 로그레벨들을 확인할 수 있습니다.

 

 

'/actuator/loggers/로거명' 을 GET으로 요청하면 해당 로거만 나타나게 됩니다.

 

이제 목표인 로그레벨 동적 변경을 위해서는

'/actuator/loggers/로거명' 에 POST로 설정할 값을 보내주면 됩니다.

{"configuredLevel":null,"effectiveLevel":"INFO"} 를

{"configuredLevel":"ERROR","effectiveLevel":"ERROR"} 로 변경하고자 하면

 

헤더는 컨텐츠 타입을 application/json에 body에 {"configuredLevel":"ERROR","effectiveLevel":"ERROR"} 을 넣어 요청하도록 하면 됩니다.

 

 

 

'JAVA > Spring' 카테고리의 다른 글

[MSA] sidecar 패턴  (0) 2020.01.13
[SpringConfig] Properties 암호화  (0) 2019.12.24
reactor Schedulers  (0) 2019.12.16
스프링 부트 2.2 릴리즈노트  (0) 2019.11.01
[Spring] zuul 사용시 Eureka client로 분배가 안되는경우  (0) 2019.08.16

댓글()

스프링 부트 2.2 릴리즈노트

JAVA/Spring|2019. 11. 1. 18:20

한 달 동안 잠시 해외를 다녀온 사이 Spring Boot 2.2가 릴리즈 되었습니다.
지금까지 버전업 되면서 변경 사항들을 모두 파악하지는 못했지만
계속 사용하게될 SpringBoot이기 때문에 2.1x에서 2.2x로 올라가며 변경돼 사항을 파악하고자
릴리즈 노트를 번역 및 개인적으로 궁금한 사항을 파악해보았습니다.

릴리즈 정보 출처

https://spring.io/blog/2019/10/16/spring-boot-2-2-0
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.2-Release-Notes


스프링 관련 프로젝트 업데이트

  • Spring AMQP 2.2
  • Spring Batch 4.2
  • Spring Data Moore
  • Spring Framework 5.2
  • Spring HATEOAS 1.0
  • Spring Integration 5.2
  • Spring Kafka 2.3
  • Spring Security 5.2
  • Spring Session Corn

서드 파티 라이브러리 업데이트

  • Elasticsearch 6.7
  • Flyway 6.0
  • Jackson 2.10
  • JUnit 5.5
  • Micrometer 1.3
  • Reactor Dysprosium
  • Solr 8.0

성능 개선

SpringBoot2.1보다 2.2에서는 더 빠른 시작과 더 적은 메모리 사용량을 보여줄 것이며 특히 타이트한 메모리 환경에서 유용할 것입니다.

초기화 지연(Lazy initialization)

spring.main.lazy-initialization 속성을 통해 전역으로 lazy init을 활성화시킬 수 있습니다.
초기화를 늦춤에 따라 아래의 추가적인 비용들이 발생합니다.

Java13 지원

Spring 5.2가 Java 13을 지원함에 따라 Spring Boot2.2도 Java 13을 지원하며, Java11과 Java8 또한 지원합니다.

@ConfigurationProperties 생성자 바인딩 지원

설정 properties는 이제 생성자 바인딩을 지원하기 때문에 클래스의 불변을 지원합니다.
@ConfigurationProperties를 붙이거나, @ConstructorBinding를 붙이면 생성자 바인딩이 활성화되며, @DefaultValue와 @DateTimeFormat 이 생성자 바인딩으로 동작합니다.

RSocket 지원

RSocket에 대한 자동 설정을 지원합니다. spring-boot-starter-rsocket

 

수정 중이며 잘못된 내용이 있으면 의견 부탁드립니다.

감사합니다.

댓글()

[Spring][Kotlin] 필드에 @Autowired 어떻게 사용하나?

Kotlin|2019. 9. 6. 19:02

아직 익숙하지 않지만, 코틀린을 조금씩 학습중에 @Autowired를 어떻게 써야하는지 난감한 상황이 생겼습니다.

 

자바에서는 일반적으로 

 

@Autowired
private EmpDao empDao;

형태로 간단히 사용할수 있지만

 

코틀린에서

 

@Autowired
var empDao: EmpDao;

'Property must be initialized or be abstract' 에러와 함께 동작하지 않았습니다.

 

그럴때는'lateinit' 을 사용하면 에러 없이 사용가능합니다.

@Autowire
lateinit var empDao : EmpDao;

 

참고 : https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties

'Kotlin' 카테고리의 다른 글

split과 동시에 assign  (0) 2021.11.29
코틀린 upgrade 1.3.7 to 1.5.0  (0) 2021.05.28
[Kotlin] default argument, named argument  (0) 2019.09.18
[Kotlin] 코틀린에 primitive가 없다고? 느리지 않을까?  (1) 2019.09.10
[Kotlin] data class  (0) 2019.09.09

댓글()

[Spring] zuul 사용시 Eureka client로 분배가 안되는경우

JAVA/Spring|2019. 8. 16. 19:56

Toy 프로젝트에 zuul 을 적용해서 사용해보고있는데

여러 appSvr를 EurekaServer에 붙이고 zuul로 호출해봤으나 이상하게도

하나의 appSvr로 호출되는 현상이 발생했습니다.

 

이게 원래 그런가?(active-standby로..?) 라고 처음에는 생각해봤지만 그건 너무 아닌것 같아서

이런저런 시도를 하다 eureakServer에 /eureka/apps 로 등록된 app을 확인해보니

zuul(API-GATEWAY)이랑 appSvr(MEMBER-API 라는 샘플..)이 정상적으로 등록되어있지만

appSvr가 3개가 나타나야 하는데 하나만 나타나는것을 확인했습니다.

 

등록된 정보들을 살펴보다가 떠오른것이..

eureka.instanceId 설정을.. 안했...네요..

 

설정을 안하다보니, ip:applicationName:port 으로 instanceId가 다 지정되어

(port는 일부러 random으로 띄우기 위해 0으로 설정했었습니다.)

동일한 instanceId 로 등록을 시도하고 있었던것 이였습니다.

 

그래서 'eureka.instance.instance-id' 설정을 추가해주었고

설정값은 'hostname:applicationname:springinstanceId:random값'

으로 하여 중복이 발생하지 않고 기존처럼 인식할수 있도록 변경하였습니다.

 

eureka.instance.instance-id=${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${random.value}}

 

간단한 설정 실수였지만.. 역시 reference 를 잘 읽어야.. 하겠습니다.

 

요약

1. eureka.instance.instance-id 를설정하지 않거나 중복 된다면 제대로 동작 안할수 있다.

 

 

 

댓글()

[Spring] JDBC Template 어떻게 Thread-Safe 할까?

JAVA/Spring|2019. 8. 6. 18:27

Spring 스터디중 나온 질문 입니다.

 

DAO 클래스를 만들때 "JDBC Template"는 new 해서 사용하기도 하지만, "Thread-Safe 하기 때문에 빈으로 등록해서 사용할 수 있다"

 

Toy 프로젝트 때는 MyBatis를 쓰거나, JPA를 사용하기 때문에 JDBC Template를 사용할 일이 많지 않았지만,

대체 내부 구조가 어떻게 되어있길래 Thread-Safe한거지? 라는 의문이 들었습니다.

(JDBC에 Connection, Statement, ResultSet 은 Thread-Safe 하지 않기 때문에..)

 

예상 할 수 있는건

락(sync)를 잡아 처리 하나? 아니면 ThreadLocal로 처리하나?

정도로 예상해볼수 있는데 락잡아 처리한다면.. 쫌 아닐꺼라 생각되지만 코드를 살펴봤습니다.

JdbcTemplate의 query, update, execute 등 대부분의 메소드들은 살펴보면 메소드 내에서

DataSourceUtils.getConnection(ds) 를 통해 Connection을 얻어오고 있으며

메소드에서 생성된 ps나 rs 그리고 connection(물론 connection은 무조건 정리하지는 않습니다.) 정리 하고 있습니다.

//즉, JdbcTemplate 객체에 상태 변화 없이 메소드 내에서 모든 리소스가 정리 됨

 

JdbcTemplate 객체내에서 리소스(예를 들어 Connection)를 정리하지 않고 보존해야 하는경우도 있는데

(예를 들어 @Transaction)

그경우를 위해 DataSourceUtils.getConnection(ds) 코드를 따라가보면

TransactionSynchronizationManager.getResource(ds)를 통해 ConnectionHolder를 가져오는데

TransactionSynchronizationManager.getResource(ds)를 더 들어가보면

ThreadLocal<Map<Object,Object>>로 되어있는 resources를 가져와 ds를 키로 ConnectionHolder를 가져오는것을 볼수 있었습니다.

 

 

 

결론

1. JdbcTemplate 인스턴스는 상태를 갖지 않고 메소드 내에서 생성된 리소스(rs, ps, connection) 들을 정리하기 때문에 Thread-Safe하다

2. Transaction이 필요한경우 정리하면 안되는 Connection의 경우 JdbcTemplate이 상태를 가지지 않고TransactionSynchronizationManager에 ThreadLocal로 보관 하기 때문에 JdbcTemplate를 Thread-Safe하며,

Connection 객체 전달 및 전파 필요 없이 트랜잭션 제어를 하기 용이 하다.

 

 

댓글()