2011-09-27 13 views
5

Estoy tratando de validar todos los archivos XML entrantes que vienen a través de mi interfaz REST (contratar primero) en una aplicación que se ejecuta dentro de JBoss AS 7. He escrito un @Decorator para Pretty- Impresión (como en el ejemplo de la documentación de JBoss RESTeasy) y análoga para activar la validación de esquema XML para el unmarshaller. Lamentablemente, el decorador para el unmarshaller nunca se llama.JBoss RESTeasy JAX-RS JAXB validación de esquema con Decorator

Este es el código para el decorador Bastante:

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 {} 

Y la aplicación:

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; 
    } 
} 

Ahora la anotación para el validar (que no funciona):

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 aplicación:

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; 
    } 
} 

Y el código de la interfaz 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; 
} 

Por el mismo método REST, (actualizar) la @Pretty Decorador se llama mientras que @Validate no. ¿Qué estoy haciendo mal aquí?

He encontrado un viejo error Decorator for Jaxb unmarshaller doesn't work que está cerrado.

Los comentarios allí dicen que todo funciona, y el código anterior es casi exactamente el de allí, incluida la solución. Sin embargo, nada funciona para el Unmarshaller.

Respuesta

2

Finalmente este problema fue resuelto para JBoss AS 7.

El problema radica en la aplicación Resteasy el que está libre de errores, hasta versión 2.3.5.Final.

Consulte https://issues.jboss.org/browse/RESTEASY-711 pero ignore la solución antes mencionada, no funciona hasta la versión 2.3.5.

La solución de trabajo es descargar la versión de distribución Restwasy 2.3.5.Final o superior, extraerlo y buscar resteasy-jboss-modules-2.3.5.Final.zip

Extracto de este archivo en la raíz de JBoss AS 7.1.1 y resteasy se actualizarán a la nueva versión. Después de este paso, todo el código anterior simplemente funciona.

Gracias a Bill Burke me apuntan a la solución,

0

Puede implementar un MessageBodyReader que establece Schema en JAXB Unmarshaller para realizar la validación. Para código de ejemplo echa un vistazo a mi respuesta a una pregunta similar:

+0

Sí, he visto que la solución durante mi investigación para el problema en cuestión. Aún así, los decoradores deberían funcionar y aparentemente no. El informe de error que he vinculado debe ser reabierto, en mi humilde opinión. Escribir un MessageBodyReader seguramente funcionaría, pero a mis ojos es la solución incorrecta para mi problema. Gracias de todos modos por la respuesta rápida! – Frank

Cuestiones relacionadas