2015-04-04 40 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

相关问题