2013-02-21 23 views
8

Używamy Jersey do implementacji API RESTful wykorzystując jego fajną cechę automatycznego generowania WADL.Uwzględnij możliwe wartości @PathParam do WADL

Tylko jako przykład mamy metoda

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

To generuje następujący fragment w WADL:

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

Atrybut może być name, type, size i chcemy nie tylko do sprawdzania wartości w czasie wykonywania, ale również pokaż go w wygenerowanej wawelce Zgodnie z this document taka funkcja powinna być wspierana przez generowanie kilku znaczników <option> wewnątrz <param>, i . .e ja spodziewałem się czegoś tak:

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

Moim problemem jest to, aby włączyć go z Jersey. Jeśli nie udało się znaleźć odpowiedni dokument i zakłada się, że pewnie gdybym zmienić typ parametru z String do enum ta funkcja będzie działać automatycznie, więc zmienił podpis metody do:

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

gdzie

public enum Attribute { 
    name, type, size 
} 

ale Jersey nadal generuje znacznik <param> bez opcji, a typem parametru jest nadal xs:string.

Próbowałem znaleźć go w kodzie Jersey i znalazłem klasę com.sun.research.ws.wadl.Option z odpowiednimi adnotacjami JAXB, więc wydaje mi się to istotne, ale nie wiem jak sprawić, żeby działało. Domyślam się, że problem jest w WadlGeneratorConfig.

Oto odpowiednia część definicji Jersey w naszym 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> 

gdzie kod OurWADLGenerator jest:

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

Co ja tu brakuje? Z góry dzięki.

+0

'public enum Attribure' powinno być 'publiczne enum Attribute' ... zostało skopiowane z twojego kodu lub tylko literówki? –

+0

@martinjakubik, na pewno to było literówka. Dziękuję Ci. Właśnie zredagowałem wpis i naprawiłem ten błąd. – AlexR

Odpowiedz

2

Po kilku badań nie znaleźliśmy żadnych kodu w Jersey, gdzie lista opcji jest zaludnionych. (Chyba, że ​​coś jest nie jeszcze obsługiwane)

Więc można zaimplementować własną WadlGenerator i wkładając ją łańcuch generatora.

Oto próbka OptionsWadlGenerator dodanie <option> elementy dla parametru typu 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  
} 

I oczywiście, aby wstawić go w swojej sieci, zrobić coś takiego:

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(); 
    } 
} 
3

Szybkie wyszukiwanie zastosowań com.sun.research.ws.wadl.Param.getOption() (zobacz wyniki here) pokazuje, że w rzeczywistości nigdy nie jest wywoływany z biblioteki. Sądzę, że jest tylko tam, ponieważ te klasy są generowane przez xjc z pliku wadl.xsd. Wygląda jednak na to, że Jersey zasadniczo ignoruje tę informację w plikach wadl i podobnie nie uwzględnia jej w plikach wadl, które generuje.

Kilka lat temu skończyło się na napisaniu własnego kodu do generowania wadla, ponieważ dostępne narzędzia były tak słabe. To mogło się zmienić od tego czasu, ale powyższy problem pokazuje, że właściwe wsparcie dla wadl nadal nie jest do końca odpowiednie. :(

+0

Dziękuję za twój wysiłek. Nie widziałem też żadnych odniesień do tej funkcjonalności, ale przypuszczałem, że prawdopodobnie jest ona wywołana w pewien sposób inderictly przez odbicie. – AlexR

+0

Istnieje tylko kilka implementatorów 'WadlGenerator', a' createParam() 'nie jest bardzo wyrafinowany w żadnym z nich, więc doszedłem do wniosku, że lista opcji jest ignorowana, jeśli nie ma odniesienia do jej pobierającego. – zagyi