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