Spring boot call external API with external YAML API definition - java

I am trying to find way, how to call external API based on YAML definition:
I have (Spring boot, external) API-1, generated with OpenAPI plugin, which has
it's YAML file.
I have (Spring boot) API-2, which calls API-1. But all I have is YAML definition of API-1.
We know external API can be called with:
#Bean
public WebClient remoteApiBean() {
return WebClient.create("http://example.com/api");
}
And e.g. Service implementation:
#Autowired
public MyService(WebClient remoteApiBean) {
this.remoteApiBean = remoteApiBean;
}
And requesting resource
this.remoteApiBean.get()
.uri("/request")
.retrieve()
.bodyToMono(ModelDTO.class)
.block(REQUEST_TIMEOUT);
API and model info are stored inside of API-1 YAML config. My question is, if it is possible to use API-1 YAML definition as a resource for API-2. Generate code above and also generate DTOs. I think, there MUST be any plugin which generate this, but I am unable to find it, because there are very similar issues with Spring Boot yaml external configurations and google result are bad according this searching.

Related

Can Spring boot create an application.properties template

We've created a Spring Boot application with some property sources configuring the modules of application. Now it comes to document configuration of the application. Instead of writing a separate document I'd like to document in code and create documentation.
First naiv approach would be to write property files like this and then generate a default application.properties (or yaml) to be adapted by end user:
a.b.c.myProperty=42
a.b.c.myProperty.desc=This is the documentation for myProperty
a.b.c.foo=baa
a.b.c.foo.desc=foo is the most important parameter ever!
Before reinventing the wheel, is there already some way to create configuration documentation out of my property sources?

Would this be a correct to remove Router/Handler Function in the code (Spring Boot)?

There is Spring Boot Cloud repository on GitHub with simple route handler example.
#Bean
public RouterFunction<ServerResponse> indexRouter(
#Value("classpath:/static/index.html") final Resource indexHtml) {
// Serve static index.html at root, for convenient message publishing.
return route(
GET("/"),
request -> ok().contentType(MediaType.TEXT_HTML).bodyValue(indexHtml));
}
You can pay attention that index.html is in a static folder which was instantiated by Spring in default mode, so this file is loaded when index path ("/") is requested.
I understand that it is possible that some webservers will not associate main path with index.html file. However from Spring Boot and Java perspective would this be a correct not to include such Bean to the project in this case (when the main path is requested)?
I have tried to test it in different contexts including Spring Boot Security and everything works well. So I close this question, however if someone has wider experience appreciate additional arguments.

What is the right approach for extending Spring Cloud Config Client?

I want to replace Basic Authentication for Spring Cloud Config Server with oAuth implementation. Let's leave Config Server alone for now and focus on changes for Config Client. Obviously I don't want to write my own implementation for whole thing, but instead execute my own logic and fallback on standard Config Client. Also I have to pack my changes into library since I will use it in multiple micro-services.
Long story short I want to achieve following:
1a. Create custom Starter which will contain Spring Cloud Config Client as dependency. Is it even doable or necessary?
or
1b. Create custom Starter with only my custom logic which will be executed before Spring Cloud Config Client. In this case each micro-service will have Spring Cloud Config Client and custom Starter as dependencies. How can I manage execution order and inject custom logic results into Config Client?
2.Introduce new bootstrap settings. e.g. spring.cloud.config.custom.username and spring.cloud.config.custom.password (Optional).
3.Introduce custom annotation for custom Starter. e.g. #enableCustomConfigClient (Optional).
I started with building custom Starter with following code in /resources/META-INF/spring.factories:
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.example.greeter.config.ConfigClientBootstrapConfiguration
But this code invoked after profile is set, not the first thing like Config Client does.
Any suggestions and especially code samples are appreciated. Thanks!
Posting approach I chose for future reference.
Create new package which will be executed on top of / before Spring Cloud Config Client. Two main features here:
Create file src/main/resources/META-INF/spring.factories with org.springframework.cloud.bootstrap.BootstrapConfiguration={YOUR_CLASS}
In {YOUR_CLASS} apply custom logic. Don't forget to use #org.springframework.core.annotation.Order({YOUR_PRECEDENCE}) and fact that Ordered.LOWEST_PRECEDENCE will be executed first
Build jar from previous step and include it into your project (as local file or via artifactory)
Add Custom logic to Spring Cloud Config Server so it can use JWT.
Working example is here: https://github.com/ka4ok85/spring-cloud-config-client-jwt

Can I obtain the Swagger documentation from pre existing Java code?

I am absolutly new in Swagger and I have the following doubt:
I know that gnerally I have to create Swagger document before code my REST API and the use this document to create my API (I know that from the Swagger Editor I can also generate my API server automatically).
My problem is the following one:
I am working on a Java application (a Spring Boot application) that implements my REST API. I want to use Swagger to create my API documentation.
Exist a way to automatically do it? From my Java code to the Swagger yaml file? For example annoting my Java code in some way that could be parsed by some tool?
Yes, there is a tool which can easily generate the swagger documentation from the code you have already written.
This included into a Spring Appllication will create the documentation
https://springfox.github.io/springfox/docs/current/
To my mind this is the right way to it. Don't create a documentation and have the code generated, rather generate the documentation. That's the way Javadoc is created as well.
You don't need to annotate nothing in particular.
Create a class similar to the following to access the API with Swagger:
#Configuration
#EnableSwagger2
public class SwaggerConfig{
#Bean
public Docket api(){
return new Docket(DocumentationType.SWAGGER_2).select().apis(
RequestHandlerSelectors.basePackage("com.yourcompany.restcode")).paths(PathSelectors.any()).build();
}
}
Then access the API documentation with something like:
localhost:8080/swagger-ui.html#/

Accessing CloudFoundry user-provided services using Spring Cloud connectors

I'm trying to use Spring Cloud to consume a generic REST service from a Cloud Foundry app.
This service is created using Spring Boot, as follows:
package com.something;
#RestController
public class DemoServiceController {
#RequestMapping("/sayHi")
public String sayHi() {
return "Hello!";
}
}
This works fine - I can access http://www.example.com/srv/demo/sayHi and get "Hello!" back.
Next, I created a user-provided service instance using the CF-CLI and bound it to my app. I can now see the bound service in VCAP_SERVICES.
cf cups my-demo-service -p '{"url":"http://www.example.com/srv/demo/"}'
cf bs my-demo-app my-demo-service
Next, as described here, I added this bean to my app's Spring config, with the connector-type set to my original controller (I have a reference to it as well).
<cloud:service id="myDemoService"
service-name="my-demo-service"
connector-type="com.something.DemoServiceController"
/>
Now when I auto-wire "myDemoService" into my app,
#Autowired
private DemoController myDemoService;
I get an error:
No services of the specified type could be found.
I've made sure to include all required dependencies, including spring-cloud-spring-service-connector and spring-cloud-cloudfoundry-connector.
What's going wrong here? Am I giving the wrong bean parameters? Any help is much appreciated.
Spring Cloud Connectors won't know what to do with this service, as each supported service must be of a known type (MySQL, Postgres, Redis, MongoDB, RabbitMQ, etc). Setting the connector-type to your Controller class won't do what you want.
What you will need to do is to create a custom Connectors extension. Here's an example of a project that does that: https://github.com/cf-platform-eng/spring-boot-cities.

Categories