I was developing a simple application to learn redis caching. Until I add redis as a caching mechanism on spring boot project the API’s works fine. REST project you can say. Using Postman for calling different API. After adding redis I saw that @CacheEvict
which is used for deleting data works fine. But when I call request like GetMapping, PutMapping which annotated with @Cacheable
, @CachePut
doesn’t work. I don’t understand what is the problem where @CacheEvict
working perfectly @Cacheable
, @CachePut
doesn’t.
Here is the error given by postman when I’m calling API’s using following url:
PUT: http://localhost:8080/bank/2/deposit
GET: http://localhost:8080/bank/holderName/Aysha
{
"dateTime": "2024-03-30T16:49:17.7557062",
"message": "Cannot serialize",
"error": "uri=/bank/2/deposit",
"path": "Bad Request"
}
Let me explain in more detail how I configured redis:
POM:
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
application.properties:
spring.cache.type=redis
spring.cache.redis.time-to-live=60000
spring.cache.redis.host=localhost
spring.cache.redis.port=6379
Account (Entity):
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String holderName;
private double balance;
}
Here I enabled caching:
@SpringBootApplication
@EnableCaching
public class SimpleBankingApplication {
@Bean
public ModelMapper mapper(){
return new ModelMapper();
}
public static void main(String[] args) {
SpringApplication.run(SimpleBankingApplication.class, args);
}
}
Controller class:
@Controller
@RequestMapping("bank")
@AllArgsConstructor
@CacheConfig(cacheNames = "account")
public class AccountController {
private AccountService service;
@PostMapping("createAccount")
public ResponseEntity<AccountDTO> createAccount(@RequestBody @Valid AccountDTO dto){
return new ResponseEntity<>(service.addAccount(dto), HttpStatus.CREATED);
}
@GetMapping("holderName/{name}")
@Cacheable(value = "account", key = "#name")
public ResponseEntity<AccountDTO> getAccountByName(@PathVariable String name){
return new ResponseEntity<>(service.getAccount(name),HttpStatus.ACCEPTED);
}
@PutMapping("{id}/deposit")
@CachePut(cacheNames = "account", key = "#id")
public ResponseEntity<AccountDTO> deposit(@PathVariable Long id, @RequestBody Map<String, Double> request){
Double value = request.get("balance");
return new ResponseEntity<>(service.deposit(id,value), HttpStatus.ACCEPTED);
}
@PutMapping("{id}/withdraw")
public ResponseEntity<AccountDTO> withdraw(@PathVariable Long id, @RequestBody Map<String, Double> request){
Double value = request.get("withdraw_balance");
return new ResponseEntity<>(service.withdraw(id,value), HttpStatus.ACCEPTED);
}
@GetMapping("allAccounts")
public ResponseEntity<List<AccountDTO>> getAllAccount(){
return new ResponseEntity<>(service.getAllAccounts(),HttpStatus.ACCEPTED);
}
@DeleteMapping("deleteAccount/{id}")
@CacheEvict(cacheNames = "account", key = "#id", beforeInvocation = true)
public ResponseEntity<String> deleteAccount(@PathVariable Long id){
service.delete(id);
return new ResponseEntity<>("Account has been deleted!!!", HttpStatus.ACCEPTED);
}
}
Project link: view the project
2
Answers
On your github code, you have changed the annotation @Controller to @RestController on the AccountController. It solved the problem? Because @RestController returns JSON. The next step is try to remove the mapper bean that you’ve created in SimpleBankingApplication class, because Spring manages it with Jackson JSON Mapper by default
Try implementing Serializable
Here is the reference.