I was able to get a #GET request working on jersey and the relevant code is as follows
The code for the server
#Path("/Text")
#GET
public String Hello() {
System.out.println("Text Being print");
return "Abc";
}
#POST
#Path("/post/{name}/{gender}")
public Response createDataInJSON(#PathParam("name") String data, #PathParam("gender") String data2) {
System.out.println("Post Method 1");
JSONObject obj = new JSONObject();
obj.put("Name", data);
obj.put("Gender", data2);
return Response
.status(200)
.entity(obj.toJSONString())
.build();
}
The #POST also works when the parameters are passed in the url. (as mentioned in the above code segment)
But, it doesn't work when the parameters are not sent via the url. Like the code which follows.
#POST
#Path("/post2")
public Response createDataInJSON2(#FormParam("action") String data) {
System.out.println("Post Method 2 : Data received:" + data);
JSONObject obj = new JSONObject();
obj.put("data", data);
return Response
.status(200)
.entity(obj.toJSONString())
.build();
}
May be the problem lies with the way the services are called.
//GET call (Plain Text)
System.out.println(service.path("Hello").accept(MediaType.TEXT_PLAIN).get(String.class));
//POST call (Param)
ClientResponse response = service.path("Hello/post/Dave/Male").post(ClientResponse.class);
System.out.println(response.getEntity(String.class));
//POST call (JSON)
String input = "hello";
ClientResponse response2 = service.path("Hello/post2").post(ClientResponse.class, input);
System.out.println(response2.getEntity(String.class));
Can anyone tell me what am I missing here?
Try to add a #Consumes (application/x-www-form-urlencoded) on your #POST method createDataInJSON2 and explicitly add the same mime type in your request service.path("Hello/post2").type(MediaType.APPLICATION_FORM_URLENCODED).post(ClientResponse.class, input).
Also consider that your input is just a simple string. Have a look at the class MultivaluedMap
If you have troubles with the Encoding then have a look at this post https://stackoverflow.com/a/18005711/3183976
Try this. This worked for me.
The post method:
#POST
#Path("/post2")
public Response post2(String data) {
System.out.println("Post method with File: " + data);
return Response
.status(200)
.entity(data)
.build();
}
The calling method:
ClientResponse response2 =service.path("Hello/post2").post(ClientResponse.class,"some value");
System.out.println(response2.getEntity(String.class));
Hope this helps. Peace.
Related
My code is as follows:
#Path("/test")
public class Test {
#POST
#Path("/postSomething")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public RestMessageResponse postSomething(JSONObject inputJSONObject) {
..do something
}
}
when I send a post request to the appropriate url, it doesn't reach the code.
Why would you want to do this anyway?
Just send the plain JSON in your HTTPRequest and parse it. For me, this usually looks like this:
#RequestMapping(path= "/app/syncImages", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
public ResponseEntity<?> someMethod(#RequestBody String body){
JSONObject request = new JSONObject(body);
...
}
Have you tried your code? Does it not work in some capacity?
Hey so I'm trying to send some json-object to a rest web service, then get the value of some specific keys, then process the data to finally return a new json-object which is going to be used in another place. Anyway, I'm getting HTTP 204 when I try to communicate with the service.
My rest service looks like this
#Path("/example")
public class PdfMaker {
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response PruebasMet(JSONObject json) throws IOException, JSONException{
try{
String xml = json.getString("xml");
String plantilla = json.getString("plant");
//method that uses "xml" and "plant" and returns "pdf"
JSONObject response = new JSONObject();
response.put("pdf", pdf);
return Response.status(200).entity(pdfb64.toString()).build();
}catch(Exception e){
e.getStackTrace();
return null;
}
}
and I'm trying to communicate with this
public class Jersey {
public static String baseuri = "http://localhost:8080/PdfMakerGF/rest/example/post";
public static void main(String[] args) {
try {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource webResource = client.resource(baseuri);
JSONObject objTest = new JSONobject();
objTest.put("xml","Data1");
objTest.put("plan", "Data2");
ClientResponse res = webResource.header("Content-Type","application/json;charset=UTF-8")
.post(ClientResponse.class, objTest.toString());
System.out.println("output..." + "\n");
System.out.println("Answer "+res);
} catch (Exception e) {
e.printStackTrace();
}
}
But the response that I receive is this one
Answer POST http://localhost:8080/PdfMakerGF/rest/example/post
returned a response status of 204 No Content
Obviously there is something wrong but can't see what is it.
Since I'm stuck with this. Any kind of help would be appreciated.
I'm using netbeans 8.1, Glassfish 4.1 and Jersey.
Thanks
If your server runs into an exception and goes to the catch block, it returns null which corresponds to HTTP 204 (No Content). As sisyphus commented, there should be some exception in the server standard output.
So you probably need to:
Return a different response code (e.g. INTERNAL_SERVER_ERROR or
BAD_REQUEST) in the catch block
Check why the server code is throwing
the exception
Most likely you get an Exception. I guess it is because you have "plant" in one place and "plan" in another.
okey so finaly it works what i need to change was the way that the service was reciving the data, with a inner class in my case, end up working like this ..
Class Aux{
String xml;
String plant;
//generate gettes and setters :)
}
#Path("/example")
public class PdfMaker {
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response PruebasMet(Aux json) throws IOException,
JSONException{
try{
String xml = json.getXml();
String plant = json.getPlant();
//method that uses "xml" and "plant" and returns "pdf"
JSONObject response = new JSONObject();
response.put("pdf", pdf);
return Response.status(200).entity(pdf)).build();
}catch(Exception e){
e.getStackTrace();
return null;
}
}
and the client is ..
Client client = new Client();
WebResource wresource = client.resource("http://localhost:8080/PdfMakerGF/rest/example/post");
JSONObject json = new JSONObject();
json.put("xml", DATA);
json.put("plant", DATA);
ClientResponse response =
wresource.type("application/json").post(ClientResponse.class,
json.toString());
out = response.getEntity(String.class);
System.out.println("RES = "+response);
System.out.println("OUT = "+out);
out has the info that the service is Providing
I am trying to connect to an API of another company.
from the doc there is ::
even with your GET request, you'll need to include the Java equivalent of
curl_setopt($ch, CURLOPT_POSTFIELDS, $content), and you can set $data equal
to an empty array.
$content in their example is an empty JSON array.
I am using org.apache.commons.httpclient.
i am not sure how to add post fields to a org.apache.commons.httpclient.methods.GetMethod or if it is even possible.
i tried faking with a Content-Length of 2 but the GET times out (probably looking for content that i am not providing. if i remove the content-length i get an invalid response from the api server)
HttpClient client = new HttpClient();
GetMethod method = new GetMethod("https://api.xxx.com/account/");
method.addRequestHeader("Content-Type", "application/json");
method.addRequestHeader("X-Public-Key", APKey);
method.addRequestHeader("X-Signed-Request-Hash", "xxx");
method.addRequestHeader("Content-Length", "2");
int statusCode = client.executeMethod(method);
I don't think GetMethod includes any means of attaching a request body, because a GET request isn't supposed to have a body. (But having a body isn't actually prohibited, either - see: HTTP GET with request body .)
You're trying to use documentation written with a different language and a different client library in mind, so you'll have to use trial and error a bit. It sounds like they expect a request with no body, and you already have that. There's no good reason why they'd require a "Content-Length" with GET, but if that's the case, try setting it to 0.
This is how i resolved this issue
Created this class
public class HttpGetWithEntity extends HttpEntityEnclosingRequestBase {
public HttpGetWithEntity() {
super();
}
public HttpGetWithEntity(URI uri) {
super();
setURI(uri);
}
public HttpGetWithEntity(String uri) {
super();
setURI(URI.create(uri));
}
#Override
public String getMethod() {
return HttpGet.METHOD_NAME;
}
}
Then the calling function looks like
public JSONObject get(JSONObject payload, String URL) throws Exception {
JSONArray jsonArray = new JSONArray();
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpGetWithEntity myGet = new HttpGetWithEntity(WeeblyAPIHost+URL);
myGet.setEntity( new StringEntity("[]") );
myGet.setHeader("Content-Type", "application/json");
myGet.setHeader("X-Public-Key", APIKey);
HttpResponse response = client.execute(myGet);
JSONParser parser = new JSONParser();
Object obj = parser.parse( EntityUtils.toString(response.getEntity(), "UTF-8") ) ;
JSONObject jsonResponse = (JSONObject) obj;
return jsonResponse;
}
I have 2 Spring Web applications: Application1 and Application2. In Application1, I have an endpoint at "http://application1/getbigcsv" that uses streaming in order to serve a gigantic 150MB CSV file back to the user if they hit that URL.
I dont want users to hit Application1 directly, but hit Application2 instead.
If I have the following method in my controller in Application2
#RequestMapping(value = "/large.csv", method = GET, produces = "text/csv")
#ResponseStatus(value = HttpStatus.OK)
public String streamLargeCSV() {
// Make an HTTP Request to http://application1/getbigcsv
// Return its response
}
My worry is the above is not doing "streaming" whereas Application1 is doing streaming. Is there some way I can make sure that the application2 will be serving back the same data from application1's rest endpoint in a streaming fashion? Or is the method above actually returning things in a "Streaming" method already because Application1 is serving its endpoint as streaming?
First of all: you can but not with that method signature.
Unfortunately, you have not shown how you produce that CSV file in app1, whether this is truly streaming. Let's assume it is.
You signature will look like this:
#RequestMapping(value = "/large.csv", method = GET, produces = "text/csv")
#ResponseStatus(value = HttpStatus.OK)
public void streamLargeCSV(OutputStream out) {
// Make an HTTP Request to http://application1/getbigcsv
// Return its response
}
Now we have to grab the input stream from app1 first. Use Apache HttpClient to get your HttpEntity. This entity has a writeTo(OutputStream) method which will receive your out parameter. It will block until all bytes are consumed/streamed. When you are done, free all HttpClient resources.
Complete code:
#RequestMapping(value = "/large.csv", method = GET, produces = "text/csv")
#ResponseStatus(value = HttpStatus.OK)
public void streamLargeCSV(OutputStream out) {
// Make an HTTP Request to http://application1/getbigcsv
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://application1/getbigcsv");
CloseableHttpResponse response = httpclient.execute(httpGet);
try {
HttpEntity entity = response.getEntity();
// Return its response
entity.writeTo(out);
} finally {
response.close();
}
}
Here is my real world example. Start reading from "Interesting to say what I have achieved in particular with this:"
In java.ws.rs.core package you have classes: StreamingOutput and ResponseBuilder.
Not sure if it will help you, but you may try.
Example:
#Produces("application/octet-stream")
public Response doThings () {
...
StreamingOutput so;
try {
so = new StreamingOutput() {
public void write(OutputStream output) {
…
}
};
} catch (Exception e) {
...
}
ResponseBuilder response = Response.ok(so);
response.header("Content-Type", ... + ";charset=utf-8");
return response.build();
}
Change your methods return type to ResponseEntity<?> and return as following:
#GetMapping("/download")
public ResponseEntity<?> fetchActivities(
#RequestParam("filename") String filename) {
String string = "some large text"
InputStream is = new ByteArrayInputStream(string.getBytest());
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=large.txt");
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
return ResponseEntity.ok().headers(headers).body(new InputStreamResource(is));
}
I struggled with an extrange spring behavior using RestTemplate (org.springframework.web.client.RestTemplate) without success.
I use in my hole application below code and always receive an XML response, which I parse and evaluate its result.
String apiResponse = getRestTemplate().postForObject(url, body, String.class);
But can't figure out why a server response is in JSON format after executing:
String apiResponse = getRestTemplate().getForObject(url, String.class);
I've debugged at low level RestTemplate and the content type is XML, but have no idea why the result is in JSON.
When I access from a browser the response is also in XML, but in apiResponse I got JSON.
I tried many options after reading Spring documentation
http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/web/client/RestTemplate.html
Also tried to modify explicitly the headers but still can't figure it out.
I debugged RestTemplate class and noticed that this method is always setting application/json:
public void doWithRequest(ClientHttpRequest request) throws IOException {
if (responseType != null) {
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
if (messageConverter.canRead(responseType, null)) {
List<MediaType> supportedMediaTypes = messageConverter.getSupportedMediaTypes();
for (MediaType supportedMediaType : supportedMediaTypes) {
if (supportedMediaType.getCharSet() != null) {
supportedMediaType =
new MediaType(supportedMediaType.getType(), supportedMediaType.getSubtype());
}
allSupportedMediaTypes.add(supportedMediaType);
}
}
}
if (!allSupportedMediaTypes.isEmpty()) {
MediaType.sortBySpecificity(allSupportedMediaTypes);
if (logger.isDebugEnabled()) {
logger.debug("Setting request Accept header to " + allSupportedMediaTypes);
}
request.getHeaders().setAccept(allSupportedMediaTypes);
}
}
}
Could you give an idea?
I could solve my issue with RC.'s help. I'll post the answer to help other people.
The problem was that Accept header is automatically set to APPLICATION/JSON so I had to change the way to invoke the service in order to provide the Accept header I want.
I changed this:
String response = getRestTemplate().getForObject(url, String.class);
To this in order to make the application work:
// Set XML content type explicitly to force response in XML (If not spring gets response in JSON)
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> response = getRestTemplate().exchange(url, HttpMethod.GET, entity, String.class);
String responseBody = response.getBody();