1

RAML (およびおそらく Swagger も) を使用して文書化したい ReSTful サービスを準備していますが、JAX-RS と RAML の両方を同じアプリケーションに同時に実装することはできないようです。

次のように、JAX-RS の Application クラスを作成しました。

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 Application オブジェクトを次のようにアタッチします。

    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 Router に関連付けられており、独自の Application クラスを持っているようです。2つを組み合わせる方法はありますか?

4

1 に答える 1

1

実際、Restlet の RAML 拡張は、JAXRS アプリケーション内で使用するようには設計されていません。ただし、以下で説明するように、ApplicationIntrospectorRestlet およびRAML パーサーのクラスに基づいて 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 の RAML 拡張が機能する方法です。このようなアプローチを Swagger に使用することもできますが、Swagger 1.2 にはいくつかのリソース (各カテゴリのメインといくつかのサブ リソース) が必要なので注意してください。Swagger 2 の場合はもうありません。

extension に Swagger の JAX-RS サポートがあることがわかりorg.restlet.ext.swaggerます。

----- 編集済み

JaxRsApplicationSwaggerSpecificationRestletクラスのRAMLへの移植に相当するこのクラスで試してみてはいかがでしょうか。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 の拡張機能 raml への貢献のために提案することができます...

お役に立てば幸いです、ティエリー

于 2015-04-13T09:48:20.580 に答える