2011-09-27 4 views
5

J'essaie de valider tous les fichiers XML entrants qui surviennent sur mon interface REST (contrat premier) dans une application exécutée dans JBoss AS 7. J'ai écrit un @Decorator pour Pretty- Impression (comme dans l'exemple de la documentation de JBoss RESTeasy) et analogue pour activer la validation de schéma XML pour unmarshaller. Malheureusement, le décorateur pour le unmarshaller n'est jamais appelé.JBoss RESTeasy Validation du schéma JAX-RS JAXB avec Decorator

Voici le code pour le décorateur Jolie:

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

import javax.xml.bind.Marshaller; 

import org.jboss.resteasy.annotations.Decorator; 

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) 
@Retention(RetentionPolicy.RUNTIME) 
@Decorator(processor = PrettyProcessor.class, target = Marshaller.class) 
public @interface Pretty {} 

Et la mise en œuvre:

import java.lang.annotation.Annotation; 

import javax.ws.rs.core.MediaType; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.PropertyException; 

import org.apache.log4j.Logger; 
import org.jboss.resteasy.annotations.DecorateTypes; 
import org.jboss.resteasy.spi.interception.DecoratorProcessor; 

@DecorateTypes({ "text/*+xml", "application/*+xml", MediaType.APPLICATION_XML, MediaType.TEXT_XML }) 
public class PrettyProcessor implements DecoratorProcessor<Marshaller, Pretty> { 
    private static final Logger LOGGER = Logger.getLogger(PrettyProcessor.class); 

    @Override 
    public Marshaller decorate(Marshaller target, Pretty annotation, Class type, Annotation[] annotations, MediaType mediaType) { 
     LOGGER.debug("Pretty."); 
     try { 
      target.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 
     } catch (PropertyException e) { 
     } 
     return target; 
    } 
} 

Maintenant, l'annotation pour la validation (qui ne fonctionne pas):

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

import javax.xml.bind.Unmarshaller; 

import org.jboss.resteasy.annotations.Decorator; 

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD}) 
@Retention(RetentionPolicy.RUNTIME) 
@Decorator(processor = ValidateProcessor.class, target = Unmarshaller.class) 
public @interface Validate {} 

La mise en œuvre:

import java.lang.annotation.Annotation; 

import javax.ws.rs.core.MediaType; 
import javax.ws.rs.ext.Provider; 
import javax.xml.XMLConstants; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.PropertyException; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.transform.Source; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.validation.Schema; 
import javax.xml.validation.SchemaFactory; 

import org.apache.log4j.Logger; 
import org.jboss.resteasy.annotations.DecorateTypes; 
import org.jboss.resteasy.spi.interception.DecoratorProcessor; 
import org.xml.sax.SAXException; 

@DecorateTypes({ "text/*+xml", "application/*+xml", MediaType.APPLICATION_XML, MediaType.TEXT_XML }) 
public class ValidateProcessor implements DecoratorProcessor<Unmarshaller, Validate> { 
    private static final Logger LOGGER = Logger.getLogger(ValidateProcessor.class); 

    @Override 
    public Unmarshaller decorate(Unmarshaller target, Validate annotation, Class type, Annotation[] annotations, MediaType mediaType) { 
     target.setSchema(getSchema()); 
     LOGGER.debug("Set validation schema."); 
     System.out.println("Set validation schema."); 
     return target; 
    } 
} 

Et le code de l'interface REST:

import javax.annotation.security.RolesAllowed; 
import javax.ws.rs.Consumes; 
import javax.ws.rs.POST; 
import javax.ws.rs.Path; 
import javax.ws.rs.PathParam; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.Response; 
import javax.ws.rs.core.SecurityContext; 
import javax.xml.ws.WebServiceException; 

@Path("/{mdvt}/{ouid}/order") 
public interface OrderResource { 

    @RolesAllowed({ "mpa" }) 
    @POST 
    @Path("/update") 
    @Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) 
    @Produces(MediaType.APPLICATION_XML) 
    @Pretty 
    public Response update(@Context SecurityContext sec, 
      @PathParam("ouid") String ouID, 
      @PathParam("mdvt") long masterDataVersionTag, 
      @Validate UpdateOrdersRequest uor) throws WebServiceException; 
} 

Sur la même méthode REST (mise à jour) le décorateur @Pretty est appelé alors que le @Validate ne l'est pas. Qu'est-ce que je fais mal ici?

J'ai trouvé un vieux bug Decorator for Jaxb unmarshaller doesn't work qui est fermé.

Les commentaires là-bas disent que tout fonctionne, et le code ci-dessus est presque exactement celui de là, y compris la solution. Néanmoins, rien ne fonctionne pour le Unmarshaller.

Répondre

2

Enfin, ce problème a été résolu pour JBoss AS 7.

Le problème réside dans la mise en œuvre Resteasy qui est buggé jusqu'à version 2.3.5.Final.

Voir https://issues.jboss.org/browse/RESTEASY-711 mais ignorer la solution de contournement mentionnée, il ne fonctionne pas jusqu'à la version 2.3.5.

La solution de travail est de télécharger la version de distribution Restwasy 2.3.5.Final ou au-dessus, l'extraire et de chercher

resteasy-jboss-modules-2.3.5.Final.zip

Extrait ce fichier à la racine de JBoss AS 7.1.1 et resteasy sera mis à jour à la nouvelle version. Après cette étape, tout le code ci-dessus fonctionne.

Merci à Bill Burke me pointent à la solution,

0

Vous pouvez implémenter un MessageBodyReader qui définit un Schema sur le JAXB Unmarshaller pour effectuer la validation. Pour exemple de code vérifier ma réponse à une question similaire:

+0

Oui, j'ai vu cette solution au cours de mes recherches pour le problème à portée de main. Pourtant, les décorateurs devraient travailler et apparemment ils ne le font pas. Le rapport de bogue que j'ai lié devrait être rouvert, à mon humble avis. Ecrire un MessageBodyReader fonctionnerait sûrement, mais à mes yeux c'est la mauvaise solution pour mon problème. Merci quand même pour la réponse rapide! – Frank