Springboot throwing giving Jackson exceptions - spring-boot

During testing , I have faced the issue.I have published a rest API with a controller class with a model input .
While Calling the API , instead of a single string , an array [{"a":1,"b":2}] has been used. Which triggered the following error:
{
"timestamp": "2018-12-19T12:33:36.729+0000",
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token\n at [Source: (PushbackInputStream); line: 3, column: 14] (through reference chain: com.xy.df.model.inputReq[\"req\"])",
"path": "x/y/z"
}
We did not imported JACKSON dependency in application , explicitly in POM. I have noticed in the parent pom jackson version used is :2.9.5
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
1.Is it vulnerable for RCE? How to resolve this in Spring-boot ?
2. How I can supress/override the exception message so that client never gets to know what libraries used underneath ?

JsonMappingException: out of START_ARRAY token exception is thrown by Jackson object mapper as it's expecting an Object {} whereas it found an Array [{}] in response.
This can be solved by replacing Object with Object[] in the argument for geForObject("url",Object[].class).
References:
Ref.1
Ref.2
Ref.3

I have resolved issue . Before going ahead , one needs to understand couple of very useful annotations-
#ExceptionHandler - This handler helps you define an error class for which you want to catch the exception
#controller advice - It caters a cross cutting approach . Any class mentioned as controller advice , it is available for all the controller under your microservice.
#ControllerAdvice
public class ExceptionController {
#Autowired
SomeGenericResponse someGenericResponse ; /* data model of common response */
#ExceptionHandler(value = <My case Jackson Class>.class)
public ResponseEntity<SomeGenericResponse> CustomException(HttpServletRequest req, HttpServletResponse res,Exception ex) {
someGenericResponse.setMessage("Your Message");
someGenericResponse.setStatus("false");
return new ResponseEntity<SomeGenericResponse> someGenericResponse ,HttpStatus.BAD_REQUEST);
}
}

Related

Spring Boot #RequestScope and Hibernate schema based multi-tenancy

I'm working on a schema based multi-tenant app, in which I want to resolve the Tenant Identifier using a #RequestScope bean. My understanding is that #RequestScope uses/injects proxies for the request scoped beans, wherever they are referred (e.g. in other singleton beans). However, this is not working in the #Component that implements CurrentTenantIdentifierResolver and I get the following error when I start my service,
Caused by: org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'scopedTarget.userContext': Scope 'request' is not active for the current thread;
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Following are the relevant pieces of code.
#Component
public class CurrentTenant implements CurrentTenantIdentifierResolver {
#Autowired
private UserContext userContext;
#Override
public String resolveCurrentTenantIdentifier() {
return Optional.of(userContext)
.map(u -> u.getDomain())
.get();
}
#Component
#RequestScope
public class UserContext {
private UUID id;
private String domain;
My questions,
Isn't the proxy for the #RequestScope injected (by default)? Do I need to do anything more?
Is Hibernate/Spring trying to establish a connection to the DB at startup (even when there is no tenant available)?
Hibernate properties:
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
properties.remove(AvailableSettings.DEFAULT_SCHEMA);
properties.put(AvailableSettings.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
properties.put(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
properties.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
For the time being, I'm preventing the NullPointerException by checking if we are in the RequestContext. However, a connection still gets established to the master database (although I've explicitly specified the dialect and am not specifying hbm2ddl.auto). Since this connection is not associated with any schema, I'd like to avoid making it, so that it does not look for any tables that it won't find anyways.
What seems to be happenning is that when a HTTP request is received, hibernate is trying to resolve the current tenant identifier, even before my #RequestScope bean is created (and even before my #RestController method is called.) If a provide the default connection to the databse, I then get the following error. If I don't provide a connection, it throws an exception and aborts.
2021-09-26 11:55:44.882 WARN 19759 --- [nio-8082-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 42P01
2021-09-26 11:55:44.882 ERROR 19759 --- [nio-8082-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: relation "employees" does not exist
Position: 301
2021-09-26 11:55:44.884 ERROR 19759 --- [nio-8082-exec-2] o.t.n.controller.EmployeeController : Exception: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet

Jackson Error When Doing Integration Test with Sprint Boot & GraphQL

I'm trying to write integration tests for my GraphQL code with Spring Boot and having problems.
First, this is the library I'm using for GraphQL Spring Boot integration:
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>7.0.1</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter-test</artifactId>
<version>7.0.1</version>
<scope>test</scope>
</dependency>
I've got all my resolvers built perfectly, I can call them from postman no problem. It's my test code where the problem comes up. I want to do integration tests, running end-to-end. For my first test, here is my GraphQL query file:
query {
clients {
id
name
clientKey
enabled
allowAuthCode
allowClientCredentials
allowPassword
}
}
This is a perfectly valid query for my GraphQL API, I can run it from Postman successfully. Here is my test code:
#ExtendWith(SpringExtension::class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ClientQueryIntegrationTest {
#Autowired
private lateinit var graphqlRestTemplate: GraphQLTestTemplate
#Test
fun test() {
graphqlRestTemplate.addHeader("Authorization", "Bearer $token")
val response = graphqlRestTemplate.postForResource("graphql/getAllClients.graphql")
}
}
When I run this, I get a Jackson deserialization error with my initial GraphQL request. I know it is loading my GraphQL query correctly because of the information in the error message, I just don't know why Jackson is de-serializing this incorrectly during my tests.
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `graphql.kickstart.execution.GraphQLRequest` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"query":"query {\n clients {\n id\n name\n clientKey\n enabled\n allowAuthCode\n allowClientCredentials\n allowPassword\n }\n}\n","variables":null}')
at [Source: (String)""{\"query\":\"query {\\n clients {\\n id\\n name\\n clientKey\\n enabled\\n allowAuthCode\\n allowClientCredentials\\n allowPassword\\n }\\n}\\n\",\"variables\":null}""; line: 1, column: 1]
What can I try next?

Spring Boot WebClient XML

My spring boot application wants to use Webclient to make an http request (XML request body) and receives XML response. Hence I created another spring boot application with jackson-dataformat-xml and created an endpoint to receive and return XML as below.
spring-boot-version=2.2.5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
#PostMapping(value = "/api",
consumes = MediaType.APPLICATION_XML_VALUE,
produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<MyXmlResponse> trip(#RequestBody MyXmlRequest request) throws Exception {
MyXmlResponse response = new MyXmlResponse();
response.setStatus("SUCCESS");
response.setTripID(request.getTripID());
return ResponseEntity.ok().body(response);
}
It works perfect and obviously no JaxB annotations are required as I use jackson-dataformat-xml. Also the request XML can be case-insensitive.
Now, in my first application I want to consume this API via webclient. I read that Spring webflux do not support Jackson-dataformat-xml yet. Hence I have to annotate my classes with Jaxb annotations.
spring-boot-version=2.2.5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
webClient.post()
.uri(URI.create("url-to-api-endpoint"))
.body(Mono.just(myXmlRequest), MyXmlRequest.class)
.exchange()
.doOnSuccess(response -> {
HttpStatus statusCode = response.statusCode();
log.info("Status code of external system request {}", statusCode);
})
.doOnError(onError -> {
log.error("Error on connecting to external system {}", onError.getMessage());
})
.flatMap(response -> response.bodyToMono(MyXmlResponse.class))
.subscribe(this::handleResponse);
Above code throws an exception as follows
org.springframework.webreactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=com.example.MyXmlRequest
at org.springframework.web.reactive.function.BodyInserters.unsupportedError(BodyInserters.java:391)
I fixed this problem by annotating with XmlRootElement as follows
#Getter #Setter #NoArgsConstructor #ToString
#XmlRootElement()
public class MyXmlRequest {
private String attribute1;
}
On the next attempt I got another error as follows
reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=com.example.MyXmlResponse
Caused by: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=com.example.MyXmlResponse
This could be solved by annotating MyXmlResponse with XmlRootElement as follows
#Getter #Setter #NoArgsConstructor #ToString
#XmlRootElement()
public class MyXmlResponse {
private String attr1;
private String attr2;
}
This time I get unmarshallexception as follows
reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.core.codec.DecodingException: Could not unmarshal XML to class com.example.MyXmlResponse; nested exception is javax.xml.bind.UnmarshalException
- with linked exception:
[com.sun.istack.internal.SAXParseException2; lineNumber: 1; columnNumber: 15; unexpected element (uri:"", local:"MyXmlResponse"). Expected elements are <{}myXmlResponse>]
Caused by: org.springframework.core.codec.DecodingException: Could not unmarshal XML to class com.example.MyXmlResponse; nested exception is javax.xml.bind.UnmarshalException
- with linked exception:
I fixed it with additional attributes passed to annotation as follows.
#XmlRootElement(name = "MyXmlResponse", namespace = "")
public class MyXmlResponse {
In future, my XML structures going to be tremendously complex. I want to know if I am doing it the right way.

SpEL evaluation of path variable in WebsocketSecurityConfiguration

I am running a JHipster 6.1.2 Gateway with Websockets and am trying to restrict access to a messaging topic, so that users can only subscribe to topics of the institution they belong to. So basically I want to perform a check on the id from the subscription path.
My current solution is based on https://stackoverflow.com/a/44895369/4246074 and looks as follows:
WebsocketSecurityConfiguration.java:
#Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
//...
//User can only subscribe to own institution topic
.simpSubscribeDestMatchers("/topic/institution.{id}")
.access("#institutionIdGuard.checkInstitutionId(#id)")
//...
}
InstitutionIdGuard.java:
#Component
public class InstitutionIdGuard {
public boolean checkInstitutionId(Long institutionId) {
//validation logic for institutionId would go here
return true;
}
The problem:
Apparently the SpEL expression can't access {id} from the path because i get a nullpointer error with the following log:
2019-08-08 10:30:08.367 ERROR 31097 --- [ XNIO-1 I/O-1] o.s.w.s.m.StompSubProtocolHandler : Failed to send client message to application via MessageChannel in session j2a0jlos. Sending STOMP ERROR to client.
org.springframework.messaging.MessageDeliveryException: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is java.lang.IllegalArgumentException: Failed to evaluate expression '#institutionIdGuard.checkInstitutionId(#id)'
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:146)
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122)
at org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageFromClient(StompSubProtocolHandler.java:284)
at org.springframework.web.socket.messaging.SubProtocolWebSocketHandler.handleMessage(SubProtocolWebSocketHandler.java:324)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56)
at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58)
at org.springframework.web.socket.sockjs.transport.session.AbstractSockJsSession.delegateMessages(AbstractSockJsSession.java:386)
at org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession.handleMessage(WebSocketServerSockJsSession.java:195)
at org.springframework.web.socket.sockjs.transport.handler.SockJsWebSocketHandler.handleTextMessage(SockJsWebSocketHandler.java:93)
at org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:113)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:42)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:84)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:81)
at io.undertow.websockets.jsr.FrameHandler$7.run(FrameHandler.java:286)
at io.undertow.websockets.jsr.ServerWebSocketContainer$1.call(ServerWebSocketContainer.java:170)
at io.undertow.websockets.jsr.ServerWebSocketContainer$1.call(ServerWebSocketContainer.java:167)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.websockets.jsr.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:604)
at io.undertow.websockets.jsr.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:594)
at io.undertow.websockets.jsr.FrameHandler.invokeTextHandler(FrameHandler.java:266)
at io.undertow.websockets.jsr.FrameHandler.onFullTextMessage(FrameHandler.java:317)
at io.undertow.websockets.core.AbstractReceiveListener$2.complete(AbstractReceiveListener.java:156)
at io.undertow.websockets.core.AbstractReceiveListener$2.complete(AbstractReceiveListener.java:152)
at io.undertow.websockets.core.BufferedTextMessage.read(BufferedTextMessage.java:105)
at io.undertow.websockets.core.AbstractReceiveListener.readBufferedText(AbstractReceiveListener.java:152)
at io.undertow.websockets.core.AbstractReceiveListener.bufferFullMessage(AbstractReceiveListener.java:90)
at io.undertow.websockets.jsr.FrameHandler.onText(FrameHandler.java:182)
at io.undertow.websockets.core.AbstractReceiveListener.handleEvent(AbstractReceiveListener.java:44)
at io.undertow.websockets.core.AbstractReceiveListener.handleEvent(AbstractReceiveListener.java:33)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener.handleEvent(AbstractFramedChannel.java:951)
at io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener.handleEvent(AbstractFramedChannel.java:932)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:88)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:561)
Caused by: java.lang.IllegalArgumentException: Failed to evaluate expression '#institutionIdGuard.checkInstitutionId(#id)'
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:30)
at org.springframework.security.messaging.access.expression.MessageExpressionVoter.vote(MessageExpressionVoter.java:57)
at org.springframework.security.messaging.access.expression.MessageExpressionVoter.vote(MessageExpressionVoter.java:39)
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:63)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233)
at org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor.preSend(ChannelSecurityInterceptor.java:69)
at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178)
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132)
... 37 common frames omitted
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1004E: Method call: Method checkInstitutionId(null) cannot be found on type com.mycompany.websocketgateway.security.InstitutionIdGuard
at org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:225)
at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:134)
at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:54)
at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:390)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:90)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:114)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:300)
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:26)
... 44 common frames omitted
I would be grateful for any ideas how to make my solution work or other other ways of performing checks in the id.
I found the solution on the Spring Security issue tracker. Apparently before Spring Security 5.2 you can pass the implicit message variable to the SpEL expression
.simpSubscribeDestMatchers("/topic/institution.*")
.access("#institutionIdGuard.checkInstitutionId(authentication, message)")
Then in the verification method its possible to get the path from the message and do your own verification with it:
public boolean checkInstitutionId(Authentication authentication, Message<?> message) {
StompHeaderAccessor sha = StompHeaderAccessor.wrap(message);
String topic = sha.getDestination();
String id = topic.replace("/topic/institution/", "");
//validation logic for institutionId would go here
return true;
}
Spring Security 5.2 should have fixed the issue according to this pull request.

Jersey 2.6 with Jackson JSON deserialization

My goal is to make web calls and convert returned JSON to POJOs. I'm trying to use Jersey+Jackson for this but am getting exceptions when running.
My maven pom file includes the following dependencies -
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.6</version>
</dependency>
The code I use to make fetch some data is as follows -
Client client = ClientBuilder.newBuilder()
.register(JacksonFeature.class)
.build();
ClientResponse response = client.target(url).request(MediaType.APPLICATION_JSON).get(ClientResponse.class);
But the following exception is throw -
javax.ws.rs.ProcessingException: Error reading entity from input stream.
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:868)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:785)
at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:335)
...
...
Caused by: org.codehaus.jackson.map.JsonMappingException: Can not find a deserializer for non-concrete Map type [map type; class javax.ws.rs.core.MultivaluedMap, [simple type, class java.lang.String] -> [collection type; class java.util.List, contains [simple type, class java.lang.String]]]
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCache2(StdDeserializerProvider.java:315)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCacheValueDeserializer(StdDeserializerProvider.java:290)
at org.codehaus.jackson.map.deser.StdDeserializerProvider.findValueDeserializer(StdDeserializerProvider.java:159)
at org.codehaus.jackson.map.deser.std.StdDeserializer.findDeserializer(StdDeserializer.java:620)
at org.codehaus.jackson.map.deser.BeanDeserializer.resolve(BeanDeserializer.java:379)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._resolveDeserializer(StdDeserializerProvider.java:407)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCache2(StdDeserializerProvider.java:352)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCacheValueDeserializer(StdDeserializerProvider.java:290)
at org.codehaus.jackson.map.deser.StdDeserializerProvider.findValueDeserializer(StdDeserializerProvider.java:159)
at org.codehaus.jackson.map.deser.StdDeserializerProvider.findTypedValueDeserializer(StdDeserializerProvider.java:180)
at org.codehaus.jackson.map.ObjectMapper._findRootDeserializer(ObjectMapper.java:2829)
at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2699)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1315)
at org.codehaus.jackson.jaxrs.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:419)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:257)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:229)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:149)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1124)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:853)
... 90 more
Caused by: java.lang.IllegalArgumentException: Can not find a deserializer for non-concrete Map type [map type; class javax.ws.rs.core.MultivaluedMap, [simple type, class java.lang.String] -> [collection type; class java.util.List, contains [simple type, class java.lang.String]]]
at org.codehaus.jackson.map.deser.BasicDeserializerFactory.createMapDeserializer(BasicDeserializerFactory.java:424)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createDeserializer(StdDeserializerProvider.java:380)
at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCache2(StdDeserializerProvider.java:310)
... 108 more
Am I missing some setup to get this to work right?
I have tried the url via curl and browser and it returns JSON as expected.
What you need is a Response and not a ClientResponse:
javax.ws.rs.core.Response jsonResponse = client.target(url).request(MediaType.APPLICATION_JSON).get();
Then you can see what comes in your response (debugging is your friend here). Is it by any chance a map of some type? If it is, you can read it by doing e.g.
Map<SomeClassOfYours> entitiesFromResponse = jsonResponse.readEntity(new GenericType<Map<SomeClassOfYours>>() {});
If you've put a normal entity in the response you can simply do something like:
SomeClassOfYours entityFromResponse = jsonResponse.readEntity(SomeClassOfYours.class);
Edit: For this to work you'd also need to define SomeClassOfYours and put the corresponding fields, constructor, getters and setters in there.
Edit2: When in doubt you can always read the jsonResponse as a String.class and put it in a String variable.
Response jsonResponse = getClient().target(URI).request().get();
T result = jsonResponse.readEntity(type);

Resources