Avant de commencer rappelons ce que sont les « Google Apps » :
On peut penser immédiatement aux applications « phares » de Google : gmail, agendas, google docs, etc.
Souvent, on confond « Google Apps » et « Google docs »
Pour plus d’infos sur les « Google Apps », voir la page d’accueil : http://www.google.com/apps.
On peut dire que Google Apps, c’est à la fois
Toutes ces « applications » peuvent être interconnectées, ce qui permet de construire un S.I. complet dans le « cloud » Google.
Pour l’entreprise, comme Oxiane, c’est également la possibilité de déclarer un domaine Google Apps d’entreprise, et gérer de façon centralisée, les utilisateurs, les services et les applications installées.
Je viens de découvrir Google Apps Engine (GAE) ou comment développer une application pour Google Apps
.
Il est possible de développer en Python ou en Java.
Pour développer en Java, il vous faut :
Inutile d’en ajouter, le tutorial est super bien fait. Il se trouve ici :
http://code.google.com/intl/fr/appengine/docs/whatisgoogleappengine.html.
J’ai commencé par installer le plugin Google pour Eclipse.
Notons que le plugin Google pour la dernière version d’Eclipse (Indigo) n’était pas mentionnée dans le tutorial mais il m’a suffit de modifier le lien vers l’update site : http://dl.google.com/eclipse/plugin/3.7 pour obtenir la dernière version !
Après l’installation du plugin, j’ai suivi le tutorial qui montre comment en très peu de temps on développe et on déploie une application GAE.
On crée sous Eclipse un projet (« New Web Application Project ») avec un exemple Hello world. Le plugin embarque tout ce qui est nécessaire (dont les différents SDK). On retrouve une architecture Java EE web Servlet/JSP.
On peut tester son application localement (le SDK simule l’environnement google apps). Ensuite, le déploiement se fait en quelques clics une fois qu’on a obtenu de google un id unique pour son application, id à renseigner dans les paramètres de configuration du projet.
Tout ceci est très simple : il m’a fallu environs 10 min pour développer, tester et déployer le premier exemple.
Une phase peut mal se passer : la première fois que vous allez demander un ID pour créer votre application, Google va vérifier votre compte et la seule façon de le faire est l’envoi d’un code par SMS, sur votre portable. Il arrive que ça ne fonctionne pas, avec une erreur énigmatique : « The phone number has been sent too many messages or has already been used to confirm an account ».
Si vous utilisez un compte utilisateur google appartenant à un domaine d’entreprise, il vaut mieux utiliser l’url d’accès http://appengine.google.com/a/yourdomain.com/ plutôt que celle par défaut : http://appengine.google.com/.
Si ça ne change rien, le mieux est d’utiliser ce formulaire pour demander une assistance, celle-ci arrivera très vite par mail.
OxTweets
Cette première étape était pour se mettre en jambes puisque l’objet de mes travaux était surtout de réaliser une application que nous avons nommé OxTweets et qui correspondait à un besoin chez oxiane.
Que fait cette application ?
L’objectif d’OxTweets est de permettre à plusieurs utilisateurs (par exemple les employés d’une entreprise) de publier des tweets sur un compte unique (par exemple celui de l’entreprise).
J’ai commencé par développer l’interface pour accéder à l’application. Comme je suis fan du monde Spring, j’ai utilisé Spring-MVC. J’ai fait une petite JSP avec un controller Spring.
package com.oxiane.gae.tweets.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.oxiane.gae.tweets.data.Tweet;
import com.oxiane.gae.tweets.service.TweetService;
@Controller
@RequestMapping("/sendTweet.htm")
@SessionAttributes("tweet")
public class TweetController {
private TweetService tweetService;
@Autowired
public void setTweetService(TweetService tweetService) {
this.tweetService = tweetService;
}
@RequestMapping(method = RequestMethod.GET)
public String showUserForm(ModelMap model) {
........
}
.....
}
Ensuite j’ai effectué quelques recherches afin de trouver une API Java permettant d’accéder à un compte Twitter et pouvant être utilisée avec GAE. Cette dernière phrase est primordiale car on ne peut pas tout utiliser dans une application GAE notamment les Sockets.
Après des recherches, je suis tombé sur plusieurs API :
J’ai commencé par utiliser JTwitter. Son utilisation est assez simple mais lorsque j’ai voulu tester l’application sur ma machine, j’ai eu une erreur car GAE n’accepte pas l’utilisation des Socket :
java.lang.NoClassDefFoundError: java.net.Socket is a restricted class.
Please see the Google App Engine developer's guide for more details.
J’ai donc commencé à utiliser Twitter4J. Pour utiliser cette API, il faut tout d’abord enregistrer son application sur Twitter dev.twitter en utilisant l’identifiant du compte sur lequel on veut tweeter. Lors de l’enregistrement de l’application, il faut noter les informations suivantes :
- – Consumer key
- – Consumer secret
- – Access token
- – Access token secret
Ces informations sont nécessaires pour la configuration de l’API Twitter4J. La configuration s’effectue soit à travers un fichier de propriété ou un programme Java. Personnellement, j’ai utilisé le bean de configuration de Spring :
PropertyPlaceholderConfigurer
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/oxconfig.properties</value>
</list>
</property>
</bean>
<bean id="tweetService" class="com.oxiane.gae.tweets.service.TweetServiceImpl" >
<property name="authAccessTokenSecret" value="${oauth.accessTokenSecret}" />
<property name="authConsumerKey" value="${oauth.consumerKey}" />
<property name="authConsumerSecret" value="${oauth.consumerSecret}" />
<property name="authAccessToken" value="${oauth.accessToken}" />
</bean>
</beans>
Pour envoyer un tweet, il suffit d’utiliser l’instance de la classe Twitter.
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true).setOAuthConsumerKey(getAuthConsumerKey())
.setOAuthConsumerSecret(getAuthConsumerSecret())
.setOAuthAccessToken(getAuthAccessToken())
.setOAuthAccessTokenSecret(getAuthAccessTokenSecret());
TwitterFactory tf = new TwitterFactory(cb.build());
twitter = tf.getInstance();
L’appel de la méthode updateStatus envoie automatiquement le tweet passé en paramètre.
@RequestMapping(method = RequestMethod.POST)
public String onSubmit(@ModelAttribute("tweet") Tweet tweet) {
try {
tweetService.getTwitter().updateStatus(tweet.getBody());
} catch (Exception e) {
e.getStackTrace();
// TODO: handle exception
}
return "redirect:tweetSuccess.htm";
}
L’objectif de départ était de limiter l’application aux utilisateurs du domaine oxiane. Il fallait donc gérer un service d’authentification. Le Kit de développement de GAE fournit de nombreux services, notamment l’accès aux utilisateurs (UserService). Ce service permet d’intégrer les comptes utilisateurs Google existants à votre application.
On dispose donc de méthodes pour accéder aux informations de l’utilisateur connecté (son domaine, son mail, son nom, …). En utilisant ce service, j’ai eu des problèmes d’accès au domaine d’un utilisateur. En effet la méthode getDomain présente un comportement non trivial :
Dans mon exemple mtoure@www.oxiane.com est un utilisateur du domaine google apps www.oxiane.com. On s’attendrait donc à ce que user.getDomain() retourne « www.oxiane.com » mais l’appel à cette méthode me retourne systématiquement « gmail.com »!.
Pourtant, j’ai bien un user du domaine www.oxiane.com et j’ai créé l’application avec cet user.
En fait, le domaine renvoyé par getDomain() semble correspondre au domaine pour lequel l’application aurait été restreinte lors de sa création (par un administrateur du domaine).
Pour résoudre le problème de façon partielle, j’ai utilisé le mail pour accéder au domaine d’un utilisateur (xxxx@www.oxiane.com, le domaine de xxxx est www.oxiane.com.
Voici l’interface principale :
Le nom de l’utilisateur loggué est inscrit en haut à droite. Si un utilisateur n’est pas loggué ou n’appartient pas au domaine « www.oxiane.com », on ne lui présente pas le panneau de tweet. Sinon, un tweet apparaîtra sur le compte, directement :
Pour conclure
Je dirai que Google App Engine offre des services pour exécuter des applications web sur l’infrastructure Google, de façon très accessible au développeur Java. Il offre la possibilité de mettre vos applications à la disposition des internautes. L’utilisateur développe son application et la déploie en utilisant des scripts ou le plugin GAE eclipse.
Pour aller plus loin avec notre POC (Proof Of Concept), nous allons devoir regarder la persistance sur GAE, mettre en place un petit modèle métier qui permettra à n’importe qui d’utiliser OxTweets avec un compte Twitter lui appartenant. Cet utilisateur, l’administrateur, pourra inviter d’autres personnes qui auront alors la possibilité d’émettre des tweets sur le compte Twitter ainsi partagé.
Enfin, nous pourrons voir un autre volet de GAE : la publication de l’application sur le Google Apps Marketplace afin de la rendre utilisable par d’autres.
La suite sans un prochain billet …