Spring boot RestTemplate post giving 400 error - java

I've written a simple webService in Java 8, on Eclipse Photon, using RestTemplate to post (using postForObject) an object (called patentListWrapper) that wraps a List of objects (called PatentDetails ). I post from a Java client (called MainWsClient ) , then set a value in patentDetails on the server side and read the patentListWrapper object back at the client. It works fine when the server side (program SpringWebServiceHello) uses old Spring MVC 4 technology with only 1 jar file (Spring-web.5.07.RELEASE.jar) following this - serverSideExample ie a web.xml and rest-servlet.xml files controlling the access point. I then wrote another server side program (PndGuidRequestWs) using SpringBoot 2.03 with Spring 5.07 jars, and Maven ,with an identicle #RequestMapping method but no web.xml file and the access point defined in the application.properties file:
server.port=8082
server.servlet.path=/
#spring.mvc.servlet.path=/
#server.servlet.contextPath=/
When I call this new server program using this client - ARC it also works fine
but when I call it using the same java client and exactly the same request (accept for a different url obviously). I get a 400 error:
2018-12-18 16:56:53,861 [main] INFO - Running MainWsClient with name = DS fileType = post3
2018-12-18 16:56:54,101 [main] DEBUG - Created POST request for "http://localhost:8082/guidRequest/xmlList"
2018-12-18 16:56:54,145 [main] DEBUG - Setting request Accept header to [application/xml, text/xml, application/json, application/*+xml, application/*+json]
2018-12-18 16:56:54,152 [main] DEBUG - Writing [com.springservice.client.PatentListWrapper#4ba2ca36] using [org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter#3444d69d]
2018-12-18 16:56:54,384 [main] DEBUG - POST request for "http://localhost:8082/guidRequest/xmlList" resulted in 400 (null); invoking error handler
2018-12-18 16:56:54,387 [main] ERROR - DS1B org.springframework.web.client.HttpClientErrorException: 400 null
The non working ,PndGuidRequestWs, server side has:
#RestController
public class PndController {
#RequestMapping(value = "/guidRequest/xmlList", method = RequestMethod.POST, produces = { "application/xml" } )
public PatentListWrapper guidSearchList(#RequestBody PatentListWrapper patentListWrapper) {
for (PatentDetails pd : patentListWrapper.getPatentList())
{
pd.setGuid("guidSetOnServer3");
}
return patentListWrapper;
}
}
The working (SpringWebServiceHello) server side is identicle except for :
value = "/service/greeting/xml/post2"
The Java client has:
public void runCode(String name , String fileType)
{
String url;
if (fileType.equalsIgnoreCase("post2")) {
url = "http://localhost:8080/SpringWebServiceHello/service/greeting/xml/post2";
// This method is identicle to postToPndGuidRequestWs() but this method works fine.
postToSpringWebServiceHello(url);
}else if (fileType.equalsIgnoreCase("post3")) {
url = "http://localhost:8082/guidRequest/xmlList";
// This method gives 404 error
postToPndGuidRequestWs(url);
}
}
private void postToPndGuidRequestWs(String url)
{
PatentListWrapper patentListWrapper = new PatentListWrapper();
PatentDetails pd = new PatentDetails("CN","108552082","A","00000000",12345,"guidIn");
List<PatentDetails> patentList = new ArrayList<PatentDetails>();
patentList.add(pd);
patentListWrapper.setPatentList(patentList);
RestTemplate restTemplate = new RestTemplate();
/* HttpHeaders headers = new HttpHeaders();
headers.add("header_name", "header_value");
headers.setContentType(MediaType.APPLICATION_XML);
HttpEntity<PatentListWrapper> request = new HttpEntity<PatentListWrapper>(patentListWrapper, headers); */
/*List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
Jaxb2RootElementHttpMessageConverter jaxbMessageConverter = new Jaxb2RootElementHttpMessageConverter();
List<MediaType> mediaTypes = new ArrayList<MediaType>();
mediaTypes.add(MediaType.APPLICATION_XML);
jaxbMessageConverter.setSupportedMediaTypes(mediaTypes);
messageConverters.add(jaxbMessageConverter);
restTemplate.setMessageConverters(messageConverters);*/
/* headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML));
HttpEntity<String> entity = new HttpEntity<>("parameters", headers);*/
try {
patentListWrapper = restTemplate.postForObject(
url,
patentListWrapper,
PatentListWrapper.class);
logger.debug("DS1A employee obj returned. guid = " + patentListWrapper.getPatentList().get(0).getGuid());
}catch(Exception e) {
logger.error("DS1B " + e);
}
}
}
ie fileType="post2" calls SpringWebServiceHello, fileType="post3" calls PndGuidRequestWs. As you can see i've tried several commented out solutions but nothing works. Since the only real difference between the 2 server side programs is that none working one uses Spring boot and the working one doesn't the problem must be in the SpringBoot setup ie directory structure, application.properties or pom.xml. My pom.xml has:
<?xml version="1.0" encoding="UTF-8"?>
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
<groupId>com.clarivate</groupId>
<artifactId>pndguidrequestws</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>pndGuidRequestWs</name>
<description>Guid request webService</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<start-class>com.clarivate.pndguidrequestws.PndGuidRequestWsApplication</start-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.1.0</version>
<!-- <scope>provided</scope> --> <!-- DS insert for unix -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Implementing XML Representation for Spring Boot Services -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<!-- httpcomponents jars are Required by PndGuidGenerator -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
<build>
<finalName>PndGuidRequestWs</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
</project>
The PatentListWrapper class is:
package com.clarivate.pndguidrequestws.model;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class PatentListWrapper {
private List<PatentDetails> patentList;
public PatentListWrapper() {}
public List<PatentDetails> getPatentList() {
return patentList;
}
public void setPatentList(List<PatentDetails> patentList) {
this.patentList = patentList;
}
}
Any suggestions most welcome.
EDIT:
To simplify the object I created PatentListWrapper2 with just 1 string member:
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class PatentListWrapper2 {
private String name;
public PatentListWrapper2() {}
public PatentListWrapper2(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I can again successfully send this xml using the ARC client:
<patentListWrapper2>
<name>DSDS</name>
</patentListWrapper2>
with contentType="application/xml"
but when I try to send patentListWrapper2 from java I get an unmarshalling error:
2018-12-20 09:17:13,931 [main] INFO - Running MainWsClient with name = DS fileType = post4
2018-12-20 09:17:14,166 [main] DEBUG - Created POST request for "http://localhost:8082/guidRequest/xmlList2"
2018-12-20 09:17:14,200 [main] DEBUG - Setting request Accept header to [application/xml, text/xml, application/json, application/*+xml, application/*+json]
2018-12-20 09:17:14,206 [main] DEBUG - Writing [com.springservice.client.PatentListWrapper2#517cd4b] using [org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter#6cc7b4de]
2018-12-20 09:17:14,246 [main] DEBUG - POST request for "http://localhost:8082/guidRequest/xmlList2" resulted in 200 (null)
2018-12-20 09:17:14,248 [main] DEBUG - Reading [com.springservice.client.PatentListWrapper2] as "application/xml;charset=UTF-8" using [org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter#6cc7b4de]
2018-12-20 09:17:14,255 [main] ERROR - DS2B org.springframework.web.client.RestClientException: Error while extracting response for type [class com.springservice.client.PatentListWrapper2] and content type [application/xml;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: Could not unmarshal to [class com.springservice.client.PatentListWrapper2]: unexpected element (uri:"", local:"PatentListWrapper2"). Expected elements are <{}patentListWrapper2>; nested exception is javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"PatentListWrapper2"). Expected elements are <{}patentListWrapper2>
EDIT2 I ran pndGuidRequestWs on Eclipse Tomcat , instead of - Run As -> Spring Boot App. The server log is below:
2018-12-20 11:15:45.655 WARN 236 --- [nio-8080-exec-6] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.clarivate.pndguidrequestws.model.PatentDetails` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('CN'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.clarivate.pndguidrequestws.model.PatentDetails` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('CN') at [Source: (PushbackInputStream); line: 1, column: 98] (through reference chain: com.clarivate.pndguidrequestws.model.PatentListWrapper["patentList"]->java.util.ArrayList[0])

Can you test with :
try {
HttpHeaders headers = new HttpHeaders();
//headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
//headers.setContentType((MediaType.APPLICATION_JSON));
// I comment the code abouve because you did not specify a consumes whitch defines the media types that the methods of
//a resource class or MessageBodyReader can accept. If not specified, a container will assume that any media type is acceptable.
HttpEntity<PatentListWrapper> request = new HttpEntity<>(patentListWrapper, headers);
PatentListWrapper patentListWrapperResult = = restTemplate.exchange(url, HttpMethod.POST, request,PatentListWrapper.class);
logger.debug("DS1A employee obj returned. guid = " + patentListWrapper.getPatentList().get(0).getGuid());
}catch(Exception e) {
logger.error("DS1B " + e);
}

PatentListWrapper is a complex object, not a piece of xml , so the answer is to remove all references to xml ie
Remove #XmlRootElement(name="PatentListWrapper") from PatentListWrapper.
Add jackson-*.jar(s) into the classpath to do the message converting
Change the server side #RequestMapping from :
#RequestMapping(value = "/xmlList", method = RequestMethod.POST , consumes = { "application/xml" }, produces = { "application/xml" })
to
#RequestMapping(value = "/xmlList", method = RequestMethod.POST )
This means that the ARC client now returns JSON (as it's the default return type), even when I send xml, but that's not important as it's just a test tool.
So, when posting objects with RestTemplate in Spring 2, no contentType settings or additional messageConverters are required on the client side , just:
RestTemplate restTemplate = new RestTemplate();
MyObject myObjectReturn = restTemplate.postForObject(url,myObject,MyObject.class);
and on the server side:
#RestController
#RequestMapping(value = "/endPoint", method = RequestMethod.POST)
public MyObject anyMethodName(#RequestBody MyObject myObject) {
//Do stuff to myObject
return myObject;
}

Related

Contract testing messages in a Flux in Spring Cloud Stream gives IllegalArgumentException Message must not be null

I'm trying to contract test a Flux of events emitted from an endpoint using Spring Cloud Stream and Spring Cloud Contract. However, I'm getting an IllegalArgumentException with detailMessage Message must not be null when running my test. Or in other words I'm not receiving any messages on my message receiver. My spring cloud version is Hoxton. I've added the following dependencies in my pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-kafka</artifactId>
</dependency>
<!--TEST -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-test-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-verifier</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
<type>test-jar</type>
<scope>test</scope>
<classifier>test-binder</classifier>
</dependency>
I've configured a new binding following the samples here. Is working properly when I run the app and I send a curl -X POST localhost:8080 request.
application.properties
stubrunner.stream.enabled=true
spring.cloud.stream.bindings.uppercase-in-0.destination=test
spring.cloud.stream.bindings.uppercase-in-0.group=testGroup
spring.cloud.stream.bindings.uppercase-out-0.destination=hood
spring.cloud.stream.bindings.consume-in-0.destination=hood
spring.cloud.stream.bindings.consume-out-0.destination=downtown
spring.cloud.stream.bindings.supplier-out-0.destination=test
spring.cloud.function.definition=uppercase;consume;supplier
Controller
#PostMapping(value = "/")
public void handlePost() {
Faker faker = new Faker();
Message<String> message = MessageBuilder.withPayload(faker.chuckNorris().fact()).build();
// supplier.get();
EventSupplier.processor.onNext(message);
}
Bean definition
#Configuration
public class EventSupplier {
public static final EmitterProcessor<Message<String>> processor = EmitterProcessor.create();
#Bean
// public Supplier<String> supplier() {
public Supplier<Flux<Message<String>>> supplier() {
// return () -> "";
return () -> processor;
}
}
Contracts Base test
#ActiveProfiles("test")
#SpringBootTest
#RunWith(SpringRunner.class)
#AutoConfigureMessageVerifier
#EnableBinding(KafkaStreamerApplication.class)
public abstract class KafkaStreamerApplicationTests {
#Autowired
private DummyController dummyController;
public void supply() {
dummyController.handlePost();
}
}
Contract
org.springframework.cloud.contract.spec.Contract.make {
label 'some_label'
input {
triggeredBy("supply()")
}
outputMessage {
sentTo('supplier-out-0')
body(
anyNonBlankString()
)
headers {
messagingContentType(applicationJson())
}
}
}
I've tried creating contracts for function and consumer and both worked. I've also tried using a supplier of type String instead of Flux<Message<String>> and worked too. You can look at the commented lines at the code above.
While debugging I've seen that in StreamMessageCollectorMessageReceiver I'm getting a DirectWithAttributesChannel instance when retrieving the MessageChannel bean at receive("supplier-out-0", 5, "SECONDS") method. Also while looking into the documentation I've found a MessageChannel implementation that, to me, looks like a candidate to be the one should have been instantiated FluxMessageChannel.
My guess is that spring cloud contract is waiting for a message to be sent into the queue directly(DirectWithAttributesChannel) but since the flux is already in the queue and I'm just updating the flux content, it means that not message is pushed into the queue(FluxMessageChannel?) so no message is received(null) and that's why I'm getting an IllegalArgumentException with details Message must not be null error when running my tests.
Is there something missing in my configuration? Can this scenario be tested by contracts? Is a bad approach to test this by using contracts?

Jersey test set max http header size

Does any body know how to set the max header size while using Grizzly2 and Jersey Test .
I'm currently using the following dependencies :
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.23.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.23.2</version>
</dependency>
and i have a simple Test class extending Jersey test like this :
public class JerseyTestInitializer extends JerseyTest {
#Override
public Application configure() {
// Configuration stuff
}
#Test
public void test() {
WebTarget webTarget = target(URL);
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON)
.header("test",SOME VALUE THAT IS MORE THAN 8K Characters);
SomeEntity someEntity = new SomeEntity();
Response response = invocationBuilder.post(Entity.entity(someEntity, MediaType.APPLICATION_JSON));
}
}
While performing the post i'm currently getting a HTTP status 400 with no other information about the bad request. If I use a header value with less than 8K characters , than it's working for me.
Please advice.
Thanks
Mohit
Please check on this question about URI size (this is also a header).
Jersey/Grizzly POST fails for large URI

How to enable multiple Content-Types for a response in spring-mvc?

I have a simple #RestController and would like to response with both JSON or XML depending on the http header content-type.
Problem: I'm always only getting XML response, never JSON. Of course I'm using Content-Type: application/json as http header.
What might be missing in the following configuration?
#RestController
public void MyServlet {
#RequestMapping(value = "test", method = RequestMethod.GET,
produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public MyResponse test() {
return new MyResponse();
}
}
#XmlRootElement
public class MyResponse {
private String test = "somevalue";
//getter, setter
}
pom.xml:
<!-- as advised in: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
</dependency>
Interestingly: if I switch the produces statement:
produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}),
then I'm always getting JSON out and never XML!
So the question is: why does the first MediaType always have precedence, and the http header is never taken into account?
In your case, you should use Accept header not Content-Type.
On a request, the Accept header is used to request the Content-Type of the response from the server.
On a request the Content-Type is used to define the structure of the request body.

Can't get json from Swagger + Jersey

I have RESTful service based on Jersey 1.18.1 and I want to show my API via Swagger.
Firstly I have to get JSON. I read this instruction: Swagger Core Jersey 1.X Project Setup 1.5. Swagger allows to set up a configuration different methods and I decided to use custom Application subclass. I did everything step by step but I can't get JSON which I have to use for swagger-ui.
What I did:
My custom Application
#ApplicationPath("api/v1")
public class DiscountsApp extends Application{
public DiscountsApp() {
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.2");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8002");
beanConfig.setBasePath("swaggerapi");
beanConfig.setResourcePackage("alexiuscrow.diploma.endpoints");
beanConfig.setScan(true);
}
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet();
resources.add(ShopsResources.class);
//...
resources.add(com.wordnik.swagger.jaxrs.listing.ApiListingResource.class);
resources.add(com.wordnik.swagger.jaxrs.listing.SwaggerSerializers.class);
return resources;
}
}
ShopsResources
#Path("/shops")
#Api(value="/shops", description="Shops")
public class ShopsResources {
#GET
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation(value = "List shops", httpMethod = "GET",
notes = "List nearest or locality shops",
response = Shops.class, responseContainer = "List")
public String getShops(
#ApiParam( value = "Radius", required = false)
#QueryParam("radius") String radiusParam,
#ApiParam( value = "Latitude", required = true)
#QueryParam("lat") String latParam,
#ApiParam( value = "Longitude", required = true)
#QueryParam("lng") String lngParam) throws SQLException{
//The list of Shops objects is serialized to string
//using the custom GSON serializer and I know
//that there is the better method of the solution of this task.
}
}
}
Some dependencies from pom.xml
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jersey-jaxrs</artifactId>
<version>1.5.1-M2</version>
</dependency>
After deploy application to Tomcat I tried to get http://localhost:8002/swaggerapi but I've got no result.
I didn't find the swagger.json in root of my application (/tomcat8/webapps/app).
What's wrong?
How can I get JSON with my API?
I did not correctly build the url.
Correct:
http://{host}:{port}/{context root of application}/{path from #ApplicationPath}/swagger.json
In my case: http://localhost:8080/app/api/v1/swagger.json
Thx to Ron.
adding a relative path worked for me (this is using .netcore 1.1)
app.UseSwaggerUI(s => {
s.RoutePrefix = "help";
s.SwaggerEndpoint("../swagger/v1/swagger.json", "MySite");
s.InjectStylesheet("../css/swagger.min.css");
});

REST Jersey Client - unable to parse JSON into POJO class

I am trying to build a rest client using jersey 2.13.
The rest endpoint is in : https://gist.githubusercontent.com/richersoon/ff4dd5c5abe414c5ec4c/raw/4ce49c32e57bf071d052f7efa76f332d60308035/user.json
But when I tried to run the application I got:
Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/plain, type=class com.napier.entity.User, genericType=class com.napier.entity.User.
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:173)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:134)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:988)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:833)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:768)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:96)
at org.glassfish.jersey.client.ScopedJaxrsResponse.access$001(ScopedJaxrsResponse.java:56)
at org.glassfish.jersey.client.ScopedJaxrsResponse$1.call(ScopedJaxrsResponse.java:77)
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:397)
at org.glassfish.jersey.client.ScopedJaxrsResponse.readEntity(ScopedJaxrsResponse.java:74)
at com.napier.service.rest.UsersClient.main(UsersClient.java:20)
Here's the code:
public class UsersClient {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
WebTarget target = client.target(
UriBuilder.fromUri(
"https://gist.githubusercontent.com/richersoon/ff4dd5c5abe414c5ec4c/raw/4ce49c32e57bf071d052f7efa76f332d60308035/user.json"));
Response response = target.request().accept(MediaType.APPLICATION_JSON).get(Response.class);
User user = response.readEntity(User.class);
System.out.println(user);
}
}
Here's the POJO:
#XmlRootElement
public class User {
private String firstname;
private String lastname;
private String photourl;
... setters and getters...
}
Here's the POM:
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.13</version>
</dependency>
Please guide me because I am totally new to webservices.
Your client is accepting results of media type "application/json", but your REST webservice returns "text/plain". Check this post to see a possible solution: MessageBodyReader not found for media type=application/octet-stream
Seems you are trying to access the wring uri, which is plain text.
I was able to get it to work with this uri, which is the actual .json file
"https://gist.github.com/richersoon/ff4dd5c5abe414c5ec4c#file-user-json"

Categories

Resources