개요

redis 서버에 저장된 데이터를 ResponseEntity에 담아 클라이언트에게 넘겨주는 과정에서 발생된 문제이다. 

 

 

문제 : org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Cannot construct instance of `org.springframework.data.domain.PageRequest`

에러 발생 코드 

Controller : 

@GetMapping("/test/cache/pageable")
public ResponseEntity<?> testCachePageable(@PageableDefault Pageable pageable) {
	Pageable page = service.testCachePageEntity(pageable);

	return new ResponseEntity<>(page, HttpStatus.OK);
}

Service : 

@Cacheable(key = "#pageable.getPageNumber", cacheNames = "testCache")
public Pageable testCachePageEntity(Pageable pageable) {
	Page<TestEntity> entities = testRepository.findAll(pageable);

	return entities.getPageable();
}

 

Cache에 key 값이 없을 경우에는 value 값을 직렬화 하여 redis server에 저장되어 있다가 다시 한번 호출될 경우 역직렬화를 통하여 요청된 값을 다시 반환해 준다.

그런데 한 가지 의문이 들었다. 첫 요청 시 캐시에는 값이 없기 때문에 db에 요청하여 Pageable을 직렬 화하게 되면 내부에 Pageable을 가리키는 값이 있으므로 반복적인 값이 나오므로 에러가 발생하게 될 것이다. 하지만 정상적으로 데이터가 redis server안에 정상적으로 들어가 있다.

그럼에도 다시 요청할 경우에는 에러가 발생하게 된다. redis server에서 따로 json으로 변형시켜주지 않는 것일까? 해결하기 위하여 구글링을 했다. stackoverflow에 나와 같은 에러를 발생한 사람이 있었고 해결방안을 찾아냈다.

해결 방법 1. RedisSerializer.java()

config : 변경 전

config : 변경 후 ( 변경 후  redis cli 로 이동하여 FLUSHALL을 해준다.)

 

 

의문 1) RedisSerializer.java()와 GenericJakson2JsonRedisSerializer()의 차이와 실험

RedisSerializer 속성:

  리턴 값  성공 여부
byteArray() return ByteArrayRedisSerializer.INSTANCE; O
java() return java(null); O
java(ClassLoader) return new JdkSerializationRedisSerializer(classLoader); 실험 X
json() return new GenericJackson2JsonRedisSerializer(); X
string() return StringRedisSerializer.UTF_8; O

아직 모르는게 너무 많기에 따로 정리해야겠다.

최종 

Controller : 

@GetMapping("/test/cache/pageable")
public ResponseEntity<?> testCachePageable(@PageableDefault Pageable pageable) {
	Page<TestEntity> page = service.testCachePageEntity(pageable);

	return new ResponseEntity<>(page, HttpStatus.OK);
}

Service :

@Cacheable(key = "#pageable.getPageNumber", cacheNames = "testCache")
public Page<TestEntity> testCachePageEntity(Pageable pageable) {
	Page<TestEntity> entities = testRepository.findAll(pageable);

	return entities;
}

Entity

public class TestEntity implements Serializable{

.. setter, getter .. entity elments
}

리턴 클래스에는 Serializable을 꼭 implments 해야 한다.

 

참고 

https://stackoverflow.com/questions/55965523/error-during-deserialization-of-pageimpl-cannot-construct-instance-of-org-spr

 

https://stackoverflow.com/questions/38695886/cannot-deserialize-nested-exception-is-org-springframework-core-serializer-supp

 

https://yakolla.tistory.com/46

 

+ Recent posts