Spring boot + Jersey parse Response JSON data - java

I am trying to build a simple page the will display some places on the map. I'm really new to rest in Java and i'm using Spring boot + jersey framework.
I'm using google places api to search for places, i made the GET respond for a lat/lng that i'm passing thru PostMan:
http://localhost:9000/res/-23.558712/-46.592235
Inside the code im calling:
#GET
#Path("/{lat}/{lng}")
#Produces("application/json")
public void getBook(#PathParam("lat") String lat,#PathParam("lng") String lng) {
this.lat = lat;
this.lng = lng;
getdata();
}
public static void getdata(){
Client client = ClientBuilder.newClient();
String entity = client.target("https://maps.googleapis.com/maps/api/place/nearbysearch/json?location="+ lat + "," + lng + "&radius=5000&types=market&name=dia&key=MY_KEY")
.request(MediaType.TEXT_PLAIN_TYPE)
.header("some-header", "true")
.get(String.class);
System.out.println(entity);
}
And i get a really big Json in the response:
"results" : [
{
"geometry" : {
"location" : {
"lat" : -23.5703071,
"lng" : -46.58153289999999
},
"viewport" : {
"northeast" : {
"lat" : -23.56895811970849,
"lng" : -46.5801839197085
},
"southwest" : {
"lat" : -23.5716560802915,
"lng" : -46.58288188029149
}
}
},....
And much more, my question is, how do i parse this JSON response to away that i can manage data? I want to get, name, location... to plot on the map.
I will have to create a model class with all response parameters?
I really don't know if this is all wrong.

This resource falls under reverse geocoding and if you need name of the location you should get it from "fromatted_address" attiribute, and address components will give you exact address. The following link has some information which might help you further. [reverse geocoding] https://developers.google.com/maps/documentation/geocoding/intro#ReverseGeocoding

Related

Azure Functions CosmosDb Binding api keeps loading

First of all, the api works as intended locally, when deploying to azure functions app, the api endpoint keeps loading and it will eventually show HTTP.504(Gateway Timeout)
page keeps loading, no response from azure functions
Integration
I'm looking to fetch all data from the collection when I call HttpTrigger
Function.java
#FunctionName("get")
public HttpResponseMessage get(
#HttpTrigger(name = "req",
methods = {HttpMethod.GET, HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
#CosmosDBInput(name = "database",
databaseName = "progMobile",
collectionName = "news",
partitionKey = "{Query.id}",
connectionStringSetting = "CosmosDBConnectionString")
Optional<String> item,
final ExecutionContext context) {
// Item list
context.getLogger().info("Parameters are: " + request.getQueryParameters());
context.getLogger().info("String from the database is " + (item.isPresent() ? item.get() : null));
// Convert and display
if (!item.isPresent()) {
return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
.body("Document not found.")
.build();
}
else {
// return JSON from Cosmos. Alternatively, we can parse the JSON string
// and return an enriched JSON object.
return request.createResponseBuilder(HttpStatus.OK)
.header("Content-Type", "application/json")
.body(item.get())
.build();
}
}
Function.json
{
"scriptFile" : "../ProgMobileBackend-1.0-SNAPSHOT.jar",
"entryPoint" : "com.function.Function.get",
"bindings" : [ {
"type" : "httpTrigger",
"direction" : "in",
"name" : "req",
"methods" : [ "GET", "POST" ],
"authLevel" : "ANONYMOUS"
}, {
"type" : "cosmosDB",
"direction" : "in",
"name" : "database",
"databaseName" : "progMobile",
"partitionKey" : "{Query.id}",
"connectionStringSetting" : "CosmosDBConnectionString",
"collectionName" : "news"
}, {
"type" : "http",
"direction" : "out",
"name" : "$return"
} ]
}
Azure Functions monitor log does not show any error
Running the function in the portal(Code + Test menu) does not show any error either
httpTrigger I'm using: https://johnmiguel.azurewebsites.net/api/get?id=id
I added CosmosDBConnectionString value to Azure Functions App configuration(did not check on "Deployment slot" option)
I'm using an instance of CosmosDB for NoSQL
Functions App runtime is set to Java and version set to Java 8
figured it out. Java function was in Java 17 and Function App in Java 8.

Wiremock - Autoconfigure doesn't load stubs

My wiremock doesn't seem to work with autoconfigure. I have json files in a folder named stubs in the classpath and I ran the standalone jar on the port 8080.
#AutoConfigureWireMock(stubs="classpath:/stubs", port = 0)
public class TestResource {
#Autowired
private Service service;
#Test
public void contextLoads() throws Exception {
assertThat(this.service.go()).isEqualTo("Hello World!");
}
}
Example of a json file
{
"request" : {
"url" : "/api/users",
"method" : "GET",
"bodyPatterns" : [ {
"contains" : "some soap body"
}]
},
"response" : {
"status" : 200,
"body" : "Hello World",
"headers" : {
"X-Application-Context" : "application:-1",
"Content-Type" : "text/plain"
}
}
}
When I launch a request with GET -> localhost:8080/api/users/ It doesn't match with the json file.
Thanks in advance
I simply added all my json with a POST request on localhost:8080/__admin/mappings/import
http://wiremock.org/docs/stubbing/

Get coordinates from a Tweet using the Twitter API

I'm trying to correctly get information from tweets using the Twitter API and Java. I'm trying to get the exact coordinates from this tweet which have geo tag enabled.
From now, I've created the corresponding Java classes as the documentation dictates, but maybe I'm not understanding very well the Geo Objects, since neither the coordinates, bounding_box or place appear. My guess is that I'm not declaring correctly those classes.
For the Tweet class:
// Imports here
public class Tweet {
#SerializedName("created_at")
public String created_at;
#SerializedName("id")
public long id;
// ... All the rest of the parameters
#SerializedName("coordinates")
public Coordinates coordinates;
#SerializedName("place")
public transient Place place;
For the Coordinates class:
// Imports here
public class Coordinates {
#SerializedName("coordinates")
public String coordinates;
#SerializedName("type")
public String type;
}
For the Place class:
// Imports here
public class Place {
#SerializedName("id")
public String id;
#SerializedName("url")
public String url;
// ... All the rest of the parameters
#SerializedName("bounding_box")
public String bounding_box;
}
When I make a petition to get the json information from the linked tweet I get the following data, and as you can see the fields coordinates or places does not appear. If it is useful, I'm using MongoDB Java API to store the json files and its Java POJO manager. You can find all the code here: https://github.com/marmatsan/theTrainEngine
{
"_id" : NumberLong("1212893878430420992"),
"created_at" : "Fri Jan 03 00:30:09 +0000 2020",
"favorite_count" : 0,
"favorited" : false,
"id_str" : "1212893878430420992",
"is_quote_status" : false,
"lang" : "en",
"possibly_sensitive" : false,
"quoted_status_id" : NumberLong(0),
"quoted_status_id_str" : NumberLong(0),
"reply_count" : 0,
"retweet_count" : 0,
"retweeted" : false,
"source" : "Twitter for Android",
"text" : "Test 1",
"truncated" : "false",
"user" : {
"_id" : NumberLong(593955589),
"created_at" : "Tue May 29 18:59:38 +0000 2012",
"default_profile" : false,
"default_profile_image" : false,
"description" : "En búsqueda del verdadero camino del Tao estudiando Ingeniería en Tecnologías de Telecomunicación.",
"favourites_count" : 7497,
"followers_count" : 186,
"friends_count" : 114,
"id_str" : "593955589",
"listed_count" : 5,
"location" : "Salamanca/Toledo/Madrid",
"name" : "Martín 👾",
"profile_banner_url" : "https://pbs.twimg.com/profile_banners/593955589/1513111580",
"profile_image_url_https" : "https://pbs.twimg.com/profile_images/1130587021678927874/50unsAd3_normal.png",
"protected_att" : false,
"screen_name" : "MMateos97",
"statuses_count" : 19420,
"url" : "https://github.com/marmatsan",
"verified" : false
}
}
Edit: As stated in the answer, the problem is of the implementation, because when I remove the transient modifier from the Place object the program does not work. If someone has a fix for this problem please leave it in the comments.
When I request the status it has the correct fields for this status.
$ okurl https://api.twitter.com/1.1/statuses/show/1212893878430420992.json
...
"geo":null,
"coordinates":null,
"place":{"id":"fd110fb449209bc4","url":"https:\/\/api.twitter.com\/1.1\/geo\/id\/fd110fb449209bc4.json","place_type":"city","name":"Burguillos de Toledo"
https://developer.twitter.com/en/docs/tweets/data-dictionary/overview/geo-objects#tweet-exact
Read the difference between "Tweet with Twitter Place" and "Tweet with exact location".
I suspect your "transient" field is causing Mongo not to save this field.

How get JSON Object with Retrofit 2 and Android Studio?

I am making an application in Android Studio and I want to consume API for cooking recipes, I have the following response from the API that I am consuming with Android Studio and Java:
API Response
"q" : "pollo",
"from" : 0,
"to" : 10,
"params" : {
"sane" : [ ],
"q" : [ "pollo" ],
"app_id" : [ "02" ],
"app_key" : [ "\n66b" ]
},
"more" : true,
"count" : 1000,
"hits" : [ {
"recipe" : {
"uri" : "http://www.edamam.com/ontologies/edamam.owl#recipe_d56f75c72ab67a45174441af1efe4473",
"label" : "Pollo con Crema a las Hierbas",
"image" : "http://cdn.kiwilimon.com/recetaimagen/23127/thumb120x90-15802.jpg",
"source" : "KiwiLimon",
"url" : "http://www.kiwilimon.com/receta/carnes-y-aves/pollo-con-crema-a-las-hierbas",
"shareAs" : "http://www.edamam.com/recipe/pollo-con-crema-a-las-hierbas-d56f75c72ab67a45174441af1efe4473/pollo",
"yield" : 42.0,
And continue with more 'recipe', what I want is to get only the array of hits that all the recipes have to be able to show in my application, the problem is that I get the following error:
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
I understand that it is because it expects an array and it obtains a JSON object, but I do not know how to parse it, I have my Recipe model class and the RecipeService service and I manage everything in MainActivity, I have seen in some answers that I would have to do an intermediate response, but I do not understand how I could implement it in my code, then I show the classes that handle all this.
Recipe Class (Model):
public class Recipe {
private String label;
private String image;
private String source;
private String shareAs;
private List<String> dietLabels;
private List<String> healthLabels;
private List<String> cautions;
private List<String> ingredientLines;
private List<String> ingredients;
private double calories;
private double totalWeight;
private List<String> totalNutrients;
private List<String> totalDaily;
public String getLabel() {
return label;
}
.
.
.
RecipeService Class:
public interface RecipeService {
String API_ROUTE = "/search";
String API_KEY = "&app_key=" + Credentials.API_KEY;
String APP_ID = "&app_id=" + Credentials.APP_ID;
//String query = "";
#GET(API_ROUTE)
Call< List<Recipe> > getRecipe(#Query("q") String q);
}
MainActivity:
private void getRecipes() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://test-es.edamam.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
RecipeService recipeService = retrofit.create(RecipeService.class);
Call<List<Recipe>> call = recipeService.getRecipe("pollo");
System.out.println("GET RECIPES");
System.out.println("HEADERS: "+ call.request().headers());
call.enqueue(new Callback<List<Recipe>>() {
#Override
public void onResponse(Call<List<Recipe>> call, Response<List<Recipe>> response) {
System.out.println("RESPONSE CODE: " + response.code());
for(Recipe recipe : response.body()){
System.out.println("AÑADIENDO: " + recipe.getLabel());
recipes.add(recipe.getLabel());
}
//System.out.println(recipes.toArray().toString());
}
#Override
public void onFailure(Call<List<Recipe>> call, Throwable t) {
System.out.println("HA OCURRIDO UN FALLO");
System.out.println(t.getMessage());
}
});
}
If API response is exactly what you post then the response is INVALID JSON format. You may check your JSON validity by jsonlint.
Secondly, your error says,
Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
Which means, POJO is designed for a JSON array, but from the API you are getting a JSON object.
The solution is really simple.
There are tons of plugins in Android Studio like this, or go this online converter tool. Then hopefully you will not get the same error,

How to create Spring Data Rest entities response format manually [duplicate]

This question already has answers here:
Calling spring data rest repository method doesn't return links
(2 answers)
Closed 6 years ago.
I'm using Spring Data Rest to create a RESTful api. I want to handle an exception returning an entity representation like the ones generated by the Spring Data Rest repositories (with HATEOAS links). The method from where I need to return the entity representation is the following:
#ExceptionHandler(value = {ExistentUGVException.class})
#ResponseBody
protected ResponseEntity<UGV> existentUGVHandler(HttpServletRequest request, HttpServletResponse response, ExistentUGVException ex) {
return new ResponseEntity<UGV>(ex.ugv, HttpStatus.OK);
}
This implementation returns the UGV representation without links:
{
"title" : "Golden Eagle Snatches Kid",
"publishDate" : "2012-12-19T13:55:28Z",
"url" : "https://www.youtube.com/watch?v=Xb0P5t5NQWM"
}
But it would be:
{
"title" : "Golden Eagle Snatches Kid",
"publishDate" : "2012-12-19T13:55:28Z",
"url" : "https://www.youtube.com/watch?v=Xb0P5t5NQWM",
"_links" : {
"self" : {
"href" : "http://localhost/youTubeVideos/Xb0P5t5NQWM"
},
"youTubeVideo" : {
"href" : "http://localhost/youTubeVideos/Xb0P5t5NQWM{?projection}",
"templated" : true
},
"user" : {
"href" : "http://localhost/youTubeVideos/Xb0P5t5NQWM/user"
}
}
}
You'll have to transform your ResponseEntity to Resource first and then add the links manually.
It should be something like this :
#ExceptionHandler(value = {ExistentUGVException.class})
#ResponseBody
protected ResponseEntity<Resource<UGV>> existentUGVHandler(HttpServletRequest request, HttpServletResponse response, ExistentUGVException ex) {
final Resource<UGV> resource = getResource(ex.ugv);
return new ResponseEntity<Resource<UGV>>(resource, HttpStatus.OK);
}
public Resource<T> getResource(T object, Link... links) throws Exception {
Object getIdMethod = object.getClass().getMethod("getId").invoke(object);
Resource<T> resource = new Resource<T>(object); // The main resource
final Link selfLink = entityLinks.linkToSingleResource(object.getClass(), getIdMethod).withSelfRel();
String mappingRel = CLASSMAPPING.getMapping(this.getClass());
final Link resourceLink = linkTo(this.getClass()).withRel(mappingRel);
resource.add(selfLink, resourceLink);
resource.add(links);
return resource;
}
Take a look here, there's all you need : spring hateoas documentation

Categories