Parsing the String params received in POST query - java

I running a very simple REST web service to receive string params in post query, process them and send back a string response. In order to parse the params from string
param1=testData1&param2=testData2&
I'm using String.split() as under:
#POST
#Produces(MediaType.TEXT_PLAIN)
public String post(String str) {
String[] parts = str.split("&");
String part1 = parts[0]; // param1=testData1
String part2 = parts[1]; // param2=testData2
......do something on these values and return String....
return str;
}
for getting the param values I'll have to split again.....
can someone please suggest a cleaner and elegant solution to get these param values..

Assuming its form parameters, one way that will work for either Jersey 1.x or Jersey 2.x is to inject MultivaluedMap
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String post(MultivaluedMap<String, String> form) {
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, List<String>> params : form.entrySet()) {
for (String key: params.getValue()) {
builder.append("key: ").append(params.getKey()).append("; ")
.append("value: ").append(params.getValue().get(0)).append("\n");
}
}
return builder.toString();
}
If you know ahead of time the name of the form key, you could create a bean.
public class Bean {
#FormParam("key1")
private String value1;
#FormParam("key2")
private String value2;
// getter and setters
}
For Jersey 2.x, you would inject with #BeanParam
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response post(#BeanParam Bean bean) {
}
For Jersey 1.x you would inject with #InjectParam
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response post(#InjectParam Bean bean) {
}
Note that the bean injection will work for all the other #XxxParams also, not just #FormParam, for instance #QueryParam, #PathParam. You can mix and match them.
Or if you know the names ahead of time, if you don't need the bean, you can simply declare all the form params in the method signature
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response post(#FormParam("key1") String value1,
#FormParam("key2") String value2) {
}

Related

How to automatically map multipart/form-data input to a bean in Jersey

I have a Jersey REST api that receives inputs as multipart/form-data. The signature is as follows:
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Path("/getorders")
public Response getOrders(final FormDataMultiPart request) {
The input parameters in the form are:
clientName
orderType
year
I would like instead to have something like this:
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Path("/getOrders")
public Response getOrders(final OrderBean order) {
And get all my inputs in a bean like this:
public class OrderBean {
private String clientName;
private int orderType;
private int year;
// Getters and setters
}
Is there a way to do that automatically with Jersey? I know that I can map the fields manually and fill in the bean, but actually I'm looking for an annotation or something like that, that can fill in the bean automatically.
Jersey supports #FormDataParams in a #BeanParam bean. If you were to do this (as you would see in most examples):
#POST
public Response post(#FormDataParam("clientName") String clientName) {}
Then you can also do
class OrderBean {
#FormDataParam("clientName")
private String clientName;
// getter/setters
}
#POST
public Response post(#BeanParam OrderBean order) {}

Java REST API Query annotation

I am currently trying to add a new feature to my REST API.
Basically I want to add the ability to add query parameters to the end of a path and turn this into a Map of all the query options for example.
my current code allows me to do things like
localhost:8181/cxf/check/
localhost:8181/cxf/check/format
localhost:8181/cxf/check/a/b
localhost:8181/cxf/check/format/a/b
and this will use all the #pathparam as String variables to generate a response.
What I want to do now is add:
localhost:8181/cxf/check/a/b/?x=abc&y=def&z=ghi&...
localhost:8181/cxf/check/format/a/b/?x=abc&y=def&z=ghi&...
and I would then have this generate a Map which can be used along with the pathparam to build the response
x => abc
y => def
z => ghi
... => ...
I was thinking something like this [Below] however the #QueryParam seem to only handle one key value and not a Map of them.
#GET
#Path("/{format}/{part1}/{part2}/{query}")
Response getCheck(#PathParam("format") String format, #PathParam("part1") String part1, #PathParam("part2") String part2, #QueryParam("query") Map<K,V> query);
below is my current interface code.
#Produces(MediaType.APPLICATION_JSON)
public interface RestService {
#GET
#Path("/")
Response getCheck();
#GET
#Path("/{format}")
Response getCheck(#PathParam("format") String format);
#GET
#Path("/{part1}/{part2}")
Response getCheck(#PathParam("part1") String part1,#PathParam("part2") String part2);
#GET
#Path("/{format}/{part1}/{part2}")
Response getCheck(#PathParam("format") String format, #PathParam("part1") String part1, #PathParam("part2") String part2);
}
QueryParam("") myBean allows to get all the query parameters injected. Remove also the last {query} part
#GET
#Path("/{format}/{part1}/{part2}/")
Response getCheck(#PathParam("format") String format, #PathParam("part1") String part1, #PathParam("part2") String part2, #QueryParam("") MyBean myBean);
public class MyBean{
public void setX(String x) {...}
public void setY(String y) {...}
}
You can also not declare parameters and parse the URI. This option could be useful if you can accept non-fixed parameters
#GET
#Path("/{format}/{part1}/{part2}/")
public Response getCheck(#PathParam("format") String format, #PathParam("part1") String part1, #PathParam("part2") String part2, #Context UriInfo uriInfo) {
MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
String x= params.getFirst("x");
String y= params.getFirst("y");
}

How to retrieve the JSON message body in JAX-RS REST method?

I have the following JSON that will be passed as part of a HTTP request, in the message body.
{
"names": [
{
"id":"<number>",
"name":"<string>",
"type":"<string>",
}
]
}
My current REST handler is below. I am able to get the Id and `Version that is passed in as path params, but I am not sure how to retrieve the contents on the message body?
#PUT
#Path("/Id/{Id}/version/{version}/addPerson")
public Response addPerson(#PathParam("Id") String Id,
#PathParam("version") String version) {
if (isNull(Id) || isEmpty(version)) {
return ResponseBuilder.badRequest().build();
}
//HOW TO RECIEVE MESSAGE BODY?
//carry out PUT request and return DTO: code not shown to keep example simple
if (dto.isSuccess()) {
return Response.ok().build();
} else {
return Response.serverError().build();
}
}
Note: I am using the JAX-RS framework.
You just need to map your name json to a POJO and add #Consumes annotation to your put method, here is an example:
#PUT
#Consumes("application/json")
#Path("/Id/{Id}/version/{version}/addPerson")
public Response addPerson(#PathParam("Id") String Id,
#PathParam("version") String version,
List<NamObj> names) {
I assume you are trying to retrieve a list of elements if is not the case just use you POJO as it in the param.
Depending on what json library are you using in your server you may need to add #xml annotation to your POJO so the parser could know how to map the request, this is how the mapping for the example json should look like:
#XmlRootElement
public class NameObj {
#XmlElement public int id;
#XmlElement public String name;
#XmlElement public String type;
}
Jersey doc: https://jersey.java.net/documentation/latest/user-guide.html#json
#cosumes reference: http://docs.oracle.com/javaee/6/tutorial/doc/gilik.html#gipyt

Custom annotation injection with Jersey 1.x

I am using jersey 1.9.1. I have rest method like following where
Authorization header contained encoded credentials such as username
and password and it is parsed in a method and mapped local values.
#PUT
#Path(SystemConstants.REST_MESSAGE_SENDSMS)
#Consumes(MediaType.APPLICATION_JSON)
#Produces({MediaType.APPLICATION_JSON})
public Response sendSms(#HeaderParam("Authorization") String authorization, String param) {
String[] credentials = ImosUtils.getUserCredentials(authorization);
String username = credentials[0];
String password = credentials[1];
}
I am trying to design a way to make this process automatically, without writing same parsing code in each method. I mean I would like to know if writing a special annotation such as HeaderParamExtended to this is used to parse this credentials.
I am using jersey 1.9.1 version as rest api. Where I have to edit a class in that life cycle?
#PUT
#Path(SystemConstants.REST_MESSAGE_SENDSMS)
#Consumes(MediaType.APPLICATION_JSON)
#Produces({MediaType.APPLICATION_JSON})
public Response sendSms(#HeaderParamExtended("Authorization","username") String username, #HeaderParamExtended("Authorization","password") String password, , String param) {
}
Normally you need an InjectableProvider to support the custom injection, and also an Injectable to provide the value.
Here's an example
#BasicAuth
#Target(ElementType.PARAMETER)
#Retention(RetentionPolicy.RUNTIME)
public #interface BasicAuth {
}
InjectableProvider
#Provider
public class BasicAuthInjectionProvider
implements InjectableProvider<BasicAuth, Parameter> {
#Override
public ComponentScope getScope() {
return ComponentScope.PerRequest;
}
#Override
public Injectable getInjectable(ComponentContext cc, BasicAuth a, Parameter c) {
return new BasicAuthInjectable();
}
}
Injectable
public class BasicAuthInjectable extends AbstractHttpContextInjectable<User>{
#Override
public User getValue(HttpContext hc) {
String authHeaderValue = hc.getRequest()
.getHeaderValue(HttpHeaders.AUTHORIZATION);
String[] credentials = ImosUtils.getUserCredentials(authHeaderValue);
return new User(credentials[0], credentials[1]);
}
}
One thing you'll notice is that I have a User class. This is to wrap the username and password, and just have one injection point. i.e.
public Response getSomething(#BasicAuth User user) {
}
I actually tried to do it your way, with
public Response getSomething(#BasicAuth("username") String username,
#BasicAuth("password") String password) {
And in the InjectableProvider get the annotation value from the annotation passed to the getInjectable, then pass that value onto the BasicAuthInjectable. From there check to see if the value is "username" or "password" and return the corresponding value. But for some reason the injection providers were not even called. You can play around with it to see if you can get it to work. But to me the User looks cleaner anyway, and with the two strings, the injection providers are called twice and you need to parse the headers twice. Seems unnecessary.

How to parse JSON Response to POJO with AndroidAnnotations?

I'm using AndroidAnnotations to build a Rest for an Android Application.
On the Serverside im using PHP, which send a json looking like :
{"tag":"register","success":0,"error":2,"msg":"User already existed","body":[]}
I have two POJOS :
User.java:
public class User implements Serializable {
private String name;
private String email;
private String password;
//getter and setter Methods
}
Response.java:
public class RegistrationResponse implements Serializable {
private String tag;
private int success;
private int error;
private String msg;
private String body;
//getter and setter Methods
}
Rest Client:
#Rest(rootUrl = "http://my.domain.com", converters = {
MappingJacksonHttpMessageConverter.class,
StringHttpMessageConverter.class, GsonHttpMessageConverter.class }, interceptors = { MyInterceptor.class })
public interface RestClient extends RestClientErrorHandling {
#Post("/user/register/{name}/{email}/{pass}")
#Accept(MediaType.APPLICATION_JSON_VALUE)
Response sendUserRegistration(User user, String name, String email,
String pass);
RestTemplate getRestTemplate();
}
Activity.java:
//User and Response are POJOs
Response result = RestClient.sendUserRegistration(user,
user.getName(),user.getEmail(),user.getPassword());
But i got an Null Pointer Exception error on Activity.java. But if i change the return value of "sendUserRegistration" function to String all work. So my "Response" POJO seems not to be converted from AndroidAnnotations.
How can i convert the Rest Response to my "Response"-POJO using AndroidAnnotations?
You don't need to return the entire response object per rest call, just set the response to your custom object. Or you can also return a JsonObject also and use gson to convert it later on.
#Rest(rootUrl = "http://my.domain.com", converters = {
MappingJacksonHttpMessageConverter.class,
StringHttpMessageConverter.class, GsonHttpMessageConverter.class }, interceptors = { MyInterceptor.class })
public interface RestClient extends RestClientErrorHandling {
#Post("/user/register/{name}/{email}/{pass}")
#Accept(MediaType.APPLICATION_JSON_VALUE)
User sendUserRegistration(User user, String name, String email,
String pass);
RestTemplate getRestTemplate();
}
then just simply call
User newUser = RestClient.sendUserRegistration(user,
user.getName(),user.getEmail(),user.getPassword());
AA relies on Spring Android RestTemplate to make the rest call. And in order to build requests and handle responses this lib uses converters. And to know which converter the RestTemplate should use, it checks the content-type response header.
As MappingJacksonHttpMessageConverter and GsonHttpMessageConverter handles only http response with content-type=application/json and your result is converted to string, I'm pretty sure you forgot to set this header in your php server. So it send the default one (ie: text/plain) which is only handle by StringHttpMessageConverter.
Also, the body field is an object in your json example, but in your POJO you declared it as a String. So parsing will fail on this point.

Categories