Optional response body for rest client using RESTEasy - resteasy

I'm writing a POC for Quarkus. I'm using this quick start guide to build a REST client. The REST service I'll be integrating with is third party. Here is a simple example of my current implementation:
#Path("/v1")
#RegisterRestClient
public class EmployeeApi {
#POST
#Path("/employees")
ApiResponse createEmployee(#RequestBody Employee employee)
}
This works fine. The issue I'm having is that the third party API will, depending on success / failure, return a response body. In the scenario it does fail, it provides details in the response body (ApiResponse) on why it was unsuccessful. When it succeeds, it returns nothing. This causes Quarkus to throw the following exception:
javax.ws.rs.ProcessingException: RESTEASY003145: Unable to find a MessageBodyReader of content-type application/octet-stream and type com.test.app.ApiResponse
I've tried to wrap ApiResponse in an Optional type but does not solve the problem. I see absolutely nothing in Quarkus / RESTEasy documentation that would indicate a work-around.
I'm wondering if I should be using javax.ws.rs.core.Response instead.

The problem is JaxRS tries to fit ApiResponse to a default return type being application/octet-stream
You should make sure to specify explicitly that you're returning application/json
This is possible using #Produces(APPLICATION_JSON) on top of your service.
Here is the correct code snippet
#Path("/v1")
#RegisterRestClient
public class EmployeeApi {
#POST
#Path("/employees")
#Produces(APPLICATION_JSON)
ApiResponse createEmployee(#RequestBody Employee employee)
}

Related

Several GET Methods in ASP .NET WEB API causing 500 when sending array using URI

In my ASP .NET WEB API, I want to use the following methods:
[Route(""), HttpGet]
public IDictionary<int, string> GetAll()
{
//doSth
}
[Route(""), HttpGet]
public IDictionary<int, string> GetSpecificOnes([FromUri]IEnumerable<int> carsIds)
{
//doSth
}
When requesting the second one using angular, I get the following exception:
angular.js:12011 GET http://localhost:12345/_api/cars?&carsIds[0]=1&carsIds[1]=2&carsIds[2]=5 500 (Internal Server Error)
I think the problem is, that I have two GET-Methods without a route. But I don't need one. How do I solve this problem?
You actually don't need to define a route, like you say, as long as the GET methods in the controllers have different signatures and parameterlist.
The problem in your case is that you call the method the wrong way.
Either change the parameter name in the api method to carsIds or change the angular HTTP query string to ?ids[0]=1&ids[1]=2&ids[2]=5

How to call App Engine Endpoints with the JavaScript library in promises mode

I have a web application which calls several App Engine Endpoints with the Google API JavaScript client library.
I am currently changing this application from callback mode to promises mode, as recommended by Google (https://developers.google.com/api-client-library/javascript/features/promises#using-promises) and I am encountering a problem. Note that the app works well with the callback mode.
My problem with the promises mode is to find what is the correct path argument to use when calling the request method:
JavaScrit code:
var params = {'webSafeKeyParent’: ‘neN4fm15xW52b2ljZXMtb19saW5lmlYLEglBY1NFwpRpdHkYgICAgQj97AoM’};
gapi.client.request({
'path': 'https://myappenginename.appspot.com/_ah/api/customerApi/v1/?????????',
'params': params
}).then(function(response) {
// Handle response
}, function(reason) {
// Handle error
});
Endpoint definition in "customerApi":
#ApiMethod(
name = "listByParent",
path = "customerByParent/{webSafeKeyParent}",
httpMethod = ApiMethod.HttpMethod.GET,
scopes = {Constants.EMAIL_SCOPE},
clientIds = {Constants.WEB_CLIENT_ID, com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
audiences = {Constants.ANDROID_AUDIENCE})
public List<Customer> listByParent(final User user, #Named("webSafeKeyParent") final String webSafeKeyParent, #Nullable #Named("cursor") String cursor, #Nullable #Named("limit") Integer limit) throws UnauthorizedException {
For few of my endpoints it works by including in the path argument of the JavaScript request method, the values of "path" and "name" as declared in the #ApiMethod annotation.
i.e. for the above endpoint, the following path works:
https://myappenginename.appspot.com/_ah/api/customerApi/v1/customerByParent/listByParent
Strangely enough this does NOT work for some other endpoints of the same kind. I receive either a 404 HTTP error or a 503 one.
I've also tried with the paths displayed under "Request" when you query the endpoints with the APIs Explorer but without success....
Is there any detailed documentation on how to call App Engine Endpoints with promises, with the Google API JavaScript client library? I have not found any. Do you have some advice to share please?
Thanks in advance
Actually the request method DOES work ALL THE TIME with the "path" argument composed of the values of "path" and "name" as declared in the #ApiMethod annotation...
It was a mistake on my side if it didn't work for some endpoints. Don't know which mistake, however.
Note that I have noticed that it is very important to pass to the JavaScript request method the correct httpMethod of the App Engine Endpoints. By default the request methid assumes that it is a GET. In case your Endpoint has httpMethod= ApiMethod.HttpMethod.POST in the #ApiMethod annotation, you shall pass the argument 'method': 'POST', as detailed in the doc: https://developers.google.com/api-client-library/javascript/reference/referencedocs#gapiclientrequestargs

Web api is giving error on passing * as the input value to the api method parameter

I am using asp.net mvc web api and i have this method
[HttpGet]
public LoginResult AuthenticateOnlineBookingUser(String userName,String password)
{
//My Code
}
The problem is that when i pass (*) as input value to the parameter (password)
i receieve this error but on other inputs it is working perfectly
A potentialy dangerous Request.Path.value was detected from client(*)
Thanks in advance
Note:My client side is written in angular js
i tried this solution as well Getting "A potentially dangerous Request.Path value was detected from the client (&)" but it is not working for me
You need to set the options for invalid characters. You can do this in your web.config as shown here.
Use url encoder to encode the request before sending it to server.
Finally solved my problem by changing my GET request to POST request The problem was with query string in Order to solve it with GET Request i have to make some changes to my query string in order to make it work but

CXF wsdl2java, GZip compression, and stub reutilization

I´m using CXF to consume a WebService and, as the responses are quite large, I´m requesting with a gzip "Accept-Encoding" and using GZIPInInterceptor to handle the gziped response. Also my WSDL is very large (360kb) and it takes a long time(+10 seconds) to create the stub, because it has to read and parse the WSDL, so I´m creating the stub once and reusing it.
The problem is, whenever I try to use two different methods the second request gives me an error saying it is expecting the previous request.
To illustrate my problem I created a simple example with this public WebService:
http://www.webservicex.net/BibleWebservice.asmx?WSDL
Without the GZip compression it works fine:
BibleWebserviceSoap bibleService = new BibleWebservice().getBibleWebserviceSoap();
String title = bibleService.getBookTitles();
response.getWriter().write(title);
String johnResponse = bibleService.getBibleWordsbyKeyWord("John");
response.getWriter().write(johnResponse);
I´m able to receive both responses.
Enabling Gzip compression:
BibleWebserviceSoap bibleService = new BibleWebservice().getBibleWebserviceSoap();
//GZIP compression on bibleService
Client client = ClientProxy.getClient(bibleService);
client.getInInterceptors().add(new GZIPInInterceptor());
client.getInFaultInterceptors().add(new GZIPInInterceptor());
// Creating HTTP headers
Map<String, List<String>> headers = new HashMap<String, List<String>>();
headers.put("Accept-Encoding", Arrays.asList("gzip"));
// Add HTTP headers to the web service request
client.getRequestContext().put(Message.PROTOCOL_HEADERS, headers);
String title = bibleService.getBookTitles();
response.getWriter().write(title);
String johnResponse = bibleService.getBibleWordsbyKeyWord("John");
response.getWriter().write(johnResponse);
When I try to receive the second response I´m getting this exception:
org.apache.cxf.interceptor.Fault: Unexpected wrapper element {http://www.webserviceX.NET}GetBookTitlesResponse found. Expected {http://www.webserviceX.NET}GetBibleWordsbyKeyWordResponse.
On my real application I´m getting an exception with the request:
org.apache.cxf.binding.soap.SoapFault: OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'GetAvailabilityRequest' and namespace 'http://schemas.navitaire.com/WebServices/ServiceContracts/BookingService'. Found node type 'Element' with name 'ns4:PriceItineraryRequest' and namespace 'http://schemas.navitaire.com/WebServices/ServiceContracts/BookingService'
My sample project can be downloaded here:
http://www.sendspace.com/file/plt0m4
Thank you
Instead of setting the protocol headers directly like that, use CXF's GZIPOutInterceptor to handle that.
Either that or reset the PROTOCOL headers for each request. When set like that, the headers map gets updated as the request goes through the chain. In this case, the soapaction gets set. This then gets resent on the second request.

How to know if a Kohana request is an internal one?

I'm writing an API using Kohana. Each external request must be signed by the client to be accepted.
However, I also sometime need to do internal requests by building a Request object and calling execute(). In these cases, the signature is unnecessary since I know the request is safe. So I need to know that the request was internal so that I can skip the signature check.
So is there any way to find out if the request was manually created using a Request object?
Can you use the is_initial() method of the request object? Using this method, you can determine if a request is a sub request.
Kohana 3.2 API, Request - is_initial()
It sounds like you could easily solve this issue by setting some sort of static variable your app can check. If it's not FALSE, then you know it's internal.
This is how I ended up doing it: I've overridden the Request object and added a is_server_side property to it. Now, when I create the request, I just set this to true so that I know it's been created server-side:
$request = Request::factory($url);
$request->is_server_side(true);
$response = $request->execute();
Then later in the controller receiving the request:
if ($this->request->is_server_side()) {
// Skip signature check
} else {
// Do signature check
}
And here is the overridden request class in application/classes/request.php:
<?php defined('SYSPATH') or die('No direct script access.');
class Request extends Kohana_Request {
protected $is_server_side_ = false;
public function is_server_side($v = null) {
if ($v === null) return $this->is_server_side_;
$this->is_server_side_ = $v;
}
}
Looking through Request it looks like your new request would be considered an internal request but does not have any special flags it sets to tell you this. Look at 782 to 832 in Kohana_Request...nothing to help you.
With that, I'd suggest extending the Kohana_Request_Internal to add a flag that shows it as internal and pulling that in your app when you need to check if it is internal/all others.
Maybe you are looking for is_external method:
http://kohanaframework.org/3.2/guide/api/Request#is_external
Kohana 3.3 in the controller :
$this->request->is_initial()
http://kohanaframework.org/3.3/guide-api/Request#is_initial

Resources