JBoss RESTeasy JAX-RS Проверка схемы JAXB с помощью Decorator - PullRequest
5 голосов
/ 27 сентября 2011

Я пытаюсь проверить все входящие XML-файлы, которые поступают через мой (сначала контрактный) интерфейс REST, в приложении, работающем внутри JBoss AS 7. Я написал @Decorator для Pretty-Printing (как на примере в JBoss RESTeasyдокументация) и аналог для включения проверки схемы XML для демаршаллера.К сожалению, декоратор для unmarshaller никогда не вызывается.

Вот код для Pretty Decorator:

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

И реализация:

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

Теперь аннотация для валидации (которая не работает):

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

Реализация:

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

И код 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;
}

В том же методе REST (обновление) вызывается @Pretty Decorator, а @Validate - нет.Что я здесь не так делаю?

Я обнаружил старую ошибку Декоратор для Jaxb unmarshaller не работает , который закрыт.

В комментариях говорится, что все работаети приведенный выше код почти точно такой же, включая решение.Тем не менее, ничего не работает для Unmarshaller.

Ответы [ 2 ]

2 голосов
/ 21 ноября 2012

Наконец эта проблема была решена для JBoss AS 7.

Проблема заключается в реализации Resteasy, которая глючит до версии 2.3.5.Final.

См. https://issues.jboss.org/browse/RESTEASY-711, но игнорируйте упомянутый обходной путь, он не работает до версии 2.3.5.

Рабочим решением является загрузка дистрибутива Restwasy версии 2.3.5. Наконец-то или выше, распакуйте его и ищите resteasy-jboss-modules-2.3.5.Final.zip

Распакуйте этот файл в корень JBoss AS 7.1.1 и resteasy будет обновлен до новой версии. После этого шага весь приведенный выше код просто работает.

Спасибо Биллу Бёрку, что указал мне на решение,

0 голосов
/ 27 сентября 2011

Вы можете реализовать MessageBodyReader, который устанавливает Schema на JAXB Unmarshaller для выполнения проверки.Для примера кода проверьте мой ответ на похожий вопрос:

...