将@PathParam的可能值包含到WADL中

时间:2013-02-21 17:11:22

标签: java rest jersey wadl

我们正在使用Jersey来实现RESTful API,利用其自动WADL生成的强大功能。

就像一个例子我们有方法

@GET
@Path("/{id}/{attribute}")
@Produces(MediaType.APPLICATION_JSON)
public Object getAttributeByID(@PathParam("id") long id, @PathParam("attribute") String attribute) {
....
}

这会在WADL中生成以下片段:

<param type="xs:string" style="template" name="attribute:.*"/>

属性可以是nametypesize,我们不仅要在运行时验证值,还要在生成的wadl中显示它。根据this document这样的功能应该通过在<option>内生成多个标记<param>来支持,即我期待以下内容:

<param type="aws:Attributes" style="template" name="attribute">
  <option value="name"/> 
  <option value="type"/> 
  <option value="size"/> 
</param>

我的问题是用泽西岛启用它。如果找不到相关文档并假设我可能会将参数类型从String更改为enum,则此功能会自动生效,因此我将方法签名更改为:

@Path("/{id}/{attribute}")
@Produces(MediaType.APPLICATION_JSON)
public Object getAttributeByID(@PathParam("id") long id, @PathParam("attribute") Attribute attribute) {
....
}

,其中

public enum Attribute {
    name, type, size
}

但泽西岛仍然生成<param>标签而没有选项,参数类型仍为xs:string

我试图在Jersey的代码中找到它并找到带有相关JAXB注释的类com.sun.research.ws.wadl.Option,所以它似乎是相关的,但我不知道如何让它工作。我想问题出在WadlGeneratorConfig

以下是我们web.xml

中泽西岛定义的相关部分
<filter>
<filter-name>REST-API</filter-name>
<filter-class>com.sun.jersey.spi.container.servlet.ServletContainer</filter-class>
    ................
<init-param>
    <param-name>com.sun.jersey.config.property.WadlGeneratorConfig</param-name>
    <param-value>com.mycompany.resource.OurWADLGenerator</param-value>
</init-param>
<init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>com.mycompany</param-value>
</init-param>
</filter>

其中OurWADLGenerator代码为:

public class OurWADLGenerator extends WadlGeneratorConfig {
    @Override
    public List<WadlGeneratorDescription> configure() {
        return generator(WadlGeneratorApplicationDoc.class)
                .prop("applicationDocsStream", "application-doc.xml")
            .generator(WadlGeneratorResourceDocSupport.class)
                .prop("resourceDocStream", "resourcedoc.xml").descriptions();
    }
}

我在这里缺少什么? 提前致谢。

2 个答案:

答案 0 :(得分:3)

快速搜索com.sun.research.ws.wadl.Param.getOption()的用法(请参阅结果here)表明它实际上从未从库中调用过。我想这只是因为这些类是由wadl.xsd的xjc生成的。看来,泽西岛基本上忽略了wadl文件中的这条信息,同样也不关心将它包含在它生成的wadl文件中。

几年前,我们最终编写了自己的代码来生成wadl,因为可用的工具非常糟糕。从那时起,这可能已经发生了变化,但上述问题表明对wadl的适当支持仍然不存在。 :(

答案 1 :(得分:2)

经过一些调查后,我没有在球衣中找到填充选项列表的任何代码。 (可能尚不支持

因此,您可以实现自己的WadlGenerator并将其插入生成器链。

以下为OptionsWadlGenerator类型参数添加<option>元素的示例Enum

package com.mycompany;

import com.sun.jersey.api.model.AbstractMethod;
import com.sun.jersey.api.model.AbstractResource;
import com.sun.jersey.api.model.AbstractResourceMethod;
import com.sun.jersey.api.model.Parameter;
import com.sun.jersey.server.wadl.WadlGenerator;
import com.sun.research.ws.wadl.Application;
import com.sun.research.ws.wadl.Method;
import com.sun.research.ws.wadl.ObjectFactory;
import com.sun.research.ws.wadl.Option;
import com.sun.research.ws.wadl.Param;
import com.sun.research.ws.wadl.RepresentationType;
import com.sun.research.ws.wadl.Request;
import com.sun.research.ws.wadl.Resource;
import com.sun.research.ws.wadl.Resources;
import com.sun.research.ws.wadl.Response;

import javax.ws.rs.core.MediaType;

public class OptionsWadlGenerator implements WadlGenerator {

    private WadlGenerator _delegate;

    private ObjectFactory objectFactory = new ObjectFactory();

    @Override
    public Param createParam(AbstractResource r, AbstractMethod m, Parameter p) {
        Param param = _delegate.createParam(r, m, p);
        if(((Parameter)p).getParameterClass().isEnum()){
            Object[] values = p.getParameterClass().getEnumConstants();
            for(Object enumItem:values){
                Option option = objectFactory.createOption();
                option.setValue(((Enum)enumItem).name());
                param.getOption().add(option);
            }
        }
        return param;
    }

    @Override
    public void setWadlGeneratorDelegate(WadlGenerator delegate) {
        this._delegate = delegate;
    }

    @Override
    public Application createApplication() {
        return _delegate.createApplication();
    }

    ... all other methods also simply call the _delegate equivalent method    
}

当然,要将它插入您的链中,请执行以下操作:

public class OurWADLGenerator extends WadlGeneratorConfig {
    @Override
    public List<WadlGeneratorDescription> configure() {
        return generator(WadlGeneratorApplicationDoc.class)
                .prop("applicationDocsStream", "application-doc.xml")
            .generator(WadlGeneratorResourceDocSupport.class)
                .prop("resourceDocStream", "resourcedoc.xml")
            .generator(OptionsWadlGenerator.class).descriptions();
    }
}