From e767d1dc0edea5398d4ce2d64b36821883fe040d Mon Sep 17 00:00:00 2001 From: Jean-Pierre Portier <141755467+JPPortier@users.noreply.github.com> Date: Thu, 30 Nov 2023 10:10:48 +0100 Subject: [PATCH] Create integrated numbers flow (#25) * Demo app chaining request from the Numbers API * feat: Adding helper for auto-pagination: getting a Stream --------- Co-authored-by: Antoine Sein --- .../adapters/AvailableNumberService.java | 6 +- .../core/models/pagination/ListResponse.java | 15 + sample-app/README.md | 5 + sample-app/pom.xml | 7 +- .../com/sinch/sample/BaseApplication.java | 66 +-- .../src/main/java/com/sinch/sample/Utils.java | 68 +++ .../sample/numbers/NumbersSampleFlow.java | 393 ++++++++++++++++++ .../sinch/sample/numbers/available/List.java | 36 -- .../com/sinch/sample/sms/batches/Send.java | 4 +- 9 files changed, 495 insertions(+), 105 deletions(-) create mode 100644 sample-app/src/main/java/com/sinch/sample/Utils.java create mode 100644 sample-app/src/main/java/com/sinch/sample/numbers/NumbersSampleFlow.java diff --git a/client/src/main/com/sinch/sdk/domains/numbers/adapters/AvailableNumberService.java b/client/src/main/com/sinch/sdk/domains/numbers/adapters/AvailableNumberService.java index f158c800..1ce0e924 100644 --- a/client/src/main/com/sinch/sdk/domains/numbers/adapters/AvailableNumberService.java +++ b/client/src/main/com/sinch/sdk/domains/numbers/adapters/AvailableNumberService.java @@ -88,12 +88,16 @@ public AvailableNumber checkAvailability(String phoneNumber) throws ApiException public ActiveNumber rent(String phoneNumber, AvailableNumberRentRequestParameters parameters) throws ApiException { + + AvailableNumberRentRequestParameters guardParameters = + null != parameters ? parameters : AvailableNumberRentRequestParameters.builder().build(); + ActiveNumberDto response = getApi() .numberServiceRentNumber( configuration.getProjectId(), phoneNumber, - AvailableRentRequestParametersDtoConverter.convert(parameters)); + AvailableRentRequestParametersDtoConverter.convert(guardParameters)); return ActiveNumberDtoConverter.convert(response); } diff --git a/core/src/main/com/sinch/sdk/core/models/pagination/ListResponse.java b/core/src/main/com/sinch/sdk/core/models/pagination/ListResponse.java index cfdf40ff..1dfaf8c1 100644 --- a/core/src/main/com/sinch/sdk/core/models/pagination/ListResponse.java +++ b/core/src/main/com/sinch/sdk/core/models/pagination/ListResponse.java @@ -4,6 +4,8 @@ import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; /** * Abstract class used for handling unified paginated response @@ -50,6 +52,19 @@ public Iterator iterator() { return new ItemsIterator<>(this); } + /** + * Getting a stream across all items + * + *

Underline API (HTTP request) will be called on demand when next page content will be + * required to fulfill iterator with items for consecutive page + * + * @return Stream onto items + */ + public Stream stream() { + Iterable iterable = this::iterator; + return StreamSupport.stream(iterable.spliterator(), false); + } + static class ItemsIterator implements Iterator { ListResponse response; diff --git a/sample-app/README.md b/sample-app/README.md index 6690df83..2769d783 100644 --- a/sample-app/README.md +++ b/sample-app/README.md @@ -49,6 +49,11 @@ See https://developers.sinch.com for details about these parameters ## Available samples classes +### Full workflow +A full application chaining calls to Numbers service to onboard onto Java SDK and Numbers: [NumbersSampleFlow](src/main/java/com/sinch/sample/numbers/NumbersSampleFlow.java) + +### Dedicated service feature samples + | API | Service | Sample | Class | Notes | |---------|----------------|------------------------|---------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------| | Numbers | Available | - CheckAvailability | [com.sinch.sample.numbers.available.CheckAvailability](src/main/java/com/sinch/sample/numbers/available/CheckAvailability.java) | Require `PHONE_NUMBER` parameter | diff --git a/sample-app/pom.xml b/sample-app/pom.xml index c1aa0ce1..859bef44 100644 --- a/sample-app/pom.xml +++ b/sample-app/pom.xml @@ -12,11 +12,8 @@ [0.0.0,) - 1.8 - 1.8 - 1.8 - 1.8 - 8 + 11 + 11 3.8.0 true true diff --git a/sample-app/src/main/java/com/sinch/sample/BaseApplication.java b/sample-app/src/main/java/com/sinch/sample/BaseApplication.java index 7ac80671..e114e055 100644 --- a/sample-app/src/main/java/com/sinch/sample/BaseApplication.java +++ b/sample-app/src/main/java/com/sinch/sample/BaseApplication.java @@ -2,29 +2,16 @@ import com.sinch.sdk.SinchClient; import com.sinch.sdk.models.Configuration; -import com.sinch.sdk.models.SMSRegion; import java.io.IOException; -import java.io.InputStream; import java.util.Properties; -import java.util.logging.LogManager; import java.util.logging.Logger; public abstract class BaseApplication { - /** duplicate of SinchClient property files for lisibility facility but could be anything else */ - private static final String OAUTH_URL_KEY = "oauth-url"; - - private static final String NUMBERS_SERVER_KEY = "numbers-server"; - private static final String SMS_REGION_KEY = "sms-region"; - private static final String SMS_SERVER_KEY = "sms-server"; - private static final String BATCH_ID_KEY = "BATCH_ID"; private static final String PHONE_NUMBER_KEY = "PHONE_NUMBER"; - private static final String SINCH_KEY_ID = "SINCH_KEY_ID"; - private static final String SINCH_KEY_SECRET = "SINCH_KEY_SECRET"; - private static final String SINCH_PROJECT_ID = "SINCH_PROJECT_ID"; - protected static Logger LOGGER; + protected static final Logger LOGGER = Utils.initializeLogger(BaseApplication.class.getName()); protected SinchClient client; protected String phoneNumber; @@ -32,36 +19,11 @@ public abstract class BaseApplication { protected BaseApplication() throws IOException { - Properties properties = handleConfigurations(); - - String keyId = - null != System.getenv(SINCH_KEY_ID) - ? System.getenv(SINCH_KEY_ID) - : properties.getProperty(SINCH_KEY_ID); - String keySecret = - null != System.getenv(SINCH_KEY_SECRET) - ? System.getenv(SINCH_KEY_SECRET) - : properties.getProperty(SINCH_KEY_SECRET); - String projectId = - null != System.getenv(SINCH_PROJECT_ID) - ? System.getenv(SINCH_PROJECT_ID) - : properties.getProperty(SINCH_PROJECT_ID); - - Configuration.Builder builder = - Configuration.builder().setKeyId(keyId).setKeySecret(keySecret).setProjectId(projectId); - LOGGER.info("Starting application"); - // override by local config - if (properties.containsKey(NUMBERS_SERVER_KEY)) { - builder.setNumbersUrl(properties.getProperty(NUMBERS_SERVER_KEY)); - } - if (properties.containsKey(SMS_SERVER_KEY)) { - builder.setSmsUrl(properties.getProperty(SMS_SERVER_KEY)); - } - if (properties.containsKey(SMS_REGION_KEY)) { - builder.setSmsRegion(SMSRegion.from(properties.getProperty(SMS_REGION_KEY))); - } + Configuration configuration = Utils.loadConfiguration(LOGGER); + + Properties properties = Utils.loadProperties(LOGGER); phoneNumber = null != System.getenv(PHONE_NUMBER_KEY) ? System.getenv(PHONE_NUMBER_KEY) @@ -71,25 +33,7 @@ protected BaseApplication() throws IOException { ? System.getenv(BATCH_ID_KEY) : properties.getProperty(BATCH_ID_KEY); - client = new SinchClient(builder.build()); - } - - private static Properties handleConfigurations() throws IOException { - - InputStream is = BaseApplication.class.getResourceAsStream("/logging.properties"); - if (null != is) { - LogManager.getLogManager().readConfiguration(is); - is.close(); - } - LOGGER = Logger.getLogger(BaseApplication.class.getName()); - - Properties prop = new Properties(); - is = BaseApplication.class.getResourceAsStream("/config.properties"); - if (null != is) { - prop.load(is); - is.close(); - } - return prop; + client = new SinchClient(configuration); } public abstract void run(); diff --git a/sample-app/src/main/java/com/sinch/sample/Utils.java b/sample-app/src/main/java/com/sinch/sample/Utils.java new file mode 100644 index 00000000..51e1297a --- /dev/null +++ b/sample-app/src/main/java/com/sinch/sample/Utils.java @@ -0,0 +1,68 @@ +package com.sinch.sample; + +import com.sinch.sdk.models.Configuration; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import java.util.logging.LogManager; +import java.util.logging.Logger; + +public class Utils { + + private static final String SINCH_KEY_ID = "SINCH_KEY_ID"; + private static final String SINCH_KEY_SECRET = "SINCH_KEY_SECRET"; + private static final String SINCH_PROJECT_ID = "SINCH_PROJECT_ID"; + + public static Logger initializeLogger(String className) { + try (InputStream logConfigInputStream = + Utils.class.getClassLoader().getResourceAsStream("logging.properties")) { + if (logConfigInputStream != null) { + LogManager.getLogManager().readConfiguration(logConfigInputStream); + } else { + throw new RuntimeException("The file 'logging.properties' couldn't be loaded."); + } + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + return Logger.getLogger(className); + } + + public static Properties loadProperties(Logger logger) { + Properties properties = new Properties(); + + try (InputStream input = + Utils.class.getClassLoader().getResourceAsStream("config.properties")) { + if (input != null) { + properties.load(input); + } else { + logger.severe("'config.properties' file could not be loaded"); + } + } catch (IOException e) { + logger.severe("Error loading properties from 'config.properties'"); + } + return properties; + } + + public static Configuration loadConfiguration(Logger logger) { + Properties properties = loadProperties(logger); + + String keyId = + null != System.getenv(SINCH_KEY_ID) + ? System.getenv(SINCH_KEY_ID) + : properties.getProperty(SINCH_KEY_ID); + String keySecret = + null != System.getenv(SINCH_KEY_SECRET) + ? System.getenv(SINCH_KEY_SECRET) + : properties.getProperty(SINCH_KEY_SECRET); + String projectId = + null != System.getenv(SINCH_PROJECT_ID) + ? System.getenv(SINCH_PROJECT_ID) + : properties.getProperty(SINCH_PROJECT_ID); + + return Configuration.builder() + .setKeyId(keyId) + .setKeySecret(keySecret) + .setProjectId(projectId) + .build(); + } +} diff --git a/sample-app/src/main/java/com/sinch/sample/numbers/NumbersSampleFlow.java b/sample-app/src/main/java/com/sinch/sample/numbers/NumbersSampleFlow.java new file mode 100644 index 00000000..35cd7f90 --- /dev/null +++ b/sample-app/src/main/java/com/sinch/sample/numbers/NumbersSampleFlow.java @@ -0,0 +1,393 @@ +package com.sinch.sample.numbers; + +import com.sinch.sample.Utils; +import com.sinch.sdk.SinchClient; +import com.sinch.sdk.core.exceptions.ApiException; +import com.sinch.sdk.domains.numbers.models.*; +import com.sinch.sdk.domains.numbers.models.requests.*; +import com.sinch.sdk.models.Configuration; +import java.util.Collections; +import java.util.Optional; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class NumbersSampleFlow { + + private static final Logger LOGGER = Utils.initializeLogger(NumbersSampleFlow.class.getName()); + + public static void main(String[] args) { + + try { + Configuration configuration = Utils.loadConfiguration(LOGGER); + new NumbersSampleFlow().run(configuration); + } catch (ApiException apiException) { + LOGGER.severe(apiException.toString()); + System.exit(-1); + } + } + + public void run(Configuration configuration) { + + String testRegionCode = "US"; // region code we are interested in + String testCodePattern = "+1781"; // Boston area code + + SinchClient sinch = new SinchClient(configuration); + // ===================================================================== \\ + // Scenario: We want to rent a number of type 'LOCAL' in the 'US' region \\ + // ===================================================================== \\ + int step = 0; + + // 1. check and retrieve region code availability + var regionCode = checkAndGetRegionCodeAvailability(++step, sinch, testRegionCode); + + // 2. retrieve a number for this region code + boolean rentByNumber = true; + String phoneNumber; + + if (rentByNumber) { + // 2.1 can be rent by phone number + phoneNumber = getAvailablePhoneNumber(++step, sinch, regionCode, testCodePattern); + // Rent by phone number + rentPhoneNumber(++step, sinch, phoneNumber); + } else { + // 2.2 or can be rent by filtering parameters + phoneNumber = rentPhoneNumberByAny(++step, sinch, regionCode, testCodePattern); + } + + echo("Let's use now the 'ActiveNumbers' API to see how to manage this number.\n"); + + // 3 Verify number is active + // 3.1: verify by dedicated phone number request + verifyActiveNumberByNumber(++step, sinch, phoneNumber); + // 3.2: verify by listing page after page and check for requested number + verifyActiveNumberByPagination(++step, sinch, phoneNumber, regionCode); + // 3.3: verify by using auto pagination feature and check for requested number + verifyActiveNumberByAutoPagination(++step, sinch, phoneNumber, regionCode); + + // 4: Update an active number + updateActiveNumber(++step, sinch, phoneNumber); + + // 5. Release the number + releasePhoneNumber(++step, sinch, phoneNumber); + } + + String checkAndGetRegionCodeAvailability(int step, SinchClient sinchClient, String regionCode) { + + echoStep( + step, + "List the available regions that support the type 'LOCAL' and check if '" + + regionCode + + "' is" + + " part of them"); + + // 1. Build the request data for listing the regions that support 'LOCAL' numbers + var availableRegionsRequestData = + AvailableRegionListAllRequestParameters.builder() + .setTypes(Collections.singletonList(NumberType.LOCAL)) + .build(); + + // 2. Request for available regions using the built-in SDK method + var availableRegionListResponse = + sinchClient.numbers().regions().list(availableRegionsRequestData); + + // 3. This API is following the SDK pattern for list and the server response is wrapped inside a + // ListResponse + // The response list is found using the getContent() method + var regions = availableRegionListResponse.getContent(); + // Check whether we have some results and stop the program otherwise + if (regions.isEmpty()) { + throw new ApiException( + "No regions are available for the number type " + + availableRegionsRequestData.getTypes().orElseThrow().stream() + .map(NumberType::valueOf) + .collect(Collectors.joining(", "))); + } + + // 4. auto iteration other items is available for all List responses. + // In case of underlying API is requiring new calls (paginated results): it will be handled + // automatically + echo("List of available regions:"); + availableRegionListResponse.iterator().forEachRemaining(f -> echo(" - " + f.getRegionCode())); + + // 4. Check if 'US' is part of the regions that support the 'LOCAL' type + if (availableRegionListResponse.stream() + .noneMatch(region -> regionCode.equals(region.getRegionCode()))) { + throw new ApiException("The '" + regionCode + "' region is not supported."); + } + + echo( + "The region '" + + regionCode + + "' is available. Let's use it in the following of this program.\n"); + + return regionCode; + } + + String getAvailablePhoneNumber( + int step, SinchClient sinchClient, String regionCode, String codePattern) { + + echoStep( + step, + "List available numbers in the '" + + regionCode + + "' region with pattern '" + + codePattern + + "'"); + + // 1. Build the request data for listing the numbers of type 'LOCAL' in the regionCode with an + // area code pattern + var availableNumbersRequestData = + AvailableNumberListAllRequestParameters.builder() + .setRegionCode(regionCode) + .setType(NumberType.LOCAL) + .setNumberPattern( + NumberPattern.builder() + .setSearchPattern(SearchPattern.START) + .setPattern(codePattern) + .build()) + .build(); + + // 2. Request for available numbers using the built-in SDK method + // This API is following the SDK pattern for list and the server response is wrapped inside a + var availableNumbersListResponse = + sinchClient.numbers().available().list(availableNumbersRequestData); + + // 3. Looking for first available number + // auto iteration other items is available for all List responses. + // In case of underlying API is requiring new calls (paginated results): it will be handled + // automatically + AvailableNumber availableNumber = + availableNumbersListResponse.stream() + .findFirst() + .orElseThrow( + () -> + new ApiException( + "No numbers are available for the number type " + + availableNumbersRequestData.getType() + + " in the region " + + availableNumbersRequestData.getRegionCode() + + " with the pattern " + + availableNumbersRequestData.getNumberPattern().get().getPattern())); + + // 4. return the phone number + String phoneNumber = availableNumber.getPhoneNumber(); + echo("The phone number '" + phoneNumber + "' is available. Let's rent it!\n"); + + return phoneNumber; + } + + void rentPhoneNumber(int step, SinchClient sinchClient, String phoneNumber) { + + echoStep(step, "Rent phone number: '" + phoneNumber + "'"); + + // 1. Build the request data + var rentRequestData = + AvailableNumberRentRequestParameters.builder().setCallbackUrl("https://foo.url").build(); + + // 2. Request to rent the number + ActiveNumber rentedNumber = + sinchClient.numbers().available().rent(phoneNumber, rentRequestData); + + echo( + "The number " + + rentedNumber.getPhoneNumber() + + " has been rented with the 'rent' operation.The next charge date is " + + rentedNumber.getNextChargeDate()); + } + + String rentPhoneNumberByAny( + int step, SinchClient sinchClient, String regionCode, String pattern) { + + echoStep(step, "Rent a phone number for region '" + regionCode + "'"); + + // 1. Build the request data + var rentAnyNumberRequestData = + AvailableNumberRentAnyRequestParameters.builder() + .setRegionCode(regionCode) + .setType(NumberType.LOCAL) + .setNumberPattern( + NumberPattern.builder() + .setSearchPattern(SearchPattern.START) + .setPattern(pattern) + .build()) + .build(); + + // 2. rent a number + ActiveNumber rentedNumber = sinchClient.numbers().available().rentAny(rentAnyNumberRequestData); + + echo( + "The number " + + rentedNumber.getPhoneNumber() + + " has been rented with the 'rentAny' operation.The next charge date is " + + rentedNumber.getNextChargeDate() + + "\n"); + return rentedNumber.getPhoneNumber(); + } + + void verifyActiveNumberByNumber(int step, SinchClient sinchClient, String phoneNumber) { + echoStep( + step, + "Verify the number is part of our active numbers - Method 1: Give the number in input"); + + // 1. Simple request to get information related to active number + ActiveNumber activeNumber = sinchClient.numbers().active().get(phoneNumber); + + echo( + "SUCCESS: The number " + + phoneNumber + + " has been found as an active number. Cost is " + + activeNumber.getMoney().getAmount() + + " " + + activeNumber.getMoney().getCurrencyCode() + + "\n"); + } + + void verifyActiveNumberByPagination( + int step, SinchClient sinchClient, String phoneNumber, String regionCode) { + + echoStep( + step, + "Check the number is part of our active numbers - Method 2: List all active numbers and" + + " navigate across pages"); + + // 1. Build the request data + var listActiveNumbersRequestData = + ActiveNumberListRequestParameters.builder() + .setRegionCode(regionCode) + .setType(NumberType.LOCAL) + .setPageSize(2) // Set a low number to demonstrate the pagination later on + .build(); + + // 2. Request for active number using the built-in SDK method + var activeNumbersListResponse = + sinchClient.numbers().active().list(listActiveNumbersRequestData); + + // 3. To check if the phone number is part of the active numbers: check the page + // content and if not present, check the next page until we find the phone number, or we reach + // the end of the list + Optional found; + boolean reachedEndOfPages = false; + do { + // use stream onto page content to looking for phoneNumber + found = + activeNumbersListResponse.getContent().stream() + .filter( + f -> + phoneNumber.equals(f.getPhoneNumber()) + && regionCode.equals(f.getRegionCode())) + .findFirst(); + + // not present within current page + if (found.isEmpty()) { + // need to load the next one... if there is one available + if (activeNumbersListResponse.hasNextPage()) { + activeNumbersListResponse = activeNumbersListResponse.nextPage(); + } else { + reachedEndOfPages = true; + } + } + } while (found.isEmpty() && !reachedEndOfPages); + + echo( + (found.isPresent() ? "SUCCESS:" : "FAILED:") + + " The number " + + phoneNumber + + " is " + + (found.isPresent() ? "" : "NOT ") + + "listed in the active numbers.\n"); + } + + void verifyActiveNumberByAutoPagination( + int step, SinchClient sinchClient, String phoneNumber, String regionCode) { + + echoStep( + step, + "Check the number is part of our active numbers - Method 3: List all active numbers and" + + " navigate across pages using auto pagination SDK feature"); + + // 1. Build the request data + var listActiveNumbersRequestData = + ActiveNumberListRequestParameters.builder() + .setRegionCode(regionCode) + .setType(NumberType.LOCAL) + .setPageSize(2) // Set a low number to demonstrate the pagination later on + .build(); + + // 2. Request for active number using the built-in SDK method + var activeNumbersListResponse = + sinchClient.numbers().active().list(listActiveNumbersRequestData); + + // 3. To check if the phone number is part of the active numbers: use the + // auto-iterator. Like for hasNextPage/nextPage, http calls will be performed automatically when + // required + var iterator = activeNumbersListResponse.iterator(); + boolean found = false; + while (iterator.hasNext()) { + var number = + iterator + .next(); // If we are at the end of the current page content, the next() method will + // perform an HTTP call to load more elements in the iterator + if (phoneNumber.equals(number.getPhoneNumber()) + && regionCode.equals(number.getRegionCode())) { + found = true; + break; + } + } + + echo( + (found ? "SUCCESS:" : "FAILED:") + + " The number " + + phoneNumber + + " is " + + (found ? "" : "NOT ") + + "listed in the active numbers.\n"); + } + + void updateActiveNumber(int step, SinchClient sinchClient, String phoneNumber) { + + echoStep(step, "Update active number: '" + phoneNumber + "'"); + + // 1. Build the request data + var updateActiveNumberRequestData = + ActiveNumberUpdateRequestParameters.builder() + .setDisplayName("Rented in the scope of testing the Java SDK") + .build(); + + // 2. Request to update the number + ActiveNumber updatedNumber = + sinchClient.numbers().active().update(phoneNumber, updateActiveNumberRequestData); + + echo( + "SUCCESS: The number " + + phoneNumber + + " has been updated; the display name is '" + + updatedNumber.getDisplayName() + + "'\n"); + } + + void releasePhoneNumber(int step, SinchClient sinchClient, String phoneNumber) { + echoStep(step, "Releasing phone number: '" + phoneNumber + "'"); + + // 1. Request to release the number + ActiveNumber releasedNumber = sinchClient.numbers().active().release(phoneNumber); + + echo( + "SUCCESS: The number " + + phoneNumber + + " has been released; it will expire at " + + releasedNumber.getExpireAt()); + } + + void echoStep(int step, String text) { + String formatted = "| Step " + step + ": " + text + " |"; + String separator = String.format("+%0" + (formatted.length() - 2) + "d+", 0).replace('0', '-'); + + System.out.println(separator); + System.out.println(formatted); + System.out.println(separator); + } + + void echo(String text) { + System.out.println(" " + text); + } +} diff --git a/sample-app/src/main/java/com/sinch/sample/numbers/available/List.java b/sample-app/src/main/java/com/sinch/sample/numbers/available/List.java index 67970a46..1ff7f50d 100644 --- a/sample-app/src/main/java/com/sinch/sample/numbers/available/List.java +++ b/sample-app/src/main/java/com/sinch/sample/numbers/available/List.java @@ -1,11 +1,8 @@ package com.sinch.sample.numbers.available; import com.sinch.sample.BaseApplication; -import com.sinch.sdk.core.exceptions.ApiException; import com.sinch.sdk.domains.numbers.models.Capability; -import com.sinch.sdk.domains.numbers.models.NumberPattern; import com.sinch.sdk.domains.numbers.models.NumberType; -import com.sinch.sdk.domains.numbers.models.SearchPattern; import com.sinch.sdk.domains.numbers.models.requests.AvailableNumberListAllRequestParameters; import com.sinch.sdk.domains.numbers.models.responses.AvailableNumberListResponse; import java.io.IOException; @@ -48,38 +45,5 @@ public void run() { page++; LOGGER.info(String.format("Response (page %d): %s", page, response)); } - - try { - LOGGER.info("List with error"); - page = 1; - response = - client - .numbers() - .available() - .list( - AvailableNumberListAllRequestParameters.builder() - .setRegionCode("SE") - // this will throw an error but from server side as an invalid parameter: we - // can pass new values (or private) - .setType(NumberType.from("foo")) - .setNumberPattern( - NumberPattern.builder() - .setPattern("93652") - .setSearchPattern(SearchPattern.CONTAINS) - .build()) - .setCapabilities(Collections.singletonList(Capability.SMS)) - .setSize(3) - .build()); - LOGGER.info(String.format("Response (page %d): %s", page, response)); - - while (response.hasNextPage()) { - response = response.nextPage(); - page++; - LOGGER.info(String.format("Response (page %d): %s", page, response)); - } - - } catch (ApiException e) { - LOGGER.severe("Error: " + e); - } } } diff --git a/sample-app/src/main/java/com/sinch/sample/sms/batches/Send.java b/sample-app/src/main/java/com/sinch/sample/sms/batches/Send.java index afa44d61..03286734 100644 --- a/sample-app/src/main/java/com/sinch/sample/sms/batches/Send.java +++ b/sample-app/src/main/java/com/sinch/sample/sms/batches/Send.java @@ -23,14 +23,14 @@ public static void main(String[] args) { public void run() { - LOGGER.info("Send Text"); + LOGGER.info("Send Text to " + phoneNumber); BatchText value = client .sms() .batches() .send( SendSmsBatchTextRequest.builder() - .setTo(Collections.singletonList("+foo ")) + .setTo(Collections.singletonList(phoneNumber)) .setBody("the body") .setClientReference("a client reference") .setFrom("+33123456789")