My project is written in the Java programming language using the Spring Boot framework.
I use Unirest library for getting requests to some API and I want to get response in forms, which looks like List<SomeResponse>
Below I write some example of request, which I try to make.
Why do I need a list? Because this data structure is more convenient and used throughout the rest of the huge project.
I tried various options for receiving a response to the request, but I could not get the List <SomeResponse> in any way. At the moment, my efforts have led me only to the fact that I get an array of the objects I need. Of course, we could try to cast the array to list, but here, as it seems to me, we lose in speed.
try {
SomeResponse[] SomeResponses = Unirest.post(url)
.header("Content-Type", "application/json")
.header("Authorization", key)
.body("[\"" + address + "\"]")
.asObject(SomeResponse[].class)
.getBody();
return Result.ok(SomeResponses);
} catch (UnirestException e) {
return Result.error("Error in call API " + url);
}
Also, I have configured the Jackson library, which serializes the JSON format, which that we receive in response to a request, in POJO classes. Perhaps you could tell how to configure the mapper correctly so that it can accept and serialize this response.
Few words about versions of libraries and frameworks. I used Gradle to build and manage dependencies.
org.springframework.boot:spring-boot-starter:2.0.0.RELEASE
com.fasterxml.jackson.core:jackson-databind:2.10.1
com.mashape.unirest:unirest-java:1.4.9
Thanks a lot for your answers!
P.S.
Sorry, this question may have a bad structure, but this is the first time I am writing a problem on this platform, I promise to make my question better in the future.
Replace the SomeResponse[].class in asObject with a GenericType<List<SomeResponse>> object.
try {
List<SomeResponse> someResponses = Unirest.post(url)
.header("Content-Type", "application/json")
.header("Authorization", key)
.body("[\"" + address + "\"]")
.asObject(new GenericType<List<SomeResponse>>() {})
.getBody();
return Result.ok(someResponses);
} catch (UnirestException e) {
return Result.error("Error in call API " + url);
}
Related
I need my Java application to make a PATCH request to a web server using SSL.
I have tried the following:
public String patchForm(FormDataMultiPart f, Map<String,String> headers) {
Entity<FormDataMultiPart> entity = Entity.entity(f, f.getMediaType());
webTarget.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
Builder request = webTarget.request();
if (headers != null){
for (String key : headers.keySet()){
request = request.header(key, headers.get(key));
}
}
Response result = request.method("PATCH", entity);
return result.readEntity(String.class);
}
Where Entity is javax.ws.rs.client.Entity and webTarget is a javax.ws.rs.client.WebTarget.
However, when I make the request, the server interprets it as a POST request and gives me the wrong response.
What could be the cause of the problem? Is there any way to fix it?
Thank you in advance.
For a Patch you need to set which url you are hitting to be secure.
For example
Your webTarget will have
webTarget.path("https://secureUrlWichWillForceSsl.com");
if it starts with http:// it will not be secure and no SSL.
After a lot of trial and error, doing and undoing, adding _HttpMethod=PATCH to the query string and then removing it because it turned out not to be necessary, especially adding a missing break to a switch close which was causing the patchForm function to not be called at all (yes, that was a stupid oversight which cost me hours of work), and then fixing the errors which kept cropping up, I have finally arrived at something which works.
The code which finally worked was the following:
public String patchForm(FormDataMultiPart f, Map<String,String> headers) {
Entity<FormDataMultiPart> entity = Entity.entity(f, f.getMediaType());
webTarget.register(MultiPartFeature.class);
webTarget.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
Builder request = webTarget.request();
headers.put("X-HTTP-Method-Override", "PATCH");
if (headers != null){
for (String key : headers.keySet()){
request = request.header(key, headers.get(key));
}
}
Response result = request.patch(entity);
return result.readEntity(String.class);
}
Note that the Builder class has a built-in patch method. I was using an old library which did not have it. And yet, the method workaround is still necessary because otherwise I get an exception since the PATCH method is non-standard.
Also note that, when submitting multipart forms, it is important to register the Multipart feature. I have read that it is possible to register it either on the client by overriding the configureClient method (when writing a custom client) or on the web target. Doing it on the web target suited my needs better, but you can do it in whatever way works best for you.
I have a monolithic legacy application that I need to read and submit data to. It's using Google Web Kit and Java Servlets.
I have access to the source code, but I'm new to both Servlets and GWT.
I'm trying to encapsulate a rest client in my project that can communicate with GET/POST rest calls to the legacy server.
I've been able to send a POST request using Postman, and then used Reactive Spring 5.0 framework to sending that request.
When I try to deserialize the response, I'm running into a ton of errors.
How would I deserialize this payload?
7|0|7|http://localhost:8080/testproject/
|29F4EA1240F157649C12466F01F46F60|
com.test.client.GreetingService|greetServer|java.lang.String|
myInput1|myInput2|1|2|3|4|2|5|5|6|7|
I've searched all day, and followed a few blogs like these:
https://docs.google.com/document/d/1eG0YocsYYbNAtivkLtcaiEE5IOF5u4LUol8-LL0TIKU/edit#
https://blog.gdssecurity.com/labs/2009/10/8/gwt-rpc-in-a-nutshell.html
I'm not sure code wise how I can serialize them into my own object for my new service.
static WebClient webClient = WebClient.create();
public static void main(String[] args) {
Mono<String> body = Mono.just("7|0|7|http://localhost:8080/testproject/|29F4EA1240F157649C12466F01F46F60|com.test.client.GreetingService|greetServer|java.lang.String|myInput1|myInput2|1|2|3|4|2|5|5|6|7|");
Mono<String> response = webClient.post()
.uri("http://localhost:8080/testproject/")
.header("Content-Type", "text/x-gwt-rpc;charset=UTF-8")
.header("X-GWT-Module-Base", "http://localhost:8080/testproject/")
.header("X-GWT-Permutation", "29F4EA1240F157649C12466F01F46F60")
.cookie("JSESSIONID", "2BCEBF12GE2C3A0335F5012812A73638")
.body(body, String.class)
.retrieve()
.bodyToMono(String.class);
String unBlocked = response.block();
System.out.println(unBlocked);
//OK[1,1,["java.lang.Integer/3438228391"],0,2]
try {
ServerSerializationStreamReader streamReader = new ServerSerializationStreamReader(
Thread.currentThread().getContextClassLoader(), null);
streamReader.prepareToRead(unBlocked);
System.out.println(streamReader.readObject());
} catch ( Exception e) {
e.printStackTrace();
}
}
Error:
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: This application is out of date, please click the refresh button on your browser. ( Malformed or old RPC message received - expecting version between 5 and 7 )
I've tried every version of GWT because of the malformed RCP message.
Also, I tried to stick it into a string, which I'm sure is failing on its own.
You are trying to decode the server response with the code meant decode the client request. At present they use a different format for historical reasons - note how the response starts with "//OK", but the request has the version/flags/stringcount "7|0|7" beginning.
In at least a small part this is because when a client calls a server, it needs to describe what version it is speaking and where the server should find the file listing the set of classes that the client expects are allowed to be serialized. When the server responds, since the client already told it about the typed that can be serialized, it doesn't need to tell the client the same thing again.
Reading the com.google.gwt.user.client.rpc.impl.ClientSerializationStreamReader class and its docs will show the response format and how it can be decoded into objects. There is presently no server-side code that I'm aware of that is intended to do this job, but could probably be written with fairly little difficulty, just some persistence.
I have a Spring Boot application that (among other things) gets some data from a third party JSON API (secured with OAuth), processes the result and presents it to the user. The application receives approx. 1 request each second.
Unfortunately this process is very slow at the moment (and in many cases even ends with a 503 error) and I am looking for some idea to improve the implementation. (by the way: the third party API itself does not seem to be the bottleneck as a instance of my app running on my local machine using the exact same API response very fast at the same time that the deploy instance takes very long).
For the API call I use the Apache HTTP library - or more specifically the Async HTTP Client:
this.httpClientAsync = HttpAsyncClients.custom()
.setDefaultCredentialsProvider(credsProvider) //for forward proxy
.build();
And the actual call to the API is this:
updateToken(); //get or update OAuth Token
HttpGet httpget = new HttpGet(URL);
httpget.addHeader("Authorization", "Bearer " + accessToken);
Future<HttpResponse> f = this.httpClientAsync.execute(httpget, callback);
Do you have any suggestion on how to improve the implementation?
To be honest, I don't even have an idea where the bottleneck is at the moment. Any idea on how to find out about that?
Thanks for your hints!
One more thing/update:
the Spring Controller looks something like this:
#RequestMapping(value = "/api/v1/api_data")
public DeferredResult<ResponseEntity<Map>> getAPIData() throws IOException, InterruptedException {
DeferredResult<ResponseEntity<Map>> res = new DeferredResult<>();
triggerAPICall(new FutureCallback() {
public void completed(Object o) {
(...)
res.setResult(...);
}
(...)
}
return res;
}
Furthermore, I was originally not using the async version of the HTTP client, but the blocking version. This then even slowed down the rest of the application...
I have to call a web service located in http://ip:port/ws which has no wsdl.
I can send an HTTP POST using Spring framework's RestTemplate and get answer as raw input from the service. But this is annoying a bit, that's why I am looking for the correct way to consume this web service without WSDL.
Can anybody suggest a 'best practice' way for this task?
There is really no best practice, recreating the WSDL or at least the XML Schema seems like your only option to improve upon your current approach.
If you're really lucky, it'll return some consistent XML that you might be able to throw an XPath parser at to extract the bits you need. You might be able to tease out the XML schema either from the data it returns (look for a namespace declaration at the top of the document somewhere, and see if you can follow the URI it references), or drop the data into an on-line schema generator like this one
I could not find the best solution, and did some workaround. So as we know the SOAP call in HTTP environment is a standard HTTP POST with the soap envelope in HTTP POST body. So I did the same. I stored the xml soap requests in different place just not mess with the code:
public static final String REQ_GET_INFO = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:urn=\"urn:xyz\">" +
" <soapenv:Header/>" +
" <soapenv:Body>" +
" <urn:export>" +
" <cardholderID>%s</cardholderID>" +
" <bankId>dummy_bank</bankId>" +
" </urn:export>" +
" </soapenv:Body>" +
"</soapenv:Envelope>";
And in service layer I used RestTemplate post call with required headers:
#Value("${service.url}") // The address of SOAP Endpoint
private String wsUrl;
public OperationResponse getCustomerInfo(Card card) {
OperationResponse operationResponse = new OperationResponse(ResultCode.ERROR);
try {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "text/xml");
HttpEntity<String> request = new HttpEntity<>(String.format(Constants.SoapRequest.REQ_GET_INFO,
card.getCardholderId()), headers);
String result = restTemplate.postForObject(wsUrl, request, String.class);
if(!result.contains("<SOAP-ENV:Fault>")) {
// Do SOAP Envelope body parsing here
}
}
catch(Exception e) {
log.error(e.getMessage(), e);
}
return operationResponse;
}
A little bit of dirty job, but it worked for me :)
Basically I need to read the body of HttpServletRequest multiple times, based on my research I found that one of easiest way for doing that is by using ContentCachingRequestWrapper
Here is how I implemented it:
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper((HttpServletRequest) request);
try{
MultipartRequest multipartRequest = new MultipartRequest(requestWrapper, ImageDirecoty, 1024*1024*5);
String test = requestWrapper.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
System.out.print(test);
} catch(IOException e){
System.out.println(e.getMessage());
return;
}
FYI: I am uploading a simple file from my client to server.
Now at first it reads the request body just fine, but in the second line which I have String test = requestWrapper to read it's content and to output it to console I don't get my Ecplise console outputing me anything and I don't get any error too, I'd really appreciate if somebody tell me what am i doing wrong.
actually the easy est way to do it is to use(convert the response), to some kind of Pojo class, and then saving it to whatever you want.
here is a link to convert it to pojo
http://www.jsonschema2pojo.org/
also you can use library's like Retrofit 2.0 to make your http calls much easier.
http://square.github.io/retrofit/