amadeus4dev / amadeus-java

Java library for the Amadeus Self-Service travel APIs
https://developers.amadeus.com/
MIT License
87 stars 69 forks source link

shopping hotel-offers : issue sending array of hotel id's #211

Closed steve-donovan closed 1 year ago

steve-donovan commented 2 years ago

Description

API indicates that it is possible to supply an array of hotel id's, but the Params class used by API only works with Strings. Passing an array causes an Exception.

Screenshot 2022-09-20 at 18 17 28 Screenshot 2022-09-20 at 18 20 29
tsolakoua commented 2 years ago

Hello @steve-donovan ,

You can pass the list of hotels as an ArrayList of Strings such us below:

import java.util.ArrayList;
import java.util.List;
import com.amadeus.Amadeus;
import com.amadeus.Params;
import com.amadeus.exceptions.ResponseException;
import com.amadeus.resources.HotelOfferSearch;

public class FlightSearch {

  public static void main(String[] args) throws ResponseException {

    Amadeus amadeus = Amadeus
      .builder("YOUR_ID","YOUR_SECRET")
      .build();

      List<String> ids = new ArrayList<String>();
      ids.add("MCLONGHM");
      ids.add("WIMAD079");

      HotelOfferSearch[] offers = amadeus.shopping.hotelOffersSearch.get(
        Params.with("hotelIds", ids)
          .and("adults", 2)
      );

      if (offers[0].getResponse().getStatusCode() != 200) {
        System.out.println("Wrong status code: " + offers[0].getResponse().getStatusCode());
        System.exit(-1);
      }

      System.out.println(offers[0]);
  }
}

Would that solution work for you?

steve-donovan commented 2 years ago

Hi @tsolakoua

That does not work, and can't work. The Params.and used String valueof which would give the wrong format - it called the toString of the object, and for ArrayList, it will bracket the result

I took the List from your code above , and added your test test :

@Test
  public void given_client_when_call_hotel_offers_search_with_params_then_ok()
      throws ResponseException, IOException {

    //Given
    String address = "/v3/shopping/hotel-offers"
        + "?hotelIds=MCLONGHM"
        + "&roomQuantity=1"
        + "&adults=1"
        + "&checkInDate=2022-11-22"
        + "&paymentPolicy=NONE"
        + "&bestRateOnly=true";
    wireMockServer.stubFor(get(urlEqualTo(address))
        .willReturn(aResponse().withHeader("Content-Type", "application/json")
        .withStatus(200)
        .withBodyFile("hotel_offers_search_response_ok.json")));

    // ***** HERE *****
    List<String> ids = new ArrayList<String>();
    ids.add("MCLONGHM");
    ids.add("WIMAD079");

    //When
    HotelOfferSearch[] result = amadeus.shopping.hotelOffersSearch.get(
      Params.with("hotelIds", ids) // ***** HERE *****
        .and("adults", 1)
        .and("checkInDate", "2022-11-22")
        .and("roomQuantity", 1)
        .and("paymentPolicy", "NONE")
        .and("bestRateOnly", true)
    );

    //Then
    then(result.length).isNotEqualTo(0);
  }

The test then fails

Screenshot 2022-10-05 at 11 55 05
tsolakoua commented 2 years ago

Thanks @steve-donovan for your response!

As a workaround you could convert the list to String with one of the following ways and then call the API:

      List<String> ids = new ArrayList<String>();
      ids.add("MCLONGHM");
      ids.add("WIMAD079");

      // Option 1
      String idsToStr1 = String.join(",", ids);
      // Option 2
      String idsToStr2 = ids.stream().collect(Collectors.joining(","));

And the test could be updated as

  @Test
  public void given_client_when_call_hotel_offers_search_with_params_then_ok()
      throws ResponseException, IOException {

    //Given
    String input = URLEncoder.encode("MCLONGHM,WIMAD079", "UTF-8");
    String address = "/v3/shopping/hotel-offers"
        + "?hotelIds=" + input
        + "&roomQuantity=1"
        + "&adults=1"
        + "&checkInDate=2022-11-22"
        + "&paymentPolicy=NONE"
        + "&bestRateOnly=true";
    wireMockServer.stubFor(get(urlEqualTo(address))
        .willReturn(aResponse().withHeader("Content-Type", "application/json")
        .withStatus(200)
        .withBodyFile("hotel_offers_search_response_ok.json")));

    // ***** HERE *****
    List<String> ids = new ArrayList<String>();
    ids.add("MCLONGHM");
    ids.add("WIMAD079");
    String idsToStr1 = String.join(",", ids);
    // String idsToStr2 = ids.stream().map(String::valueOf).collect(Collectors.joining(","));

    //When
    HotelOfferSearch[] result = amadeus.shopping.hotelOffersSearch.get(
      Params.with("hotelIds", idsToStr1) // ***** HERE *****
        .and("adults", 1)
        .and("checkInDate", "2022-11-22")
        .and("roomQuantity", 1)
        .and("paymentPolicy", "NONE")
        .and("bestRateOnly", true)
    );

    //Then
    then(result.length).isNotEqualTo(0);
  }

We encoded the hotel list in the given since in Params.java the parameters are encoded so they were not matching with the query at when.

Internally we are going to review the rest of the APIs to identify more of similar scenarios and we will decide how we can evolve and expand the Params.

tsolakoua commented 1 year ago

Closing and keeping the #215 instead.