Masked Phone Numbers with Java and Servlets

Download the Code

This Java Servlets sample application is modeled after the amazing rental experience created by AirBnB, but with more Klingons.

Host users can offer rental properties which other guest users can reserve. The guest and the host can then anonymously communicate via a disposable Twilio phone number created just for a reservation. In this tutorial, we'll show you the key bits of code to make this work.

To run this sample app yourself, download the code and follow the instructions on GitHub.

Read how Lyft uses masked phone numbers to let customers securely contact drivers.

Create a Reservation

The first step in connecting a guest and host is creating a reservation. Here, we handle a form submission for a new reservation which contains the message. The guest's information is pulled out from the logged user.

Loading Code Samples...
Language
package org.twilio.airtng.servlets;

import org.twilio.airtng.lib.notifications.SmsNotifier;
import org.twilio.airtng.lib.servlets.WebAppServlet;
import org.twilio.airtng.lib.web.request.validators.RequestParametersValidator;
import org.twilio.airtng.models.Reservation;
import org.twilio.airtng.models.User;
import org.twilio.airtng.models.VacationProperty;
import org.twilio.airtng.repositories.ReservationRepository;
import org.twilio.airtng.repositories.UserRepository;
import org.twilio.airtng.repositories.VacationPropertiesRepository;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ReservationServlet extends WebAppServlet {

    private final VacationPropertiesRepository vacationPropertiesRepository;
    private final ReservationRepository reservationRepository;
    private UserRepository userRepository;
    private SmsNotifier smsNotifier;

    public ReservationServlet() {
        this(new VacationPropertiesRepository(), new ReservationRepository(), new UserRepository(), new SmsNotifier());
    }

    public ReservationServlet(VacationPropertiesRepository vacationPropertiesRepository, ReservationRepository reservationRepository, UserRepository userRepository, SmsNotifier smsNotifier) {
        super();
        this.vacationPropertiesRepository = vacationPropertiesRepository;
        this.reservationRepository = reservationRepository;
        this.userRepository = userRepository;
        this.smsNotifier = smsNotifier;
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        VacationProperty vacationProperty = vacationPropertiesRepository.find(Long.parseLong(request.getParameter("id")));
        request.setAttribute("vacationProperty", vacationProperty);
        request.getRequestDispatcher("/reservation.jsp").forward(request, response);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        super.doPost(request, response);

        String message = null;
        VacationProperty vacationProperty = null;

        if (isValidRequest()) {
            message = request.getParameter("message");
            String propertyId = request.getParameter("propertyId");
            vacationProperty = vacationPropertiesRepository.find(Long.parseLong(propertyId));

            User currentUser = userRepository.find(sessionManager.get().getLoggedUserId(request));
            Reservation reservation = reservationRepository.create(new Reservation(message, vacationProperty, currentUser));
            smsNotifier.notifyHost(reservation);
            response.sendRedirect("/properties");
        }
        preserveStatusRequest(request, message, vacationProperty);
        request.getRequestDispatcher("/reservation.jsp").forward(request, response);
    }

    @Override
    protected boolean isValidRequest(RequestParametersValidator validator) {

        return validator.validatePresence("message");
    }

    private void preserveStatusRequest(
            HttpServletRequest request,
            String message, Object vacationProperty) {
        request.setAttribute("message", message);
        request.setAttribute("vacationProperty", vacationProperty);
    }
}
src/main/java/org/twilio/airtng/servlets/ReservationServlet.java
Create a Reservation

src/main/java/org/twilio/airtng/servlets/ReservationServlet.java

Part of our reservation system is receiving reservation requests from potential renters. However, these reservations need to be confirmed. Let's see how we would handle this step.

Confirm the Reservation

Before the reservation is finalized, the host needs to confirm that the property was reserved. Learn how to automate this process in our first AirTNG tutorial, Workflow Automation.

Loading Code Samples...
Language
package org.twilio.airtng.servlets;

import com.twilio.twiml.MessagingResponse;
import com.twilio.twiml.TwiMLException;
import org.twilio.airtng.lib.helpers.TwiMLHelper;
import org.twilio.airtng.lib.notifications.SmsNotifier;
import org.twilio.airtng.lib.servlets.WebAppServlet;
import org.twilio.airtng.models.Reservation;
import org.twilio.airtng.models.User;
import org.twilio.airtng.repositories.ReservationRepository;
import org.twilio.airtng.repositories.UserRepository;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ReservationConfirmationServlet extends WebAppServlet {

    private UserRepository userRepository;
    private ReservationRepository reservationRepository;
    private SmsNotifier smsNotifier;

    public ReservationConfirmationServlet() {
        this(new UserRepository(), new ReservationRepository(), new SmsNotifier());
    }

    public ReservationConfirmationServlet(UserRepository userRepository, ReservationRepository reservationRepository, SmsNotifier smsNotifier) {
        super();
        this.userRepository = userRepository;
        this.reservationRepository = reservationRepository;
        this.smsNotifier = smsNotifier;
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

        String phone = request.getParameter("From");
        String smsContent = request.getParameter("Body");

        String smsResponseText = "Sorry, it looks like you don't have any reservations to respond to.";

        try {
            User user = userRepository.findByPhoneNumber(phone);
            Reservation reservation = reservationRepository.findFirstPendantReservationsByUser(user.getId());
            if (reservation != null) {
                if (smsContent.contains("yes") || smsContent.contains("accept"))
                    reservation.confirm();
                else
                    reservation.reject();
                reservationRepository.update(reservation);

                smsResponseText = String.format("You have successfully %s the reservation", reservation.getStatus().toString());
                smsNotifier.notifyGuest(reservation);
            }

        respondSms(response, smsResponseText);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void respondSms(HttpServletResponse response, String message)
            throws IOException, TwiMLException {
        MessagingResponse twiMLResponse = TwiMLHelper.buildSmsRespond(message);
        response.setContentType("text/xml");
        response.getWriter().write(twiMLResponse.toXml());
    }
}
src/main/java/org/twilio/airtng/servlets/ReservationConfirmationServlet.java
Confirm the Reservation

src/main/java/org/twilio/airtng/servlets/ReservationConfirmationServlet.java

Once the reservation is confirmed, we need to purchase a Twilio number that the guest and host can use to communicate.

Purchase a Twilio Number

Here we use a Twilio Java helper library to search for and buy a new phone number to associate with the reservation. When we buy the number, we designate a Twilio Application that will handle webhook requests when the new number receives an incoming call or text.

We then save the new phone number on our Reservation model, so when our app receives calls or texts to this number, we'll know which reservation the call or text belongs to.

Loading Code Samples...
Language
package org.twilio.airtng.lib.phonenumber;

import com.twilio.base.ResourceSet;
import com.twilio.http.TwilioRestClient;
import com.twilio.rest.api.v2010.account.IncomingPhoneNumberCreator;
import com.twilio.rest.api.v2010.account.availablephonenumbercountry.Local;
import com.twilio.type.PhoneNumber;
import org.twilio.airtng.lib.Config;

public class Purchaser {

    private final TwilioRestClient client;

    public Purchaser() {
        client = new TwilioRestClient.Builder(Config.getAccountSid(), Config.getAuthToken()).build();
    }

    public Purchaser(TwilioRestClient client) {
        this.client = client;
    }

    public String buyNumber(Integer areaCode) {
        ResourceSet<Local> availableNumbersForGivenArea = Local.reader("US")
                .setAreaCode(areaCode)
                .setSmsEnabled(true)
                .setVoiceEnabled(true)
                .read();

        if (availableNumbersForGivenArea.iterator().hasNext()) {
            PhoneNumber availableNumber = createBuyNumber(
                    availableNumbersForGivenArea.iterator().next().getPhoneNumber()
            );

            return availableNumber.toString();
        } else {
            ResourceSet<Local> generalAvailableNumbers = Local.reader("US")
                    .setSmsEnabled(true)
                    .setVoiceEnabled(true)
                    .read();
            if (generalAvailableNumbers.iterator().hasNext()) {
                PhoneNumber availableNumber = createBuyNumber(
                        generalAvailableNumbers.iterator().next().getPhoneNumber()
                );
                return availableNumber.toString();
            } else {
                return null;
            }
        }
    }

    private PhoneNumber createBuyNumber(PhoneNumber phoneNumber) {
        return new IncomingPhoneNumberCreator(phoneNumber)
                .setSmsApplicationSid(Config.getApplicationSid())
                .setVoiceApplicationSid(Config.getApplicationSid())
                .create(client).getPhoneNumber();
    }
}
src/main/java/org/twilio/airtng/lib/phonenumber/Purchaser.java
Purchase a Twilio Number

src/main/java/org/twilio/airtng/lib/phonenumber/Purchaser.java

Now that each reservation has a Twilio Phone Number, we can see how the application will look up reservations as guest or host calls come in.

Find a Reservation

When someone sends an SMS or calls one of the Twilio numbers you have configured, Twilio makes a request to the URL you set in the Twiml app. In this request, Twilio includes some useful information including:

  • The incomingPhoneNumber number that originally called or sent an SMS.
  • The anonymousPhoneNumber Twilio number that triggered this request.

Take a look at Twilio's SMS Documentation and Twilio's Voice Documentation for a full list of the parameters you can use.

In our servlet we use the to parameter sent by Twilio to find a reservation that has the number we bought stored in it, as this is the number both hosts and guests will call and send SMS to.

Loading Code Samples...
Language
package org.twilio.airtng.servlets;

import com.twilio.twiml.TwiML;
import com.twilio.twiml.TwiMLException;
import org.twilio.airtng.lib.servlets.WebAppServlet;
import org.twilio.airtng.models.Reservation;
import org.twilio.airtng.repositories.ReservationRepository;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

public class BaseExchangeServlet extends WebAppServlet {
    protected ReservationRepository reservationRepository;

    public BaseExchangeServlet(ReservationRepository reservationRepository) {
        this.reservationRepository = reservationRepository;
    }

    protected String gatherOutgoingPhoneNumber(String incomingPhoneNumber, String anonymousPhoneNumber) {
        String outgoingPhoneNumber = null;

        Reservation reservation = reservationRepository.findByAnonymousPhoneNumber(anonymousPhoneNumber);

        if (Objects.equals(reservation.getUser().getPhoneNumber(), incomingPhoneNumber)) {
            outgoingPhoneNumber = reservation.getVacationProperty().getUser().getPhoneNumber();
        } else {
            outgoingPhoneNumber = reservation.getUser().getPhoneNumber();
        }

        return outgoingPhoneNumber;
    }

    protected void respondTwiML(HttpServletResponse response, TwiML twiMLResponse)
            throws IOException {
        response.setContentType("text/xml");
        try {
            response.getWriter().write(twiMLResponse.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
src/main/java/org/twilio/airtng/servlets/BaseExchangeServlet.java
Find a Reservation

src/main/java/org/twilio/airtng/servlets/BaseExchangeServlet.java

Next, let's see how to connect the guest and the host via SMS.

Connect Via SMS

Our Twilio application should be configured to send HTTP requests to this controller method on any incoming text message. Our app responds with TwiML to tell Twilio what to do in response to the message.

If the initial message sent to the anonymous number was sent by the host, we forward it on to the guest. Conversely, if the original message was sent by the guest, we forward it to the host.

To find the outgoing number we'll use the gatherOutgoingPhoneNumberAsync helper method.

Loading Code Samples...
Language
package org.twilio.airtng.servlets;

import com.twilio.twiml.Body;
import com.twilio.twiml.Message;
import com.twilio.twiml.MessagingResponse;
import org.twilio.airtng.repositories.ReservationRepository;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ExchangeSmsServlet extends BaseExchangeServlet {

    @SuppressWarnings("unused")
    public ExchangeSmsServlet() {
        this(new ReservationRepository());
    }

    public ExchangeSmsServlet(ReservationRepository reservationRepository) {
        super(reservationRepository);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String from = request.getParameter("From");
        String to = request.getParameter("To");
        String body = request.getParameter("Body");

        String outgoingNumber = gatherOutgoingPhoneNumber(from, to);

        MessagingResponse messagingResponse = new MessagingResponse.Builder()
                .message(new Message.Builder().body(new Body(body)).to(outgoingNumber).build())
                .build();

        respondTwiML(response, messagingResponse);
    }
}
src/main/java/org/twilio/airtng/servlets/ExchangeSmsServlet.java
Connect Via SMS

src/main/java/org/twilio/airtng/servlets/ExchangeSmsServlet.java

Let's see how to connect the guest and the host via phone call next.

Connect Via Phone Call

Our Twilio application will send HTTP requests to this method on any incoming voice call. Our app responds with TwiML instructions that tell Twilio to Play an introductory MP3 audio file and then Dial either the guest or host, depending on who initiated the call.

Loading Code Samples...
Language
package org.twilio.airtng.servlets;

import com.twilio.twiml.Dial;
import com.twilio.twiml.Number;
import com.twilio.twiml.Play;
import com.twilio.twiml.VoiceResponse;
import org.twilio.airtng.repositories.ReservationRepository;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ExchangeVoiceServlet extends BaseExchangeServlet {

    @SuppressWarnings("unused")
    public ExchangeVoiceServlet() {
        this(new ReservationRepository());
    }

    public ExchangeVoiceServlet(ReservationRepository reservationRepository) {
        super(reservationRepository);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String from = request.getParameter("From");
        String to = request.getParameter("To");

        String outgoingNumber = gatherOutgoingPhoneNumber(from, to);

        VoiceResponse voiceResponse = new VoiceResponse.Builder()
                .play(new Play.Builder("http://howtodocs.s3.amazonaws.com/howdy-tng.mp3").build())
                .dial(new Dial.Builder().number(new Number.Builder(outgoingNumber).build()).build())
                .build();

        respondTwiML(response, voiceResponse);
    }

}
src/main/java/org/twilio/airtng/servlets/ExchangeVoiceServlet.java
Connect Via Phone Call

src/main/java/org/twilio/airtng/servlets/ExchangeVoiceServlet.java

That's it! We've just implemented anonymous communications that allow your customers to connect while protecting their privacy.

Where to Next?

If you're a Java developer working with Twilio, you might want to check out these other tutorials:

IVR: Phone Tree

Create a seamless customer service experience by building an IVR Phone Tree for your company.

Click To Call

Allow your company to convert web traffic into phone calls with the click of a button.

Did this help?

Thanks for checking out this tutorial! If you have any feedback to share with us, we'd love to hear it. Tweet @twilio to let us know what you think.

Agustin Camino
David Prothero
Andrew Baker
Jose Oliveros

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
package org.twilio.airtng.servlets;

import org.twilio.airtng.lib.notifications.SmsNotifier;
import org.twilio.airtng.lib.servlets.WebAppServlet;
import org.twilio.airtng.lib.web.request.validators.RequestParametersValidator;
import org.twilio.airtng.models.Reservation;
import org.twilio.airtng.models.User;
import org.twilio.airtng.models.VacationProperty;
import org.twilio.airtng.repositories.ReservationRepository;
import org.twilio.airtng.repositories.UserRepository;
import org.twilio.airtng.repositories.VacationPropertiesRepository;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ReservationServlet extends WebAppServlet {

    private final VacationPropertiesRepository vacationPropertiesRepository;
    private final ReservationRepository reservationRepository;
    private UserRepository userRepository;
    private SmsNotifier smsNotifier;

    public ReservationServlet() {
        this(new VacationPropertiesRepository(), new ReservationRepository(), new UserRepository(), new SmsNotifier());
    }

    public ReservationServlet(VacationPropertiesRepository vacationPropertiesRepository, ReservationRepository reservationRepository, UserRepository userRepository, SmsNotifier smsNotifier) {
        super();
        this.vacationPropertiesRepository = vacationPropertiesRepository;
        this.reservationRepository = reservationRepository;
        this.userRepository = userRepository;
        this.smsNotifier = smsNotifier;
    }

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        VacationProperty vacationProperty = vacationPropertiesRepository.find(Long.parseLong(request.getParameter("id")));
        request.setAttribute("vacationProperty", vacationProperty);
        request.getRequestDispatcher("/reservation.jsp").forward(request, response);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        super.doPost(request, response);

        String message = null;
        VacationProperty vacationProperty = null;

        if (isValidRequest()) {
            message = request.getParameter("message");
            String propertyId = request.getParameter("propertyId");
            vacationProperty = vacationPropertiesRepository.find(Long.parseLong(propertyId));

            User currentUser = userRepository.find(sessionManager.get().getLoggedUserId(request));
            Reservation reservation = reservationRepository.create(new Reservation(message, vacationProperty, currentUser));
            smsNotifier.notifyHost(reservation);
            response.sendRedirect("/properties");
        }
        preserveStatusRequest(request, message, vacationProperty);
        request.getRequestDispatcher("/reservation.jsp").forward(request, response);
    }

    @Override
    protected boolean isValidRequest(RequestParametersValidator validator) {

        return validator.validatePresence("message");
    }

    private void preserveStatusRequest(
            HttpServletRequest request,
            String message, Object vacationProperty) {
        request.setAttribute("message", message);
        request.setAttribute("vacationProperty", vacationProperty);
    }
}
package org.twilio.airtng.servlets;

import com.twilio.twiml.MessagingResponse;
import com.twilio.twiml.TwiMLException;
import org.twilio.airtng.lib.helpers.TwiMLHelper;
import org.twilio.airtng.lib.notifications.SmsNotifier;
import org.twilio.airtng.lib.servlets.WebAppServlet;
import org.twilio.airtng.models.Reservation;
import org.twilio.airtng.models.User;
import org.twilio.airtng.repositories.ReservationRepository;
import org.twilio.airtng.repositories.UserRepository;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ReservationConfirmationServlet extends WebAppServlet {

    private UserRepository userRepository;
    private ReservationRepository reservationRepository;
    private SmsNotifier smsNotifier;

    public ReservationConfirmationServlet() {
        this(new UserRepository(), new ReservationRepository(), new SmsNotifier());
    }

    public ReservationConfirmationServlet(UserRepository userRepository, ReservationRepository reservationRepository, SmsNotifier smsNotifier) {
        super();
        this.userRepository = userRepository;
        this.reservationRepository = reservationRepository;
        this.smsNotifier = smsNotifier;
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

        String phone = request.getParameter("From");
        String smsContent = request.getParameter("Body");

        String smsResponseText = "Sorry, it looks like you don't have any reservations to respond to.";

        try {
            User user = userRepository.findByPhoneNumber(phone);
            Reservation reservation = reservationRepository.findFirstPendantReservationsByUser(user.getId());
            if (reservation != null) {
                if (smsContent.contains("yes") || smsContent.contains("accept"))
                    reservation.confirm();
                else
                    reservation.reject();
                reservationRepository.update(reservation);

                smsResponseText = String.format("You have successfully %s the reservation", reservation.getStatus().toString());
                smsNotifier.notifyGuest(reservation);
            }

        respondSms(response, smsResponseText);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void respondSms(HttpServletResponse response, String message)
            throws IOException, TwiMLException {
        MessagingResponse twiMLResponse = TwiMLHelper.buildSmsRespond(message);
        response.setContentType("text/xml");
        response.getWriter().write(twiMLResponse.toXml());
    }
}
package org.twilio.airtng.lib.phonenumber;

import com.twilio.base.ResourceSet;
import com.twilio.http.TwilioRestClient;
import com.twilio.rest.api.v2010.account.IncomingPhoneNumberCreator;
import com.twilio.rest.api.v2010.account.availablephonenumbercountry.Local;
import com.twilio.type.PhoneNumber;
import org.twilio.airtng.lib.Config;

public class Purchaser {

    private final TwilioRestClient client;

    public Purchaser() {
        client = new TwilioRestClient.Builder(Config.getAccountSid(), Config.getAuthToken()).build();
    }

    public Purchaser(TwilioRestClient client) {
        this.client = client;
    }

    public String buyNumber(Integer areaCode) {
        ResourceSet<Local> availableNumbersForGivenArea = Local.reader("US")
                .setAreaCode(areaCode)
                .setSmsEnabled(true)
                .setVoiceEnabled(true)
                .read();

        if (availableNumbersForGivenArea.iterator().hasNext()) {
            PhoneNumber availableNumber = createBuyNumber(
                    availableNumbersForGivenArea.iterator().next().getPhoneNumber()
            );

            return availableNumber.toString();
        } else {
            ResourceSet<Local> generalAvailableNumbers = Local.reader("US")
                    .setSmsEnabled(true)
                    .setVoiceEnabled(true)
                    .read();
            if (generalAvailableNumbers.iterator().hasNext()) {
                PhoneNumber availableNumber = createBuyNumber(
                        generalAvailableNumbers.iterator().next().getPhoneNumber()
                );
                return availableNumber.toString();
            } else {
                return null;
            }
        }
    }

    private PhoneNumber createBuyNumber(PhoneNumber phoneNumber) {
        return new IncomingPhoneNumberCreator(phoneNumber)
                .setSmsApplicationSid(Config.getApplicationSid())
                .setVoiceApplicationSid(Config.getApplicationSid())
                .create(client).getPhoneNumber();
    }
}
package org.twilio.airtng.servlets;

import com.twilio.twiml.TwiML;
import com.twilio.twiml.TwiMLException;
import org.twilio.airtng.lib.servlets.WebAppServlet;
import org.twilio.airtng.models.Reservation;
import org.twilio.airtng.repositories.ReservationRepository;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

public class BaseExchangeServlet extends WebAppServlet {
    protected ReservationRepository reservationRepository;

    public BaseExchangeServlet(ReservationRepository reservationRepository) {
        this.reservationRepository = reservationRepository;
    }

    protected String gatherOutgoingPhoneNumber(String incomingPhoneNumber, String anonymousPhoneNumber) {
        String outgoingPhoneNumber = null;

        Reservation reservation = reservationRepository.findByAnonymousPhoneNumber(anonymousPhoneNumber);

        if (Objects.equals(reservation.getUser().getPhoneNumber(), incomingPhoneNumber)) {
            outgoingPhoneNumber = reservation.getVacationProperty().getUser().getPhoneNumber();
        } else {
            outgoingPhoneNumber = reservation.getUser().getPhoneNumber();
        }

        return outgoingPhoneNumber;
    }

    protected void respondTwiML(HttpServletResponse response, TwiML twiMLResponse)
            throws IOException {
        response.setContentType("text/xml");
        try {
            response.getWriter().write(twiMLResponse.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
package org.twilio.airtng.servlets;

import com.twilio.twiml.Body;
import com.twilio.twiml.Message;
import com.twilio.twiml.MessagingResponse;
import org.twilio.airtng.repositories.ReservationRepository;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ExchangeSmsServlet extends BaseExchangeServlet {

    @SuppressWarnings("unused")
    public ExchangeSmsServlet() {
        this(new ReservationRepository());
    }

    public ExchangeSmsServlet(ReservationRepository reservationRepository) {
        super(reservationRepository);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String from = request.getParameter("From");
        String to = request.getParameter("To");
        String body = request.getParameter("Body");

        String outgoingNumber = gatherOutgoingPhoneNumber(from, to);

        MessagingResponse messagingResponse = new MessagingResponse.Builder()
                .message(new Message.Builder().body(new Body(body)).to(outgoingNumber).build())
                .build();

        respondTwiML(response, messagingResponse);
    }
}
package org.twilio.airtng.servlets;

import com.twilio.twiml.Dial;
import com.twilio.twiml.Number;
import com.twilio.twiml.Play;
import com.twilio.twiml.VoiceResponse;
import org.twilio.airtng.repositories.ReservationRepository;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ExchangeVoiceServlet extends BaseExchangeServlet {

    @SuppressWarnings("unused")
    public ExchangeVoiceServlet() {
        this(new ReservationRepository());
    }

    public ExchangeVoiceServlet(ReservationRepository reservationRepository) {
        super(reservationRepository);
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String from = request.getParameter("From");
        String to = request.getParameter("To");

        String outgoingNumber = gatherOutgoingPhoneNumber(from, to);

        VoiceResponse voiceResponse = new VoiceResponse.Builder()
                .play(new Play.Builder("http://howtodocs.s3.amazonaws.com/howdy-tng.mp3").build())
                .dial(new Dial.Builder().number(new Number.Builder(outgoingNumber).build()).build())
                .build();

        respondTwiML(response, voiceResponse);
    }

}