Implementing a Conditional-GET - java

I Have a RESTful web service created using Java connected to a db containing cars and implamenting CRUD operations and testing using Postman.
Currently it just uses the conventional HTTP GET returning status 200ok when a car in the database is returned successfully.
I am trying now to implement a conditional GET to return status 304 when a second GET request is submitted and the entity has not been modified from the previous GET request.
Reading about the conditional GET i know it uses the Last-modified and if-modified-since headers but struggling on how to go about implementing this.
Within the db i have a trigger to update a TIMESTAMP associated with each entity after they have been modified and i presume this will be the value that will be checked to see if the entity has been modified since the last request ?
Any Help appreciated
The Current GET request:
#GET
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Path("{reg}")
public Response getOneCar(#PathParam("reg") String reg) {
Car car = dao.getCarDetails(reg);
System.out.println("GET CarReg == "+reg);
if(car == null){ // no car with that reg exists
return Response
.status(Response.Status.NOT_FOUND)
.entity("<carNotFound reg='"+reg+"' />")
.build();
}else{
car.setLink(new ArrayList<Link>());
Link linkSelf = new Link();
linkSelf.setRel("self");
linkSelf.setUri(context.getPath());
Link deleteLink = new Link();
deleteLink.setRel("/linkrels/car/delete");
deleteLink.setUri(context.getPath());
Link updateLink = new Link();
updateLink.setRel("/linkrels/car/update");
updateLink.setUri(context.getPath());
car.getLink().add(linkSelf);
car.getLink().add(deleteLink);
car.getLink().add(updateLink);
return Response
.status(Response.Status.OK)
.entity(car)
.build();
}
}
Example of one of the entities:
<car>
<id>3</id>
<regNo>03G333</regNo>
<make>Ford</make>
<model>Focus</model>
<link rel="self" uri="cars/03G333"/>
<link rel="/linkrels/car/delete" uri="cars/03G333"/>
<link rel="/linkrels/car/update" uri="cars/03G333"/>
<time>2018-03-23 10:00:05.772</time>
</car>

Thanks for the response #Andrew,
I am currently trying to do this using the "If-Modified-Since" and "Last-Modified" Headers.
On The server i am sending a "Last-Modified" Header to the client which takes the timestamp from the current car in the db as shown in the image --> postman server responce
Now i am trying to configure postman to send back the "if-Modified-Since" header.
if i compare these values and depending on the timestamp being the same or different i can determine the response to be sent back.
currently having trouble configuring postman to send the "If-Modified-Since" Header and then taking this value in on the Server somehow.
Date date = null;
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String lastmodifiedDate = car.getTime();
date = sdf.parse(lastmodifiedDate);
} catch (ParseException ex) {
}
return Response
.status(Response.Status.OK).lastModified(date)
.entity(car)
.build();
}
}

Related

Getting bad response using JRAW

I am trying to read data from reddit using java. I am using JRAW.
Here is my code:
public class Main {
public static void main(String args[]) {
System.out.println('a');
String username = "dummyName";
UserAgent userAgent = new UserAgent("crawl", "com.example.crawl", "v0.1", username);
Credentials credentials = Credentials.script(username, <password>,<clientID>, <client-secret>);
NetworkAdapter adapter = new OkHttpNetworkAdapter(userAgent);
RedditClient reddit = OAuthHelper.automatic(adapter, credentials);
Account me = reddit.me().about();
System.out.println(me.getName());
SubmissionReference submission = reddit.submission("https://www.reddit.com/r/diabetes/comments/9rlkdm/shady_insurance_work_around_to_pay_for_my_dexcom/");
RootCommentNode rcn = submission.comments();
System.out.println(rcn.getDepth());
System.out.println();
// Submission submission1 = submission.inspect();
// System.out.println(submission1.getSelfText());
// System.out.println(submission1.getUrl());
// System.out.println(submission1.getTitle());
// System.out.println(submission1.getAuthor());
// System.out.println(submission1.getCreated());
System.out.println("-----------------------------------------------------------------");
}
}
I am making two requests as of now, first one is reddit.me().about(); and the second is reddit.submission("https://www.reddit.com/r/diabetes/comments/9rlkdm/ shady_insurance_work_around_to_pay_for_my_dexcom/");
The output is:
a
[1 ->] GET https://oauth.reddit.com/api/v1/me?raw_json=1
[<- 1] 200 application/json: '{"is_employee": false, "seen_layout_switch": true, "has_visited_new_profile": false, "pref_no_profanity": true, "has_external_account": false, "pref_geopopular": "GL(...)
dummyName
[2 ->] GET https://oauth.reddit.com/comments/https%3A%2F%2Fwww.reddit.com%2Fr%2Fdiabetes%2Fcomments%2F9rlkdm%2Fshady_insurance_work_around_to_pay_for_my_dexcom%2F?sort=confidence&sr_detail=false&(...)
[<- 2] 400 application/json: '{"message": "Bad Request", "error": 400}'
Exception in thread "main" net.dean.jraw.ApiException: API returned error: 400 (Bad Request), relevant parameters: []
at net.dean.jraw.models.internal.ObjectBasedApiExceptionStub.create(ObjectBasedApiExceptionStub.java:57)
at net.dean.jraw.models.internal.ObjectBasedApiExceptionStub.create(ObjectBasedApiExceptionStub.java:33)
at net.dean.jraw.RedditClient.request(RedditClient.kt:186)
at net.dean.jraw.RedditClient.request(RedditClient.kt:219)
at net.dean.jraw.RedditClient.request(RedditClient.kt:255)
at net.dean.jraw.references.SubmissionReference.comments(SubmissionReference.kt:50)
at net.dean.jraw.references.SubmissionReference.comments(SubmissionReference.kt:28)
at Main.main(Main.java:36)
Caused by: net.dean.jraw.http.NetworkException: HTTP request created unsuccessful response: GET https://oauth.reddit.com/comments/https%3A%2F%2Fwww.reddit.com%2Fr%2Fdiabetes%2Fcomments%2F9rlkdm%2Fshady_insurance_work_around_to_pay_for_my_dexcom%2F?sort=confidence&sr_detail=false&raw_json=1 -> 400
... 6 more
As it can been that my first request gives me a response of my username but in the second response i am getting a bad request 400 error.
To check whether my client ID and client secret were working correctly I did the same request using python PRAW library.
import praw
from praw.models import MoreComments
reddit = praw.Reddit(client_id=<same-as-in-java>, client_secret=<same-as-in-java>,
password=<same-as-in-java>, user_agent='crawl',
username="dummyName")
submission = reddit.submission(
url='https://www.reddit.com/r/redditdev/comments/1x70wl/how_to_get_all_replies_to_a_comment/')
print(submission.selftext)
print(submission.url)
print(submission.title)
print(submission.author)
print(submission.created_utc)
print('-----------------------------------------------------------------')
This gives the desired result without any errors so the client secret details must be working.
The only doubt I have is in the user agent creation in java UserAgent userAgent = new UserAgent("crawl", "com.example.crawl", "v0.1", username);.
I followed the following link.
What exactly does the target platform, the unique ID or the version mean. I tried to keep the same format as in the link. Also using the same username as in other places. On the other hand the user_agent in python was a string crawl.
Please tell me if I am missing anything and what could be the issue.
Thank you
P.S. I want to do this in java. not python.
Since your first query is working the credentials are correct. In JRAW don't give the whole URL but only the id in the submission function.
Change this
SubmissionReference submission = reddit.submission("https://www.reddit.com/r/diabetes/comments/9rlkdm/shady_insurance_work_around_to_pay_for_my_dexcom/");
to this
SubmissionReference submission = reddit.submission("9rlkdm");
where the id is the random string after /comment/ in the URL.
Hope this helps.

Lagom Send custom header

I'm working on Lagom POC on sending POST request to Non lagom service with custom Header. In my case I'm trying to hit postman-echo to test the custom header.
However, it looks the headers are not set though I made code changes accordingly:
public CompletionStage<DsapAuthorizationResponse> hitAPI(AuthorizationRequest request) {
DsapWSRequest dsapWSRequest = new DsapWSRequest();
dsapWSRequest.username = request.username;
dsapWSRequest.password = request.password;
CompletionStage<DsapAuthorizationResponse> dsapresponse = dsapExternalService
.authenticate()
.handleRequestHeader(requestHeader -> {
requestHeader.withHeader("Authorization","Basic mncndsjna");
System.out.println("My Headers>>>>>>>> " + requestHeader);
return requestHeader;
})
.handleResponseHeader((responseHeader,b) -> {
System.out.println("RESPonse Header >>>>>>> : "+responseHeader);
return b;
})
.invoke(dsapWSRequest);
return dsapresponse;
}
In the above code header authorization is not set in the request. I am not getting this header in the echo which is mapped correctly in my POJO.
here is the complete code from my GitHub
https://github.com/sourabhsar/Lagom-Unmanaged-Service-Demo/tree/poc/lagom-request-response
I followed the steps mentioned here:
https://groups.google.com/forum/#!topic/lagom-framework/yvKmqvtZWFs
and also followed few other blogs/articles.
However so far I haven't found any blog which they are sending request to unmanaged external service with custom header. I'm not sure whats wrong in my code.
requestHeader.withHeader returns a new object with the added header, but the code you have written returns the original requestHeader object. In general, many Lagom APIs follow a principle of using immutable objects, with methods that return a new, modified instance, rather than changing the instance the method is called on.
Try this:
.handleRequestHeader(requestHeader -> {
RequestHeader modifiedRequestHeader =
requestHeader.withHeader("Authorization","Basic mncndsjna");
System.out.println("My Headers>>>>>>>> " + modifiedRequestHeader);
return modifiedRequestHeader;
})

Spring Boot Error Handling code 404 blank page

I am making app with Rest Services and i want to handle the exceptions and status code.
When i send the correct parametars to Postman i get the response and the status code is 202 OK so that is good.
When i send the first parameter correct and for seccond i send some chars i get status code 400 Bad Request and some message so that is good too.
But, when i send the first parameter correct and in the seccond i delete one number i am getting Status: 404 Not Found (Which is correct) and blank page in Postman without some message.
So my question is:
Is that alright to get only status code 404 and blank page or i need to change something in the code to get the message too.
My second question is about Internal Server Error 500. How can i implement it and how to test it?
#CrossOrigin
#RequestMapping(value = "/blaa/{startDate}/{endDate}", method = RequestMethod.GET)
public ResponseEntity<List<Nodes>> listsOfbla(#PathVariable Long startDate,
#PathVariable Long endDate) {
startEndDateRequestTotal.inc();
List<Nodes> listOfbla= NodesService.getFromToData(startDate, endDate);
LOG.info("GET Request was made with two paramaters ", startDate, endDate);
for (int i = 0; i < listOfbla (); i++) {
if (listOfbla(i).getStampm().equals(startDate)) {
for (int j = 0; j < listOfbla (); j++) {
if (listOfbla(j).getStampm().equals(endDate)) {
return new ResponseEntity<List<Nodes>>listOfbla HttpStatus.OK);
}
}
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
if (listOfbla.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
LOG.info("Retruning Nodes objects from specified date");
return new ResponseEntity<List<Nodes>>(listOfbla, HttpStatus.OK);
}
For your first question:
That is enough you receive the status code and you can make for example.
If status code = 404 send me this message.

REST API using POST showing blank response

While working on REST API, I am using POST method to fetch data from Mongo DB using #FormParam annotation. When I use GET type, then it returns the response in JSON and while changing the method from GET to POST, I am getting blank response.
The code:
//GetResponse.java
//
#Path("/Location")
public class GetProjectLocationResponse {
#POST
#Path("/State")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Object[] addBuild2(
#FormParam("Country") String Country,
#FormParam("State") String State) throws UnknownHostException, JSONException
{
System.out.println("ïnside Location");
Location loc = new Location();
List<DBObject> basicDBList=(List<DBObject>) loc.getState2(Country, State); //calling state method
return basicDBList.toArray();
}
//Location.java
//This defines the list of available zipcpdes on the basis on parameter 'Country' and 'States'.
public List<DBObject> getState2(String Country, String State) throws UnknownHostException {
DB db=ConnectToDB.getConnection();
DBCollection collection = db.getCollection("location");
BasicDBObject obj = new BasicDBObject();
obj.put("Country",Country);
obj.put("State",State);
BasicDBObject fields = new BasicDBObject();
fields.put("_id", 0);
DBCursor cursor = collection.find(obj, fields);
List<DBObject> obj1 =cursor.toArray();
System.out.println(""+obj1);
return obj1;
}
}
//index.html
//This file includes parameters 'country' and 'states' to return the JSON response.
<form action="rest/Location/State" method="post">
Enter Country:<input type="text" name="Country"/><br/><br/>
Enter State:<input type="text" name="State"/><br/><br/>
<input type="submit" value="submit"/>
I have checked the code but did not find any clue what is wrong in this that causing this blank response for POST type, while its working fine for GET type. I though it should have worked for POST type as the code specification is correct for both type. Please specify any issue there. Thanks in advance
You are using POST for a different and wrong purpose here.
Use GET for retrieving data and POST for creation of the required entity. A typical response from a POST call would be 201 - Created and the UI should not expect any response from the POST call.
HTTP POST was not specified to return data and do not expect it to return.
Similar question :
Can I use POST method to get data and GET method to post data?

How to get Facebook Rate Limit Header using Facebook4J?

According to Facebook Docs
If your app is making enough calls to be considered for rate limiting by our system, we return an X-App-Usage HTTP header. [...] When any of these metrics exceed 100 the app will be rate limited.
I am using Facebook4J to connect my application to the Facebook API. But I could not find any documentation about how I can get the X-App-Usage HTTP header after a Facebook call, in order to avoid being rate limited. I want to use this header to know dinamically if I need to increase or decrease the time between each API call.
So, my question is: using Facebook4J, is possible to check if Facebook returned the X-App-Usage HTTP header and get it? How?
There is a getResponseHeader method for the response of BatchRequests in facebook4j see Facebook4j code examples
You could try getResponseHeader("X-App-Usage")
// Executing "me" and "me/friends?limit=50" endpoints
BatchRequests<BatchRequest> batch = new BatchRequests<BatchRequest>();
batch.add(new BatchRequest(RequestMethod.GET, "me"));
batch.add(new BatchRequest(RequestMethod.GET, "me/friends?limit=50"));
List<BatchResponse> results = facebook.executeBatch(batch);
BatchResponse result1 = results.get(0);
BatchResponse result2 = results.get(1);
// You can get http status code or headers
int statusCode1 = result1.getStatusCode();
String contentType = result1.getResponseHeader("Content-Type");
// You can get body content via as****() method
String jsonString = result1.asString();
JSONObject jsonObject = result1.asJSONObject();
ResponseList<JSONObject> responseList = result2.asResponseList();
// You can map json to java object using DataObjectFactory#create****()
User user = DataObjectFactory.createUser(jsonString);
Friend friend1 = DataObjectFactory.createFriend(responseList.get(0).toString());
Friend friend2 = DataObjectFactory.createFriend(responseList.get(1).toString());

Categories

Resources