default spring data elasticsearch `CrudRepository` doesn't support routing - spring-data-elasticsearch

Spring data CrudRepository's findById method is useful and handy to use, but in spring-data-elasticsearch, we should specify not only id but routing attribute together to find a doc in index with multiple shards.
Does it mean CrudRepository#findById is useless or even misleading(if _id is not equal to _routing) in spring-data-elasticsearch?
Is there any way to find a doc by id and routing, without construct a search request manually, in spring-data-elasticsearch?
Any suggestion would be appreciated!

Routing support is available since version 4.2 (released in April 2021) and described in the documentation.
It is supported on the ElastcisearchOperations level.
To use it in a repository you'd need to integrate it in a custom repository fragment

Related

Rename endpoint /openapi and /openapi/ui

The API documentation created using OpenAPI is usually called using the endpoints /openapi (YAML) or /openapi/ui (Frontend).
How can I rename these endpoints for that I can call e.g. /myappapi and /myappapi/ui respectively? (OpenAPI 3)
This massively depends on how you're generating that OpenAPI. From your comment I see that you're using Eclipse MicroProfile and I've not come across that before, but a quick DuckDuckGo shows this extension might be what you're up to: https://github.com/eclipse/microprofile-open-api
I couldn't see any specific config options to change the endpoint, but you could always slap a nginx redirect in there.
If you're finding limitations with the way you're generating OpenAPI to be a problem, I recommend not doing that.
Of all the approaches: Annotations, DSL, writing YAML by hand in text-editors, or GUI's, I can't help but recommend the GUI approach as it allows for API Design First for new APIs and new functionality in old APIs.
I just did a huge talk about that: https://www.youtube.com/watch?v=nfkppuQ-Eg0&feature=youtu.be
Blog version: https://stoplight.io/blog/api-design-first-vs-code-first/
Otherwise, see if you can pick that extension apart and tweak the config options until it does whatever you want. :)

Rails and graphql casing convention

I am starting to dive into graphql, building my first API with Rails. I have tons of questions regarding standards and conventions.
For example, I noticed the gem graphql by default requires the fields to be passed in CammelCase, when actually when I used to build RESTful API in Rails I always received the arguments in snake_case.
So I was wondering, is CammelCase the convention for Graphql? Should I still use it in my API? All my tests would assert the responses are in snake case too, is that correct?
It's certainly up to you and your application, and some libraries will automatically convert to and from camelCase, but given the choice, the GraphQL Rules website highly recommended that you just commit to using camelCase for all GraphQL fields and arguments, then convert those to camel_case fields in Ruby where necessary.
From the GraphQL Rules website website:
Rules and recommendations mentioned here were the results of 3 years' experience of using GraphQL both on the frontend and backend sides. We also include the recommendations and experience of Caleb Meredith (PostGraphQL author, Facebook ex-employee) and Shopify engineers.
Naming rules
1.1. Use camelCase for GraphQL-fields and arguments.
1.2. Use UpperCamelCase for GraphQL-types.
1.3. Use CAPITALIZED_WITH_UNDERSCORES to name ENUM-types.
I wish a bit that I had followed these for some past projects, but hey, they are still running just fine though :), but there has been churn where occassonally we were faced with some inconsistencies and chose to convert some fields.

How to make versioning with Swagger and Spring Boot?

I've read a lot of StackOverflow questions, but there is no good solution for me. I'm searching for a way to document our API with a version number.
We have v1 and v2. So the best way is to generate 2 different swaggers.
The controllers are in different packages and for one version is one controller.
Is this possible with swagger? And how we can do it?
The best way to do this is to use swagger groups. Check out this documentation: Springfox Documentation

Need for versioning api

Can somebody please explain me what exactly is API versioning and why is it needed. I know how to create versions for api on a rails web app, but I really want to know why is it needed. Before somebody downvotes or flags or anything, I googled , I couldn't find any satisfying answer. I would really appreciate it if somebody answers this.
API versioning allows you to have multiple versions of your API and use them at the same time. With this solution, you are assuring backward compatibility for all of the applications integrated with your API.
Simple example
Your API is used by 10 different applications. You are using Basic access authentication, but you noticed that it could be done better. So, you decided to use modify this and use Oauth.
No API versioning
You will have to wait for all of 10 applications to implement changes before releasing the new API version. Otherwise, you will lose the integration. Of course, you can use if/else statements in your code to distinguish which authentication method should you use but this will be not elegant.
API versioning
You can release new API version whenever you want. Then, you can inform your client, that the old API will be deprecated in 3 months, so they have time to implement changes on their side.
Also, you can ask them to add a param to all requests (to choose which API version they will use), and you can set it by the default to the new version. That will allow you to avoid problems with new applications that want to use your API.
Summary(in my opinion):
Pros
1. clean and elegant code (without additional if/else statements)
2. backward compatibility
Cons
1. sometimes you have to duplicate your code
2. it might look like a complex solution at the beginning but don't be scared
Here you can read about two options of API versioning - URL param and HTTP header
I hope that my explanation is clear and helps you understand API versioning
The main reason for versioning your APIs is to provide a constant structure for everybody using them. Let's say you define an initial API for your service (v1) that you send out to your clients. After some time your app changes, and you maybe want to exclude some fields/add new ones. This would be a problem for the client, since their implementation of your API might break if some fields that they are expecting is missing. So you create a v2 with those features, without breaking the initial functionality.

How to manage multiple APIs in Rails

I have a Rails backend that serves multiple clients:
Angular JS App
iOS App
At first, I only had the iOS App, and used classical API versioning in rails when substantial changes were brought to the client (naming my versions v1, v2 and so on).
When we came up with the Angular front end, we needed a specific API, so I did a new version that I would use only with Angular (let's say v5).
At that point, v1 through v4 are dedicated to iOS, and v5 to Angular.
Obviously, I can simultaneously update my backend along with my Angular API, since both are served to the client every time they access the website. Therefore, there is no need for the Angular API to be versioned.
However, I'm at that point where I need to update my iOS API, and it is starting to get very wrong : v1..v4 are for iOS, and v5 is taken by Android. So the supposed next iOS API should be... v6? Definitely wrong.
I wanted to know if it was possible to name an API version angular, and thanks to this answer on SO I understand why this is not possible. I'll quote the interesting part for my case:
Ryan Bigg wrote:
I couldn't figure out how to get /api/asdf/users to match, because how do you determine if that is supposed to be a request to /api/<resource>/<identifier> or /api/<version>/<resource>?
Now you understand better my situation, here's the question.
The question
How am I supposed to manage multiple APIs, but which are not really like versions?
Is it possible to subdivide API versions? Like:
api/angular/v1
api/ios/v5 (moving v1..v4 to api/ios/ as well)
api/android/v1
Is there any best practice to do so? Or should I just be using the current API versioning system, knowing which version corresponds to which client?
I think in the end this is a design issue. Your API should be thought of as the methods to access your model in networked MVC. Just as in any MVC the model should be independent of it's view and controller. I think having a different API per client is almost like having a different model for each client, which I don't think is what you are intending.
As an example, (I am assuming your API is Restful), a GET request to
api/v1/user/1
might return a json "view" of user 1, each of your clients should be written to work with that same output. If you decide you will no longer support this, or add or remove some content from the returned json that would break an existing client, then you might bump the version and implement the change on that version
I would suggest your next API version expose all of the resources needed by any clients you currently have, and then overtime update your clients to work with this new unified API. If you find your self making changes to your model (API) that would break an existing client, then you can release a new version, allowing existing clients to continue to work with the old API and new or updated clients can pick up the new version.
A set of automated tests on your API will help identify when you break an existing client.
I am not expert at this, but I did (as a learning project) create a rails app with an api, and I was able to use the same api for android and ios.
In regards to your routing issue quoted from Ryan Bigg, you can resolve it by applying a constraint to the route. For example:
get /api/:type/:version/users/all, to: "users#index", constraints: {type: /(ios|angular)/, version: /\d+/}
Ensuring the the version is a number and the type is either "ios" or "angular", you can easily set up the routes for two separate APIs.
To answer the questions as to whether or not it is possible--yes. Anything is possible, especially with Ruby!
I, first of all, would not have two separate APIs to manage. However, if I did, I would create separate namespaces for each API and name the as AngularAPI and IosAPI. I would just route to them separately. The correct answer will depend on how exactly you've set up your API system.
How would I maintain two separate APIs? (from the comment)
It depends on how substantially different the APIs are. If there are only a few differences, it would make sense to simply use a different controller with different routes. For example, AngularUsersController and IosUsersController. They would both extend a ApiUsersController and alter only what was needed for each platform. This would still allow for proper versioning as it grew, and also keep code duplication at bay.

Resources