i am sending post request through postman request to my spring boot application but it encounters the following error message
2022-08-03 11:30:51.637 WARN 7140 --- [nio-9002-exec-7] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character (' ' (code 160)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character (' ' (code 160)): was expecting double-quote to start field name<EOL> at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 2, column: 3]]
this is my postman request
{ "operationClient": "03", "module": "03", "moduleName": "ECH", "operation": "10", "ip": "127.0.0.1", "channelId": "5", "connectionType": "1" }
my API call request
localhost:9002/cms/online/v1/channel/operation
my controller class of spring-boot
#PostMapping(value = "/operation", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ResponseBean> doChannelOperation(#RequestBody #Valid RequestBean requestBean) throws Exception {
System.out.println(requestBean.toString());
ResponseBean responseBean = services.sendRequest(requestBean);
return new ResponseEntity<>(responseBean, HttpStatus.OK);
}
Related
I want to get a map schema in components, e.g.
components:
schemas:
Response:
type: object
additionalProperties:
type: string
Here is my code:
#Bean
public OpenAPI customOpenAPI() {
MapSchema mySchema = new MapSchema();
mySchema.setAdditionalProperties(new StringSchema());
return new OpenAPI().components(new Components()
.addSchemas("Response", mySchema)
);
}
But it will raise an exception:
{"timestamp":"2022-11-24 14:23:54.686","component":"","level":"WARN","thread-id":"http-nio-8080-exec-1","logger":"org.springdoc.core.OpenAPIService","message":"Json Processing Exception occurred: Cannot deserialize value of type `java.lang.Boolean` from Object value (token `JsonToken.START_OBJECT`)
at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: io.swagger.v3.oas.models.OpenAPI["components"]->io.swagger.v3.oas.models.Components["schemas"]->java.util.LinkedHashMap["Response"])"}
{"timestamp":"2022-11-24 14:23:54.711","component":"","level":"ERROR","thread-id":"http-nio-8080-exec-1","logger":"org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet]","message":"Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause"}
java.lang.NullPointerException: null
at java.base/java.util.Objects.requireNonNull(Objects.java:208)
at org.springdoc.core.OpenAPIService.buildOpenAPIWithOpenAPIDefinition(OpenAPIService.java:520)
at org.springdoc.core.OpenAPIService.build(OpenAPIService.java:259)
at org.springdoc.api.AbstractOpenApiResource.getOpenApi(AbstractOpenApiResource.java:314)
at org.springdoc.webmvc.api.OpenApiResource.openapiYaml(OpenApiResource.java:156)
at org.springdoc.webmvc.api.OpenApiWebMvcResource.openapiYaml(OpenApiWebMvcResource.java:133)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
If I changed the code to
#Bean
public OpenAPI customOpenAPI() {
MapSchema mySchema = new MapSchema();
mySchema.setAdditionalProperties(false); <-- I pass a boolean value instead of a schema
return new OpenAPI().components(new Components()
.addSchemas("Response", mySchema)
);
}
SpringDoc can generate the swagger doc successfully.
components:
schemas:
Response:
type: object
additionalProperties: false
Can you help to check what's wrong with my previous code ? Thanks.
I'm using spring-boot 2.7.5 and
org.springdoc/springdoc-openapi-webmvc-core 1.6.11
In a Spring Boot app, using Spring Cloud OpenFeign, I'm about to read an endpoint for a Talend server but just noticed this isn't valid JSON (missing double quotes around the word transactions):
{
transactions: [
"some-uuid",
"another-one-uuid",
"and-so-on-uuid"
]
}
My model class:
#Data
#SuperBuilder
#NoArgsConstructor
#JsonInclude(JsonInclude.Include.ALWAYS)
public class Transactions {
private List<String> transactions;
}
My service/client class:
#Service
#FeignClient(value = "nativeTalend", url = "http://talend-server:8180/talendmdm/services/rest/")
public interface TalendNativeAPI {
#GetMapping(path = "transactions", produces = MediaType.APPLICATION_JSON_VALUE)
Transactions transactions();
}
Note: it needs the "produces" in the #GetMapping annotation because otherwise the server answers with a 500 HTTP error...
Here is the OpenFeign log:
[TalendNativeAPI#transactions] ---> GET http://talend-server:8180/talendmdm/services/rest/transactions HTTP/1.1
[TalendNativeAPI#transactions] Accept: application/json
[TalendNativeAPI#transactions] Authorization: Basic ==xxx==xxx==xxx==
[TalendNativeAPI#transactions] ---> END HTTP (0-byte body)
[TalendNativeAPI#transactions] <--- HTTP/1.1 200 (282ms)
[TalendNativeAPI#transactions] cache-control: no-cache
[TalendNativeAPI#transactions] content-type: application/json;charset=UTF-8
[TalendNativeAPI#transactions] date: Sun, 27 Sep 2020 13:54:50 GMT
[TalendNativeAPI#transactions] expires: Thu, 01 Jan 1970 00:00:00 GMT
[TalendNativeAPI#transactions] pragma: No-cache
[TalendNativeAPI#transactions] set-cookie: JSESSIONID=XXX_XXX_XXX; Path=/talendmdm; HttpOnly
[TalendNativeAPI#transactions] transfer-encoding: chunked
[TalendNativeAPI#transactions] x-content-type-options: nosniff
[TalendNativeAPI#transactions] x-frame-options: DENY
[TalendNativeAPI#transactions] x-xss-protection: 1; mode=block
[TalendNativeAPI#transactions] <--- END HTTP (17-byte body)
and the exception stacktrace (I run this through a unit test):
feign.codec.DecodeException: Error while extracting response for type [class my.company.app.Transactions] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('t' (code 116)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:180)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:140)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:78)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
at com.sun.proxy.$Proxy147.transactions(Unknown Source)
at my.company.app.TalendIntegrationTest.test_noTransactions(TalendIntegrationTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
Caused by: org.springframework.web.client.RestClientException: Error while extracting response for type [class my.company.app.Transactions] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('t' (code 116)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:117)
at org.springframework.cloud.openfeign.support.SpringDecoder.decode(SpringDecoder.java:59)
at org.springframework.cloud.openfeign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:62)
at feign.optionals.OptionalDecoder.decode(OptionalDecoder.java:36)
at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:176)
... 36 more
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('t' (code 116)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:245)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:227)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:102)
... 40 more
Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:693)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:591)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleOddName(UTF8StreamJsonParser.java:1996)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._parseName(UTF8StreamJsonParser.java:1647)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:733)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:155)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4014)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3085)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:239)
... 42 more
How can I configure/"fix" Jackson to make it still read this falsy JSON from this specific endpoint (with the whole context of Spring Boot + Spring Cloud OpenFeign + Jackson auto-declared bean (by Spring)?
Thanks.
The ALLOW_UNQUOTED_FIELD_NAMES feature should do the trick:
public class Unquote {
public static void main(String[] args) throws Exception {
ObjectMapper om = new ObjectMapper()
.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
JsonNode tree = om.readTree("{transactions:[\"some.uuid\"]}".getBytes());
System.out.println(tree);
}
}
This answer explains how to do this in the Spring context:
Configuring ObjectMapper in Spring
I am trying to use "PUT" method in json to an existing kafka connector by trying blacklist two tables.(using postman)
{
"connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector",
"table.blacklist": ["abc", "def"],
}
I tried to pass as a list, also tried dictionary i am getting an error . Tried passing as a string still same error .
Error:
-08-01 02:07:04,627] WARN (org.eclipse.jetty.servlet.ServletHandler:620)
javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream#68885dec; line: 2, column: 68] (through reference chain: java.util.LinkedHashMap["table.blacklist"])
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:489)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
This worked for me
"table.blacklist": "abc,def",
when i hit the url i got the respose in json
[{"action":"rs","version":"5","productCatalogName":"tet","productId":"1252","price":"1.5","operator_Code":"15252"}]
i am using the object mapper to read the response from url and store it into the object
eventProductDetail = objectMapper.readValue(url,
new TypeReference<EventProductDetail>() {
});
i am getting Exception:
Exception ing etProductDetails com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'http': was expecting ('true', 'false' or 'null')
i created a small json example... all worked quite fine, i'am just not able to send complex multiparameter to a service-method. With just one parameter it works... at the moment i'm not sure that my json call is wrong or something in my source/config is wrong.
First of all my lib-Dependencies:
org.springframework.spring-webmvc 4.0.6.RELEASE
org.springframework.spring-context 4.0.0.RELEASE
com.fasterxml.jackson.core.jackson-databind 2.2.3
Here is my spring-config:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Configure to plugin JSON as request and response in method handler -->
<annotation-driven>
<message-converters>
<beans:bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<beans:property name="objectMapper">
<beans:bean class="com.test.webservice.EnvironmentObjectMapper" />
</beans:property>
</beans:bean>
</message-converters>
</annotation-driven>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<!-- only components from this package can be wired by spring -->
<context:component-scan base-package="com.test.*" />
</beans:beans>
Here is the used ObjectMapper:
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
public class EnvironmentObjectMapper extends ObjectMapper{
/**
*
*/
private static final long serialVersionUID = -4831947927759735004L;
public EnvironmentObjectMapper() {
this.setVisibilityChecker(
getSerializationConfig().
getDefaultVisibilityChecker().
withFieldVisibility(JsonAutoDetect.Visibility.ANY).
withGetterVisibility(JsonAutoDetect.Visibility.NONE).
withSetterVisibility(JsonAutoDetect.Visibility.NONE).
withCreatorVisibility(JsonAutoDetect.Visibility.NONE).
withIsGetterVisibility(JsonAutoDetect.Visibility.NONE));
this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
}
}
Here is a Simple-Test Code:
#RequestMapping(value = "/rest/test1", method = RequestMethod.POST)
public void test(#RequestBody String name, #RequestBody String name2){
System.out.println("Test - name: "+ name + " name2: " + name2);
}
To call this method i use the Firefox RESTClient. Header is set to Content-Type:application/json
Body is set to: {"name":"karl", "name2:"fritz"}
I get this response:
Status Code: 400 Bad Request
Cache-Control: must-revalidate,no-cache,no-store
Content-Length: 1379
Content-Type: text/html;charset=ISO-8859-1
Server: Jetty(7.2.0.v20101020)
and at the server this:
15:32:30.588 [qtp1879112077-17] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'appServlet' processing POST request for [/rest/test1]
15:32:30.588 [qtp1879112077-17] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /rest/test1
15:32:30.588 [qtp1879112077-17] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Returning handler method [public void com.test.webservice.JustAServiceController.test(java.lang.String,java.lang.String)]
15:32:30.588 [qtp1879112077-17] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'justAServiceController'
15:32:30.588 [qtp1879112077-17] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Reading [class java.lang.String] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#3d467064]
15:32:30.588 [qtp1879112077-17] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [public void com.test.webservice.JustAServiceController.test(java.lang.String,java.lang.String)]: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: org.eclipse.jetty.server.HttpInput#309efc1f; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: org.eclipse.jetty.server.HttpInput#309efc1f; line: 1, column: 1]
15:32:30.588 [qtp1879112077-17] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [public void com.test.webservice.JustAServiceController.test(java.lang.String,java.lang.String)]: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: org.eclipse.jetty.server.HttpInput#309efc1f; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: org.eclipse.jetty.server.HttpInput#309efc1f; line: 1, column: 1]
15:32:30.588 [qtp1879112077-17] DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [public void com.test.webservice.JustAServiceController.test(java.lang.String,java.lang.String)]: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: org.eclipse.jetty.server.HttpInput#309efc1f; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: org.eclipse.jetty.server.HttpInput#309efc1f; line: 1, column: 1]
15:32:30.588 [qtp1879112077-17] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'appServlet': assuming HandlerAdapter completed request handling
15:32:30.588 [qtp1879112077-17] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
I have tried many different variants to set the parameters into the request body. But nothing worked. Anybody an idea what i did wrong? Thank you very much in advance.
You cannot have multiple #RequestBody annotations. #RequestBody annotated parameter is expected to hold the entire body of the request and bind to one object.
You should use different approach such as
Introduce a wrapper object that encapsulates your strings, and change your signature. e.g
Wrapper Object
class MyWrapper{
String name, name2;
//ToDo: Create constructors
String getname(){
return name;
}
String getName2(){
return name2;
}
//ToDo: create Setters
}
Your test code
#RequestMapping(value = "/rest/test1", method = RequestMethod.POST)
public void test(#RequestBody MyWrapper wrapper){
System.out.println("Test - name: "+ wrapper.getName() + " name2: " + wrapper.getName2());
}
Other options would be to pass the data with the URI path, or define custom annotations (which is more complex) see Passing multiple variables in #RequestBody to a Spring MVC controller using Ajax