====== Appeler un service distant avec GWT ====== Les articles précédents ont montré comment [[nui:articles:gwt|créer une application GWT]] et y [[nui:articles:gwt_rialto|inclure des composants Rialto]] proposés par le module **Rialto/GWT**, disponible prochainement dans la plateforme de développement communautaire [[http://www.improve-foundations.com|Improve Foundations]]. Nous allons maintenant voir comment nous pouvons récupérer la saisie d'un utilisateur et appeler un service distant avec ces données. ===== Création d'un écran de login ===== L'[[nui:articles:gwt_rialto|article précédent]] faisait mention d'un écran de login. Voici le résultat que nous allons obtenir avec Rialto : {{:nui:articles:capture-4.jpg|:nui:articles:capture-4.jpg}} Créons le maintenant avec le code suivant : package fr.improve.rialto.gwt.newsreader.client; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; import fr.improve.rialto.gwt.core.client.Alert; import fr.improve.rialto.gwt.core.client.Button; import fr.improve.rialto.gwt.core.client.Composite; import fr.improve.rialto.gwt.core.client.Frame; import fr.improve.rialto.gwt.core.client.Label; import fr.improve.rialto.gwt.core.client.Password; import fr.improve.rialto.gwt.core.client.RialtoObject; import fr.improve.rialto.gwt.core.client.SimpleWindow; import fr.improve.rialto.gwt.core.client.Text; import fr.improve.rialto.gwt.core.client.event.ClickListener; import fr.improve.rialto.gwt.newsreader.client.service.LogonService; import fr.improve.rialto.gwt.newsreader.client.service.LogonServiceAsync; public class LogonWindow extends Composite{ private SimpleWindow window; private Text username; private Password password; Button button1; Button button2; protected void create() { window = SimpleWindow.create("Logon", 0, 0, 750, 550); Frame frame = Frame.create(100, 300, "395", 165, "Logon", window); Label.create("name", 45, 10, frame, "Username"); username = Text.create("nameText", 40, 130, 200, frame); Label.create("password", 75,10, frame, "Password"); password = Password.create("passwordText", 70, 130, 200, frame); button1 = Button.create(115, 80, "Logon", null, 100, frame); button2 = Button.create(115, 200, "Cancel", null, 100, frame); } protected void init() { // TODO } } Ce code crée simplement une nouvelle fenêtre, contenant un cadre, des libellés, des champs de saisie et des boutons. Nous désirons maintenant appeler un service distant pour vérifier le login et le mot de passe. Pour cela, nous devons d'abord récupérer ces informations sur un évènement onclick : protected void init() { button1.setClickListener(new ClickListener() { public void onClick(RialtoObject sender) { String login = username.getValue(); String pass = password.getValue(); } }); } ===== Création du service d'identification ===== A ce point, il faut envoyer le login et le mot de passe au serveur pour vérification. GWT propose pour cela une API mettant en oeuvre l'appel de services via des callbacks asynchrones. ==== Interface du service ==== La première étape de la réalisation de ce service consiste à créer un interface pour notre service. Par exemple, l'interface suivant définit une méthose checkLogin, prenant en paramètre un login, un mot de passe et retournant l'utilisateur correspondant si le couple concorde. Une bonne pratique est de placer ce code dans un package finissant en "service" (dans client obligatoirement) package fr.improve.rialto.gwt.newsreader.client.service; import com.google.gwt.user.client.rpc.RemoteService; import fr.improve.rialto.gwt.newsreader.client.User; public interface LogonService extends RemoteService { User checkLogin(String username, String password); } ==== Implémentation de l'interface côté serveur ==== Notre interface doit être implémentée par un servlet spécial côté serveur. Voici un exemple d'implémentation. Une bonne pratique est de placer ce code dans un package finissant en "server". Notez que le service hérite de RemoteServiceServlet et implémente LogonService. Notez également comment il garde en session l'utilisateur authentifié. package fr.improve.rialto.gwt.newsreader.server; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import fr.improve.rialto.gwt.newsreader.client.User; import fr.improve.rialto.gwt.newsreader.client.service.LogonService; public class LogonServiceImpl extends RemoteServiceServlet implements LogonService { public User checkLogin(String username, String password) { // TODO : // check login and password from a database // return user from database if match. if ("user".equals(username) && ("pass".equals(password) { User user = new User("user", "John", "Doe"); getThreadLocalRequest().getSession().setAttribute("user", user); return user; } else { return null; } } } ==== Interface asynchrone côté client ==== Côté client (Javascript), GWT nous propose d'utiliser une légère variante de service : le service asynchrone. Le service asynchrone est défini par un interface quasi identique au service, mais sans type de retour et avec un paramètre AsyncCallBack supplémentaire : package fr.improve.rialto.gwt.newsreader.client.service; import com.google.gwt.user.client.rpc.AsyncCallback; public interface LogonServiceAsync { void checkLogin(String username, String password, AsyncCallback callback); } ==== Appel du service ==== Pour appeler notre service depuis notre écran, il faut passer par GWT.create(Class) pour récupérer le service, spécifier sous quel nom il est déployé, et créer un callback. Voici un exemple : protected void init() { button1.setClickListener(new ClickListener() { public void onClick(RialtoObject sender) { String login = username.getValue(); String pass = password.getValue(); LogonServiceAsync logonService = (LogonServiceAsync) GWT.create(LogonService.class); ServiceDefTarget endpoint = (ServiceDefTarget) logonService; String moduleRelativeURL = GWT.getModuleBaseURL() + "logon"; endpoint.setServiceEntryPoint(moduleRelativeURL); AsyncCallback callback = new AsyncCallback() { public void onFailure(Throwable caught) { Alert.alert("Login process failed !"); } public void onSuccess(Object result) { User user = (User) result; if (user!=null) { window.close(); username = null; password = null; new MenuWindow(user); } else { Alert.alert("Invalid login/password !"); } } }; logonService.checkLogin(login, pass, callback); } }); } ==== Déploiement du service ==== En production, le service doit être déployé comme un servlet standard, avec le nom spécifié lors de son utilisation (ici "logon"). En développement, il est possible de configurer GWT pour qu'il déploie le servlet dans l'environnement GWT en rajoutant une ligne dans le fichier de configuration du module GWT : ===== Pour en savoir plus ===== Le module **Rialto/GWT** est en cours d'intégration dans la plateforme de développement communautaire [[http://www.improve-foundations.com|Improve Foundations]]. Il sera prochainement disponible en preview sur le site [[http://www.improve-community.com|Improve Community]] Vous pouvez aussi consulter l'actualité autour de GWT sur le site [[http://www.ongwt.com|onGWT]].