En una API REST de Java, usar PATCH vs PUT para actualizar una entidad

Estoy a punto de comenzar a desarrollar una nueva API de descanso en Java. Mi pregunta es sobre el uso de PATCH - ¿Por qué?

Digamos que tenemos una entidad llamada Address.java

public class Address {

    @Id
    private Long id

    @NotNull
    private String line1;

    private String line2;       //optional

    @NotNull
    private String city;

    @NotNull
    private String state;   
}

Para crear una nueva dirección, haría esta solicitud http:

POST http://localhost:8080/addresses

con la siguiente solicitud:

{
    "line1" : "mandatory Address line 1",
    "line2" : "optional  Address line 2",
    "city"  : "mandatory City",
    "state" : "cd"
}

Suponga que el registro creado tiene una identificación 1

El correspondiente @RestController AddressResource.java tendrá este método:

@PostMapping(value = "/addresses")
public ResponseEntity<Address> create(@valid Address newAddress) {
    addressRepo.save(newAddress);
}

@valid asegurará que la entidad sea válida antes de almacenar los datos en la tabla.

Ahora suponga que me mudo de mi departamento de arriba a una casa calle abajo. Si uso un parche, se convierte en

PATCH http://localhost:8080/addresses/1

con solicitud de carga útil:

{
    "line1" : "1234 NewAddressDownTheStreet ST",
    "line2" : null
}

El método correspondiente de @RestController sería:

@PatchMapping(value = "/addresses/{id}")
public ResponseEntity<Address> patchAddress(@PathVariable Long id, Address partialAddress) 
{
    Address dbAddress = addressRepo.findOne(id);
    if (partialAddress.getLine1() != null) {
        dbAddress.setLine1(partialAddress.getLine1());
    }
    if (partialAddress.getLine2() != null) {
        dbAddress.setLine2(partialAddress.getLine2());
    }
    if (partialAddress.getCity() != null) {
        dbAddress.setCity(partialAddress.getCity());
    }
    if (partialAddress.getState() != null) {
        dbAddress.setState(partialAddress.getState());
    }

    addressRepo.save(dbAddress)
}

Ahora, si consulta la tabla, ¿no será mi dirección?

"line1" : "1234 NewAddressDownTheStreet ST",
"line2" : "optional  Address line 2",       <-- INCORRECT. Should be null.
"city"  : "mandatory City",
"state" : "cd"

Como se puede ver, las actualizaciones anteriores dan como resultado un valor incorrecto para la línea 2. Esto se debe a que en Java todas las variables de instancia en la clase Dirección se inicializan a nulo (o valores iniciales predeterminados si son primitivas) cuando se instancia una clase. Por lo tanto, no hay forma de distinguir entre la línea 2 que se cambia a nula del valor predeterminado.

Pregunta 1) ¿Hay una forma estándar de solucionar esto?

Otra desventaja es que no puedo usar la anotación @Valid para validar la solicitud en el punto de entrada, porque es solo parcial. Entonces, los datos no válidos podrían ingresar al sistema.

Por ejemplo, imagine que había un campo adicional con la siguiente definición:

@Min(0) 
@Max(100)
private Integer lengthOfResidencyInYears, 

Y el usuario escribió accidentalmente 190 (cuando realmente significaban 19 años), no fallaría.

En lugar de PATCH, si hubiera usado PUT, el cliente necesitaría enviar el objeto de dirección completo. Esto tiene la ventaja de que puedo usar @Valid para asegurarme de que la dirección sea realmente válida

Si se parte de la premisa de que siempre se DEBE realizar una OBTENCIÓN antes de realizar cualquier actualización, ¿por qué no se debe usar PUT over PATCH? ¿Me estoy perdiendo de algo?

Aparte

Mi conclusión es que los desarrolladores que usan lenguajes escritos dinámicamente son los defensores del uso de PATCH, ya que no puedo ver ningún beneficio al usarlo desde una línea de lenguaje estáticamente escrito Java o C #. Simplemente parece agregar más complejidad.

Respuestas a la pregunta(1)

Su respuesta a la pregunta