Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Redis - erro Serializable

Implementei o cache na aplicação com o Redis, no entanto está dando o erro:

2024-05-16T16:27:45.320-03:00 ERROR 8872 --- [template] [nio-8080-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.data.redis.serializer.SerializationException: Cannot serialize] with root cause
java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [org.springframework.http.ResponseEntity]

os métodos do UsuarioService são:

@Cacheable(value = "listaUsuarios")
    public ResponseEntity<Page<DadosDetalheUsuario>> listar(Pageable paginacao) {
        var page = repository.findAll(paginacao).map(DadosDetalheUsuario::new);
        return ResponseEntity.ok(page);
    }

    @CacheEvict(value = "listaUsuarios", allEntries = true)
    public DadosDetalheUsuario cadastrarUsuario(DadosUsuario dados) {
        if (dados.nome() == null || dados.nome().isEmpty()) {
            throw new RegraDeNegocioException("O nome deve estar preenchido!");
        }

        ValidarCpf validador = new ValidarCpf();

        if(validador.valida(dados.cpf())) {
            if (dados.cpf() == null || dados.cpf().isEmpty()) {
                throw new RegraDeNegocioException("O CPF do usuário deve estar preenchido.");
            }
        }else{
            throw new RegraDeNegocioException("O CPF do usuário não é válido.");
        }

        var usuario = new Usuario(dados);

        repository.save(usuario);

        return new DadosDetalheUsuario(usuario);
    }

os records:

public record DadosUsuario(
    Long id,
    String nome,
    String cpf,
    LocalDate data,
    String email,
    String login,
    String senha) implements Serializable {

    public DadosUsuario(String nome, String cpf, LocalDate data, String email, String login, String senha) {
        this(null, nome, cpf, data, email, login,  senha);
    }
}
public record DadosDetalheUsuario (
    Long id,
    String nome,
    String cpf,
    LocalDate data,
    String email,
    String login,
    String senha) implements Serializable {

    public DadosDetalheUsuario(Usuario usuario) {
        this(usuario.getId(), usuario.getNome(), usuario.getCpf(), usuario.getData(), usuario.getEmail(), usuario.getLogin(), usuario.getSenha());
    }

}
4 respostas

Oi!

As anotações de cache devem ser adicionados nos métodos da classe service e não na classe controller.

Bons estudos!

As anotações estão na classe service : public class UsuarioService {

private final UsuarioRepository repository;

public UsuarioService(UsuarioRepository repository) {
    this.repository = repository;
}

@Cacheable(value = "listaUsuarios")
public ResponseEntity<Page<DadosDetalheUsuario>> listar(Pageable paginacao) {
    var page = repository.findAll(paginacao).map(DadosDetalheUsuario::new);
    return ResponseEntity.ok(page);
}

@CacheEvict(value = "listaUsuarios", allEntries = true)
public DadosDetalheUsuario cadastrarUsuario(DadosUsuario dados) {
    if (dados.nome() == null || dados.nome().isEmpty()) {
        throw new RegraDeNegocioException("O nome deve estar preenchido!");
    }

    ValidarCpf validador = new ValidarCpf();

    if(validador.valida(dados.cpf())) {
        if (dados.cpf() == null || dados.cpf().isEmpty()) {
            throw new RegraDeNegocioException("O CPF do usuário deve estar preenchido.");
        }
    }else{
        throw new RegraDeNegocioException("O CPF do usuário não é válido.");
    }

    var usuario = new Usuario(dados);

    repository.save(usuario);

    return new DadosDetalheUsuario(usuario);
}

public DadosDetalheUsuario atualizarUsuario(Long id, DadosUsuario dados) {
    var usuario = repository.findById(id).orElseThrow(() -> new RuntimeException("Usuário não encontrado"));

    //DadosDetalheUsuario usuarioAtualizado = new DadosDetalheUsuario(dados);

    repository.save(usuario);

    return new DadosDetalheUsuario(usuario);
}

public DadosDetalheUsuario detalhar(Long id) {
    var usuario = repository.findById(id).get();
    return new DadosDetalheUsuario(usuario);
}

public void excluirUsuario(Long id) {
    repository.deleteById(id);
}

}

solução!

O método listar está devolvendo um ResponseEntity, mas isso é detalhe que deve estar no Controller. Na service, o método deveria estar assim:

@Cacheable(value = "listaUsuarios")
public Page<DadosDetalheUsuario> listar(Pageable paginacao) {
    return repository.findAll(paginacao).map(DadosDetalheUsuario::new);
}

O problema era esse mesmo.

Obrigado, Rodrigo