Comportamento de Campos @Deprecated na Serialização com ProtoStuff

Análise do Comportamento

Ao integrar a biblioteca ProtoStuff em ambientes Java, a presença da anotação @Deprecated em atributos de classes de dados pode causar a perda silenciosa de valores durante o ciclo de serialização e desserialização. Por padrão, o mecanismo de geração de esquemas ignora automaticamente eses campos, retornando null na reconstrução do objeto. A seguir, detalha-se a reprodução técnica e a estratégia para manter a compatibilidade dos dados.

Dependências Utilizadas

O cenário foi validado com as seguintes coordenadas Maven:

<dependency>
    <groupId>io.protostuff</groupId>
    <artifactId>protostuff-runtime</artifactId>
    <version>1.5.9</version>
</dependency>
<dependency>
    <groupId>io.protostuff</groupId>
    <artifactId>protostuff-core</artifactId>
    <version>1.5.9</version>
</dependency>

Validação do Fluxo de Conversão

Considere a estrutura de dados abaixo, onde o segundo campo recebe a marcação de descontinuação:

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class RegistroLegado implements Serializable {
    private String chavePrimaria;
    @Deprecated
    private String chaveAnterior;
}

Ao converter a instância para um array de bytes e reconstruí-la utilizando o esquema padrão, o campo obsoleto permanece não inicializado:

@Test
public void testarCicloCompletoPadrao() {
    RegistroLegado origem = new RegistroLegado("VALOR_ATUAL", "VALOR_ANTIGO");
    Schema<RegistroLegado> esquemaAutomatico = RuntimeSchema.getSchema(RegistroLegado.class);
    
    LinkedBuffer areaTrabalho = LinkedBuffer.allocate(768);
    byte[] payload;
    try {
        payload = ProtostuffIOUtil.toByteArray(origem, esquemaAutomatico, areaTrabalho);
    } finally {
        areaTrabalho.clear();
    }

    RegistroLegado destino = esquemaAutomatico.newMessage();
    ProtostuffIOUtil.mergeFrom(payload, destino, esquemaAutomatico);
    
    assert destino.getChaveAnterior() == null;
}

Para isolar a fase exata onde a informação é descartada, realiza-se um cruzamento com um modelo alternativo que não possui a anotação:

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class RegistroCorrente implements Serializable {
    private String chavePrimaria;
    private String chaveAnterior;
}

Serializando um objeto RegistroLegado e direcionando o resultado para uma instância de RegistroCorrente, o valor continua ausente. Isso comprova que a omissão ocorre durente a etapa de encoding, pois o campo nunca é escrito no stream de bytes. O processo inverso (serializar RegistroCorrente e desserializar para RegistroLegado) também falha em popular o campo descontinuado, mesmo quando o dado está presente no payload original.

Estratégia de Contorno via Esquema Explícito

O comportamneto padrão da biblioteca alinha-se à intenção semântica da anotação, assumindo que campos descontinuados devem ser excluídos do ciclo de vida dos dados. Para forçar a inclusão desses atributos, é possível substituir a geração automática por um mapeamento manual durante a criação do esquema:

@Test
public void contornarFiltroDeAnnotacao() {
    RegistroLegado entrada = new RegistroLegado("COD_X", "COD_Y");
    
    Map<String, String> dicionarioCampos = new HashMap<>();
    dicionarioCampos.put("chavePrimaria", "chavePrimaria");
    dicionarioCampos.put("chaveAnterior", "chaveAnterior");

    Schema<RegistroLegado> esquemaManual = RuntimeSchema.createFrom(
        RegistroLegado.class,
        dicionarioCampos,
        RuntimeEnv.ID_STRATEGY
    );

    LinkedBuffer bufferSerializacao = LinkedBuffer.allocate(768);
    byte[] fluxoDados;
    try {
        fluxoDados = ProtostuffIOUtil.toByteArray(entrada, esquemaManual, bufferSerializacao);
    } finally {
        bufferSerializacao.clear();
    }

    RegistroLegado saida = esquemaManual.newMessage();
    ProtostuffIOUtil.mergeFrom(fluxoDados, saida, esquemaManual);
    
    assert "COD_Y".equals(saida.getChaveAnterior());
}

Ao fornecer explicitamente o conjunto de campos via createFrom, o motor de reflexão do ProtoStuff ignora as verificações padrão de anotações e inclui o atributo descontinuado nas rotinas de conversão, garantindo a integridade dos dados durante a transição entre versões.

Tags: protostuff-runtime java-serialization runtime-schema deprecated-annotation object-mapping

Publicado em 9-27 22:50