I am trying to implement a new project with OpenAPI 3 and Java 16. Every time I am trying to build I am seeing errors due to internal dependencies.
This is the error I am seeing every time I try to build.
[JAVA] java.lang.reflect.InaccessibleObjectException: Unable to make public boolean java.util.Collections$EmptyMap.isEmpty() accessible
I just want to know if people have used OpenAPI 3 with Java 16 and if did what dependencies they have used.
I was curious and just created a Java 16 Spring Boot 2.5.2 application with spring-boot-starter-web via https://start.spring.io. Then I added a #RestController and this springdoc dependency:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
<version>1.5.9</version>
</dependency>
At least that worked.
{
"openapi": "3.0.1",
"info": {
"title": "OpenAPI definition",
"version": "v0"
},
"servers": [
{
"url": "http://localhost:8080",
"description": "Generated server url"
}
],
"paths": {
"/hello": {
"get": {
"tags": [
"my-controller"
],
"operationId": "hello",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
}
}
}
}
},
"components": {}
}
Related
We are trying to migrate our Spring Cloud Config Server from a Git Backend to S3.
With git when we want to get config for the service my-service and profile development we hit
https://my-config-server/my-service/development
and this returns something like
{
"name": "my-service",
"profiles": [
"development"
],
"label": null,
"version": "fgdfgdfg",
"state": null,
"propertySources": [
{
"name": "https://bitbucket.org/company/config-repo.git/my-service-development.yml",
"source": {
[properties]
}
},
{
"name": "https://bitbucket.org/company/config-repo.git/application-development.yml",
"source": {
[properties]
}
},
{
"name": "https://bitbucket.org/company/config-repo.git/my-service.yml",
"source": {
[properties]
}
},
{
"name": "https://bitbucket.org/company/config-repo.git/application.yml",
"source": {
[properties]
}
}
]
}
And we have the files my-service-development.yml, application-development.yml, my-service.yml and application.yml so that properties in the more specific ones override properties in the more general ones.
Eg we can set a property in my-service.yml but override it for the development environment in my-service-development.yml. Likewise we can set common properties for an environment (such as database connections or messaging connections in application-development.yml.
However when we switch to S3 and hit the same URL we only get
{
"name": "my-service",
"profiles": [
"development"
],
"label": null,
"version": "twtwert",
"state": null,
"propertySources": [
{
"name": "s3:my-service-development",
"source": {
[properties]
}
}
]
}
ie we only get the most specific property source and not the others.
Is there something we are missing or is this a bug in the S3 implementation?
We are using spring boot 2.5.4, spring cloud 2020.0.3 and spring-cloud-aws 2.3.2
I am implementing my Alexa Home Skill using AWS Lambda.
Given the following request I receive when I try to detect new devices on Alexa Skil test page:
{directive={header={namespace=Alexa.Discovery, name=Discover, payloadVersion=3, messageId=0160c7e7-031f-47ee-a1d9-a23f38f87a9e}, payload={scope={type=BearerToken, token=...}}}}
I respond with the following:
{
"event": {
"payload": {
"endpoints": [
{
"displayCategories": [
"SMARTPLUG"
],
"capabilities": [
{
"type": "AlexaInterface",
"interface": "Alexa",
"version": "3"
},
{
"type": "AlexaInterface",
"interface": "Alexa.PowerController",
"version": "3",
"properties": {
"retrievable": true,
"supported": [
{
"name": "powerState"
}
],
"proactivelyReported": true
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.EndpointHealth",
"version": "3",
"properties": {
"retrievable": true,
"supported": [
{
"name": "connectivity"
}
],
"proactivelyReported": true
}
}
],
"manufacturerName": "mirko.io",
"endpointId": "ca84ef6d-53b1-430a-8a5e-a62f174eac5e",
"description": "mirko.io forno (id: ca84ef6d-53b1-430a-8a5e-a62f174eac5e)",
"friendlyName": "forno"
}
]
},
"header": {
"payloadVersion": "3",
"namespace": "Alexa.Discovery",
"name": "Discover.Response",
"messageId": "c0555cc8-ad7a-4377-b310-9de9b9ab6282"
}
}
}
Despite that, for some reasons Alexa answers that it did not find any new device.
I may be mistaken but I am pretty sure it used to work before I decided to add the Alexa.EndpointHealth interface.
Your response object looks right to me, except the extra "endpoint" field.
"endpoint": {
"endpointId": "INVALID",
"scope": {
"type": "BearerToken",
"token": "INVALID"
}
}
There's no such field in the Alexa.Discovery documentation. Try removing it and see if it resolves the issue.
We are using 2.1.3 version for spring cloud stream kafka streams -
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka-streams</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka-core</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
application.yml has property set -
management.health.binders.enabled = true
management.health.kafka.enabled = true
But we are still get the status as UNKNOWN for kafka binders -
"binders": {
"status": "UNKNOWN",
"details": {
"ktable": {
"status": "UNKNOWN"
},
"kstream": {
"status": "UNKNOWN"
},
"globalktable": {
"status": "UNKNOWN"
}
}
}
Appreciate any help on this.
The health indicators for Kafka Streams family of binders only went into the 2.2 line. Any chance you can upgrade to 2.2 from 2.1.3? Here is an application where the health indicators are working. This is using the 3.0 snapshots, but 2.2 also should work. When running this app, I am getting the output as below.
curl --silent http://localhost:8080/actuator/health/ | jq .
{
"status": "UP",
"components": {
"binders": {
"status": "UP",
"components": {
"globalktable": {
"status": "UP",
"details": {
"threadState": "RUNNING",
"standbyTasks": {},
"activeTasks": {
"partitions": [
"partition=0, topic=process-applicationId-KSTREAM-AGGREGATE-STATE-STORE-0000000003-repartition"
],
"taskId": "1_0"
},
"threadName": "process-applicationId-fa4e65eb-6060-43f0-94eb-4c4bf1497613-StreamThread-1"
}
},
"kstream": {
"status": "UP",
"details": {
"threadState": "RUNNING",
"standbyTasks": {},
"activeTasks": {
"partitions": [
"partition=0, topic=process-applicationId-KSTREAM-AGGREGATE-STATE-STORE-0000000003-repartition"
],
"taskId": "1_0"
},
"threadName": "process-applicationId-fa4e65eb-6060-43f0-94eb-4c4bf1497613-StreamThread-1"
}
},
"ktable": {
"status": "UP",
"details": {
"threadState": "RUNNING",
"standbyTasks": {},
"activeTasks": {
"partitions": [
"partition=0, topic=process-applicationId-KSTREAM-AGGREGATE-STATE-STORE-0000000003-repartition"
],
"taskId": "1_0"
},
"threadName": "process-applicationId-fa4e65eb-6060-43f0-94eb-4c4bf1497613-StreamThread-1"
}
}
}
},
"diskSpace": {
"status": "UP",
"details": {
...
}
},
"ping": {
"status": "UP"
}
}
}
Note - The issue mentioned in the comments below where multiple processor's health information is not shown is addressed in the latest snapshots of the binder (3.0.0) and will be available as part of RC1.
I want to add token endpoint oauth/token into my API documentation so I configured Docket like this:
public Docket api(UserProperties userProperties) {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(Predicates.not(PathSelectors.regex("/error")))
.paths(Predicates.not(PathSelectors.regex("/oauth/authorize")))
.paths(Predicates.not(PathSelectors.regex("/oauth/check_token")))
.paths(Predicates.not(PathSelectors.regex("/oauth/token_key")))
.paths(Predicates.not(PathSelectors.regex("/oauth/confirm_access")))
.paths(Predicates.not(PathSelectors.regex("/oauth/error")))
.build().apiInfo(apiInfo());
}
swagger-ui display page correctly, however 3rd party validator claims that:
Swagger schema validation failed.
Data does not match any schemas from 'oneOf' at #/paths//oauth/token/post/parameters/1
Data does not match any schemas from 'oneOf' at #/paths//oauth/token/post/parameters/1
Missing required property: schema at #/
Missing required property: type at #/
Missing required property: $ref at #/paths//oauth/token/post/parameters/1
JSON_OBJECT_VALIDATION_FAILED
The swagger.json taken from /api/v2/api-docs:
"/oauth/token": {
"get": {
...
},
"post": {
"tags": [
"token-endpoint"
],
"summary": "postAccessToken",
"operationId": "postAccessTokenUsingPOST",
"consumes": [
"application/json"
],
"produces": [
"*/*"
],
"parameters": [
{
"name": "name",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "parameters",
"in": "query",
"description": "parameters",
"required": true,
"items": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
],
"responses": {
...
},
"deprecated": false
}
},
Why springfox generates invalid schema?
Pretty sure I am missing something clearly obvious but not seeing it.
How can I use my updated swagger.json file?
I took my boilerplate swagger/v1/swagger.json code and pasted it into the editor.swagger.io system. I then updated the descriptions etc, added examples to my models and then saved the contents as swagger.json.
Moved the file into the root of my api application, set the file to copy always.
public void ConfigureServices(IServiceCollection services)
{...
services.AddSwaggerGen(c => { c.SwaggerDoc("V1", new Info {Title = "Decrypto", Version = "0.0"}); });
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseSwagger();
//--the default works fine
// app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/V1/swagger.json", "Decrypto v1"); });
app.UseSwaggerUI(c => { c.SwaggerEndpoint("swagger.json", "Decrypto v1"); });
app.UseMvc();
}
I have tried a few different variation but none seem to be the trick. I don't really want to rewrite the work in SwaggerDoc as it seems dirty to me put documentation in the runtime.
the custom swagger.json file I want to use looks like this:
{
"swagger": "2.0",
"info": {
"version": "0.0",
"title": "My Title"
},
"paths": {
"/api/Decryption": {
"post": {
"tags": [
"API for taking encrypted values and getting the decrypted values back"
],
"summary": "",
"description": "",
"operationId": "Post",
"consumes": [
"application/json-patch+json",
"application/json",
"text/json",
"application/*+json"
],
"produces": [
"text/plain",
"application/json",
"text/json"
],
"parameters": [
{
"name": "units",
"in": "body",
"required": true,
"schema": {
"uniqueItems": false,
"type": "array",
"items": {
"$ref": "#/definitions/EncryptedUnit"
}
}
}
],
"responses": {
"200": {
"description": "Success",
"schema": {
"uniqueItems": false,
"type": "array",
"items": {
"$ref": "#/definitions/DecryptedUnit"
}
}
}
}
}
}
},
"definitions": {
"EncryptedUnit": {
"type": "object",
"properties": {
"value": {
"type": "string",
"example": "7OjLFw=="
},
"initializeVector": {
"type": "string",
"example": "5YVg="
},
"cipherText": {
"type": "string",
"example": "596F5AA48A882"
}
}
},
"DecryptedUnit": {
"type": "object",
"properties": {
"encrypted": {
"type": "string",
"example": "7OjLV="
},
"decrypted": {
"type": "string",
"example": "555-55-5555"
}
}
}
}
}
you need to configure PhysicalFileProvider and put your swagger.json into wwwroot or anywhere accessible by PhysicalFileProvider. After that you can access it using IFileProvider
Reference: https://www.c-sharpcorner.com/article/file-providers-in-asp-net-core/
Edit If you just add app.UseStaticFiles(); into your StartUp, you can access wwwroot without hastle.
Reference
Completely Different Approach
you may also consider to serve your file using Controller/Action
public IActionResult GetSwaggerDoc()
{
var file = Path.Combine(Directory.GetCurrentDirectory(),
"MyStaticFiles", "swagger.json");
return PhysicalFile(file, "application/json");
}
.NET Core 2.2 could server physical file to url resource like below.
But if you use custom swagger json, your api is fixed except you change it every time.
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
...
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(),
"swagger/v1/swagger.json")),
RequestPath = "swagger/v1/swagger.json"
});
}