├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
└── main
├── java
└── com
│ └── twilio
│ └── starter
│ ├── Application.java
│ └── controller
│ ├── CallController.java
│ ├── MessageController.java
│ └── TwimlController.java
└── resources
└── public
├── css
└── app.css
├── img
├── TwilioQuest32.png
├── favicon.png
├── heart.gif
└── java_shield256.png
├── index.html
└── js
├── form.js
└── ui.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.class
3 |
4 | # Package Files #
5 | #*.jar
6 | *.war
7 | *.ear
8 |
9 | # Play Framework
10 | logs
11 | project/project
12 | project/target
13 | target
14 | tmp
15 | dist
16 | .cache
17 | conf/application.conf
18 | /.target
19 | .settings
20 | .idea
21 | *.iml
22 | .env
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Kevin Whinnery
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to the Java Guild!
2 |
3 | As members of the Java Guild, you will be working through the challenges of TwilioQuest using the Java programming language and the [Spark Framework](http://sparkjava.com/). This project is pre-configured to have some interesting functionality built in using the Twilio Java helper library.
4 |
5 | ## Setting Up
6 |
7 | As a first step, you should [download this project](https://github.com/twilio/starter-java), or clone it if you are a Git user. Navigate to the directory for this project, and open it with your favorite text editor.
8 |
9 | Before you can run this project, you will need to set three system environment variables. These are:
10 |
11 | * `TWILIO_ACCOUNT_SID` : Your Twilio "account SID" - it's like your username for the Twilio API. This and the auth token (below) can be found [on the console](https://www.twilio.com/console).
12 | * `TWILIO_AUTH_TOKEN` : Your Twilio "auth token" - it's your password for the Twilio API. This and the account SID (above) can be found [on the console](https://www.twilio.com/console).
13 | * `TWILIO_PHONE_NUMBER` : A Twilio number that you own, that can be used for making calls and sending messages. You can find a list of phone numbers you control (and buy another one, if necessary) [in the account portal](https://www.twilio.com/console/phone-numbers/incoming).
14 |
15 | For Mac and Linux, environment variables can be set by opening a terminal window and typing the following three commands - replace all the characters after the `=` with values from your Twilio account:
16 |
17 | export TWILIO_ACCOUNT_SID=ACXXXXXXXXX
18 | export TWILIO_AUTH_TOKEN=XXXXXXXXX
19 | export TWILIO_PHONE_NUMBER=+16518675309
20 |
21 | To make these changes persist for every new terminal (on OS X), you can edit the file `~/.bash_profile` to contain the three commands above. This will set these environment variables for every subsequent session. Once you have edited the file to contain these commands, run `source ~/.bash_profile` in the terminal to set up these variables.
22 |
23 | On Windows, the easiest way to set permanent environment variables (as of Windows 8) is using the `setx` command. Note that there is no `=`, just the key and value separated by a space:
24 |
25 | setx TWILIO_ACCOUNT_SID ACXXXXXXXXX
26 | setx TWILIO_AUTH_TOKEN XXXXXXXXX
27 | setx TWILIO_PHONE_NUMBER +16518675309
28 |
29 | ## Running the Application
30 | Now that our project is ready, we need to build it using [maven](https://maven.apache.org/):
31 |
32 | ```
33 | mvn clean install
34 | ```
35 |
36 | Start the application:
37 | ```
38 | java -jar target/starter-java-with-dependencies.jar
39 | ```
40 |
41 | Now you can visit [http://localhost:4567/](http://localhost:4567)
42 |
43 | Try out the text message and voice call demos by entering your mobile phone number and clicking the button. If you receive a text message and a call, everything is working!
44 |
45 | ## Begin Questing!
46 | This is but your first step into a larger world. [Return to TwilioQuest](http://quest.twilio.com) to continue your adventure. Huzzah!
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.twilio
8 | starter-java
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 |
14 | 1.8
15 | 1.8
16 |
17 |
18 |
19 |
20 |
21 | com.sparkjava
22 | spark-core
23 | 2.7.2
24 |
25 |
26 | org.slf4j
27 | slf4j-api
28 | 1.7.26
29 |
30 |
31 | org.slf4j
32 | slf4j-simple
33 | 1.7.26
34 |
35 |
36 | com.twilio.sdk
37 | twilio
38 | 7.40.1
39 |
40 |
41 |
42 |
43 | ${project.name}
44 |
45 |
46 | maven-assembly-plugin
47 |
48 |
49 | package
50 |
51 | single
52 |
53 |
54 |
55 |
56 | ${project.name}-with-dependencies
57 |
58 | false
59 |
60 |
61 | jar-with-dependencies
62 |
63 |
64 |
65 | com.twilio.starter.Application
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/src/main/java/com/twilio/starter/Application.java:
--------------------------------------------------------------------------------
1 | package com.twilio.starter;
2 |
3 | import com.twilio.Twilio;
4 | import com.twilio.starter.controller.CallController;
5 | import com.twilio.starter.controller.MessageController;
6 | import com.twilio.starter.controller.TwimlController;
7 |
8 | import static spark.Spark.*;
9 |
10 | public class Application {
11 |
12 | private static final String ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID");
13 | private static final String AUTH_TOKEN = System.getenv("TWILIO_AUTH_TOKEN");
14 |
15 | public static void main(String[] args) {
16 | Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
17 |
18 | staticFileLocation("/public");
19 |
20 | post("/call", CallController.handlePost);
21 | post("/message", MessageController.handlePost);
22 | post("/hello", TwimlController.handlePost);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/twilio/starter/controller/CallController.java:
--------------------------------------------------------------------------------
1 | package com.twilio.starter.controller;
2 |
3 | import com.twilio.rest.api.v2010.account.Call;
4 | import spark.Request;
5 | import spark.Response;
6 | import spark.Route;
7 |
8 | import java.net.URI;
9 |
10 | public class CallController {
11 |
12 | private static final String TWILIO_PHONE_NUMBER = System.getenv("TWILIO_PHONE_NUMBER");
13 |
14 | public static Route handlePost = (Request request, Response response) -> {
15 | // Get POST data
16 | String to = request.queryParams("to");
17 |
18 | Call call = Call.creator(
19 | new com.twilio.type.PhoneNumber(to),
20 | new com.twilio.type.PhoneNumber(TWILIO_PHONE_NUMBER),
21 | URI.create("http://demo.twilio.com/docs/voice.xml"))
22 | .create();
23 |
24 | return "Call is inbound!";
25 | };
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/twilio/starter/controller/MessageController.java:
--------------------------------------------------------------------------------
1 | package com.twilio.starter.controller;
2 |
3 | import com.twilio.rest.api.v2010.account.Message;
4 | import spark.Request;
5 | import spark.Response;
6 | import spark.Route;
7 |
8 |
9 | public class MessageController {
10 |
11 | private static final String TWILIO_PHONE_NUMBER = System.getenv("TWILIO_PHONE_NUMBER");
12 |
13 | public static Route handlePost = (Request request, Response response) -> {
14 | // Get POST data
15 | String to = request.queryParams("to");
16 |
17 | Message call = Message.creator(
18 | new com.twilio.type.PhoneNumber(to),
19 | new com.twilio.type.PhoneNumber(TWILIO_PHONE_NUMBER),
20 | "Good luck on your Twilio quest!")
21 | .create();
22 |
23 | return "Message incoming!";
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/twilio/starter/controller/TwimlController.java:
--------------------------------------------------------------------------------
1 | package com.twilio.starter.controller;
2 |
3 | import com.twilio.twiml.VoiceResponse;
4 | import com.twilio.twiml.voice.Say;
5 | import spark.Request;
6 | import spark.Response;
7 | import spark.Route;
8 |
9 | public class TwimlController {
10 |
11 | // Render a TwiML document to give instructions for an outbound call
12 | public static Route handlePost = (Request request, Response response) -> {
13 | Say one = new Say.Builder("Hello there! You have successfully configured a web hook.").build();
14 | Say two = new Say.Builder("Good luck on your Twilio quest!").build();
15 |
16 | VoiceResponse voiceResponse = new VoiceResponse.Builder().say(one).say(two).build();
17 |
18 | response.type("text/xml");
19 | return voiceResponse.toXml();
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/resources/public/css/app.css:
--------------------------------------------------------------------------------
1 | /* Eric Meyer reset */
2 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}table{border-collapse:collapse;border-spacing:0}
3 |
4 | /* Global Styles */
5 | html, body {
6 | background-color:black;
7 | }
8 |
9 | html, body, * {
10 | font-family:"Press Start 2P";
11 | font-size:18px;
12 | color:white;
13 | }
14 |
15 | form {
16 | text-align:center;
17 | }
18 |
19 | h1 {
20 | font-size: 28px;
21 | margin:10px 0;
22 | line-height: 1.3em;
23 | }
24 |
25 | h3 {
26 | font-size:18px;
27 | margin:10px 0;
28 | color:red;
29 | }
30 |
31 | pre {
32 | font-family: Monaco, monospace, sans-serif;
33 | font-size:12px;
34 | padding:10px;
35 | background-color:#232323;
36 | border:1px #fff solid;
37 | margin-bottom: 10px;
38 | }
39 |
40 | p {
41 | line-height: 1.5em;
42 | font-size:14px;
43 | margin-bottom: 10px;
44 | }
45 |
46 | a {
47 | color:orange;
48 | }
49 |
50 | b {
51 | color:yellow;
52 | font-weight:bold;
53 | }
54 |
55 | input[type=text], input[type=password], input[type=email] {
56 | background-color:black;
57 | border:5px #787878 dashed;
58 | padding:10px;
59 | }
60 |
61 | input[type=text]:focus, input[type=password]:focus, input[type=email]:focus {
62 | outline:none;
63 | }
64 |
65 | button, input[type=button], input[type=submit] {
66 | margin-top: 10px;
67 | text-align: center;
68 | border:8px solid;
69 | background-color: #000;
70 | padding:10px;
71 | color:#fff;
72 | }
73 |
74 | button:hover, input[type=button]:hover, input[type=submit]:hover {
75 | border-style:dashed;
76 | cursor:pointer;
77 | }
78 |
79 | .padding10 {
80 | padding:10px;
81 | }
82 |
83 | #content {
84 | width:900px;
85 | margin:20px auto 10px auto;
86 | }
87 |
88 | #flash {
89 | color:yellow;
90 | text-align:center;
91 | border:2px dashed;
92 | margin-bottom:20px;
93 | padding:10px;
94 | }
95 |
96 | #flash p, #flash a {
97 | color:yellow;
98 | margin:0;
99 | }
100 |
101 | #tabs {
102 | list-style:none;
103 | margin-bottom:40px;
104 | text-align: center;
105 | }
106 |
107 | #tabs li {
108 | display:inline;
109 | cursor:pointer;
110 | padding:10px;
111 | margin-right:20px;
112 | color:gray;
113 | }
114 |
115 | #tabs li.current {
116 | background-color: red;
117 | color:white;
118 | }
119 |
120 | #call-demo {
121 | display:none;
122 | }
123 |
124 | #welcome {
125 | float:left;
126 | width:300px;
127 | text-align:center;
128 | margin:0 20px 20px 0;
129 | }
130 |
131 | #welcome h1 span {
132 | color:red;
133 | }
134 |
135 | #footer {
136 | clear:both;
137 | width:900px;
138 | font-size:16px;
139 | text-align: center;
140 | margin:0 auto 10px auto;
141 | padding:50px 10px 10px 10px;
142 | }
143 |
144 | #footer span {
145 | color:red;
146 | }
147 |
148 | #footer p {
149 | font-size:12px;
150 | margin-top:10px;
151 | }
152 |
153 | #footer img {
154 | margin-bottom:-10px;
155 | }
156 |
--------------------------------------------------------------------------------
/src/main/resources/public/img/TwilioQuest32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/starter-java/28ff1255e45a1959fc90b0aed16695e3d0936688/src/main/resources/public/img/TwilioQuest32.png
--------------------------------------------------------------------------------
/src/main/resources/public/img/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/starter-java/28ff1255e45a1959fc90b0aed16695e3d0936688/src/main/resources/public/img/favicon.png
--------------------------------------------------------------------------------
/src/main/resources/public/img/heart.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/starter-java/28ff1255e45a1959fc90b0aed16695e3d0936688/src/main/resources/public/img/heart.gif
--------------------------------------------------------------------------------
/src/main/resources/public/img/java_shield256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twilio/starter-java/28ff1255e45a1959fc90b0aed16695e3d0936688/src/main/resources/public/img/java_shield256.png
--------------------------------------------------------------------------------
/src/main/resources/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Welcome to the Java Guild!
7 |
8 |
9 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
28 |
29 |
30 |
Java Guild
31 |
32 | Welcome to the Java Guild! Using the modern
33 | Spark framework,
34 | you will teach an old JVM dog new tricks on your own Twilio
35 | quest.
36 |
37 |
38 | Gather your party and
39 | venture forth
40 |
41 |
42 |
43 |
Hello World
44 |
45 | Below, we have two simple demos that will confirm your environment
46 | has been properly configured. Please refer to the
47 | README.md in your
48 | starter app repository to see how to configure this application.
49 |
50 |
51 |
52 | Messaging
53 | Voice Call
54 |
55 |
61 |
62 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/src/main/resources/public/js/form.js:
--------------------------------------------------------------------------------
1 | // Show an information box at the top of the page
2 | function showFlash(message) {
3 | $('#flash span').html(message);
4 | $('#flash').show();
5 | }
6 |
7 | // Intercept our form button click
8 | $('form button').on('click', function(e) {
9 | e.preventDefault();
10 |
11 | // Based on the selected demo, fire off an ajax request
12 | // We expect just a string of text back from the server (keeping it simple)
13 | var url = currentDemo == 'message' ? '/message' : '/call';
14 | $.ajax(url, {
15 | method:'POST',
16 | dataType:'text',
17 | data:{
18 | to:$('#to').val()
19 | },
20 | success: function(data) {
21 | showFlash(data);
22 | },
23 | error: function(jqxhr) {
24 | alert('There was an error sending a request to the server :(');
25 | }
26 | })
27 | });
--------------------------------------------------------------------------------
/src/main/resources/public/js/ui.js:
--------------------------------------------------------------------------------
1 | // Track the currently selected demo
2 | var currentDemo = 'message';
3 |
4 | // Change the currently selected demo
5 | function changeTab(newTab) {
6 | if (newTab === 'message') {
7 | currentDemo = 'message';
8 | $('#messaging').addClass('current');
9 | $('#call').removeClass('current');
10 | $('form button').html('Send me a message');
11 | } else {
12 | currentDemo = 'call';
13 | $('#call').addClass('current');
14 | $('#messaging').removeClass('current');
15 | $('form button').html('Call my phone');
16 | }
17 | }
18 |
19 | // Set up handlers for tabs
20 | $('#messaging').on('click', function(e) {
21 | e.preventDefault();
22 | changeTab('message');
23 | });
24 | $('#call').on('click', function(e) {
25 | e.preventDefault();
26 | changeTab('call');
27 | });
28 |
29 | // Set up handler for "flash" message
30 | $('#flash a').on('click', function(e) {
31 | e.preventDefault();
32 | $('#flash').hide();
33 | });
--------------------------------------------------------------------------------