Включить возможные значения @PathParam в 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:.*"/>

Атрибут может быть name, type, size и мы хотим не только проверить значение во время выполнения, но и показать его в сгенерированном wadl. Согласно этому документу такая функция должна поддерживаться путем создания нескольких тегов. <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,

Я пытался найти его в коде Джерси и нашел класс com.sun.research.ws.wadl.Option с соответствующими аннотациями JAXB, так что это кажется уместным, но я не знаю, как заставить это работать. Я думаю, проблема в 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 ответа

Решение

После нескольких исследований я не нашел никакого кода в Джерси, где заполняется список опций. (вероятно, что-то, что еще не поддерживается)

Таким образом, вы можете реализовать свой собственный 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();
    }
}

Быстрый поиск использования com.sun.research.ws.wadl.Param.getOption() (см. результаты здесь) показывает, что он на самом деле никогда не вызывается из библиотеки. Я думаю, это только там, потому что эти классы сгенерированы xjc из wadl.xsd. Кажется, однако, что Джерси в основном игнорирует эту часть информации в файлах wadl, и аналогично не хочет включать ее в генерируемые файлы wadl.

Пару лет назад мы закончили писать свой собственный код для генерации wadl, потому что доступные инструменты были очень скудными. Это могло бы измениться с тех пор, но вышеупомянутая проблема показывает, что надлежащая поддержка wadl все еще не совсем там.:(

Другие вопросы по тегам