Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Global rule:
* @Bandwidth-Samples/dx
* @Bandwidth-Samples/band-swi @Bandwidth-Samples/band-devx
11 changes: 0 additions & 11 deletions .github/actions/maven-test/Dockerfile

This file was deleted.

6 changes: 0 additions & 6 deletions .github/actions/maven-test/action.yml

This file was deleted.

3 changes: 0 additions & 3 deletions .github/actions/maven-test/entrypoint.sh

This file was deleted.

19 changes: 19 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
version: 2

updates:
- package-ecosystem: maven
directory: /
schedule:
interval: monthly
open-pull-requests-limit: 5
ignore:
- dependency-name: "com.bandwidth.sdk:bandwidth-sdk"
update-types:
- version-update:semver-minor
- version-update:semver-patch
groups:
dependencies:
patterns:
- "*"
exclude-patterns:
- "com.bandwidth.sdk:bandwidth-sdk"
16 changes: 0 additions & 16 deletions .github/workflows/on-pull-request.yaml

This file was deleted.

15 changes: 15 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Test

on:
pull_request:
branches:
- main
schedule:
- cron: "0 9 * * 1"

jobs:
contract-test:
name: Contract Test
uses: Bandwidth-Samples/sample-app-tooling/.github/workflows/java.yml@main
with:
sample: voice-gather
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020 Bandwidth Samples
Copyright (c) 2026 Bandwidth Samples

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
30 changes: 24 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
- [Description](#description)
- [Bandwidth](#bandwidth)
- [Environmental Variables](#environmental-variables)
- [Running the Application](#running-the-application)
- [Callback URLs](#callback-urls)
- [Ngrok](#ngrok)

<!-- /TOC -->

# Description
A short description of your sample app and its capabilities.

This sample app creates an outbound call to the supplied phone number, which if answered will prompt the user using [Gather BXML](https://dev.bandwidth.com/docs/voice/bxml/gather) to select between a list of options to hear different messages played back.

# Bandwidth

Expand All @@ -29,20 +31,36 @@ For more information about API credentials see [here](https://dev.bandwidth.com/
The sample app uses the below environmental variables.
```sh
BW_ACCOUNT_ID # Your Bandwidth Account Id
BW_USERNAME # Your Bandwidth API Token
BW_PASSWORD # Your Bandwidth API Secret
BW_CLIENT_ID # Your Bandwidth API OAuth Client Id
BW_CLIENT_SECRET # Your Bandwidth API OAuth Client Secret
BW_NUMBER # The Bandwidth phone number involved with this application
BW_VOICE_APPLICATION_ID # Your Voice Application Id created in the dashboard
BASE_CALLBACK_URL # Your public base url
BASE_CALLBACK_URL # Your public base url to receive Bandwidth Webhooks. No trailing '/'
LOCAL_PORT # The port number you wish to run the sample on
```

# Running the Application

To install the required packages and build the app, run the command:

```sh
mvn package
```

Use the following command to run the application:

```sh
mvn spring-boot:run
```

# Callback URLs

For a detailed introduction to Bandwidth Callbacks see https://dev.bandwidth.com/guides/callbacks/callbacks.html

Below are the callback paths:
* `/calls`
* `/callbacks/outbound/voice`
* `<add other callbacks>`
* `/callbacks/outbound/voice/gather`

## Ngrok

Expand All @@ -51,4 +69,4 @@ After you have downloaded and installed `ngrok` run the following command to ope
```cmd
ngrok http $LOCAL_PORT
```
You can view your public URL at `http://127.0.0.1:{LOCAL_PORT}` after ngrok is running. You can also view the status of the tunnel and requests/responses here.
You can view your public URL at `http://127.0.0.1:4040` after ngrok is running. You can also view the status of the tunnel and requests/responses here.
20 changes: 16 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,36 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
<spring.version>2.5.12</spring.version>
<java.version>21</java.version>
<spring.version>3.5.16</spring.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>

<!-- https://mvnrepository.com/artifact/com.bandwidth.sdk/bandwidth-sdk -->
<dependency>
<groupId>com.bandwidth.sdk</groupId>
<artifactId>bandwidth-sdk</artifactId>
<version>9.1.2</version>
<version>18.3.1</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.14.0</version>
<version>2.15.1</version>
</dependency>

<dependency>
Expand Down
21 changes: 14 additions & 7 deletions src/main/java/com/bandwidth/Main.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
package com.bandwidth;

import java.util.Collections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController

public class Main {

static Logger logger = LoggerFactory.getLogger(Main.class);

public static void main(String[] args) {
SpringApplication.run(Main.class, args);
String port = System.getenv("LOCAL_PORT");
if (System.getenv("BW_ACCOUNT_ID") == null || System.getenv("BW_CLIENT_ID") == null
|| System.getenv("BW_CLIENT_SECRET") == null || System.getenv("BW_VOICE_APPLICATION_ID") == null
|| System.getenv("BW_NUMBER") == null || System.getenv("BASE_CALLBACK_URL") == null
|| port == null || !port.matches("\\d+")) {
System.err.println("Please set the environmental variables defined in the README");
System.exit(1);
}

SpringApplication application = new SpringApplication(Main.class);
application.setDefaultProperties(Collections.singletonMap("server.port", port));
application.run(args);
logger.info("Server has started...");
}






}
3 changes: 0 additions & 3 deletions src/main/java/com/bandwidth/Model/CallRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
public class CallRequest {

private String to;
private String from;
}
12 changes: 0 additions & 12 deletions src/main/java/com/bandwidth/Model/VoiceReply.java

This file was deleted.

63 changes: 21 additions & 42 deletions src/main/java/com/bandwidth/controller/CallController.java
Original file line number Diff line number Diff line change
@@ -1,76 +1,55 @@
package com.bandwidth.controller;

import com.bandwidth.Main;
import com.bandwidth.model.CallRequest;
import com.bandwidth.model.VoiceReply;

import com.bandwidth.sdk.ApiClient;
import com.bandwidth.sdk.ApiResponse;
import com.bandwidth.sdk.ApiException;
import com.bandwidth.sdk.auth.HttpBasicAuth;
import com.bandwidth.sdk.Configuration;
import com.bandwidth.sdk.model.*;
import com.bandwidth.sdk.api.CallsApi;
import com.bandwidth.sdk.model.CreateCall;
import com.bandwidth.sdk.model.CreateCallResponse;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;

import java.net.URI;
import java.net.URISyntaxException;
import java.io.IOException;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.server.ResponseStatusException;

import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("calls")
public class CallController {

Logger logger = LoggerFactory.getLogger(CallController.class);

private final String username = System.getenv("BW_USERNAME");
private final String password = System.getenv("BW_PASSWORD");
private final String accountId = System.getenv("BW_ACCOUNT_ID");
private final String clientId = System.getenv("BW_CLIENT_ID");
private final String clientSecret = System.getenv("BW_CLIENT_SECRET");
private final String applicationId = System.getenv("BW_VOICE_APPLICATION_ID");
private final String answerUrl = System.getenv("BASE_CALLBACK_URL");

public ApiClient defaultClient = Configuration.getDefaultApiClient();
public HttpBasicAuth Basic = (HttpBasicAuth) defaultClient.getAuthentication("Basic");
public final CallsApi api = new CallsApi(defaultClient);
private static CreateCall createCallBody = new CreateCall();
private final String number = System.getenv("BW_NUMBER");
private final String baseCallbackUrl = System.getenv("BASE_CALLBACK_URL");

private final CallsApi callsApi = new CallsApi(new ApiClient(clientId, clientSecret, null));

@PostMapping()
public VoiceReply createCall(@RequestBody CallRequest callRequest) throws ApiException, URISyntaxException {

Basic.setUsername(username);
Basic.setPassword(password);
createCallBody.setTo(callRequest.getTo());
createCallBody.setFrom(callRequest.getFrom());
createCallBody.setApplicationId(applicationId);
createCallBody.setAnswerUrl(new URI(answerUrl + "/callbacks/outbound/voice"));
public ResponseEntity<Void> createCall(@RequestBody CallRequest callRequest) {
if (callRequest.getTo() == null) {
return ResponseEntity.badRequest().build();
}

CreateCall createCall = new CreateCall()
.applicationId(applicationId)
.to(callRequest.getTo())
.from(number)
.answerUrl(URI.create(baseCallbackUrl + "/callbacks/outbound/voice"));

VoiceReply voiceReply = new VoiceReply();
try {
ApiResponse<CreateCallResponse> response = api.createCallWithHttpInfo(accountId, createCallBody);
voiceReply.setSuccess(true);
} catch (ApiException e) { // Bandwidth API response status not 2XX
voiceReply.setSuccess(false);
voiceReply.setError(e.getMessage());
callsApi.createCall(accountId, createCall);
} catch (Exception e) {
logger.error("Failed to create call: " + e.getMessage());
return ResponseEntity.internalServerError().build();
}

return voiceReply;
return ResponseEntity.ok().build();
}
}
Loading
Loading