Search code examples
openapiopen-liberty

open-liberty and openapi(/ui) and "no operations defined in spec!"


I can not find out why my rest api endpoints are not visible / executable in openapi/ui with openliberty. openapi/ui reports "there are no operations defined in spec!" My project consists of an empty application class and a trivial rest controller with a single endpoint:

package sandbox.io.rest;

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationPath("/api")
public class RestApplication extends Application { }
package sandbox.io.rest;

import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Response;

@ApplicationScoped
public class RestController
{
    @GET
    @Path("/system/properties")
    @Produces(APPLICATION_JSON)
    public Response getSystemProperties()
    {
        return Response.ok(System.getProperties()).build();
    }
}

I have the following features activated in my server.xml:

    <featureManager>
        <feature>jakartaee-9.1</feature>
        <feature>microProfile-5.0</feature>
<!--        <feature>restfulWS-3.0</feature> -->
<!--        <feature>jsonp-2.0</feature> -->
<!--        <feature>jsonb-2.0</feature> -->
<!--        <feature>cdi-3.0</feature> -->
<!--        <feature>mpConfig-3.0</feature> -->
<!--        <feature>mpRestClient-3.0</feature> -->
<!--        <feature>mpOpenAPI-3.0</feature> -->
    </featureManager>

Everything was generated from openliberty/get started.

There is a real minimal reproducer here.

I also played around with activation of mpOpenAPI-3.0 feature but could not make it work. Could anybody have a look at the reproducer please?

BTW: Please don't get irritated by the repo name, it's just that I try to set up an environment for openliberty, hibernate and postgres ... However I'd like to use openapi/ui, too.


Solution

  • You can fix this by adding a class-level @Path annotation. To keep the aggregate URL path the same you can do @Path("/") so:

    @Path("/")
    @ApplicationScoped
    public class RestController
    {
        @GET
        @Path("/system/properties")
        @Produces(APPLICATION_JSON)
        public Response getSystemProperties()
        {
            return Response.ok(System.getProperties()).build();
        }
    }
    

    I believe this is more a Jakarta RESTful issue than an MicroProfile OpenAPI issue as it turns out.