How to post raw json text in Jersey Client HTTP POST request? - java

I want to make an HTTP POST request, which requires parameters must be passed as raw JSON text, but I don't know how to do in with Jersey client.
Here is the API specs (works well in Postman Rest Client): (please look at the screenshot from my Postman, the URL, parameter in body, and 2 headers are Content-Type: application/json & Accept: application/json)
And here is what I've tried with Jersey:
JsonObject parameters = new JsonObject();
parameters.addProperty("centerId", centerId);
parameters.addProperty("studentId", studentId);
if (fromDate != null) {
parameters.addProperty("fromDate", fromDate);
}
if (toDate != null) {
parameters.addProperty("toDate", toDate);
}
Object response = client.target("http://localhost:8080/rest").path("student/calendar")
.request(MediaType.APPLICATION_JSON).post(Entity.json(parameters), String.class);
but nothing worked. Can anyone suggest what is the correct way to deal with Jersey in this case? Thank you.

Use an InputStream for your entity construction, it should work
String payload = "{\"schoolId\":1,\"studentId\":1,\"fromDate\":\"1454259600000\",\"toDate\":\"1456765200000\"}";
client.target("<targetURI>")
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(
new ByteArrayInputStream(payload.getBytes()),
MediaType.APPLICATION_JSON
));
But in the end, Entity.json(payload) should also work.

Related

how to create client TGT with java cxf

I'm new to the java rest CXF client. I will make various requests to a remote server, but first I need to create a Ticket Granting Ticket (TGT). I looked through various sources but I could not find a solution. The server requests that I will create a TGT are as follows:
Content-Type: text as parameter, application / x-www-form-urlencoded as value
username
password
I create TGT when I make this request with the example URL like below using Postman. (URL is example). But in the code below, I'm sending the request, but the response is null. Could you help me with the solution?
The example URL that I make a request with POST method using Postman: https://test.service.com/v1/tickets?format=text&username=user&password=pass
List<Object> providers = new ArrayList<Object>();
providers.add(new JacksonJsonProvider());
WebClient client = WebClient.create("https://test.service.com/v1/tickets?format=text&username=user&password=pass", providers);
Response response = client.getResponse();
You need to do a POST, yet you did not specify what your payload looks like?
Your RequestDTO and ResponseDTO have to have getters/setters.
An example of using JAX-RS 2.0 Client.
Client client = ClientBuilder.newBuilder().register(new JacksonJsonProvider()).build();
WebTarget target = client.target("https://test.service.com/v1/tickets");
target.queryParam("format", "text");
target.queryParam("username", "username");
target.queryParam("password", "password");
Response response = target.request().accept(MediaType.APPLICATION_FORM_URLENCODED).post(Entity.entity(yourPostDTO,
MediaType.APPLICATION_JSON));
YourResponseDTO responseDTO = response.readEntity(YourResponseDTO.class);
int status = response.getStatus();
Also something else that can help is if you copy the POST request from POSTMAN as cURL request. It might help to see the differences between your request and POSTMAN. Perhaps extra/different headers are added by postman?
Documentation: https://cxf.apache.org/docs/jax-rs-client-api.html#JAX-RSClientAPI-JAX-RS2.0andCXFspecificAPI
Similar Stackoverflow: Is there a way to configure the ClientBuilder POST request that would enable it to receive both a return code AND a JSON object?

Why am I getting response status of 204 No content in my REST server?

I am new to REST API and working with servers in general and I am trying to make a simple client-server application. I am using Jersey.
Client sends some data to server, server receives the data and shows it on the desired uri and vice versa.
The vice-versa part of receiving the data hosted on server is working fine, but I am not able to send data to server.
I have tried POST like this:
#POST
#Path("/something")
#Consumes("application/x-www-form-urlencoded")
public void getSomething(){
}
And my client side code looks something like this:
Client client = Client.create();
MultivaluedMap formData = new MultivaluedMapImpl();
formData.add("name1", "val1");
formData.add("name2", "val2");
WebResource resource = client.resource("http://localhost:8080/artifact/rest/something");
ClientResponse response = resource.type("application/x-www-form-urlencoded").post(ClientResponse.class, formData);
System.out.println(response);
I am trying to send a string or json type object to server and it should show it on that url. But I am not able to do so.
I'd appreciate if someone could help me in this.
Edit
I would also appreciate if someone could tell me how to send data to server with code like this.
Try using this format for the jersey server side although whatever you are using is the same:
#POST
#Path("your path")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
For the client side, try using this.
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(url + "/rest/something");
post.addHeader("Accept" , "application/json");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("name1", "val1"));
params.add(new BasicNameValuePair("name2", "val2"));
post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpResponse response = httpClient.execute(post);
String out = EntityUtils.toString(response.getEntity());
Your getSomething is not returning anything. This translates to a 204 No Content response: The operation was successful (the 2xx of the code indicates this) but there is nothing to return.
If you want to return something, change the return type from void to Response.
#POST
#Path("/something")
#Consumes("application/x-www-form-urlencoded")
#Produces("text/plain")
public Response getSomething() {
return Response.ok("Success!").build();
}
This will return the HTTP status code 200 OK with Success! as the content of the response body.
But you probably want to somehow use the content of the request. Take a look at jax-rs retrieve form parameters for how you can do this.

JAX-RS Jersey Read entity with Content-Type "*"

I am using Jax-RS to make a request to a server, which just returns a one word String, and read that response into a String variable. The issue is that I have no idea how to use the response, as its Content-Type is *; charset=UTF-8 (I verified this using Postman). Jax-RS has difficulty parsing this kind of header. Here is my code:
MultivaluedMap<String, String> formData = new MultivaluedHashMap<String, String>();
formData.add("username", username);
formData.add("target", "10");
Response response = target.request().accept(MediaType.APPLICATION_JSON_TYPE).post(Entity.form(formData));
String responseString = response.readEntity(String.class);
This POST request works. I get an actual Response that I can inspect. However, when I try to read this response into a String (last line of code), the following error is thrown:
org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "*; charset=UTF-8" ! at
org.glassfish.jersey.message.internal.InboundMessageContext.exception(InboundMessageContext.java:338) ! at
org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:333) ! at
org.glassfish.jersey.message.internal.InboundMessageContext.getMediaType(InboundMessageContext.java:446) ! at
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:869)
How do I make Jax-RS properly read this kind of Content-Type?!?
I do not think there is any way to get Jersey / Jax-RS to properly read that kind of Content-Type. A solution for any kind of Response that has a Content-Type that Jax-RS does not like is to simply remove the header and (if needed) add your own Content-Type header that is more appropriate for the Response. Do this BEFORE trying to read the Response entity. This fixed my issue:
response.getHeaders().remove("Content-Type");
response.getHeaders().add("Content-Type", "text/plain");
String responseString = response.readEntity(String.class);

Spring RestTemplate exchange DELETE with body jdk 1.8

I'm trying to do a HTTP DELETE request with body with Spring RestTemplate via exchange method but I always get a 400 Bad Request like this question. With JavaScript and other tools it is posible to make this API call with DELETE.
I know java <1.8 doesent support DELETE with body, but with 1.8 it should be able: see here. I'm using spring-web-4.2.6.RELEASE with jdk 1.8 so I think there must be a way.
My code:
public DealResponse closePosition(DealCloseRequest dealCloseRequest) {
try {
ObjectMapper mapper = new ObjectMapper();
//Object to JSON in String
String jsonInString = mapper.writeValueAsString(dealCloseRequest);
HttpEntity<String> entity = new HttpEntity<String>(jsonInString, this.headers);
//execute request
ResponseEntity<DealResponse> response = restTemplate.exchange("https://" + this.domain + "/gateway/deal/positions/otc", HttpMethod.DELETE, entity, DealResponse.class);
//return filled DealResponse object
return response.getBody();
} catch (JsonProcessingException e) {
this.logger.warn("could not close Position because: "+e);
return null;
}
}
Error message:
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
Does anyone know a way to do this with spring restTemplate?
HTTP DELETE request with body works fine with rest template for Spring 4.2 release. There could be some issue with request body you are sending to your service. Can you check "jsonInString" if it is forming correct json payload.Check the headers as well for "application/json" type. You can verify your service using Postman by sending DELETE request.

JUnit for REST: Cannot POST data

I want to write a JUnit class for a REST endpoint.
This is my REST method. It works fine.
#POST
#Path("create")
#Produces(APPLICATION_JSON)
public String create(#QueryParam("parentId") String parentId, #QueryParam("name") String name) {
//do sth.
return "{\"status\": \"SUCCESS\"}";
}
Now my JUnit test looks like that, which doesn't work, because I don't know how to POST my data in the right way:
#Test
public void testCreate() {
Client client = ClientBuilder.newClient();
WebTarget wt = client.target(REST_MENU_URL + "create");
String queryParams = "parentId=1&name=NEW_JUnit_NEW";
// In the line below, I want to POST my query parameters, but I do it wrong
Response response = wt.request().post(Entity.entity(queryParams, APPLICATION_JSON), Response.class);
// The response has a 500, because the query parameters are all NULL!
assertEquals("Http code should be 200", 200, response.getStatus());
}
So how do I have to change the line with the 'Response' to make it work?
The problem is, that the query parameters (parentId and name) don't get transmitted (response = wt.request().post(...)).
I tried to POST form parameters too, but no success here either. Just like that:
Form form =new Form().param("parentId", "4").param("name", "NEW_JUnit_NEW");
Response response = wt.request().post(Entity.entity(form, APPLICATION_JSON), Response.class);
Thanks,
Bernhard
Check out the Jersey Client documentation, in particular section 5.3.4 on targeting resources.
Query parameters form a part of the URI of the resource, they're not part of the body of the document posted to the resource. You're seeing null in your resource because you're not filling in the query parameters in the URI, you're posting them as the body. You need to tell Jersey to put them in the URI...
WebTarget wt = client.target(REST_MENU_URL + "create").queryParam("parentId", 1).queryParam("name", "NEW_JUnit_NEW");
You'll also need to ensure that your POST request sets the Accept header to allow application/json (by calling the accept(...) method after calling request()) and you're going to need to construct some kind of Entity to pass to the post(...) method - the problem here is that your resource is not consuming the entity body but the client API expects you to send something - this is a code smell which suggests your API is not particularly ReSTful. You can probably get away with some kind of empty body constructed from an empty string. It should look a bit like this...
Response response = wt.request().accept(MediaType.APPLICATION_JSON).post(Entity.text(""))
Alternatively, you could look into converting your API so that it accepts a JSON document and move the query parameters into that document.

Categories