i want to ask about Retrofit 2.0
all this time, i knew Retrofit only with GSON Converter and get the object.
But i dont know how to get the data with API like this
https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty
i'm trying to display all top stories and get the object after i load all the top stories first.
i only know with old school style like this: http://pastebin.com/JMpwjH8H
I'm pretty sure for your example you can just set the response type as a list of Integers like this:
public interface ApiInterface {
#GET("topstories.json?print=pretty")
Call<List<Integer>> getTopStories();
}
Using a POJO would be too complex for what is essentially, just an array of Integers.
First of all, you should know whether it is POST web service or GET web service.
what parameters you will be giving to get the desired response and how would you store the response in POJO. This tutorial will help you with all basic thing that you require for integrating web services
Related
I have an angular project with a java backend.
the following is the scenario.
I create a DTO object in the Backend, and submit it to the frontend.
...
QuestionResponseDTO dto = new QuestionResponseDTO();
dto.setStart(ZonedDateTime.now());
dto.setEnd(ZonedDateTime.now());
dto.setDuration("X seconds");
dto.setResponse(new ActivityListResponseDTO(Arrays.asList("Cooking", "Eating")));
return dto;
}
in which the ActivityListResponseDTO just contains a List<String> activities.
Also note that ActivityListResponseDTO extends QuestionResponseBodyDTO.
In the frontend I send the request to the backend, and I receive the object back.
this is how the object looks like.
{"id":2,"responses":[{"id":0,"dto":{"start":"2021-06-16T09:08:28.142Z","end":"2021-06-16T09:08:28.142Z","duration":"X seconds",
"response":{
"activities":["Cooking","Eating"],
"typeName":"ActivityListResponseDTO",
"className":null},
"typeName":"QuestionResponseDTO",
"className":null}}]}
which means that the backend works fine.
The java classes I mentioned earlier have their corresponding classes in the Frontend with the exact same name. Idk what exactly happens to parse the response.
When I receive the object I check:
//angular
if (dto instanceof QuestionResponseDTO) {
console.log("this ran");
const responseBody = ((<QuestionResponseDTO>dto).response);
if(responseBody instanceof ActivityListResponseDTO) {
console.log("this ran 2");
// because backend only returns a string
const arr = (<ActivityListResponseDTO>responseBody)
.activities.map(s => ({stringContent: s}));
...
The responseBody per default has the Type QuestionResponseBodyDTO in the frontend as well. the ActivityListResponseDTO extends this in the frontend too, so it should work.
but for some reason the program doesn't go in the inner if statement, and "this ran 2" is never logged.
Is there something I am doing wrong?
The response received from the HTTP API will be a simple JSON Object.
For it to work correctly on frontend, you will have to map that object to its corresponding type on frontend.
You can use json-object-mapper library to achieve this.
Create a Typescript class named QuestionResponseDTO with all the nested object classes. I usually do this using json2ts which provides me interfaces and then I convert those interfaces to typescript classes.
Use json-object-mapper or use your own class constructors to initialize the properties
In your HTTP service, when you get the data, pipe that data to deserialize it to typescript object. http.get<QuestionResponseDTO>(url).pipe(map(data => ObjectMapper.deserialize(QuestionResponseDTO, data)));
Once this is done, you should be able to correctly use instanceof on any nested objects
I created a Java library for a REST service using Retrofit (https://square.github.io/retrofit/).
I have an Interface which looks like this:
public interface OrganizationUnitsApi {
#GET("organizationUnits")
Call<List<OrganizationUnit>> getOrganizationUnits();
#GET("organizationUnits/{organizationUnitId}")
Call<OrganizationUnit> getOrganizationUnit(#Path("organizationUnitId") String organizationUnitId);
}
As you can see, both times I resolve to the endpoint "organizationUnits", so my requests in the end will be sent to "https://myservice.com/organizationUnits..."
Is there a possibility in Retrofit to like "annotate" a base Url for this Interface?
Maybe something like this?
#Path("organizationUnits")
public interface OrganizationUnitsApi {
#GET("/")
Call<List<OrganizationUnit>> getOrganizationUnits();
#GET("{organizationUnitId}")
Call<OrganizationUnit> getOrganizationUnit(#Path("organizationUnitId") String organizationUnitId);
}
There is no such API at this moment in retrofit similar to what you are exactly trying to do. However, if you must need to do that, you can pass the organizationUnits as part of the baseUrl while building the retorfit object.
So now you are doing something like this
Retrofit.Builder().baseUrl(someUrl)
You can instead do something like the following
Retrofit.Builder().baseUrl(someUrl/organizationUnitId)
But in that case, if you are using the same base url for multiple API interface, you will have to do extra hassle to configure those separately.
I have the following use case. I need to transfer an XText model instance via the network in some serialized format. For this purpose I need to serialize the model on the client side, send it as the body of some kind of POST request and deserialize it on the server side.
At the time I issue the send request I do only have access to the object structure of my model. I do not have the files I created the model from any more (it would be possible, but it would destroy the cleanliness of my architecture and makes testing very complex).
I created the following code for serializing the model based on some threads here on StackOverflow and tutorials available via other Websites to serialize an XText-Model
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap( ).put("xtextbin", new XMIResourceFactoryImpl());
Injector injector = Guice.createInjector(new ScenarioRuntimeModule());
Serializer serializer = injector.getInstance(Serializer.class);
System.out.println(serializer.serialize(scenario));
However it does not work and I get the following error:
com.google.inject.CreationException: Guice creation errors:
1) Error injecting constructor, org.eclipse.emf.common.util.WrappedException: org.eclipse.emf.ecore.resource.impl.ResourceSetImpl$1DiagnosticWrappedException: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Ungültiges Byte 1 von 1-Byte-UTF-8-Sequenz.
The problem most likely lies with the XMIResourceFactoryImpl, which I do not know how to use properly.
Another approach might be to use:
String serializedScenario = ModelUtils.serialize(scenario);
But I do not know how to deserialize the result of this serialize call.
My question however is more basic, since the code above might be a completely wrong approach. Unfortunately I did not find very much about this in the documentation or anywhere else on the Web.
TL;DR:
What is the best way to serialize an XText object model and to deserialize it again?
The first line doesn't belong here at all, just remove it.
How did you create/obtain the object 'scenario'?
If it was parsed with Xtext already you can obtain the serializer like this:
((XtextResource)scenario.eResource()).getResourceServiceProvider
.get(ISerializer.class)
Currently our application uses GWT-RPC for most client-server communication. Where this breaks down is when we need to auto generate images. We generate images based on dozens of parameters so what we do is build large complex urls and via a get request retrieve the dynamically built image.
If we could find a way to serialize Java objects in gwt client code and deserialize it on the server side we could make our urls much easier to work with. Instead of
http://host/page?param1=a¶m2=b¶m3=c....
we could have
http://host/page?object=?JSON/XML/Something Magicical
and on the server just have
new MagicDeserializer.(request.getParameter("object"),AwesomeClass.class);
I do not care what the intermediate format is json/xml/whatever I just really want to be able stop keeping track of manually marshalling/unmarshalling parameters in my gwt client code as well as servlets.
Use AutoBean Framework. What you need is simple and is all here http://code.google.com/p/google-web-toolkit/wiki/AutoBean
I've seen the most success and least amount of code using this library:
https://code.google.com/p/gwtprojsonserializer/
Along with the standard toString() you should have for all Object classes, I also have what's called a toJsonString() inside of each class I want "JSONable". Note, each class must extend JsonSerializable, which comes with the library:
public String toJsonString()
{
Serializer serializer = (Serializer) GWT.create(Serializer.class);
return serializer.serializeToJson(this).toString();
}
To turn the JSON string back into an object, I put a static method inside of the same class, that recreates the class itself:
public static ClassName recreateClassViaJson(String json)
{
Serializer serializer = (Serializer) GWT.create(Serializer.class);
return (ClassName) serializer.deSerialize(json, "full.package.name.ClassName");
}
Very simple!
I know that GWT has a good RPC support. But for various purposes I need to build this on my own:
1.) How can I convert a Bean Object (on the Client Side) like;
class MyPerson {
String name;
String getName();
void setName(String name);
//..
}
with GWT into a JSON String? (Ideally only using libraries that come officially from GWT/Google).
2.) Secondly, how can I send this generated JSON String from the Client side to any Server also using any GWT Client Logik. (Ideally only using libraries that come officially from GWT/Google).
I have searched a lot, but the examples never show how to send data but only to receive JSON data.
Thank you very much!!!
Jens
There's a nifty class called AutoBeanFactory that GWT will create for you, no third-party libs required. See http://google-web-toolkit.googlecode.com/svn-history/r9219/javadoc/2.1/com/google/gwt/editor/client/AutoBeanFactory.html
Once you have your AutoBeanFactory, you can use it like this:
producing JSON from an object of type SimpleInterface
AutoBean<SimpleInterface> bean = beanFactory.create(SimpleInterface.class, simpleInterfaceInstance);
String requestData = AutoBeanCodex.encode(bean).getPayload();
useRequestBuilderToSendRequestWhereverYouWant(requestData);
parsing JSON from an object of type SimpleInterface
SimpleInterface simpleInterfaceInstance = AutoBeanCodex.decode(beanFactory, SimpleInterface.class, responseText).as();
You can use RequestBuilder to send these requests without GWT-RPC or the RF stuff.
I recommend you use RestyGWT it makes JSON rest services work just like GWT RPC services.
Take a look at GWT's AutoBean framework, which can be used to create and receive JSON payloads. The RequestBuilder type can be used to send HTTP requests to the server.
You have also another solution which is 3rd party solution, maybe a second place solution but it can be also the first place.
The 3rd party called GSON and it's a project open source on google code.
You can find it here.
I used it and it's very good and very simple.