I´m using swagger on my java EE7 application (Glassfish as application server). Everything works fine except for a method with FormDataParam, which gave me the tradicional error:
org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.AnnotationIntrospector.findPropertyIndex(Lcom/fasterxml/jackson/databind/introspect/Annotated;)Ljava/lang/Integer;
I tried everything, but is just a method, so I do not want so badly this method in my swagger.json
How can I exclude this method from swagger. I tried:
#ApiModelProperty(hidden = true) and #ApiOperation(value="",hidden = true)
#POST
#Path("something")
#Produces(MediaType.TEXT_PLAIN)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response newsomething(#FormParam("something") String something,#Context HttpServletRequest request, #Context HttpServletResponse response) throws IOException {
return "something";
}
What I´m doing wrong?
It's related with Glassfish, it use different version of Jackson. You need to upgrade Glassfish/Jackson. More details:
java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.AnnotationIntrospector.findPropertyIndex(Lcom/fasterxml/jackson/databind/introspect/Annotated;)Ljava/lang/Integer solution https://github.com/swagger-api/swagger-core/issues/1001
Upgrading Jackson in GlassFish 4.1
com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector not found --- while using Swagger
java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.AnnotationIntrospector.findPropertyIndex(Lcom/fasterxml/jackson/databind/introspect/Annotated;)Ljava/lang/Integer; solution - https://groups.google.com/forum/#!topic/swagger-swaggersocket/uQEn-anX_Og
java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.AnnotationIntrospector.findPropertyDesc solution https://groups.google.com/forum/#!topic/swagger-swaggersocket/x-Pz_3orTCE
For me adding #ApiModelProperty(hidden = true) in paths worked
Is it wrong or correct?
#ApiModelProperty(hidden = true)
#GET
#Produces({MediaType.APPLICATION_JSON})
#ApiOperation(value = "return getApi ",
tags = {"getApi"},
notes = "Returns a Array of getApi",
hidden = true
)
#ApiResponses(value = {
#ApiResponse(response = GetApi.class, message = "", code = 200)
})
#Path("getApi")
public Response getApi(#Context HttpHeaders httpHeaders, #BeanParam QueryParamBean queryParamBean) {
// codes..
}
Related
I'm in a journey to upgrade swagger-jaxrs2-jakarta 1.6.8 to 2.2.7, I got almost everything working except some object parameters that should be exploded as inputs in the Swagger-ui and them still be interpreted as JSON input... and not as 2 distinct inputs
Java: 17 Springboot: 3.0.0
Jersey: 3.1.0
swagger-jaxrs2-jakarta: 2.2.7
Resource Interface
#Tag(name = "MyResource", description = "MyResource enpoint")
#Path("/")
#RequestMapping
public interface MyResourceAPI {
#GET
#Path("/get/{name}/something")
#Produces(MediaType.APPLICATION_JSON)
#Operation(summary = "MyResource")
#GetMapping(value = "/get/{name}/something")
#ApiResponses(value = {
#ApiResponse(responseCode = "404", description = "Not found"),
#ApiResponse(responseCode = "400", description = "Bad request"),
#ApiResponse(responseCode = "200", description = "Sucesso", content = #Content(schema = #Schema(implementation = MyResourcehResponse.class)))
})
Response search(#Context HttpServletRequest servletRequest, #BeanParam MyCustomRequest myRequest);
}
Resource Impl
#Component
public class MyResourceAPIImpl extends implements MyResourceAPI {
#Override
public Response search(HttpServletRequest servletRequest, MyCustomRequest myRequest) {
#hidden logic
return Response.ok().entity(myResponse).build();
}
}
Request's classes
public class MyCustomRequest extends Request {
}
public class Request {
#BeanParam
#Builder.Default
private Pagination pagination = new Pagination();
}
public class Pagination {
#QueryParam("limit")
#DefaultValue("200")
private Integer limit = 200;
#QueryParam("offset")
#DefaultValue("0")
private Integer offset = 0;
}
Using the version: 1.6.8, swagger-ui shows
After upgrade:
If I remove #QueryParam from Pagination items, they disappear, and if I remove #BeanParam from Pagination declaration, it works as a single JSON input.
I'm without any clue to fix this... anyone already got this issue or something similar and can help me?
I have integrated Swagger (OpenAPI) with Spring Webflux as mentioned here: https://springdoc.org/#spring-weblfuxwebmvcfn-with-functional-endpoints using RouterOperation. The integration works fine and is accessible at /swagger-ui.html
However, for POST APIs, I am not seeing the "Request" sample when I click on "Try it out" button. My Post API accepts a Json as Request Body.
How do I configure this ? Can that be done via Annotations along with RouterOperation or something else ?
Edit: Below is my Router class code:
#Configuration
public class MyRouter {
#RouterOperations({
#RouterOperation(path = "/data", beanClass = MyHandler.class, beanMethod = "getData"),
#RouterOperation(path = "/allData", beanClass = MyHandler.class, beanMethod = "getAllData") })
#Bean
public RouterFunction<ServerResponse> route(MyHandler MyHandler) {
return RouterFunctions
.route(RequestPredicates.POST("/data").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), MyHandler::getData)
.andRoute(RequestPredicates.GET("/allData").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), MyHandler::getAllData);
}
}
Upon adding RouterOperations annotation I can see the swagger-ui showing both the GET and POST APIs correctly but not the request schema sample.
I also came across yaml / json file to describe this. But I am not getting where to put this file in my application so that swagger-ui uses it.
Finally found it
Using #Operation and #Schema, can define the class that is required as input in request body. This will be shown as sample json structure in Swagger-ui. No other configuration required.
#RouterOperations({
#RouterOperation(
path = "/data", beanClass = MyHandler.class, beanMethod = "getData",
operation = #Operation(
operationId = "opGetData",
requestBody = #RequestBody(required = true, description = "Enter Request body as Json Object",
content = #Content(
schema = #Schema(implementation = ApiRequestBody.class))))),
#RouterOperation(path = "/allData", beanClass = MyHandler.class, beanMethod = "getAllData")})
#Bean
public RouterFunction<ServerResponse> route(MyHandler myHandler) {
return RouterFunctions
.route(RequestPredicates.POST("/data").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), myHandler::getData)
.andRoute(RequestPredicates.GET("/allData").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), myHandler::getAllData);
}
I have an issue reading a GenericType on my webservice client.
Here is my webservice :
#GET
#Path("/results")
#Produces(MediaType.APPLICATION_JSON)
public Response getPlayerResults(#QueryParam("nick") String nick, #Context HttpServletRequest request,
#Context HttpServletResponse response) {
// if (!isAuth(request, response)) {
// authError(response);
// }
System.out.println(nick);
GenericEntity<List<JSONTournament>> entity = new GenericEntity<List<JSONTournament>>(
MongoTournaments.getPlayerResults(nick, null)) {
};
return Response.ok(entity).build();
}
My client :
Client client = ClientBuilder.newClient();
WebTarget webTarget = client.target("http://localhost:8080/WS").path("players/results");
Response response = webTarget.queryParam("nick", nick).request(MediaType.APPLICATION_JSON).get();
System.out.println(nick);
tournaments = response.readEntity(new GenericType<List<JSONTournament>>() {
});
And I get this Exception and a strange media-type (text/html) instead of application/json... :
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/html;charset=utf-8, type=interface java.util.List, genericType=java.util.List<com.winascrap.database.model.JSONTournament>.
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:232)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:853)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:812)
at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:368)
at org.glassfish.jersey.client.InboundJaxrsResponse$2.call(InboundJaxrsResponse.java:122)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:419)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:119)
I don't understand what is missing or not done correctly.
My objects have #XmlRootElement annotations, I use jersey.core, jersey.media, and moxy as dependencies... (but maybe I forgot on dependencie or configuration ?) :
Thanks for your help !
Solved !
I missed to add an empty constructor to my custom type annoted with #XmlRootElement . It's working only adding a constructor without params.
I have a project based in Spring Web model-view-controller (MVC) framework. The version of the Spring Web model-view-controller (MVC) framework is 3.2.8
I have this controller
#SuppressWarnings("unchecked")
#RequestMapping(value = { "/books/store/product",
"/books/store/product/",
"/books/store/product/{productId}",
"/books/store/product/{productId}/" }, method = { RequestMethod.POST })
public String saveProduct(#ModelAttribute("productForm") ProductForm productForm,
#PathVariable Long productId,
HttpServletRequest request, Model model) throws Exception {
..
}
Everything is fine for this URL : /books/store/product/232
but for this one /books/store/product/
I got this error:
Error 400--Bad Request
From RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1:
10.4.1 400 Bad Request
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
I've tried to put this #PathVariable(required = false), but I got a compilation error: The attribute required is undefined for the annotation type PathVariable
This is because the service is always waiting for the path variable productId
Because you're using Spring 3 I suggest you to create 2 methods. One with the path variable and the other without it.
#RequestMapping(value = { "/books/store/product",
"/books/store/product/"}, method = { RequestMethod.POST })
public String saveProduct(#ModelAttribute("productForm") ProductForm productForm,
HttpServletRequest request, Model model) throws Exception {
..
}
#RequestMapping(value = { "/books/store/product/{productId}",
"/books/store/product/{productId}/" }, method = { RequestMethod.POST })
public String saveProduct(#ModelAttribute("productForm") ProductForm productForm,
#PathVariable Long productId,
HttpServletRequest request, Model model) throws Exception {
..
}
If you're using Spring 4 and Java 8 I suggest you to use optional.
#PathVariable Optional<Long> productId
If you do not always need productId. Try using query parameter and make it optional. required=false
This url will now look like:
http://localhost:8080/books/store/product?productId=232
http://localhost:8080/books/store/product
Like this:
#SuppressWarnings("unchecked")
#RequestMapping(value = { "/books/store/product",
}, method = { RequestMethod.POST })
public String saveProduct(#ModelAttribute("productForm") ProductForm productForm,
#RequestParam(value = "productId", required = false) Long productId,
HttpServletRequest request, Model model) throws Exception {
..
}
Hope it helps.
I have a simple method where I need to change the contentType to "text/plain" but when I am using Jboss EAP 6.2 it is ignored and the returned value is "application/json.
#RestController
#RequestMapping("/upload")
public class UploadController {
...
#RequestMapping(method = RequestMethod.POST)
public Result foo(MultipartFile arquivo, HttpServletResponse response) {
response.setContentType("text/plain");
return uploadService.saveFile(arquivo);
}
}
I am using SpringMVC (rest controller) and Jackson to parse to JSON. The exactly same method works fine when I use Jetty instead of Jboss.
I can't use #RequestMapping(produces="text/plain") because the actual method has a bit more logic into it and sometimes it will return application/json others text/plain, depending if the request came from IE9 browser or not.
Can someone please tell me how can I set the contentType on Jboss?
Unfortunately the only way I could get this working for Jboss was creating a different method for IE9:
#RequestMapping(value = "/ie9", method = RequestMethod.POST, produces = MediaType.TEXT_PLAIN_VALUE)
public String fooIE9(#RequestParam("arquivo") MultipartFile arquivo) throws JsonProcessingException {
ObjectWriter ow = new ObjectMapper().writer();
return ow.writeValueAsString(uploadService.saveFile(arquivo));
}