JBoss RESTeasy使用装饰器进行JAX-RS JAXB模式验证

5
我正在尝试验证通过我的(契约优先)REST接口传输的所有XML文件,并且该应用程序运行在JBoss AS 7中。我编写了一个@Decorator进行漂亮的打印输出(如JBoss RESTeasy文档中的示例),还编写了一个类似的@Decorator,用于为非解组器开启XML模式验证。不幸的是,未调用非解组器的修饰器。
以下是漂亮的修饰器代码:
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;
    }
}

现在对于不起作用的验证(Validate)的注释如下:
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 装饰器被调用,而 @Validate 没有被调用。我在这里做错了什么?
我发现了一个旧的 bug Decorator for Jaxb unmarshaller doesn't work,它已经关闭。
那里的评论说一切正常,上面的代码几乎完全与那里的代码相同,包括解决方案。然而,对于 Unmarshaller,什么都没有起作用。
2个回答

2
最终,JBoss AS 7的这个问题得到了解决。
问题出在Resteasy实现上,直到2.3.5.Final版本之前都存在缺陷。
请参见https://issues.jboss.org/browse/RESTEASY-711,但忽略提到的解决方法,该方法仅适用于2.3.5版本及以上。
解决方案是下载Restwasy分发版2.3.5.Final或更高版本,将其解压缩并查找resteasy-jboss-modules-2.3.5.Final.zip文件。
将此文件解压缩到JBoss AS 7.1.1的根目录中,即可更新resteasy到新版本。完成此步骤后,所有上述代码都可以正常工作。
感谢Bill Burke指向解决方案。

0

是的,我在研究手头的问题时看到了那个解决方案。然而,装饰器应该可以工作,但似乎它们并没有。我认为我链接的错误报告应该重新打开。编写一个MessageBodyReader肯定会起作用,但在我看来,这是我的问题的错误解决方案。无论如何,感谢您的快速回答! - Frank

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接