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
Try implementing Serializable
public class AccountDTO implements Serializable {
//your fields, constructors, methods etc.
}
Here is the reference.