How to add two different paths to the same endpoint in swagger? - java

Using javaws we can have multiple endpoints leading to the same method. Example:
#Path("/menus")
public class MenuResource {
#Path("/{menuId}/sections")
#Timed #ExceptionMetered
public MenuSectionResource getSections(#InjectParam MenuSectionResource resource) {
return resource;
}
}
#Path("/sections")
public class MenuSectionResource {
#GET
public Section get(#PathParam("menuId") String menuId, #QueryParam("id") String id) {
/// method accessed by GET in /sections or GET in /menus/{menuid}/sections
}
}
I'm trying to use swagger to document both endpoints, but i can only use one
#Api annotation in each class, so i can generate either /sections or /menus/{menuid}/sections. Is it possible to automatically generate both entries in the swagger.json output?

Related

How to order the endpoints present within the Quarkus resource file as well as multiple resource file in Swagger-UI?

I am developing a REST based application using the Java & Quarkus. I am using the annotations from OpenAPI to create the swagger-ui. I have multiple resource file within my application. I would like to order them as per my choice also I would like to order the api endpoints within each of the resource files as per my choice. How can I achieve this?
I saw some examples examples related to it, but they are based on the Spring, so I am a bit confused about how to achieve the same thing using the Quarkus.
For example, I have created 2 resource files. Lets say the extensions endpoints are appearing on top of the fruits in the Swagger-UI. I need to ensure the fruits appear first then the extensions. Also the endpoints within the extensions and fruits should appear in the described order then how can I achieve this?
#Path("/api")
#Tag(
name = "Fuits Controller",
description = "Fruits Information")
public class FruitResource {
#GET
#Path("/get/fruits")
public String list() {
return fruits;
}
#POST
#Path("/post/fruits")
public String list() {
return fruits;
}
}
#Path("/api")
#Tag(
name = "Extensions Controller",
description = "Extensions Information")
public interface ExtensionResource {
#POST
#Path("/post/extensions")
public String list() {
return extension;
}
#GET
#Path("/get/extension")
public String list() {
return extension;
}
#POST
#Path("/post/extension")
public String list() {
return extension;
}
}

How to search elastic search via Java using ElasticsearchRepository?

I'm creating a Java application using Elastic Search.
Here is the link for my project.
https://github.com/chanakaDe/ensembl-elastic-rest
In this project, I have implemented a rest controller to take data as JSON.
This is the controller class. Now it only has 2 methods. But I need to add some method like this.
#RequestMapping(value = "/find-by/{id}/{param1}/{param2}/{param3}", method = RequestMethod.GET)
public Iterable<Track> findAllWithParams(#PathVariable int id, #PathVariable String param1, #PathVariable String param2, #PathVariable String param3) {
return trackService.someMethodWithParams(id, param1, param2, param3);
}
What I need to do is take some values from user and send them into Elastic server and make a search. I just refered some of these links and got some idea.
https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-search.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html
TrackService.java and TrackServiceImpl.java are implemented by TrackRepository.java and it's extended by ElasticsearchRepository default class. https://github.com/chanakaDe/ensembl-elastic-rest/blob/master/src/main/java/com/chanaka/book/repository/TrackRepository.java
I need to take values via REST URL and create an object like following and pass that to Elastic Server. How can I implement that with my current project configuration ?
{
"query": {
"constant_score" : {
"filter" : {
"terms" : { "user" : ["kimchy", "elasticsearch"]}
}
}
}
}
This is my TrackService.java interface.
public interface TrackService {
Track save(Track track);
Track findOne(int id);
Iterable<Track> findAll();
}
And also this is my TrackServiceImpl.java class implemented by TrackService.java.
public class TrackServiceImpl implements TrackService {
private TrackRepository trackRepository;
#Autowired
public void setTrackRepository(TrackRepository trackRepository) {this.trackRepository = trackRepository;}
#Override
public Track save(Track track) {
return trackRepository.save(track);
}
#Override
public Track findOne(int id) {
return trackRepository.findOne(id + "");
}
#Override
public Iterable<Track> findAll() {
return trackRepository.findAll();
}
}
Do I need to implement a custom method for that ? Or is there any default methods like findAll() and findOne() ?
Simply pass an object and get the value ?
I think, there's no such existing method and you need to create your own by using QueryBuilders.wrapperQuery(query.toString()) and ElasticsearchTemplate. Just to note, wrapperQuery supports only query not filter. But you can achieve filter context query with constant_score.

What is the JSON View class in Jackson and how does it work?

I don't understand what is Jackson's #JsonView(Views.MyClass.class).
I know that I can annotate POJO's fields and methods in this way to filter non-annotated ones from being serialized with JSON. But what is the Views.Myclass class? Is it a template class for Jackson library?
And why can there be many classes inside the Views class? For example like this:
class Views {
static class Public { }
static class ExtendedPublic extends PublicView { }
static class Internal extends ExtendedPublicView { }
}
Why is it needed and how does it work?
Use #JsonView to filter fields depending on the context of serialization. When returning data to a REST client, depending on which REST service was called, we need to limit which data will be serialized while using the same data model.
Lets say we want to create two REST services:
The first service returns some user information like first name and last name but not the messages attached to it.
The second service returns all information from the first service and also the messages attached to the current user.
Sample POJO classes with #JsonView annotation
User Pojo classs
#JsonView(User.Views.Public.class)
public String getFirstname() {
return firstname;
}
#JsonView(User.Views.Public.class)
public String getLastname() {
return lastname;
}
Message Pojo class
#JsonView(User.Views.Internal.class)
public List<Message> getMessages() {
return messages;
}
Rest controller
#RestController
public class SimpleRestController {
#Autowired
SimpleService simpleService;
#RequestMapping(value = "/user/public", method = RequestMethod.GET)
#JsonView(User.Views.Public.class)
public User getUserWithPublicData() {
return simpleService.loadUser();
}
#RequestMapping(value = "/user/internal", method = RequestMethod.GET)
#JsonView(User.Views.Internal.class)
public User getUserWithInternalData() {
return simpleService.loadUser();
}
}

Overriding a #Path annotation in a class by method in JAX-RS

I have a REST API service i maintain in java (over jersey, JAX-RS)
I want to support the following route in my service:
/api/v1/users/{userId}/cars
however, it concatinates to the class's #Path annotation. e.g.
/api/v1/cars/api/v1/users/{userId}/cars
This is my service class:
#Path("api/v1/cars")
public class CarsService {
#GET
#Path("/api/v1/users/{userId}/cars")
public Response getUserCars(#PathParam("userId") Long userId) {
// ...
}
#GET
public Response getCars() {
// ...
}
}
Is there any way to override it?
Note the following:
The #Path annotation in a class designates a root resource.
The #Path annotation in a method designates a sub-resource of a root resource.
When placed on methods, the #Path annotation does not override the #Path annotation of the class. JAX-RS/Jersey performs a hierarchical matching using the #Path annotations.
So, you can try:
#Path("api/v1")
public class CarsService {
#GET
#Path("/cars")
public Response getCars() {
...
}
#GET
#Path("/users/{userId}/cars")
public Response getUserCars(#PathParam("userId") Long userId) {
...
}
}
However, have you considered using different resource classes?
#Path("api/v1/cars")
public class CarsService {
#GET
public Response getCars() {
...
}
}
#Path("api/v1/users")
public class UsersService {
#GET
#Path("{userId}/cars")
public Response getUserCars(#PathParam("userId") Long userId) {
...
}
}
For more details on resources, have a look at the documentation.
You just should change the #Path annotation of the method to:
#Path("users/{userId}/cars")
In this way, the resulting path of concatenating the class and the method #Path annotations will produce your desired path.

Multiple GET methods match: select most specific

I have a web service that looks like:
#Path("/ws")
public class Ws {
#GET public Record getOne(#QueryParam("id") Integer id) { return record(id); }
#GET public List<Record> getAll() { return allRecords(); }
}
The idea is that I can either call:
http://ws:8080/ws?id=1 to get a specific record
http://ws:8080/ws to get all available records
However when I use the second URL, the first #GET method is called with a null id.
Is there a way to achieve what I want without using different paths?
I think this can be achieved with Spring using the #RequestMapping(params={"id"}) and #RequestMapping annotations for the first and second methods respectively but I can't use Spring in that project.
Since the path is the same, you cannot map it to a different method. If you change the path using REST style mapping
#Path("/ws")
public class Ws {
#GET #Path("/{id}") public Response getOne(#PathParam("id") Integer id) { return Response.status(200).entity(record(id)).build(); }
#GET public Response getAll() { return Response.status(200).entity(allRecords()).build(); }
then you should use:
http://ws:8080/ws/1 to get a specific record
http://ws:8080/ws to get all available records

Categories

Resources