I am working on a RestService
in which my URL will take lot of parameters. Below are the parameters my URL will take:
UserId
: This should always be along
and a number in general.DeviceId
: This should always be aString
.PetaId
: This should always be aString
.FlowId
: This should be along
as well and a number in general.Timeout
: This should be along
as well and a number in general.DataFlag
: This should be aboolean
, true or false.ProcessFlag
: This should be aboolean
, true or false.
Now I need to do validations on these above properties and if they are not passing correct stuff, then I need to throw proper JSON response with BAD REQUEST error message.
- If anyone is passing
UserId
in the URL, then it should not be empty ornull
and it should be a proper number. - If anyone is passing
DeviceId
in the URL, then it should not be empty ornull
. - If anyone is passing
PetaId
in the URL, then it should not be empty ornull
. - If anyone is passing
FlowId
in the URL, then it should not be empty ornull
and it should be a proper number. - If anyone is passing
Timeout
in the URL, then it should not be negative or zero. - If anyone is passing
DataFlag
in the URL, then it should be aboolean
value. - If anyone is passing
ProcessFlag
in the URL, then it should be aboolean
value.
Point is if they are setting any of the above fields, they should set it with proper values otherwise they should not. If any of the above cases fails, then I need to return back a proper JSON error response along with BAD REQUEST 400 message so that they can understand what went wrong.
For example as shown below or if there is anything better, I am open to that as well:
{"error": "user id cannot be null or empty"}
Now there are two more important things which are mandatory always:
FlowId
should always be set. IfFlowId
is not set, like if it is empty or null or zero then I need to return BAD REQUEST and with proper JSON error message likeFlowId
cannot be null or empty or anything better.- Also at least one of the keys from
UserId
,DeviceId
andPetaId
should be valid and set. If all of them are missing/invalid then I need to return BAD REQUEST with proper JSON error message like "all three keys cannot be null or empty" or anything better.
After extracting all the stuff from the URL, I need to pass these values to another library (DataClient
) which takes these parameter.
- If
UserId
is not empty and notnull
and a valid number, then pass this value to the library. - If
DeviceId
is not empty and notnull
, then pass this value to the library. - If
PetaId
is not empty and notnull
, then pass this value to the library. - If
Timeout
is present in the URL with a valid value, then pass this value, otherwise use the default value of 200. - If
DataFlag
is present in the URL with a validboolean
value, then pass this value, otherwise don't set it ifDataFlag
is not present. - If
ProcessFlag
is present in the URL with valid aboolean
value, then pass this value, otherwise don't set it ifProcessFlag
is not present.
As an example if UserId
is empty or null and then if we try to pass this value to the library, then library will throw exception that "UserId cannot be null or empty", so that's why I needed to have all these checks.
Below is my code where I am extracting all the stuff out of it from the URL:
@GET
@Path("/json/lime")
@Produces(MediaType.APPLICATION_JSON)
public Response getData(@Context UriInfo uriInfo) {
String client = getClientId();
if (DataUtils.isEmpty(client)) {
return Response.status(HttpServletResponse.SC_BAD_REQUEST)
.entity("{\"error\": \"client id is null or empty\"}").build();
}
MultivaluedMap<String, String> m = uriInfo.getQueryParameters();
String flowid = null;
if (m.get("flowid") != null) {
flowid = m.get(flowid).get(0);
}
if (DataUtils.isEmpty(flowid)) {
throw new WebApplicationException(Response.status(HttpServletResponse.SC_BAD_REQUEST)
.type(MediaType.APPLICATION_JSON).entity("{\"error\": \"flow id cannot be null or empty\"}")
.build());
}
String userId = null;
if (m.get("userid") != null) {
userId = m.get("userid").get(0);
if (DataUtils.isEmpty(userId)) {
throw new WebApplicationException(Response.status(HttpServletResponse.SC_BAD_REQUEST)
.type(MediaType.APPLICATION_JSON).entity("{\"error\": \"user id cannot be null or empty\"}")
.build());
}
}
String deviceid = null;
if (m.get("deviceid") != null) {
deviceid = m.get("deviceid").get(0);
if (DataUtils.isEmpty(deviceid)) {
throw new WebApplicationException(Response.status(HttpServletResponse.SC_BAD_REQUEST)
.type(MediaType.APPLICATION_JSON).entity("{\"error\": \"device id cannot be null or empty\"}")
.build());
}
}
String petaid = null;
if (m.get("petaid") != null) {
petaid = m.get("petaid").get(0);
if (DataUtils.isEmpty(petaid)) {
throw new WebApplicationException(Response.status(HttpServletResponse.SC_BAD_REQUEST)
.type(MediaType.APPLICATION_JSON).entity("{\"error\": \"peta id cannot be null or empty\"}")
.build());
}
}
if (DataUtils.isEmpty(userId) && DataUtils.isEmpty(petaid) && DataUtils.isEmpty(deviceid)) {
throw new WebApplicationException(Response.status(HttpServletResponse.SC_BAD_REQUEST)
.type(MediaType.APPLICATION_JSON).entity("{\"error\": \"all three keys cannot be null or empty\"}")
.build());
}
long timeout = 200;
if (m.get("timeout") != null) {
try {
timeout = Long.parseLong(m.get("timeout").get(0));
if (timeout <= 0) {
throw new WebApplicationException(Response.status(HttpServletResponse.SC_BAD_REQUEST)
.type(MediaType.APPLICATION_JSON).entity("{\"error\": \"invalid timeout is passed\"}")
.build());
}
} catch (NumberFormatException ex) {
throw new WebApplicationException(Response.status(HttpServletResponse.SC_BAD_REQUEST)
.type(MediaType.APPLICATION_JSON).entity("{\"error\": \"invalid timeout is passed\"}").build());
}
}
boolean dataFlag = false;
if (m.get("dataflag") != null) {
if (Boolean.parseBoolean(m.get("dataflag").get(0))) {
dataFlag = true;
}
}
boolean processFlag = true;
if (m.get("processflag") != null) {
if (!Boolean.parseBoolean(m.get("processflag").get(0))) {
processFlag = false;
}
}
//now build headers
org.springframework.http.HttpHeaders reqHeader = new org.springframework.http.HttpHeaders();
reqHeader.add("Context", client);
HttpEntity<Object> entity = new HttpEntity<Object>(reqHeader);
//Now send the request to DataClient
DataKey key = null;
Builder builder = null;
try {
builder = new DataKey.Builder(Integer.parseInt(flowid));
if (!DataUtils.isEmpty(userId)) {
builder.setUserId(Long.parseLong(userId));
}
if (!DataUtils.isEmpty(deviceid)) {
builder.setCguid(deviceid);
}
if (!DataUtils.isEmpty(petaid)) {
builder.setUdid(petaid);
}
if (dataFlag) {
builder.dataFlag(dataFlag);
}
if (!processFlag) {
builder.processFlag(processFlag);
}
key = builder.addTimeout(timeout).attributeMap(convertToMap(m))
.addHeaders(entity).build();
} catch (Exception e) {
throw new WebApplicationException(Response.status(HttpServletResponse.SC_BAD_REQUEST)
.type(MediaType.APPLICATION_JSON).entity("{\"error\": \""+e.getMessage()"\"}")
.build());
}
DataResponse resp = client.getDataHistory(key);
// if request is unsuccessful
if (resp.getStatus().ordinal() != 0) {
int errorCode = resp.getError().getCode();
throw new WebApplicationException(Response.status(resp.getError().getCode())
.type(MediaType.APPLICATION_JSON).entity("resp.getResponse()")
.build());
}
// if request was successful
return Response
.status(resp.getError().getCode())
.entity(resp.getResponse()).build();
}
Here is the DataResponse
class which contains actual response and error code and then whether it's a successful response or not.
public class DataResponse {
private final String response;
private final ErrorCode error;
private final StatusCode status;
// constructors/getters
}
The StatusCode
class contains two properties:
public enum StatusCode {
SUCCESS, ERROR;
}
The ErrorCode
class contains all the status code with proper error messages:
public enum ErrorCode {
OK(200, "NONE", ),
NO_CONTENT(204, "No Content"),
BAD_REQUEST(400, "Bad Request")
// other customized error messages
}
I am trying to see whether there is any improvement I can do in my rest service code as shown above.