Reactor Feign cannot deserialize Flux response - json

I have the following controller
#RestController
public void MyController {
#GetMapping("/foo")
public Flux<Foo> getFoos() { /* return a flux of Foos*/ }
}
And a Feign client
public interface MyFeignClient {
#RequestLine("GET /foo")
Mono<Foo> getFoos();
}
public class MyClients {
public static MyFeignClient myFeignClient() {
return ReactorFeign.builder().target(MyFeignClient.class, "http://localhost:8080");
}
}
But when I call
StepVerifier.create(myFeignClient.foo())
.consumeNextWith(foo -> println(foo))
.verifyCompleted();
I got this error
java.lang.AssertionError: expectation "consumeNextWith" failed
(expected: onNext(); actual: onError(feign.FeignException: Cannot
deserialize instance of
com.example.Foo out of
START_ARRAY token at [Source: (BufferedReader); line: 1, column: 1]
reading GET
http://localhost:8080/foo))
at
reactor.test.ErrorFormatter.assertionError(ErrorFormatter.java:105)
at reactor.test.ErrorFormatter.failPrefix(ErrorFormatter.java:94) at
reactor.test.ErrorFormatter.fail(ErrorFormatter.java:64) at
reactor.test.ErrorFormatter.failOptional(ErrorFormatter.java:79) at
reactor.test.DefaultStepVerifierBuilder.lambda$consumeNextWith$1(DefaultStepVerifierBuilder.java:256)
at
reactor.test.DefaultStepVerifierBuilder$SignalEvent.test(DefaultStepVerifierBuilder.java:2112)
at
reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onSignal(DefaultStepVerifierBuilder.java:1408)
at
reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onExpectation(DefaultStepVerifierBuilder.java:1356)
at
reactor.test.DefaultStepVerifierBuilder$DefaultVerifySubscriber.onError(DefaultStepVerifierBuilder.java:1030)
at
reactor.core.publisher.FluxTake$TakeSubscriber.onError(FluxTake.java:138)
at
reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.onError(FluxSubscribeOn.java:157)
at
feign.reactive.ReactiveInvocationHandler$1.request(ReactiveInvocationHandler.java:115)
at
reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.requestUpstream(FluxSubscribeOn.java:131)
at
reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.onSubscribe(FluxSubscribeOn.java:124)
at
feign.reactive.ReactiveInvocationHandler.lambda$invokeMethod$0(ReactiveInvocationHandler.java:99)
at reactor.core.publisher.FluxSource.subscribe(FluxSource.java:52)
at reactor.core.publisher.Flux.subscribe(Flux.java:7777) at
reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:194)
at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:84) at
reactor.core.scheduler.WorkerTask.call(WorkerTask.java:37) at
java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at
java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834) Suppressed:
feign.FeignException: Cannot deserialize instance of
com.example.Foo out of
START_ARRAY token at [Source: (BufferedReader); line: 1, column: 1]
reading GET
http://localhost:8080/foo at
feign.FeignException.errorReading(FeignException.java:130) at
feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:162)
at
feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:80)
at
feign.reactive.ReactiveInvocationHandler$1.request(ReactiveInvocationHandler.java:109)
... 13 more Caused by:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot
deserialize instance of
com.example.Foo out of
START_ARRAY token at [Source: (BufferedReader); line: 1, column: 1]
at
com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at
com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
at
com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1139)
at
com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1093)
at
com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromArray(BeanDeserializerBase.java:1461)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:185)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
at
com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at
com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3063)
at feign.jackson.JacksonDecoder.decode(JacksonDecoder.java:61) at
feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:183)
at
feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:147)
... 15 more
What have I done wrong here? How can I fix it?

A simple google search shows that the feign client does not support reactive. They have an incubating project trying to create support
Add Webflux support issue
Feign core
So to answer your questions
"What have i done wrong?"
You have chosen to use an HttpClient that does not support producers/consumers.
"How can i fix it?"
By not using the feign client and instead use an HttpClient that supports non blocking operations, like for instance, the spring WebClient.

Related

Send Exception and Json with spring MVC

I'm trying to manage exceptions in a Spring MVC context and send different http statuses in response.
I tried this :
#ResponseStatus(value = HttpStatus.SERVICE_UNAVAILABLE)
public class UnavailableServiceException extends RuntimeException {
}
When I send this exception in my controller, it works fine : response http status is 503.
But I want my controller to send json, and with this configuration, when 503 is send, response is html :-/
So I tried this :
Removing #ResponseStatus on my exception class and defining an Exception handler.
#ExceptionHandler(UnavailableServiceException.class)
public ResponseEntity<ExceptionJSONInfo> handleUnavailableService(UnavailableServiceException exception) {
return new ResponseEntity<ExceptionJSONInfo>(new ExceptionJSONInfo("Error xxx", exception.getMessage()), HttpStatus.SERVICE_UNAVAILABLE);
}
It's ok : 503 and json.
But I want to manage 5 or 6 different exceptions : how can I do this without duplicating handlers ?
Is it possible to retrieve #ResponseStatus defined on an exception ?
If not, my next idea will be to define an httpStatus attribute in a super class, mother of all my exceptions. And then :
public class UnavailableServiceException extends MySuperException {
super(HttpStatus.SERVICE_UNAVAILABLE);
}
#ExceptionHandler(MySuperException.class)
public ResponseEntity<ExceptionJSONInfo> handleUnavailableService(MySuperException exception) {
return new ResponseEntity<ExceptionJSONInfo>(new ExceptionJSONInfo("Error xxx", exception.getMessage()), exception.getHttpStatus());
}
Any better idea ?
Thanks
Manu

Spring 4 + #ControllerAdvice: Jsonp support for ResponseBody causes Deployment Exception?

I am adding JSONP support to a REST Service in SPRING4 + JDK 8 + STS 3.6.4
Versions:
Spring 4.1.6.RELEASE
My implementation is based on these links:
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-ann-jsonp
The REST service returns ResponseEntity or ResponseBody and use case is to return data in JSONP format.
Added a ControllerAdvice
#ControllerAdvice
public class JsonpCallbackAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpCallbackAdvice(){
super("Callback");
}
}
Here is the Controller of the REST Service
#Controller
public class AcctController {
...
#RequestMapping(value = "/act/{actNum}", method = RequestMethod.GET)
public ResponseEntity<Account> getAccount(#PathVariable("actNum") Integer accountNum) throws Exception {
...
return new ResponseEntity<account>();
}
Here is the relevant web application context configuration
...
<context:component-scan base-package="com.controllers" />
<bean name="jsonMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
...
The controller and ControllerAdvice are in same package.
When deployment of the project is initiated following exception is observed
Caused by: java.lang.ClassCastException: [Ljava.lang.String; cannot be cast to java.lang.String
at org.springframework.context.annotation.AnnotationBeanNameGenerator.determineBeanNameFromAnnotation(AnnotationBeanNameGenerator.java:91)
at org.springframework.context.annotation.AnnotationBeanNameGenerator.generateBeanName(AnnotationBeanNameGenerator.java:69)
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:246)
at org.springframework.context.annotation.ComponentScanBeanDefinitionParser.parse(ComponentScanBeanDefinitionParser.java:84)
at org.springframework.beans.factory.xml.NamespaceHandlerSupport.parse(NamespaceHandlerSupport.java:74)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1427)
at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1417)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:174)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:144)
at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:100)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:510)
at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:392)
This exception was not happening before the ControllerAdvice was added.
Also, it does not happens when #ControllerAdvice annotation is removed
or
the component scan excludes scanning package of the ControllerAdvice class
I tried with Spring version 4.2.0.RC1, and the exception still happens.
Kindly help with resolution of this exception, since not much help is available online.
It seems like a bug in SPRING 4, however am not sure.

JSON, JAXB,JSON Rest

I created a Rest Service which has is working fine in XML request ( Rest Service input JAXB generated class ). When I am trying to send a Json Request, It's throwing an exception.
SEVERE: The exception contained within MappableContainerException could not be mapped to a response, re-throwing to the HTTP container
org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type, class Transaction] from JSON String; no single-String constructor/factory method (through reference chain:
class Transaction which is inner class .
My Request class is generated from schema using JAXB, My getter method is like below but no setter method.
public List<Transaction> getORIG() {
if (origtrans == null) {
origtrans = new ArrayList<Transaction>();
}
return this.origtrans;
}
My Json Request below
{
"LOB_CD": "42424"
"ORIGINALTRANSACTION" : [
"LOGON_ID" : "TEST"
]
}
When I am addiong original Transaction it's throwing an error otherwise it's working fine.
Can you please help me out with this.
Thanks in advance.
First of all make sure you are using a valid JSON, like:
{
"LOB_CD": "42424",
"ORIGINALTRANSACTION": {
"LOGON_ID": "TEST"
}
}
Also, it would be nice if you could show us the Transaction class.
It works.
I did following steps
1) Added an empty constructor
2) Added this annotation for the list
#JsonDeserialize(as=ArrayList.class, contentAs=Transaction.class)
3) change a Json Object to
{ "LOB_CD": "42424" "ORIGINALTRANSACTION" : [ { "LOGON_ID" : "TEST" } ] }
Thanks a lot,
Patel

How to use Spring Data CouchBase 'findAll(Iterable<ID>)' Method?

I'm trying to use Spring-Data-Couchbase.
I want to get List from findAll(Iterable) method.
I set view 'all' to my Production View.
But, I meet the exception.
How Can I use findAll(Iterable) method?
Below is a Sample Code and exception.
Document Class:
#Document
public class User {
#Id
private String id;
private String userSeq;
}
Repository Class :
public interface UserRepository extends CouchbaseRepository<User, String> {
}
Service Class:
//List<String> get the Same result & exception.
Set<String> friendSet = new HashSet<String>();
friendSet.add("User8");
friendSet.add("User6");
userRepository.findAll(friendSet)
Exception:
Caused by: java.util.concurrent.ExecutionException: OperationException: SERVER: bad_request Reason: invalid UTF-8 JSON: {{error,{2,"lexical error: invalid char in json text.\n"}},
"[User8, User6]"}
at com.couchbase.client.internal.HttpFuture.waitForAndCheckOperation(HttpFuture.java:98)
at com.couchbase.client.internal.HttpFuture.get(HttpFuture.java:82)
at com.couchbase.client.internal.HttpFuture.get(HttpFuture.java:72)
at com.couchbase.client.CouchbaseClient.query(CouchbaseClient.java:778)
... 66 more
Caused by: OperationException: SERVER: bad_request Reason: invalid UTF-8 JSON: {{error,{2,"lexical error: invalid char in json text.\n"}},
"[User8, User6]"}
at com.couchbase.client.protocol.views.NoDocsOperationImpl.parseError(NoDocsOperationImpl.java:110)
at com.couchbase.client.protocol.views.ViewOperationImpl.handleResponse(ViewOperationImpl.java:68)
at com.couchbase.client.http.HttpResponseCallback.completed(HttpResponseCallback.java:103)
at com.couchbase.client.http.HttpResponseCallback.completed(HttpResponseCallback.java:51)
at org.apache.http.concurrent.BasicFuture.completed(BasicFuture.java:115)
at org.apache.http.nio.protocol.HttpAsyncRequester$RequestExecutionCallback.completed(HttpAsyncRequester.java:376)
at org.apache.http.concurrent.BasicFuture.completed(BasicFuture.java:115)
at org.apache.http.nio.protocol.BasicAsyncClientExchangeHandler.responseCompleted(BasicAsyncClientExchangeHandler.java:179)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(HttpAsyncRequestExecutor.java:349)
at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(HttpAsyncRequestExecutor.java:236)
at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:267)
at org.apache.http.impl.nio.DefaultHttpClientIODispatch.onInputReady(DefaultHttpClientIODispatch.java:165)
at org.apache.http.impl.nio.DefaultHttpClientIODispatch.onInputReady(DefaultHttpClientIODispatch.java:51)
at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:113)
at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:159)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:338)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:316)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:277)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:105)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:584)
... 1 more
You have to quote the id:s before you call findAll(...).
Set<String> friendSet = new HashSet<String>();
friendSet.add("\"User8\"");
friendSet.add("\"User6\"");
If the id:s aren't quoted the keys parameter sent to the Couchbase server will look something like [User8, User6] which isn't valid JSON, hence the exception. Pretty surprising behaviour...

Consuming JSON with Jersey 2.3 throws XML exception

I'm trying to make Jersey 2.3 + Moxy work with my custom objects. Everything is ok when I'm producing JSON from those objects, but refuses to work when I want to consume them by POST. Code first:
Custom object:
#XmlRootElement
public class ContentAction extends Action {
private String contentType;
private Integer contentLength;
public ContentAction() {
setType(ActionType.CONTENT);
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public Integer getContentLength() {
return contentLength;
}
public void setContentLength(Integer contentLength) {
this.contentLength = contentLength;
}
}
Resource fragment (path is declared on the class):
#POST
#Produces(JsonHelper.JSON_UTF8)
public Action saveAction(#QueryParam("action") ContentAction action) throws IOException {
ActionEntity entity = actionConverter.toEntity(action);
entity.setBeacon(beaconService.findById(action.getBeacon().getId()));
return actionConverter.convert(actionService.save(entity));
}
API caller (class responsible for sending requests):
URI uri = buildUri(path, params);
HttpPost httpPost = new HttpPost(uri);
httpClient.execute(httpPost);
buildUri simply creates URI from address & parameters
The action is converted to JSON as follows: mapper.writeValueAsString(action)
And the exception:
org.glassfish.jersey.server.internal.inject.ExtractorException: Error unmarshalling JAXB object of type "class com.kontakt.platform.apicommon.model.ContentAction".
at org.glassfish.jersey.server.internal.inject.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:195)
at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.convert(AbstractParamValueExtractor.java:138)
at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.fromString(AbstractParamValueExtractor.java:129)
at org.glassfish.jersey.server.internal.inject.SingleValueExtractor.extract(SingleValueExtractor.java:83)
at org.glassfish.jersey.server.internal.inject.QueryParamValueFactoryProvider$QueryParamValueFactory.provide(QueryParamValueFactoryProvider.java:88)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:81)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:121)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:353)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:343)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:255)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
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:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:235)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:983)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:359)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1008)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1852)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:512)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:209)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:140)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:123)
at org.glassfish.jersey.server.internal.inject.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:190)
... 40 more
Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:441)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1388)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:998)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:489)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
... 44 more
When I remove #XmlRootElement, Jersey tries to create object from constructor with string parameter (if added) = no automatic bean creation.
I've been stuck with this for two days and I'd be very grateful for any help.
I think the problem is that you need to set the content type. Since you are not specifying the content type, jersey is assuming it is reciving xml but it is in fact json. The error message is from jaxb trying to read the xml header and finding invalid characters. Try using the jersey client instead of an http post. Also I think you might what to change your #Produces(MediaType.APPLICATION_JSON) for consistency.
#Produces(MediaType.APPLICATION_JSON)
Example POST CODE
The most important part is that I am setting the type (type(MediaType.Application_JSON) that I am going to post.
WebResource webResource = createRestClient(true).resource(
REST_BASE_PATH + "/service");
ClientResponse response = webResource.type(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, contentActionObject);
Assert.assertTrue(response.getStatus() == 200);
If you do need to use the HttpPost object then there should be a configuration option to set http headers. I have done this using the the HttpUrlConnection. You would have to set your content type to be application/json instead of xml.
HttpURLConnection connection = null;
connection = (HttpURLConnection) new URL(requestUrl).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/xml");
connection.setRequestProperty("Content-Type", "application/xml");
EclipseLink MOXy will be picked up as the JSON-binding provder by Jersey for media types that follow the following pattern.
*/json (i.e. application/json and text/json)
/+json
Based on your exception it appears as though the media type have have represented with JsonHelper.JSON_UTF8 does not match this pattern.
I know this is a little old, but I have been encountering the essentially the identical issue using Jersey 2.3 + Moxy. Same scenario and the identical exception is occurring. The only difference is that my POST method is annotated with:
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
I did find that when if I passed the same JSON representation in the request body instead of as a query parameter that it was unmarshalled successfully. This would require changing your POST method declaration to:
public Action saveAction(ContentAction action)
Not sure if this would be a work around for you. If you found a resolution I would be interested in hearing what it was.