2013-07-04 11 views
12

Ho una classe con annotazione convalida di ibernazione in alcuni campi (ad esempio @NotNull e @Size(min = 4, max = 50), ecc ...)Come posso chiamare a livello di codice lo stesso validatore eseguito su un metodo @RequestMethod con un parametro @Valid in Spring?

public class MyClass { 

    Long id; 

    @NotEmpty 
    @Size(min = 4, max = 50) 
    String machineName; 

    @NotEmpty 
    @Size(min = 4, max = 50) 
    String humanName; 

    // Getters, setters, etc… 
} 

ho anche un controller personalizzato che funge da API JSON e JSON un deserializzatore che crea oggetti MyClass quando vengono chiamati i metodi API. Nel mio controller personalizzato Ho un metodo per creare un nuovo oggetto di quel tipo:

@RequestMapping(method = RequestMethod.POST) 
public long createMyObject(@RequestBody @Valid MyClass newObj) { 
    // Create the object in the database 
    return newObj.getId(); 
} 

e un altro metodo che aggiorna un oggetto esistente

@RequestMapping(method = RequestMethod.PUT) 
public void updateMyObject(@RequestBody MyClass updatedObj) { 
    MyClass existingObj = // Get existing obj from DB by updatedObj.getId(); 

    // Do some secondary validation, such as making sure that a specific 
    // field remains unchanged compared to the existing instance 
    if (existingObj.getMachineName() != null && 
      !existingObj.getMachineName().equals(updatedObj.getMachineName())) { 
     throw new CannotChangeMachineNameException(); 
    } 
    else { 
     updatedObj.setMachineName(existingObj.getMachineName()); 
    } 

    // [HERE IS WHERE I WANT THE MAGIC TO HAPPEN] 

    // Save updatedObj to the database 
} 

Mentre posso usare @Valid in createMyObject, non posso usare in updateMyObject poiché la nostra implementazione API richiede che machineName rimanga invariato: gli utenti possono chiamare l'API con un oggetto JSON che esclude completamente machineName o lo popola con lo stesso valore esistente nel database. *

Prima di salvare l'oggetto aggiornato nel database, desidero chiamare lo stesso validatore che chiamerebbe l'annotazione @Valid. Come posso trovare questo validatore e usarlo?

+1

Penso che si possa utilizzare i gruppi di convalida. Avere tutte le convalide diverse da '@ NotNull' su' machineName' (o un validatore personalizzato che confronta il vecchio e il nuovo nome) si trovano nel gruppo predefinito e avere il validatore rimanente nel gruppo 'Aggiorna'. Utilizza entrambi i gruppi nel metodo 'updateMyObject'. Vedi http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/chapter-groups.html#d0e2595 –

risposta

6

Nulla dice che è necessario utilizzare @Valid solo nei metodi del controller. Perché non creare un metodo di convalida che accetti un parametro annotato come @Valid, quindi restituire lo stesso parametro.

Ti piace questa:

public Book validateBook(@Valid Book book) { 
    return book; 
} 

si presenta come un alternativa sarebbe quella di usare il pacchetto di validazione di Hibernate. Here's it's documentation.

In sostanza, si ottiene un Validator da un ValidationFactory, e quindi utilizzare il validatore come questo:

@Test 
    public void manufacturerIsNull() { 
     Car car = new Car(null, "DD-AB-123", 4); 

     Set<ConstraintViolation<Car>> constraintViolations = 
      validator.validate(car); 

     assertEquals(1, constraintViolations.size()); 
     assertEquals("may not be null", constraintViolations.iterator().next().getMessage()); 
} 
+1

Grazie! Questo mi ha portato abbastanza vicino alla risposta: il primo metodo non ha funzionato, ho fatto qualcosa di simile al secondo metodo: Set > errors = Validation.buildDefaultValidatorFactory(). GetValidator(). Validate (updatedObj); // Sono arrivato a questo dalla documentazione che hai indicato – daniel