2017-10-13 15 views
0

je l'entité suivante:Comment interdire slash '/' utilisation dans l'attribut d'entité utilisant JAXB et jaxrs

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = EntityConstants.PARTNER) 
public class FilePartner 
{ 
    @XmlAttribute(name = EntityConstants.IDENTIFIER, required = true) 
    @XmlJavaTypeAdapter(RestResourceIdJaxbAdapter.class) 
    private String identifier; 
    ... 
} 

Voici l'adaptateur JAXB:

public class RestResourceIdJaxbAdapter extends XmlAdapter<String, String> 
{ 
    @Override 
    public String unmarshal(String v) throws Exception 
    { 
     if (v != null && v.contains("/")) 
     { 
      // throw new ApiException(Status.BAD_REQUEST, RestErrorMessages.BAD_REQUEST_SUFFIX, "Identifier must not contain slashes"); 

      return v.replaceAll("/", ""); 
     } 

     return v; 
    } 

    @Override 
    public String marshal(String v) throws Exception 
    { 
     return v; 
    } 
} 

J'ai un service jaxrs que accepte les requêtes POST avec le corps FilePartner:

@POST 
    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) 
    public Response createPartner(FilePartner partner, 
            @Context UriInfo uriInfo, 
            @HeaderParam(HttpHeaders.ACCEPT) String acceptHeader) 
     throws ApiException 
    { 
     ... 
    } 

Ce que je veux atteindre est d'interdire l'utilisation dans le i de barres obliques «/» dentifier de l'entité FilePartner. Aujourd'hui, je le fais en utilisant un adaptateur jaxb qui supprime simplement toutes les barres obliques de l'ID lors d'unmarshalling. Au lieu de cela, ce que je voudrais est de renvoyer une exception BAD_REQUEST appropriée à l'utilisateur.

J'ai essayé de lancer une exception dans la méthode unmarshal de l'adaptateur jaxb mais il semble que jaxrs l'avale et que je mette simplement mon identifiant à zéro. Si nous voulons surcharger ce comportement, je pense que je dois créer un nouveau @Provider et enregistrer un ValidationEventHandler spécial dans unmarshaller que javax.ws.rs.ext.MessageBodyReader crée. Malheureusement, cela est impossible à moins que je ne définisse une dépendance explicite à une implémentation JAX-RS que je veux éviter.

Existe-t-il d'autres options pour restreindre l'utilisation des barres obliques dans l'attribut identifier sans définir de dépendance explicite à jersey/resteasy et sans gérer la restriction dans la méthode @POST du service?

+0

Pourquoi ne vérifiez-vous pas la barre oblique dans la méthode de poteau elle-même (sans adaptation) et l'erreur de lancer – Optional

+0

J'aimerais pouvoir le faire de façon déclarative. J'ai déclaré cela dans la question. La chose est - J'ai des dizaines de services de repos similaires traitant de différents types d'entités mais aussi très similaires. Je ne veux pas changer toutes les méthodes POST des services de repos, mais je préférerais plutôt annoter toutes les entités. On pourrait penser que c'est un cas d'utilisation commun et très standard. Je me demande pourquoi il n'est pas facile à mettre en œuvre de manière déclarative. – mdzh

+0

Ok @mdzh laissez-moi comprendre. Je pense que nous pouvons le résoudre :). Vous avez une entité partagée entre plusieurs appels de repos et vous souhaitez empêcher "/" uniquement dans l'une des opérations pour la même entité. Ou vous avez beaucoup d'entités, et vous souhaitez limiter une seule entité à _not_ avoir un "/" – Optional

Répondre

0

à votre secours vient ReaderInterceptor

Ne faites pas un traitement spécial à l'aide @XmlJavaTypeAdapter. Enregistrez un ReaderInterceptor avec votre classe Application (si dans jersey2) ou dans web.xml si plus tôt.

import java.io.IOException; 

import javax.ws.rs.WebApplicationException; 
import javax.ws.rs.core.Response; 
import javax.ws.rs.ext.Provider; 
import javax.ws.rs.ext.ReaderInterceptor; 
import javax.ws.rs.ext.ReaderInterceptorContext; 
javax.ws.rs.ext.ReaderInterceptor 

@Provider 
public class ValidationInterceptor implements ReaderInterceptor { 
    public ValidationInterceptor() { 
     super(); 
    } 

    @Override 
    public Object aroundReadFrom(ReaderInterceptorContext readerInterceptorContext) throws IOException, 
                          WebApplicationException { 
     Object o = readerInterceptorContext.proceed(); 
     if (o instanceof FilePartner&& ((FilePartner) o).getIndentifier().contains("/")) { 
      throw new WebApplicationException(Response.status(400) 
                 .entity("Identifier must not contain a slash") 
                 .build()); 

     } 
     return o; 
    } 
} 

Et inscrivez-vous l'intercepteur à votre Application en remplacement de public Set<Class<?>> getClasses() quelque chose comme méthode classes.add(ValidationInterceptor.class);

espoir qui aide.