├── .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 | Java Shield 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 | 55 |
56 |

Enter your mobile phone number:

57 | 59 | 60 |
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 | }); --------------------------------------------------------------------------------