2015-04-04 19 views
1

我正在準備一個ReSTful服務,我想使用RAML(也可能是Swagger)來記錄這些服務,但似乎我無法同時在同一個應用程序中同時實現JAX-RS和RAML。我可以在同一應用程序中使用Restlet中的JAX-RS和RAML擴展嗎?

我已經創建了JAX-RS應用程序類,如下所示:

public class Application extends javax.ws.rs.core.Application { 

    @Override 
    public Set<Class<?>> getClasses() { 
     // Use the reflections library to scan the current package tree for 
     // classes annotated with javax.ws.rs.Path and add them to the JAX-RS 
     // application 
     Reflections reflections = new Reflections(this.getClass().getPackage().getName()); 
     return reflections.getTypesAnnotatedWith(Path.class); 
    } 
} 

我附上了JAX-RS應用程序對象如下:

Component component = new Component(); 
    Server server = new Server(Protocol.HTTP, PORT); 
    component.getServers().add(server); 

    JaxRsApplication jaxRsApplication = new JaxRsApplication(component.getContext().createChildContext()); 
    jaxRsApplication.add(new Application()); 
    jaxRsApplication.setObjectFactory(objectFactory); 
    component.getDefaultHost().attach("/rest", jaxRsApplication); 

而且我也想實現RAML擴展,但它看起來像綁定到Restlet路由器並擁有它自己的Application類。有沒有辦法將兩者結合起來?

回答

1

事實上,Restlet的RAML擴展並不是用於JAXRS應用程序中的。這就是說,你可以定義基於類的Restlet的ApplicationIntrospector和RAML解析器RamlEmitter提供腎錯構瘤的內容資源,如下所述:

public class RamlResource { 
    private Definition definition; 

    @Path("/raml") 
    @GET 
    public String getRaml() { 
     return new RamlEmitter().dump(RamlTranslator 
         .getRaml(getDefinition())); 
    } 

    private synchronized Definition getDefinition() { 
     if (definition == null) { 
      synchronized (RamlResource.class) { 
       definition = ApplicationIntrospector.getDefinition(
           Application.getCurrent(), 
           new Reference("/"), null, false); 
      } 
     } 

     return definition; 
    } 
} 

它的Restlet的錯構瘤擴展的工作方式。你也可以對Swagger使用這種方法,但要小心,因爲Swagger 1.2需要幾個資源(主類和幾個子類)。 Swagger 2不再是這種情況。

您可以注意到擴展org.restlet.ext.swagger中的Swagger支持JAX-RS。

-----編輯

也許你可以用這個類對應的類JaxRsApplicationSwaggerSpecificationRestlet的端口錯構瘤一試。它是基於類JaxRsIntrospector這似乎相關JAX-RS應用:

public class JaxRsApplicationRamlSpecificationRestlet extends Restlet { 
    private Application application; 
    private String basePath; 
    private Reference baseRef; 
    private Definition definition; 

    public JaxRsApplicationRamlSpecificationRestlet(Application application) { 
     this(null, application); 
    } 

    public JaxRsApplicationRamlSpecificationRestlet(Context context, Application application) { 
     super(context); 
     this.application = application; 
    } 

    public void attach(Router router) { 
     attach(router, "/api-docs"); 
    } 

    public void attach(Router router, String path) { 
     router.attach(path, this); 
     router.attach(path + "/{resource}", this); 
    } 

    public Representation getApiDeclaration() { 
     Raml raml = RamlTranslator.getRaml(
      getDefinition()); 
     ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); 

     try { 
      return new StringRepresentation(
         mapper.writeValueAsString(raml), 
         MediaType.APPLICATION_YAML); 
     } catch (Exception ex) { 
      return new StringRepresentation("error"); 
     } 
    } 

    public String getBasePath() { 
     return basePath; 
    } 

    private synchronized Definition getDefinition() { 
     if (definition == null) { 
      synchronized (JaxRsApplicationRamlSpecificationRestlet.class) { 
       definition = JaxRsIntrospector.getDefinition(application, 
        baseRef, false); 
      } 
     } 

     return definition; 
    } 

    @Override 
    public void handle(Request request, Response response) { 
     super.handle(request, response); 

     if (Method.GET.equals(request.getMethod())) { 
      response.setEntity(getApiDeclaration()); 
     } else { 
       response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); 
     } 
    } 

    public void setApiInboundRoot(Application application) { 
     this.application = application; 
    } 

    public void setApplication(Application application) { 
     this.application = application; 
    } 

    public void setBasePath(String basePath) { 
     this.basePath = basePath; 
     // Process basepath and check validity 
     this.baseRef = basePath != null ? new Reference(basePath) : null; 
    } 
} 

你可以使用這個類是這樣的:

JaxRsApplication application 
     = new JaxRsApplication(component.getContext()); 
MyApplication app = new MyApplication(); 
application.add(app); 

new JaxRsApplicationRamlSpecificationRestlet(app); 

(...) 

有沒有需要專用的資源。請注意,此代碼是一個有點實驗性的;-)我可以提出這回在的Restlet擴展腎錯構瘤貢獻......

希望它可以幫助你, 蒂埃裏

+0

這看起來很有希望,但我做不到似乎得到它的工作。當我試圖按照描述實現時,我在ApplicationIntrospector.addEnpoints()中得到一個NullPointerException ... baseRef.getSchemeProtocol()的結果爲null。我認爲這是我在應用程序的初始設置中缺少的東西? – 2015-04-16 01:44:12

+0

僅供參考,我的項目的源代碼可以在以下網址找到:https://github.com/InfoSec812/restlet-deltaspike-demo – 2015-04-16 01:51:58

+0

我通過使用「參考」的不同構造函數取得了一些進展。問題是雖然沒有拋出異常,但生成的RAML基本上是空的。 – 2015-04-16 10:31:44

相關問題