Jersey Client Posting Form Data - java

I'm learning about JAX-RS and Jersey. I am trying to post data to a URL however I have an issue I do not know to fix:
Form formData = new Form();
formData.param("merchant_id", mPayment.getMerchantId());
formData.param("transaction_id", mPayment.getTransactionId());
formData.param("code", mPayment.getCode());
formData.param("amount", String.valueOf(mPayment.getAmount()));
formData.param("desc", mPayment.getDesc());
formData.param("phone", mPayment.getPhone());
Response response = target.path("process").request()
.accept(MediaType.APPLICATION_JSON)
.post(Entity.form(formData));
Now everything works well when it's just a string however the server is expecting a float data type for the field amount however when I try to use it without String.valueOf() I get an error. How do I add params with different data types so I can post?

You cannot maintain the type information across the call to the server. The form data will be transferred as text with the application/x-www-form-urlencoded content type header, this is why the Form class accepts String parameter values (similarly to how you could only enter text values in a browser form).
So your code should be sufficient. At the server side, you can declare the parameter as a float and annotate it with javax.ws.rs.FormParam. If the parameter cannot be cast to the desired (float) type by the Jersey runtime, it will return a 400 BAD REQUEST.
In a nutshell:
Keep client code as it is.
Use server code similar to:
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
#Path("/service")
public class myService {
#POST
public Response addOrder(
#FormParam("merchant_id") String merchant_id,
#FormParam("amount") float amount
// more parameters
) {
return Response.ok().build();
}
}

Related

Method Not Allowed REST Java when trying to do POST

I just want to create a simple REST service and it uses #GET and #POST.
for the #GET function, everything is ok but for #POST, when I want to create a new user on my server the browser just keeps sating (METHOD NOT ALLOWED).
I read so many articles about how to fix this error but I haven't got anything yet.
My code for #POST :
#Path("/hello")
public class HelloResource(){
#POST
#Produces(MediaType.APPLICATION_JSON)
#Path("/post")
public Response createUser(#PathParam("name") String name,#PathParam("address") String address,#PathParam("birthYear") String birth,#PathParam("ps") String password) throws NotAllowedException,MethodNotFoundException,Exception {
DataStore.getInstance().putPerson(new Person(name, address, Integer.parseInt(birth), password));
String json = "{\n";
json += "\"status\": " + '"'+"CREATED" +'"'+ ",\n";
json+="}";
return Response.status(200).entity(json).build();
}}
I also tried adding #Consumes function with (MediaType.APPLICATION.JSON) and (MediaType.TEXT_PLAIN) but nothing changed.
Also the URL I enter for posting is :
http://localhost:8080/HelloREST/rest/hello/post?name=PouYad&address=mustbejsonlater&birthYear=2005&ps=12345
As you see I also tried so many exception handlers.
Can someone please help?
if you enter your URL in the browser URL address field, it won't work because the browser will send a "GET" request. So you must use a client that will allow you to send a "POST" like PostMan. Or write your own small httpConnection function that sends a "POST"
You also have to change the #PathParam to #FormParam for it to work (#QueryParam will also work, but because it is POST, it is best to use #FormParm).
Access URL directly through browser can only create Get Request, not POST Request
You should
Create HTML Form, set the action to your service url with POST method, and then submit it.
Use Rest Client like postman to access your service with POST method.
Write your own Http Client using java.net.http api or just simply use
one of the handy libraries/frameworks (Like Spring has RestTemplate).

REST WebServices - Is it a good or general practice to accept a JSON but return an XML or vice-versa?

I'm finding it a little bit tough to ask my question correctly to Google.
I'm building a REST Web Service, which can accept and return both XML and JSON media types. My client can decide what to send to my service (in case of a POST) by using the Content-Type header, and what it would like to recieve as a response by using the Accept header.
However, my question is, can I create a web service, such that it can accept only JSON (i.e., the client has to set Content-type=application/json), but the Service can return an XML only (the client has to set Accept=application/xml)?
While this can be technically possible, I would like to know if this is a good practice, and are there any general implementations of REST Webservices where a client can specify a particular Content-Type but a different Accept header.
Imagine I have implemented a Service like the one below:
#POST
#Path("/users")
#Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public User createUser(User user) {
/* Do something */
return user;
}
In the above case, a client can send the Post data as JSON, but expect to receive the response as XML, and vice versa.
Is this really a good practice? Should or should a REST Service not emphasize on returning content with the same Media Type as it accepts? Like, produce application/xml when it consumes application/xml and produce application/json when it consumes application/json and so on?
While technically possible, this is not good practice at all, especially if the client explicitely stated via its Accept header it only accepts application/json.
Instead of one method accepting both XML and JSON, you could make two methods on the same path, each one dedicated to one particular content-type:
#POST
#Path("/users")
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public User createUserJson(User user) {
/* Do something */
return user;
}
#POST
#Path("/users")
#Consumes({MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_XML})
public User createUserXml(User user) {
/* Do something */
return user;
}
See also the Accept header spec in RFC2616

Play Framework: Setting Location header eliminates response body for HTTP 303

I'm trying to send clients a 303 See Other with Location header and a response body detailing why they're being redirected (which seems allowed per RFC 2616) using Play 2.3.10:
package example;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Results;
public class SeeOtherExample extends Controller {
public Result seeOtherExample() {
response().setHeader(LOCATION, "http://example.com");
return Results.status(SEE_OTHER, "You were redirected because...");
}
}
But the response body comes back empty when I include the location header. Omitting the header causes the body to be returned correctly, but of course I need the header as well.
Also, it appears to be something specific about the Location header. Setting other headers do not cause the body to be omitted.
What's the best way to send back a Location header and a response body?

How to change the response content type for a Dropwizard REST service?

I took a look at the Dropwizard framework and I want to use it to package my existing REST service.
In the tutorial I noticed that the response content type is not set using a ResponseBuilder, can I set the reponse type like I would do for a regular REST service if it were not in a Dropwizard framework ?
The reason I want to set a dynamic response content type is because the webservice does not know the kind of data it is serving.
Thanks
You should be able to just return a Response object and adjust the type. For instance:
#Path("/hello")
#Produces(MediaType.TEXT_PLAIN)
public class Example{
#GET
public Response sayHello() {
return Response.ok("Hello world").type(MediaType.TEXT_HTML).build();
}
}

How to handle unsupported/unimplemented methods for Rest Client

so lets say, i am listening on URL v1/shop/{PATH_PARAM}/status.xml. Whenever, a request is made at v1/shop/some_value/status.xml It will be redirected to my method.
But lets say, a user does a mistake in this path ? Jersey would by itself send an response of "Bad Request" or "Un implemented" method or something like that. Is there a way that instead jersey sending this response, I can handle those reponse ? lets say i will create a new function which will listen ot everything except for those which i are implemented for business case. So any request, which is not properly structured, or some unsupported media request would go to this method, so that i can send a more resonable response to the user
You could make a Servlet Filter, configure it to intercept all URLs matching your Web Services root URL (or even the root URL of the web server where the web service is deployed), have it pass the request on to the web service and then when the response arrives at the filter, if it's some kind of web service error you can change the response to whatever you want, make it redirect to some custom error page, etc.
I just did this using an "Exception Mapper". Here is a tutorial on how to do it with resteasy: https://community.jboss.org/wiki/RESTEasyExceptionHandlingWithExceptionMapper?_sscc=t
A colleague told me there is something analogous for Jersey.
Here is the code I used to make sure that I don't get empty content, because sometimes I forget, and I'm sure others will forget, to look at the headers / HTTP status.
import org.jboss.resteasy.spi.Failure;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
#Provider
public class PipelineMgrExceptionMapper implements ExceptionMapper<Exception> {
#Override
public Response toResponse(Exception e) {
if (e instanceof Failure) {
Failure f = (Failure) e;
return Response.fromResponse(f.getResponse()).entity(f.getMessage()).type(MediaType.TEXT_PLAIN).build();
} else {
return Response.status(500).entity(e.getMessage()).type(MediaType.TEXT_PLAIN).build();
}
}
}

Categories

Resources