Monday, July 27, 2009

Authenticate user using the google accounts

It's very easy to use the google accounts login system in your website.
First let's create a class to represent the User state in the view.
public class LoginInfo implements Serializable {    private boolean loggedIn = false;   private String loginUrl;   private String logoutUrl;   private String emailAddress;   private String nickname;
(we hided the getters and setters)

Now we must create the service interface that will fill this object:
import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;  @RemoteServiceRelativePath("login") public interface LoginService extends RemoteService {   public LoginInfo login(String requestUri); }
the service Async interface:
import com.google.gwt.user.client.rpc.AsyncCallback;  public interface LoginServiceAsync {   public void login(String requestUri, AsyncCallback async); }
and the service implementation:
import com.google.appengine.api.users.User; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; import com.google.gwt.sample.stockwatcher.client.LoginInfo; import com.google.gwt.sample.stockwatcher.client.LoginService; import com.google.gwt.user.server.rpc.RemoteServiceServlet;  public class LoginServiceImpl extends RemoteServiceServlet implements     LoginService {    public LoginInfo login(String requestUri) {     UserService userService = UserServiceFactory.getUserService();     User user = userService.getCurrentUser();     LoginInfo loginInfo = new LoginInfo();      if (user != null) {       loginInfo.setLoggedIn(true);       loginInfo.setEmailAddress(user.getEmail());       loginInfo.setNickname(user.getNickname());       loginInfo.setLogoutUrl(userService.createLogoutURL(requestUri));     } else {       loginInfo.setLoggedIn(false);       loginInfo.setLoginUrl(userService.createLoginURL(requestUri));     }     return loginInfo;   }  }
Note that to use the UserService of google accounts you need to instantiate a user Object. If the user is already logged in, the call of userService.getCurrentUser(); will return this user. Else it will return null and we will need to redirect the user to login. We create the login URL using the:userService.createLoginURL(requestUri) . It will return the login url for your application. Also to get the logout url you just need to call:userService.createLogoutURL(requestUri) .
Don't forget to configure the LoginServiceImpl in the web.xml file (you can see an example of how to do this here).

To call this service in the view use:
LoginServiceAsync loginService = GWT.create(LoginService.class);     loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback() {       public void onFailure(Throwable error) {       }        public void onSuccess(LoginInfo result) {         loginInfo = result;         if(loginInfo.isLoggedIn()) {           loadUserData();         } else {           loadLogin();         }       }     });
That's it.
You may also save this LoginInfo object to the database, because it does not contain any password or anything like that.

To learn more you may visit the google code tutorial. All the source code of this post was taken from this tutorial.


Friday, July 24, 2009

AGILEBOTS - Another GWT Interface Libary

After playing a while with the GWT framework i decided to create a question-like twitter, focused on improving the knowledge of all the community.
To help create this site, i've started another project called AGILEBOTS. The main purpose of this project is to increase even more the speedy of GWT page building.

Many people that starts using GWT does not know how to create a page, or get too much time to create some basic widgets. Of course that GWT already has many widgets ready to be used. But AGILEBOTS will have much more widgets to be used on many kind of websites.

So it will be very different of frameworks that are on the market right now, like ExtGWT and many others. They have amazing widgets, but their widgets are more focused on form like websites. AGILEBOTS will aim all kind of sites. From a blog, to a company site that desire to have a very cool help system. That will be the focus of AGILEBOT.

If you want to give a look at what we are doing with agilebots you may go to the agilebots site where there is some of the widgets i've created until now.

Some of the widgets AGILEBOTS will have are:
  • Easy menu-like frontpage
  • Dynamic HELP
  • FormFields
  • Tooltips
and much more.

Wednesday, July 22, 2009

DivPanel - Creating a new Widget

Create a composite or extend a widget ?

This question has many answers. In the end it all depends on what is your needs.

When you want to make many widgets work together, like the labeltextbox we created before it's better to create a composite. But when you need to create a new behavior for your widget, maybe it's better to extend a base widget.

As example we will extend the simplePanel, that supports only one widget inside it, to support as many widgets as we need.

Unlike the HorizontalPanel and the VerticalPanel, that uses tables to align the widgets inside it, the simplePanel uses a div to wrap its widget.

Here is the code:

public class DivPanel extends SimplePanel {


private WidgetCollection children = new WidgetCollection(this);


public DivPanel() {

super();

}


public Widget getWidget(int index) {

return getChildren().get(index);

}


public int getWidgetCount() {

return getChildren().size();

}


public int getWidgetIndex(Widget child) {

return getChildren().indexOf(child);

}


public Iterator iterator() {

return getChildren().iterator();

}


public boolean remove(int index) {

return remove(getWidget(index));

}


@Override

public boolean remove(Widget w) {

// Validate.

if (w.getParent() != this) {

return false;

}

// Orphan.

orphan(w);


// Physical detach.

Element elem = w.getElement();

DOM.removeChild(DOM.getParent(elem), elem);


// Logical detach.

getChildren().remove(w);

return true;

}

public void add(Widget child){

add(child,getElement());

}


protected void add(Widget child, Element container) {

// Detach new child.

child.removeFromParent();


// Logical attach.

getChildren().add(child);


// Physical attach.

DOM.appendChild(container, child.getElement());


// Adopt.

adopt(child);

}


protected WidgetCollection getChildren() {

return children;

}


}

First and most important we need to rewrite the add method (the simplePanel.add method verify if you already added a widget and throws an exception).
Second we need to create a WidgetCollection to hold all the widgets that will be accessed.
Let's take a look at the add(Container,widget).
If we use the DOM.appendChild method our page will look like we want, but we need also to call the adopt(widget) method, so the events and handlers already associated with the widget still works.

Also when extending an widget it's very important to know what will be your base class.
It could be the widget class, some Panel class, maybe a TextBox... and so on. Choosing the rigth base widget is a key factor.

Note that when extending the widget class you need also to create a DOM element and call the setElement method. This is the method responsable for binding your element to the page.

Here is another example:

public class DockDiv extends DivPanel{


public final static int NORTH = 0;

public final static int SOUTH = 1;

public final static int EAST = 2;

public final static int WEST = 3;

public final static int CENTER = 4;

private Element north = DOM.createDiv();

private Element south = DOM.createDiv();

private Element east = DOM.createDiv();

private Element west = DOM.createDiv();

private Element center = DOM.createDiv();

private Element row = DOM.createDiv();

private Element container = DOM.createDiv();

public DockDiv(){

container.appendChild(north);

container.appendChild(row);

container.appendChild(south);

row.appendChild(west);

row.appendChild(center);

row.appendChild(east);

getElement().appendChild(container);

east.getStyle().setProperty("float", "left");

west.getStyle().setProperty("float", "left");

center.getStyle().setProperty("float", "left");

}

public void add(Widget child){

add(child,center);

}

public void add(Widget child, int pos){

switch (pos) {

case NORTH:

add(child,north);

break;

case SOUTH:

add(child,south);

break;

case EAST:

add(child,east);

break;

case WEST:

add(child, west);

break;

default:

add(child, center);

break;

}

}

public Element getRegion(int region){

switch (region) {

case NORTH:

return north;

case SOUTH:

return south;

case EAST:

return east;

case WEST:

return west;

default:

return center;

}

}

@Override

public void setWidth(String width) {

super.setWidth(width);

north.getStyle().setProperty("width", width);

row.getStyle().setProperty("width", width);

south.getStyle().setProperty("width", width);

}

public void setCenterSize(String west, String center, String east){

if (west != null && !west.equals("")){

this.west.getStyle().setProperty("width", west);

}

if (center != null && !center.equals("")){

this.center.getStyle().setProperty("width", center);

}

if (east != null && !east.equals("")){

this.east.getStyle().setProperty("width", east);

}

}

}

as you see this DockDiv extends the divPanel (working with divs, not tables).
Also there is some DOM Elements and in the add method we decide what element will be the container of the widget. This shows that you may create as many elements you need.

Friday, July 17, 2009

Composites - When you need to group widgets

When developing an user interface it's quite common to need components more complex than the ones that are available to us. By example the textfield widget does not have a label by default and every time we need to put a text field on a form, we also need to put a label with it.
And if we could create a new widget that was composed of a label and a textfield?
That's the main purpose of the Composite class. The Composite is a widget composed of widgets.
You may create a LabelTextBox composite, that has a label and a textfield. This way you don't need anymore to create each time a label and a textbox (and maybe some panel to layout them). Now you just need to create a LabelTextBox.
Also, using the composite helps you to keep your code clean and organized, by encapsulating all the logic and configuration of those widgets inside the composite class.
Here is an example of a composite:

public class LabelTextField extends Composite {


private HorizontalPanel hPanel;

private Label lblField;

private TextBox txtField;

public LabelTextField(Label lbl, TextBox txt) {

lblField = lbl;

txtField = txt;

hPanel = new HorizontalPanel();

hPanel.add(lblField);

hPanel.add(txtField);

initWidget(hPanel);

}

public String getValue(){

return txtField.getText();

}

public String getLabel(){

return lblField.getText();

}

}

One of the rules to use the composite class is that we must associate another widget as the main widget of this composite, through the method initWidget(Widget w).
In this case the main widget is a HorizontalPanel.
Also note that we hided the TextBox and the Label objects from the external access, and only exposed the getText() methods of the objects.

Thursday, July 16, 2009

How to upload the chat application to google AppEngine

In the last post we finished the chat application. Now we will learn how to upload it to google appengine.

First log in to the appEngine site with your google account.
If this is the first time you log in into appengine it will ask to validate your mobile number. (Please, don't forget to put also the country code and the area code. )
After you validate you will be able to create your first application.
Choose an application ID avaliable and the application title hit the save button.

After all you need to do is open your eclipse project. Select the project properties -> Google -> AppEngine and set the id of the application. You may also set the version of the application(the AppEngine keeps track of the versions, and you can make any version the one default). After just click on the appengine icon (its close to the button you hit to create a google project and the button to compile the gwt). Fillin your email and password, and you're done.
That's all you need to create a chat application and publish it to the internet.

Wednesday, July 15, 2009

How to create a simple chat using GWT and AppEngine - Second Part

Now comes the second part of the tutorial to create a basic chat.

In the last part we created the base of the interface and the base of the server.
Now we will create the Persistence Manager.

Create a new package under the server package named persist.

Now create a Class named PMF. Here is the code:

public final class PMF {


private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");


private PMF(){ }

public static final PersistenceManagerFactory getFactory(){

return pmfInstance;

}

public static final PersistenceManager getManager(){

return getFactory().getPersistenceManager();

}

public static final void saveObject(Object obj){

getManager().makePersistent(obj);

}

}

This class uses the PersistenceManagerFactory to get a PersistenceManager. This manager is responsable for saving, updating and deleting the objects. (Notice that this class is very simple just to explain this example).
Now open the Shout class. We need to set the time that the message was sent.
Add the Date field sentAt to it.

@Persistent

private Date sentAt;

also great the get and set for this field.
Now change the shoutToServer method of the ShoutServiceImpl class. This is the code:

public String shoutToServer(Shout s){

s.setSentAt(new Date());

PMF.saveObject(s);

return s.getMessage();

}

we just set the date to today and save the message.
Now all of our messages been saved. We need now to display them on the browser.
Create a method getAllShouts in the ShoutServiceImpl class. This is the code:

public List getAllShouts() {

Query query = PMF.getManager().newQuery(Shout.class);

query.setOrdering("sentAt ascending");

List resultset = (List)query.execute();

return resultset;

}

Here we get the PersistenceManager and create a new query based on the Shout class.
next we order the results acording to the sentAt field.
This will return all the messages in the server.
Next we need to create a method that will return only messages newer than a date we will pass.
Create a method called get getNewerThan that will receive a Date parameter. This is the code:

public List getNewerThan(Date now) {

PersistenceManager manager = PMF.getManager();

Query q = manager.newQuery(Shout.class);

ArrayList result = new ArrayList();

List resultset = (List)q.execute();

for (Shout a: resultset){

if (a.getSentAt().after(now)){

result.add(a);

}

}

return result;

}

Here we filter the messages to the ones that were sent only after some specific date. We will need this to update the browser with new messages.
Now we need to update the ShoutService and ShoutServiceAsync with this methods too. Here are the codes:
ShoutService:

public List getAllShouts();

public List getNewerThan(Date now);

ShoutServiceAsycn:

void getAllShouts(AsyncCallback> callback);

void getNewerThan(Date now, AsyncCallback> callback);

Now that your interfaces are updated let's change the EntryPoint (The .java).

First create a Date attribute called lastUpdatedAt and a Timer attribute caled t.
Here is the code:

final VerticalPanel messagesPanel = new VerticalPanel();

private Date lastUpdatedAt;

Timer t;

private void checkMessages(){

t.schedule(1000);

}

private void configureTimers(){

t = new Timer(){

@Override

public void run() {

shoutService.getNewerThan(lastUpdatedAt, new AsyncCallback>(){

public void onFailure(Throwable caught) {

checkMessages();

}

public void onSuccess(List result) {

if (result.size() > 0){

for (Shout i: result){

messagesPanel.add(new HTML(i.getMessage()));

}

lastUpdatedAt = result.get(result.size()-1).getSentAt();

}

checkMessages();

};

});

}

};

}

Here we created the Timer and the Date attributes and also changed the scope of the messagesPanel, making it accessible to all methods in the class.
In the checkMessages() method we just start the Timer, and the timer will get all the messages that were sent after the last message received.
Don't forget to remove the messagesPanel from inside the onModuleLoad method.

Finally add this to the end of the onModuleLoad method:

configureTimers();

shoutService.getAllShouts(new AsyncCallback>(){

public void onFailure(Throwable caught) {

checkMessages();

}

public void onSuccess(List result) {

for (Shout i: result){

messagesPanel.add(new HTML(i.getMessage()));

if (i.getSentAt().after(lastUpdatedAt)){

lastUpdatedAt = i.getSentAt();

}

}

checkMessages();

}

});

this will configure the timer object and also get all the messages that were sent before opening the page.
This will also start the Timer, that will loop now forever.

Here we got our chat. Later you may add a name's field to identify who is sending the message if you want.

That's all folks!
Next i will teach how to send this project online to Google AppEngine.

Until there!

Tuesday, July 14, 2009

How to create a simple chat using GWT and AppEngine - First Part

UPDATED - 2009-07-15 - WEB-INF info

Well, today i will start a series of tutorials about making some stuff in gwt.
We will begin transforming the default project the google eclipse plugin generates.

After installing the google plugin for eclipse (you may find here how to install the plugin), let's create a web application project, by clicking the google blue icon in the toolbar

After you choose your Project Name and the initial package of the project

Also select to use both GWT and App Engine sdks.

This will create a simple project with two main packages:
  • Client
  • Server
In the client package will stay all the code GWT will compile to javascript, and in the server package will stay all the code that will run on the app engine server.

Also the plugin already creates a page with a server communication. It has a textbox and a button, and when you click the button it sends the content of the textbox to the server and get a string to show in the page.

We will also add to this page a list with all the messages sent previously and also update it often using ajax.

So these are the steps we will take:
  1. add a new line to the table in the html
  2. Create a Panel and add it to the line created
  3. Create a model class to represent the message sent - We will call this class "Shout"
  4. Create a service to send this shout to the server
  5. implements the client call to the service

First we will create in the html page (it has the name of the project and stay in the war package) a place to put all of the messages.
We will do this by adding a new line to the table:


what we are doing here is creating a new container to put our panel with the messages.


Now we need to edit the java code to add a new panel in this row.
Open the .java (it is the client package) - We will call this file the EntryPoint, as it implements the EntryPoint interface. We will edit the onModuleLoad method.

Add a new final VerticalPanel and call it messagesPanel

public void onModuleLoad() {

final VerticalPanel messagesPanel = new VerticalPanel();

final Button sendButton = new Button("Send");

final TextBox nameField = new TextBox();


now we will add this panel to the row we created in the html :

// Add the nameField and sendButton to the RootPanel

// Use RootPanel.get() to get the entire body element

RootPanel.get("nameFieldContainer").add(nameField);

RootPanel.get("sendButtonContainer").add(sendButton);

RootPanel.get("messagesContainer").add(messagesPanel);


The RootPanel.get(id) method returns the element in the page with the id we passed, so we can add widgets to it.
Now our panel will be placed right under the textbox and the button.
Well now we need to create the Model class tha will represent the message we are sending.
First let's create a new package under the client package, named "model", and inside this package lets create a new Class, called "Shout".
This class must implements the serialize interface.
Also we need to put some JDO information to be able to save it in the database.
This is the code to the Shout class:

@PersistenceCapable(identityType=IdentityType.APPLICATION)

public class Shout implements Serializable{


@PrimaryKey

@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)

private Long id;

@Persistent

private String message;

public Shout(){}

public Shout(String message){

this.message = message;

}


public String getMessage() {

return message;

}


public void setMessage(String message) {

this.message = message;

}


public Long getId() {

return id;

}

}

The @PersistenceCapable annotation mark this class as persistance and each field that shoud be stored must have the @Persistence annotation on it.

Well now that we have our model we must create a service to send it to the server.
First let's create a ShoutService interface in the client package and also a ShoutServiceAsync interface.
In the first we should add a method that will receive a Shout and return a String, this is the code of the ShoutService:

@RemoteServiceRelativePath("shout")

public interface ShoutService extends RemoteService{


String shoutToServer(Shout s);

}

this interface must extends the RemoteService and also must define the path to access this service using the RemoteServiceRelativePath annottation.

In the ShoutServiceAsync we should add a void method that will receive a Shout object and a AsyncCallback object.
This is the code to the ShoutServiceAsync:

public interface ShoutServiceAsync {


void shoutToServer(Shout s, AsyncCallback callback);

}

Now we need to create the server side service.
Let's create the ShoutServiceImpl in the server package.

@SuppressWarnings("serial")

public class ShoutServiceImpl extends RemoteServiceServlet implements ShoutService{


public String shoutToServer(Shout s){

return s.getMessage();

}

}

this class must extend te RemoteServiceServlet and also implements the interface of the Service we created before. Notice that it implements the Service and not the ServiceAsync.
For now our method will just return the message of the Shout object.
Well, now we are almost there.
Let's change now the behavior of the click of the send button.
Get back to the entrypoint class and create a ShoutServiceAsync final variable:

/**

* Create a remote service proxy to talk to the server-side Greeting service.

*/

private final GreetingServiceAsync greetingService = GWT

.create(GreetingService.class);

private final ShoutServiceAsync shoutService = GWT.create(ShoutService.class);


notice that we declare the service using the Asycn interface, but in the GWT method we use the Service class.

Now, look for the method "sendNameToServer". and remove the code inside it, we wont need it anymore.
next put this code:

sendButton.setEnabled(false);

Shout s = new Shout(nameField.getText());

nameField.setText("");

shoutService.shoutToServer(s, new AsyncCallback(){

public void onFailure(Throwable caught) {};

public void onSuccess(String result) {

messagesPanel.add(new HTML(result));

sendButton.setEnabled(true);

};

});

we are just creating a shout using the text in the textfield, reseting the textfield and calling the service method, passing our shout and the asyncCallback.
In the callback we can do something if the method fails, like by connection reset or a exception in the server using the onFailure method.
In the onSuccess method we put our code to treat the answer of the server.
In this case we are just adding the string into a HTML widget inside the panel. As the panel is a VerticalPanel all this widgets will be placed one under the other.

----UPDATED----------

Also you need to edit the web.xml file inside the WEB-INF directory.
You need to configure your servlets (The ShoutServiceImpl).
Just copy and paste the greetServlet and change the servlet-name to shoutServlet and the servlet-class to your.path.to.ShoutServiceImpl . Also copy and paste the servlet-mapping of the greetServlet and change the servlet-name to shoutServlet and the url-pattern to /[module-name]/shout .
Observe that this /shout is the name we put on the service interface annottation: @RemoteServiceRelativePath("shout").

-----UPDATED-----------

In this is it. In the next post we will save this shout in the database and load the shout list when the page is loaded and keeping updating the list while the page is open.

See you there!

Monday, July 13, 2009

Google App Engine

Pessoal,

Neste post eu vou falar rapidamente sobre o google app engine, que já vem configurado para uso junto com o plugin do google para o eclipse.

Bom, primeiramente (e antes mesmo ate de falar sobre real praticidade de usar o app engine como servidor) vem o fato de um usuário google ter direito a até 8 aplicativos dentro do appengine.

Para criar um aplicativo que utiliza o app engine, primeiro é preciso acessar http://appengine.google.com e criar fazer o login pela primeira vez. Logo após já é possível criar a primeira aplicação no site mesmo.

Cada aplicação do app engine tem um ID próprio, que deve ser escolhido durante a criação da aplicação e vai ser a url de acesso para ela (id-da-aplicacao.appspot.com).

Com esse ID, abra o eclipse, clique com o botão direito sobre o projeto, selecione propriedades->Google->App engine.
Coloque o ID de sua aplicação e pronto.
Para publicá-la, clique no logo do app engine (aquela turbina com asas) que fica no topo esquerdo da tela (ao lado do desenho do google e do gwt), que o site sera enviado para o appengine.
Alem disso, é possível especificar (na tela onde coloca o id da aplicação) qual a versão atual da mesma, e assim, manter um histórico no servidor de versões.

Caso você opte por definir uma nova versão para a aplicação, quando você publica-la ela não vai atualizar para a nova versão automaticamente. Será preciso acessar o site appengine.google.com, selecionar a sua aplicação, selecionar a aba lateral "Versions" escolher qual versão do site deixar disponivel e selecionar a opção make default.

Agora que já sabemos como enviar uma aplicação para a nuvem, vamos falar das vantagens e usos do app engine.
  • Uso para hospedar sites estaticos (apenas html). Como possui um limite de 500mb de armazenamento, o app engine é uma opção rápida e barata para colocar no ar um hotsite, site institucional e afins
  • Computação nas nuvens. Uma aplicação no app engine tem acesso a toda a infraestrutura do google de servidores, o que permite uma resposta mais rápida e escalonável da aplicação ao usuário final. Outro ponto interessante é que não precisamos nos preocupar com a infraestrutura por tras do site.
  • BigTables. Acesso a mesma estrutura de armazenamento de dados que o google usa. Isso se traduz num banco de dados rápido e simples de ser utilizado.
Nem tudo são flores porém.
O App Engine é um serviço semi-free. Ele possui uma cota diária de utilização:
  • Tempo de processamento
  • Requests
  • Entrada e saída de dados
  • Pedidos de segurança
  • entre outras...
Porém essas cotas são mais que suficientes para sites médios, e mesmo para sites com muitos acessos, é possível habilitar a opção de pagamento. Onde você paga se exceder uma das cotas. Os valores são relativamente baixos... algo como R$0,20 por hora adicional de processamento e por ai vai...

Realmente vale mais a pena, pois em um dia que o trafego não exceda a cota você nao paga a mais.

Bom, esses são os motivos pelos quais o The Way better está sendo implementado utilizando o App Engine.