Coder Social home page Coder Social logo

binder-swagger-java's Introduction

binder-swagger-java

Build Status

binder-swagger-java is a simple api management solution, which let api maintainence and dev based on api easily.

Features

  • lightweight, less than 3000 line codes (framework + built-in route/fake data generating)
  • based on form-binder-java, allowing dynamic objects in operation's parameter/response definitions
  • directly integrate with swagger-models, allowing to operate swagger object when necessary
  • can generate mock response w/ fake data on demand for unimplemented api operations
  • high customizable, you can replace almost all of the core components

How it works

You define the api meta data in classes' static code blocks, then it was collected to a static global swagger object when class scan/loading, so when requested, the program can serve it right now.
With swagger.json, the swagger-ui can render the API menu in the browser. Then you can browse, fill parameters and send to/receive from service impls (p.s. the service urls were included in swagger.json).

binder-swagger description

p.s. based on form-binder-java and swagger-models, binder-swagger-java enable you to define dynamic data structures and operate the swagger object directly when necessary, so it's more expressive in theory.

How to use it

0) add the dependency to your project:

<dependency>
    <groupId>com.github.tminglei</groupId>
    <artifactId>binder-swagger-java</artifactId>
    <version>0.8.0</version>
</dependency>

1) define and register your api operations:

// in `PetResource.java`
static Mapping<?> petStatus = $(text(oneOf(Arrays.asList("available", "pending", "sold"))))
    .desc("pet status in the store").example("available").$$;
static Mapping<?> pet = $(mapping(
    field("id", $(vLong()).desc("pet id").example(gen("petId").or(gen(() -> faker.number().randomNumber()))).$$),
    field("name", $(text(required())).desc("pet name").$$),
    field("category", attach(required()).to($(mapping(
          field("id", vLong(required())),
          field("name", text(required()))
    )).refName("category").desc("category belonged to").$$)),
    field("photoUrls", $(list(text())).desc("pet's photo urls").example(Arrays.asList("http://example.com/photo1")).$$),
    field("tags", $(list(text())).desc("tags for the pet").example(Arrays.asList("tag1", "tag2")).$$),
    field("status", petStatus)
)).refName("pet").desc("pet info").$$;

static SharingHolder sharing = sharing().pathPrefix("/pet").tag("pet");

static {
    sharing.operation(GET, "/{petId}")
        .summary("get pet by id")
        .parameter(param(longv()).in("path").name("petId").example(1l))
        .response(200, response(pet))
        .response(404, response().description("pet not found"))
        .notImplemented() // MARK IT `notImplemented`, THEN `binder-swagger-java` WILL GENERATE MOCK RESPONSE FOR YOU
    ;
}
@GET
@Path("/{petId}")
public Response getPetById(@PathParam("petId") String petId) throws NotFoundException, SQLException {
...

2) supplement your other swagger info:

// in `Bootstrap.java`
static {  // for swagger
    swagger().info(info()
        .title("Swagger Sample App")
        .description("This is a sample server Petstore server.  You can find out more about Swagger " +
              "at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, " +
              "you can use the api key `special-key` to test the authorization filters.")
        .termsOfService("http://swagger.io/terms/")
        .contact(contact().email("[email protected]"))
        .license(license().name("Apache 2.0")
              .url("http://www.apache.org/licenses/LICENSE-2.0.html")
        )
    ).host("localhost:8002")
    .basePath("/api")
    .consumes("application/json")
    .produces("application/json")
    .securityDefinition("api_key", apiKeyAuth("api_key", In.HEADER))
    .securityDefinition("petstore_auth", oAuth2()
          .implicit("http://petstore.swagger.io/api/oauth/dialog")
          .scope("read:pets", "read your pets")
          .scope("write:pets", "modify pets in your account")
    ).tag(tag("pet").description("Everything about your Pets")
          .externalDocs(externalDocs().description("Find out more").url("http://swagger.io"))
    ).tag(tag("store").description("Access to Petstore orders")
    ).tag(tag("user").description("Operations about user")
          .externalDocs(externalDocs().description("Find out more about our store").url("http://swagger.io"))
    );
}

3) configure the filter, which will serv the swagger.json:

// in `web.xml`
<filter>
    <filter-name>SwaggerFilter</filter-name>
    <filter-class>com.github.tminglei.swagger.SwaggerFilter</filter-class>

    <!-- enable/disable swagger, default value: true
    <init-param>
        <param-name>enabled</param-name>
        <param-value>false</param-value>
    </init-param>
    -->

    <init-param>
        <param-name>scan-packages-and-classes</param-name>
        <param-value>com.example.resource; com.example.Bootstrap</param-value>
    </init-param>

    <!-- specify the requestURI relative to base path, to fetch your swagger json, default '/swagger.json'
    <init-param>
        <param-name>swagger-uri</param-name>
        <param-value>/swagger.json</param-value>
    </init-param>
    -->

    <!-- configure your custom mapping converter
    <init-param>
        <param-name>mapping-converter</param-name>
        <param-value>com.company.pkg.MyMappingConverter</param-value>
    </init-param>
    -->

    <!-- enable/disable mock data generation, default value: true
    <init-param>
        <param-name>fake-enabled</param-name>
        <param-value>false</param-value>
    </init-param>
    -->

    <!-- configure your custom url router used by `binder-swagger-java`
    <init-param>
        <param-name>url-router</param-name>
        <param-value>com.company.pkg.MyRouter</param-value>
    </init-param>
    -->

    <!-- configure your custom data writer used by `binder-swagger-java`
    <init-param>
        <param-name>data-writer</param-name>
        <param-value>com.company.pkg.MyDataWriter</param-value>
    </init-param>
    -->
</filter>
<filter-mapping>
    <filter-name>SwaggerFilter</filter-name>
    <url-pattern>/api/*</url-pattern>
</filter-mapping>
...
That's all. Enjoy it!

For more usage details, pls check the example project here.

Q & A

Q: Why use static code blocks to associate/register operation meta info instead of annotations?
A: Well, because we can't use annotations here. Annotation requires static defined data types, but we didn't define java beans in our project.
(p.s. because of this, we can't also use existing frameworks, like springfox.)

License

The BSD License, Minglei Tu <[email protected]>

binder-swagger-java's People

Contributors

tminglei avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

binder-swagger-java's Issues

how can i set params of each opertion not unique

It seems that each operation returned by SharingHolder's operation method hold the same ArrayList object.It turns out that each path might share the same parameters. It may be confused, cause each one should has its own parameters.

And when request /pet/ in the swagger-ui to add new pet. it may not work? was my operation incorrect?

在SwaggerFilter中抛出了ClassNotFoundException

当程序运行到这里时
c fnhqres01h5 9velx

clz的格式大概是

“com/xxx/xxx”

就会抛出 ClassNotFoundException , 然后我在

Class.forName(clz);

之前添加了

clz = clz.replaceAll("/", ".");
clz = clz.replaceAll("\\", ".");

这样就一切正常了!

我不知道 你本意就是把路径变成 xxx/xxx 这样的格式, 还是这是一个疏漏

Empty title in property spec when label not specified on field

If you don't give a field a specific label, it gets an empty title property in the spec, while I don't believe the title is a required property for object properties (only for the info object).

Although it's still a good practice of course to describe all properties in an object 😁

Add support for structured examples

Examples can only be provided as text, but in case of a json structure, this gets wrongly put in quotes, escaped and won't render properly in the Swagger UI (plus clicking an example doesn't put the right data in the 'Try now' section.

Perhaps add a utility method like:

$(mapping(
// .....
  )).rawExample(jsonContentAsString).$$

And then don't apply any sanitisation on it?

Requirements get lost when model is made a definition

I have a simple case where I want to reuse a definition for a time period:

val period = $(text().constraint(pattern("^P.*"))).refName("Period").$$

This gets translated in the following definition:

"Period": {
  "type": "string"
}

Also, if I add the required constraint to the field when used in a mapping like so:

field("tenor", period.constraint(required()))

This required field is not reflected in the spec.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.