Новости из Блогов Java-приложения для Facebook на базе Google App Engine

Discussion in 'Мировые новости. Обсуждения.' started by Suicide, 20 Sep 2012.

  1. Suicide

    Suicide Super Moderator
    Staff Member

    Joined:
    24 Apr 2009
    Messages:
    2,373
    Likes Received:
    6,619
    Reputations:
    693
    Java-приложения для Facebook на базе Google App Engine
    Создание, реализация и установка приложения для Facebook в системе Google App Engine
    Дата: 19.09.2012
    Джозеф P. Маккарти, программист, IBM
    http://www.ibm.com/developerworks/ru/library/j-fb-gae/

    Описание: Отсутствие поддержки Java™ на платформе Facebook не должно быть препятствием для создания приложений для Facebook на языке Java. Эта статья показывает, как создать приложение для Facebook, реализовать его на Java и установить в облаке Google App Engine.


    Созданная в феврале 2004 года служба Facebook превратилась в крупнейшую в мире социальную сеть, в которой более чем 900 млн пользователей обмениваться контентом со своими друзьями. Система Facebook Platform, запущенная в мае 2007 года, позволяет сторонним разработчикам писать приложения, интегрированные в Facebook. Первоначально эта платформа поддерживала широкий спектр языков программирования — включая Java, но теперь в ней есть специальный SDK только для JavaScript и PHP (а также поддержка приложений для iOS и Android-устройств). Однако проект по разработке ПО с открытым исходным кодом RestFB поддерживает API Java с тех пор, как платформа Facebook прекратила его поддержку (см. раздел Ресурсы).

    Google App Engine (GAE) — это облачная система типа "платформа как услуга" (PaaS), которая позволяет зарегистрированным разработчикам выполнять свои приложения, написанные на Python, Java или в инфраструктуре Go on Google. В этой статье показано, как зарегистрировать приложение для Facebook, разработать его на Java и бесплатно установить на платформе GAE на благо всех пользователей, зарегистрированных в Facebook. (Отметим, что Google налагает ограничение на ежедневное использование ресурсов, потребляемых приложением, установленным в GAE).

    Простое приложение, которое мы создадим, составляет список всех друзей пользователя с указанием их идентификаторов и фотографиями из профиля — как на странице друзей профиля пользователя Facebook старого образца. Чтобы разработать приложение, нужны:

    • учетная запись Facebook;
    • учетная запись Google;
    • IDE Eclipse с установленным плагином GAE (см. раздел Ресурсы);
    • знакомство с Eclipse.

    Исходный код приложения содержится в загрузках для этой статьи.


    Регистрация приложения

    Первый шаг состоит в том, чтобы зарегистрировать свое приложение на Facebook и в GAE. Приложение лучше создавать на обеих платформах одновременно, чтобы информация, которую вы вводите, совпадала.

    Регистрация приложения на Facebook

    Войдите в Facebook и запустить приложение для разработчика по адресу: https://developers.Facebook.com/apps. (Те, кто делает это впервые, должны будут предоставить приложению доступ к своему профилю.)

    Нажмите кнопку Create New App в верхнем правом углу страницы Apps, чтобы открыть диалоговое окно Create New App, показанное на рисунке 1.

    Рисунок 1. Диалоговое окно Create New App на Facebook
    [​IMG]

    Введите допустимое имя и доступное пространство имен для приложения. Пространство имен — это уникальный идентификатор в одно слово, который будет использоваться в URL-адресе приложения на Facebook. (На рисунке 1 я ввел в качестве имени приложения My Old Friends, а в качестве пространства имен ― myoldfriends.) Оставьте невыбранным пункт о предоставлении бесплатного хостинга Heroku и нажмите кнопку Continue. В следующем диалоговом окне введите код CAPTCHA и нажмите кнопку Submit, чтобы открыть окно настройки основных параметров нового приложения, показаное на рисунке 2.

    Рисунок 2. Диалоговое окно настройки основных параметров приложения для Facebook


    [​IMG]

    Обратите внимание на ключи App ID и App Secret в верхней части экрана (на рисунке 2 они скрыты). Facebook использует эти ключи для идентификации приложения. Держите их в секрете и не позволяйте другим разработчикам использовать их, чтобы ими не воспользовались злонамеренно без вашего ведома.

    Введите в поле App Domains домен приложения. Это должен быть домен GAE, в котором вы зарегистрируете приложение на сайте для разработчиков GAE, так что он должен заканчиваться на .appspot.com. Например, на рисунке 2 я ввел значение myoldfacebookfriends.appspot.com. Этот домен уже недоступен, поэтому вам придется использовать другой. Он должен соответствовать идентификатору приложения, который вы используете при регистрации приложения в GAE.

    В поле Select how your app integrates with Facebook выберите способ интеграции с Facebook Website with Facebook Login и введите URL-адрес сайта, состоящий из домена GAE, указанного в поле App Domains, с приставкой http://. (На рисунке 2 я указал http://myoldfacebookfriends.appspot.com.)

    URL-адрес фона
    По URL-адресу фона, указанному в основных параметрах приложения, Facebook определяет, где взять код для заполнения Canvas Page — пустой страницы в Facebook, на которой будет размещаться ваше приложение. Когда пользователь запрашивает Canvas Page, Facebook помещает URL-адрес фона в <iframe> на этой странице.


    Выберите App on Facebook и введите URL-адрес фона для сервлета, в котором будет выполняться приложение. Для этого приложения URL-адрес фона заканчивается вопросительным знаком, указывающим на то, что параметры приложения будут передаваться через запрос URL-адреса, передаваемый в приложение. Безопасный URL-адрес фона ― то же, что и URL-адрес фона, за исключением того, что место http занимает https. Опять же, важен вопросительный знак в конце URL-адреса. (URL-адрес для моего сервлета приложения: http://myoldfacebookfriends.appspot.com/myoldfacebookfriends, так что на рисунке 2 я ввел http://myoldfacebookfriends.appspot.com/myoldfacebookfriends? для URL-адреса фона и https://myoldfacebookfriends.appspot.com/myoldfacebookfriends? для безопасного URL-адреса фона.)

    Это все, что нужно сделать, чтобы настроить приложение для Facebook, но будет полезно настроить и некоторые другие параметры, такие как значок приложения и его категория, чтобы изменить то, как приложение будет представлено пользователям.

    Регистрация приложения в GAE

    Когда приложение зарегистрировано в Facebook, его нужно зарегистрировать в GAE.

    Войдите на страницу приложений GAE — https://appengine.google.com/ — и нажмите кнопку Create Application. В поле Application Identifier укажите то же имя домена приложения, которое использовалось в основных параметров настройки приложения для Facebook. (Часть appspot.com уже заполнена). Можно использовать любое название приложения ― по этому названию производится поиск зарегистрированных приложений. Для остальных параметров оставьте значения по умолчанию.

    Рисунок 3. Диалоговое окно GAE Create an Application

    [​IMG]

    Нажмите кнопку Create Application, чтобы завершить процесс регистрации в GAE.

    Разработка приложения

    В Eclipse создайте новый проект GAE, выбрав File > New > Web Application Project или нажав кнопку New Web Application Project в меню Google Services and Deployment Tools. Введите имя проекта и имя пакета. Снимите флажок Use Google Web Toolkit. Загрузите JAR-файл RestFB (см. раздел Ресурсы) и добавьте его в папку WEB-INF/lib проекта.

    Добавьте в файл проекта web.xml определение сервлета для приложения. Мое определение приведено в листинге 1.

    Листинг 1. Определение сервлета
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
    <servlet>
    <servlet-name>myoldFacebookfriendsServlet</servlet-name>
    <servlet-class>com.Facebook.friends.MyOldFacebookFriendsServlet</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>myoldFacebookfriendsServlet</servlet-name>
    <url-pattern>/myoldFacebookfriends</url-pattern>
    </servlet-mapping>
    </web-app>
    Отметим, что <url-pattern> тот же, что и в URL фона в окне настройки основных параметров приложения для Facebook, но без вопросительного знака.

    С октября 2011 года для приложений Facebook требуется, чтобы функция Secure Sockets Layer (SSL) была включена; в GAE она по умолчанию отключена. Чтобы включить ее, добавьте в appengine-web.xml следующую строку:
    Code:
    <ssl-enabled>true</ssl-enabled>
    Подписанный запрос к Facebook

    Для создания тела приложения Facebook отправляет в адрес сервлета приложения подписанный запрос, используя метод HTTP POST. Этот запрос содержит информационное наполнение в 64-разрядном коде, куда среди прочих метаданных включен маркер OAuth для приложения текущего пользователя. Он включается в код запроса, только если пользователь предоставил приложению доступ к своему профилю. Чтобы приложение могло использовать этот запрос, его нужно преобразовать в объект Java.

    В листинге 2 показан исходный код Java-объекта подписанного запроса. Для наглядности я опустил все методы get и set; они есть в исходном коде загрузки (см. раздел Загрузка).

    Листинг 2. Объект подписанного запроса
    Code:
    import org.apache.commons.codec.binary.Base64;
    import org.codehaus.jackson.map.ObjectMapper;
    
    public class FacebookSignedRequest {
    
       private String algorithm;
       private Long expires;
       private Long issued_at;
       private String oauth_token;
       private Long user_id;
       private FacebookSignedRequestUser user;
    
       public static class FacebookSignedRequestUser {
    
          private String country;
          private String locale;
          private FacebookSignedRequestUserAge age;
    
          public static class FacebookSignedRequestUserAge {
             private int min;
             private int max;
    
          }
    
       }
    
    }
    
    Код информационного наполнения запроса можно расшифровать с помощью декодера Base64 из библиотеки Apache Commons Codec. Результат представлен в формате JavaScript Object Notation (JSON), и его можно преобразовать в объект Java с помощью процессора JSON Jackson. Загрузите JAR-файлы и добавьте их в проект (см. раздел Ресурсы). Чтобы создать объект, добавьте к классу FacebookSignedRequest вспомогательный статический метод, приведенный в листинге 3.

    Листинг 3. Вспомогательный метод для кодирования и декодирования информационного наполнения запроса
    Code:
    public static FacebookSignedRequest getSignedRequest(String signedRequest) 
          throws Exception {
    
       String payload = signedRequest.split("[.]", 2)[1];
       payload = payload.replace("-", "+").replace("_", "/").trim();
       String jsonString = new String(Base64.decodeBase64(payload.getBytes()));
       return new ObjectMapper().readValue(jsonString, 
                                  FacebookSignedRequest.class);
    
    }
    Создание сервлета

    Теперь можно приступать к написанию кода приложения, который будет запускаться в сервлете. Создайте новый класс с той же подписью, что и у определения <servlet-class> в файле web.xml. Сначала нужно извлечь маркер OAuth из информационного наполнения запроса, используя класс SignedRequest, как показано в листинге 4.

    Листинг 4. Извлечение маркера OAuth
    Code:
    String signedRequest = (String) request.getParameter("signed_request");
    FacebookSignedRequest FacebookSR = null;
    try {
       FacebookSR = FacebookSignedRequest.getSignedRequest(signedRequest);
    } catch (Exception e) {
       // автоматически сгенерированный блок-ловушка TODO
       e.printStackTrace();
    }
    String oauthToken = FacebookSR.getOauth_token();
    Если объект oauthToken имеет значение null, у пользователя нет доступа к приложению, и он должен быть перенаправлен по URL-адресу аутентификации. URL-адрес, стандартный для всех приложений, имеет следующий формат:
    Code:
    https://www.Facebook.com/dialog/oauth?client_id=API KEY&redirect_uri=
       https://apps.Facebook.com/Application Namespace/&scope=Permissions
    API KEY и Application Namespace в URL-адресе аутентификации те же, что и в диалоговом окне настройки основных параметров приложения Facebook. Permissions - это список разрешений, необходимых для приложения. По умолчанию все приложения имеют базовые разрешения, и для целей этой статьи не нужно добавлять никакие другие. (Ссылка на полный список доступных разрешений приведена в разделе Ресурсы.)

    Внешний вид этой страницы можно изменить на странице Settings > Auth Dialog приложения Facebook для разработчиков. Обычно используется метод сервлета HttpServletRequest.sendRedirect(), но так как приложение будет выполняться в <iframe > в домене apps.Facebook.com, короткий фрагмент JavaScript, приведенный в листинге 5, заменяет местоположение окна браузера URL-адресом приложения.

    Листинг 5. Код JavaScript переадресации по URL-адресу приложения
    Code:
    PrintWriter writer = response.getWriter();
    if(oauthToken == null) {
    
         response.setContentType("text/html");
         String authURL = "https://www.Facebook.com/dialog/oauth?client_id="
           + API_KEY
           + "&redirect_uri=https://apps.Facebook.com/myoldfriends/&scope=";
         writer.print("<script> top.location.href='" + authURL + "'</script>");
         writer.close();
    
    }
    С помощью действительного маркера OAuth можно создать DefaultFacebookClient из библиотеки RestFB и использовать его для извлечения данных из API Graph Facebook с помощью вызова fetchConnection(). Перейдите в Graph Explorer на Facebook по адресу: https://developers.Facebook.com/tools/explorer. Выберите разработанное вами приложение из раскрывающегося списка в верхнем правом углу и нажмите Get access token, чтобы получить доступ. Понажимайте на различные ссылки под заголовком Connections, чтобы увидеть результаты.

    API Graph Facebook
    API Graph позволяет читать свойства и связи из социального графа Facebook. Можно читать отдельные поля, получать изображения любого объекта, углубляться в метаданные объекта и получать обновления в режиме реального времени.


    Чтобы получить список друзей пользователя, нажмите на ссылку friends. Обратите внимание, что значение URL в обозревателе имеет вид: id пользователя/friends. Параметр подключения при вызове функции обычно имеет то же значение, что и в Graph Explorer. Но поскольку приложение использует данные пользователя, вошедшего в систему, ID пользователя можно заменить на me, что дает значение me/friends. Вызов возвращает необработанный тип Connection, а так как это класс типа User, его необходимо добавить в качестве параметра. Окончательный вызов имеет вид:
    Code:
    Connection<User> myFriends = FacebookClient.fetchConnection("me/friends", User.class);
    Результат вызова метода fetchConnection() содержится в списке объектов List класса Connection. Класс Connection реализует интерфейс Iterable, так что каждый объект List из списка можно получить в с помощью расширенного цикла for:
    Code:
    for (List<User> myFriendsList : myFriends)
    На каждой итерации цикла объект myFriendsList содержит текущий список пользователей для этой возвращенной страницы данных. Каждый объект User из этого списка используется для создания строки в таблице пользователей, которую создает сервлет. Из объекта User можно получить идентификатор и имя пользователя, но не изображение из его профиля. Однако Facebook предоставляет URL-адрес для извлечения изображения из профиля любого пользователя: https://graph.facebook.com/User ID/picture. Таким образом, чтобы составить URL-адрес изображения из профиля, нужно заменить User ID в URL идентификатором пользователя из объекта User. Используя тот же объект PrintWriter, что и прежде, наложим на фон таблицу со строкой заголовка:
    Code:
    writer.print("<table><tr><th>Photo</th><th>Name</th><th>Id</th></tr>");
    Перебрав список объектов User, как описано выше, составим новую строку этой таблицы с использованием переменных экземпляра каждого объекта User:
    Code:
    for (List<User> myFriendsList : myFriends) {
    
       for(User user: myFriendsList)
          writer.print("<tr><td>" + 
             "<img src=\"https://graph.facebook.com/" + user.getId() + "/picture\"/>" +
             "</td><td>" + user.getName() +"</td><td>" + user.getId() + "</td></tr>");
    
    }
    
    Наконец, для завершения сервлета закроем тег <table> и объект PrintWriter:
    Code:
    writer.print("</table>");
    writer.close();
    
    Окончательный вид метода doPost() сервлета показан в листинге 7.

    Листинг 7. Метод DoPost()
    Code:
    public void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
    
      String signedRequest = (String) request.getParameter("signed_request");
      FacebookSignedRequest facebookSR = null;
      try {
        facebookSR = FacebookSignedRequest.getSignedRequest(signedRequest);
      } catch (Exception e) {
        // автоматически сгенерированный блок-ловушка TODO
        e.printStackTrace();
      }
      String oauthToken = facebookSR.getOauth_token();
      PrintWriter writer = response.getWriter();
      if(oauthToken == null) {
    
        response.setContentType("text/html");
        String authURL = "https://www.facebook.com/dialog/oauth?client_id="
          + Constants.API_KEY + 
          "&redirect_uri=https://apps.facebook.com/myoldfriends/&scope=";
        writer.print("<script> top.location.href='"  + authURL + "'</script>");
        writer.close();
    
      }
      else {
    
        FacebookClient facebookClient = new DefaultFacebookClient(oauthToken);
        Connection<User> myFriends = facebookClient.fetchConnection("me/friends", 
                                                    User.class);
        writer.print("<table><tr><th>Photo</th><th>Name</th><th>Id</th></tr>");
        for (List<User> myFriendsList : myFriends) {
    
          for(User user: myFriendsList)
            writer.print("<tr><td><img src=\"https://graph.facebook.com/" + 
                     user.getId() + "/picture\"/></td><td>" + user.getName() +
                     "</td><td>" + user.getId() + "</td></tr>");
    
        }
        writer.print("</table>");
        writer.close();
    
      }
    
    [SIZE=3]}
    Установка приложения[/SIZE]

    Когда сервлет создан, приложение готово к установке. Щелкните на значке Google в Eclipse и выберите пункт Deploy App Engine. После компиляции приложения и его загрузки на сервер вы (и любой другой пользователь Facebook) можете установить его в Facebook по адресу http://apps.facebook.com/APP ID/ и увидеть результаты.

    Заключение

    В этой статье показано, как зарегистрировать, реализовать и установить приложение Facebook на языке Java, размещенное в системе Google App Engine. Теперь, когда вы знакомы с основами, я предлагаю поэкспериментировать с разными вариациями.

    Вместо того чтобы писать HTML-код непосредственно на странице, можно прибегнуть к более традиционному подходу "модель-представление-контроллер" (MVC), используя стандартный вызов RequestDispatcher.forward() для страницы JavaServer Pages (JSP).

    Можно попробовать создать приложение, использующее некоторые дополнительные разрешения для данных, предоставленных API Graph. Передайте список разрешений, необходимых приложению, по URL-адресу аутентификации, добавляя каждое из них к параметру запроса scope. RestFB предоставляет вспомогательный метод — StringUtils.join() — для правильного создания списка. В качестве параметра он принимает один массив типа String; каждая запись массива представляет собой имя разрешения.

    Наконец, можно попытаться воссоздать пример приложения, используя вместо RestFB проект Facebook-java-api Google Code — альтернативную реализацию API Facebook (см. раздел Ресурсы).