Saturday, December 28, 2013

GWT nesting activities implementing Thomas Broyer proposal

This article has been moved here

http://ronanquillevere.github.io/2013/12/28/not-nesting-activities.html





-- old version --







Hi everyone,

I tried to implement Thomas Broyer's idea to solve the nesting activities problem: http://blog.ltgt.net/gwt-21-activities-nesting-yagni/

So I created a Github project, have a look and do not hesitate to comment : https://github.com/ronanquillevere/GWT-Multi-Activities

Hope it will help some of you.

I will try to have a look to slotted ASAP https://code.google.com/p/slotted/ which is a framework that does exactly the opposite ! 

Friday, August 23, 2013

Google I/O 2013

This article has been moved here

http://ronanquillevere.github.io/2013/08/23/google-io-gwt-videos.html





-- old version --






Hello everyone,

I should have posted those videos long time ago but I am lasy sorry :D

Here are 2 videos taken during google I/O 2013 talking about GWT and its futur now that is lead by a steering commitee.

Google I/O 2013 - GWT Roadmap for the Future




Google I/O 2013 - Demystifying MVP and EventBus in GWT


Friday, August 2, 2013

Nested Activities : an alternative with Presenters

This article has been moved here

http://ronanquillevere.github.io/2013/08/02/presenter-for-nesting.html





-- old version --






If you are reading this article it means you probably have already read the article called GWT 2.1 Activities – nesting? YAGNI! http://blog.ltgt.net/gwt-21-activities-nesting-yagni/ by Thomas Broyer https://plus.google.com/113945685385052458154?rel=author . If you did not, I suggest to have a look at his article.

In this article I will reformulate the idea explained by Thomas Broyer and propose another solution and try to compare them.

Activity Place Pattern


First you need to understand how the Activities and Places pattern works in detail. Below is a quick overview with the major objects involved.



When you go from one Place to another, at some point, the framework will throw a PlaceChangeEvent. Inside this event you will find a Place object corresponding to the URL of the Place your are trying to go to.

This event will be listened by the ActivityManager. The ActivityManager will call the ActivityMapper to give him back the Activity (instance) corresponding to that new Place.

Then the ActivityManager will try to start() this Activity.

So the first time you design an application using the Activities and Places pattern you will probably have something like : one web page = one url = one activity

But if your web page is complex ,with distinct regions inside (a header, a side bar, a content area etc.), with components inside that you might want to reuse in other pages you end up trying to create sub-activities or "nested" activities as Thomas call them.

One Place - Many Activities


This is how I would describe Thomas' solution. Again, please have a look at his article http://blog.ltgt.net/gwt-21-activities-nesting-yagni/ .

The idea is the following


1 ActivityManager + 1 ActivityMapper for each region of a web page
All ActivityManagers share the same Eventbus
1 layout for all the pages of the application. This layout defines all the possible regions
If a region is not needed on a certain page, the corresponding ActivityMapper will return null and the ActivityManager will not display the region (meaning the region will be hidden)

So let's say you want to go to a new Place in your application. The PlaceChangeEvent will be fired. All ActivityManagers will receive the event ( they all share the same Eventbus ) each of them will call his own ActivityMapper returning a specific Activity.

If you take the example of a "side bar" region (left part of your web page). On a Place called placeA, the ActivityMapper will return an activityA, but on a placeB, the ActivityMapper may return an activityB or may return null thus hiding the "side bar region".

One Place - One Activity - Many Presenters


Here is my proposal, another way of doing this is the following: You need to introduce another interface which is a kind of Presenter and that is not managed by the Activities and Places framework.

Your Presenter interface should probably have those kind of methods (the presenter interface should probably also have some kind of getView() method).

public interface Presenter {
    void init();
    void dispose();
   ...
}

They will be initialized/disposed by the Activity when it starts or stops.

An Activity will contain as many presenters as regions in the page (and presenters might contain nested presenters inside them). The Activity can have a view which is a DockLayoutPanel and when the Activity starts, it can add the presenters' views inside the different areas of its DockLayoutPanel view.



So the start method of the activity should look like this (you would probably pass the Eventbus to your presenters in the init method but I just want to focus on the idea, not the real implementation).

Activity.start(){
...
    headerPresenter.init();
    getView().addNorth(headerPresenter.getView());

    sideBarPresenter.init();
    getView().addLeft(sideBarPresenter.getView());

    contentPresenter.init();
    getView().add(contentPresenter.getView());
...
}

The disposal of the presenters should be called when the activity stops.

Of course your Activity can have a simpler layout for its view than the DockLayoutPanel.

So instead of having many ActivityManagers, you can have only one. The activity will be the master of ceremony between your different presenters. And you will have one Activity per Place.

You could use the Activity Interface for your Presenters but I think it is kind of dirty ...

Pros


  • One ActivityManager
  • One ActivityMapper
  • One Activity per Place

Cons


  • The history can be tricky to handle if you want to change the state of your presenters and update the URL without "really" changing the place
  • Creating a new Presenter interface and being sure that presenters are initialized/disposed correctly changing the main layout from place to place
Ok I think I will stop here, I will probably add some details in the futur if it is not understandable enough.

Tell me what you think of it, I am sure my proposal is a bad idea :D. 

Wednesday, July 31, 2013

GWT and Rest : Part 2 - Client (RestyGWT)

This article has been moved here

http://ronanquillevere.github.io/2013/07/03/gwt-rest-jersey-client.html





-- old version --







This article is part 2 of a previous post, see part1 http://wpamm.blogspot.fr/2013/03/gwt-and-rest-restygwt-jersey-part-1.html for the server side information. I know it has taken me a long time to write this part. I am really sorry if you were waiting.

This part will be focused on the GWT http://www.gwtproject.org/ client part, using RestyGWT http://restygwt.fusesource.org/index.html

This part will be really short because there is not much say as RestyGWT make things really easy ! By the way thanks for the people who have written and contributed to this library : chirino https://github.com/chirino and mkristian https://github.com/mkristian and all others.

The first thing you have to do is the inherits the resty stuff in your *.gwt.xml file

<inherits name='org.fusesource.restygwt.RestyGWT'/>

Thanks to this line, when extending the RestService Interface, the restyGWT generator will be able to generate the Java code corresponding to your interface.

Generators allow the GWT compiler to generate Java code at compile time and have it then be compiled along with the rest of the project into JavaScript. GWT generators behave a little bit like annotation preprocessors in Java.

To generate the client Java code, restyGWT is using the JAX-RS annotations to define the url of the request, the parameters to set etc. The code generated by RestyGWT will use com.google.gwt.http.client.Request class to query the server.

So all you have to do is extending the RestService interface and using the right JAX-RS annotations

The following code is an example taken from here : https://github.com/ronanquillevere/GWT-Resty-Template (code not really working right sorry need to fix it)

package rq.restygwt.template.client;

import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

import org.fusesource.restygwt.client.MethodCallback;
import org.fusesource.restygwt.client.RestService;

import rq.restygwt.template.shared.Person;

@Path("api/v1/persons")
public interface PersonService extends RestService
{
    @GET
    void getPersons(MethodCallback<List<Person>> callback);
 
    @GET
    @Path("{id}")
    void getPerson(@PathParam("id") String id, MethodCallback<Person> callback);
}
Now to use your service


package rq.restygwt.template.client;

import java.util.List;

import org.fusesource.restygwt.client.Defaults;
import org.fusesource.restygwt.client.Method;
import org.fusesource.restygwt.client.MethodCallback;

import rq.restygwt.template.shared.Person;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;

public class Template implements EntryPoint
{

    public void onModuleLoad()
    {
        Defaults.setServiceRoot(GWT.getHostPageBaseURL()); // (avoid Template in the url)

        final HTML html = new HTML();
        RootPanel.get().add(html);

        // Uses resty generator (set up in gwt.xml)
        PersonService s = GWT.create(PersonService.class);

     
        s.getPersons(new MethodCallback<List<Person>>()
        {
            public void onSuccess(Method method, List<Person> response)
            {
                for (Person person : response)
                {
                    html.getElement().setInnerHTML(html.getElement().getInnerHTML() + "Hello " + person.getFirstName() + " " + person.getLastName() + "");
                }
            }

            public void onFailure(Method method, Throwable exception)
            {
                html.setText("Rest call failed");
            }
        });

        s.getPerson("1", new MethodCallback<Person>()
        {
            public void onSuccess(Method method, Person response)
            {
                html.getElement().setInnerHTML(html.getElement().getInnerHTML() + "The first one is " + response.getFirstName() + " " + response.getLastName() + "");

            }

            public void onFailure(Method method, Throwable exception)
            {
                html.setText("Rest call failed");
            }
        });
    }
}


Hope it helped !

Sunday, March 24, 2013

GWT and Rest : Part 1 - Server Side (Jersey JAX-RS)

This article has been moved here

http://ronanquillevere.github.io/2013/03/24/gwt-rest-jersey-server.html





-- old version --







Hello everyone,

In this article I will talk about REST http://en.wikipedia.org/wiki/Representational_state_transfer and how to create a REST application using GWT (and RestyGWT http://restygwt.fusesource.org/) for the client and JAX-RS http://en.wikipedia.org/wiki/Java_API_for_RESTful_Web_Services (with Jersey http://jersey.java.net/) for the server.

This part 1 is focused on the server side.

Part 2 will focus on the client side  with GWT and RestyGWT http://wpamm.blogspot.tw/2013/07/gwt-and-rest-part-2-client-restygwt.html

Why REST ?


In GWT there are many ways to make your client and your server talk to each other: GWT-RPC https://developers.google.com/web-toolkit/doc/latest/tutorial/RPC, Request Factory https://developers.google.com/web-toolkit/doc/latest/DevGuideRequestFactory, standard servlet mechanism, REST... Which one should I use ?

GWT-RPC is probably the most common way to do it and quite an easy way to start with. Nevertheless it is not an "open" solution. By "open" I mean that if you want to write a new client in php or in another language, you will have to modify your backend communication layer.

As the futur of GWT is not clear today, I do not want to have to re-write my backend code and architecture if I decide to make a new version of my client in php. I also want third parties to be able to build thier own solutions based on my API.

That's why Facebook, LinkedIn https://developer.linkedin.com/rest etc. are building web APIs based on rest principles.

I strongly recommend to read Crafting interfaces that developers love by Brian Mulloy if you want to build a nice REST API http://info.apigee.com/Portals/62317/docs/web%20api.pdf.

Rest Backend


For the following you will need the following dependencies

jersey-server
jersey-servlet
jersey-json
jersey-guice

guice
guice-servlet


To build my rest backend I will use Jersey which is the Reference Implementation for building RESTful Web services on a Java backend. I will also use GUICE to handle the dependency injection https://code.google.com/p/google-guice/.

In the rest approach you will ask your server for resources. A resource can be a book for example.

public class Book
{

 public Book(String isbn, String author)
 {
  this.isbn = isbn;
  this.author = author;
 }

 public String getAuthor()
 {
  return author;
 }

 public void setAuthor(String author)
 {
  this.author = author;
 }

 public String getIsbn()
 {
  return isbn;
 }

 public void setIsbn(String isbn)
 {
  this.isbn = isbn;
 }

 private String isbn;
 private String author;
}


When asking you server for a book, for example the book whose isbn is 1,  you will probably make a request that will look like this :

/api/v1/books/1

On your server you must declare your books resource class. Here is what it should look like. Our resource will produce json output and will consume json (if we want to pass parameters in the payload). In this example I am creating books directly in the BookResource class but of course objects should come from a repository...

@Singleton
@Path("v1/books")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class BookResource
{
    public BookResource()
    {
         books= new HashMap<String, Book>();
         Book book1 = new Book("1","Brian");
         books.put("1", book1);

         Book book2 = new Book("2","David");
         books.put("2", book2);
    }

    //example : http://127.0.0.1:8888/api/v1/books
    @GET
    public Collection<Book> getBooks()
    {
        return books.values();
    }
 
    //example : http://127.0.0.1:8888/api/v1/books/1
    @GET
    @Path("{isbn}")
    public Book getPage(@PathParam("isbn") String isbn)
    {
        return books.get(isbn);
    }

    private HashMap<String, Book> books;
}

Now you should declare your resource class in your servlet container and tell your server which url should be mapped to this class. To do so I will use a filter in my web.xml and map it to a GuiceServletContextListener.


<filter>
  <filter-name>guiceFilter</filter-name>
  <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
 </filter>

 <filter-mapping>
  <filter-name>guiceFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

 <listener>
  <listener-class>com.rq.resty.server.GuiceServletConfig</listener-class>
 </listener>



Below is the code of the filter. The REST_INTERFACE_PACKAGE should point to your server side package where the resource class are declared. You can see below that every query starting by /api/ will be treated by the GuiceContainer. It will be responsible for deploying root resource classes with Guice integration.

Also we will use the POJO mapping feature to serialize our objects without having to create a specific serializer.

public class GuiceServletConfig extends GuiceServletContextListener
{
    @Override
    protected Injector getInjector()
    {
        final Map<String, String> params = new HashMap<String, String>();

        params.put(JERSEY_CONFIG_PROPERTY_PACKAGES, REST_INTERFACE_PACKAGE);
        params.put(JERSEY_API_JSON_POJO_MAPPING_FEATURE, "true");

        return Guice.createInjector(
            new ServletModule()
            {
                @Override
                protected void configureServlets()
                {
                    serve("/api/*").with(GuiceContainer.class, params);      
                }
            }
        );
    }

private static final String JERSEY_CONFIG_PROPERTY_PACKAGES = "com.sun.jersey.config.property.packages";
private static final String JERSEY_API_JSON_POJO_MAPPING_FEATURE = "com.sun.jersey.api.json.POJOMappingFeature";
private static final String REST_INTERFACE_PACKAGE = "com.rq.resty.server";
}

If everything is working you should be able to call your server and get all your books like this :
http://127.0.0.1:8888/api/v1/books

Your server should send you back the following json :
[{"isbn":"2","author":"David"},{"isbn":"1","author":"Brian"}]
Or you can ask directly for a particular book if you know its isbn
http://127.0.0.1:8888/api/v1/books/1
Your server should send you back the following json :
{"isbn":"1","author":"Brian"}

Check out this article if you do not want to use a Guice filter to declare your resource classes : http://blog.javaforge.net/post/30469901979/gwt-rest


Sunday, March 3, 2013

GWT Activities and Places framework Introduction

This article has been moved here

http://ronanquillevere.github.io/2013/03/03/activities-places-intro.html





-- old version --







Hello everyone,

In the following article I will try to explain and clarify the Google Activities and Places framework.

You can have a look at the following article for more thoughts on nesting activities : http://wpamm.blogspot.tw/2013/08/nested-activities-alternative-with.html

Model View Presenter (MVP)


For a lot of people, it is not clear wether or not the Activities and Places framework is equivalent to MVP. MVP is a coding pattern. It was pushed by Google in their GWT framework as an improvement of the classical MVC pattern http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

Classical MVC pattern




MVP pattern 




The difference is that the model and the view should not know each other.

The consequence is that the view should be as dumb as possible. No intelligence should be coded in the view. The view is only the graphical representation of the component. All the behaviors should be coded in the presenter. The events are transmitted by the view to the presenter.

This pattern makes it really simple to replace a view component (this can be really useful to test the application with mocked views ...)

Check out the Google I/O 2009 for more explanation on the topic (go to 21m30s)




Other MVP implementations for GWT have been developed and released before Google released their own in GWT 2.2. Example gwtmvp. http://www.gwtmpv.org/index.html

Activities and Places

Introduction

As stated by the documentation https://developers.google.com/web-toolkit/doc/latest/DevGuideMvpActivitiesAndPlaces

The Activities and Places framework allows you to create bookmarkable URLs within your application.

So Activities and Places are a lot more than just an MVP framework. Nonetheless this framework has been build around the MVP pattern. The MVP part of this framework is represented by the Activity interface

public interface Activity {

  String mayStop();

  void onCancel();

  void onStop();

  void start(AcceptsOneWidget panel, EventBus eventBus);
}

Here you find the typical methods you will find in all MVP implementations.
start() : initialize some stuff in a start() like event registrations, add your view to the dom etc.
onStop() : clean some stuff (and memory) like event registrations etc.

Sometimes these methods are called bind() and unbind() in other MVP frameworks.

So an Activity is your Presenter. All your logic should be found there. This is the glue between your view (FlowPanel, AbsolutePanel etc...) and your model (your data).

Places & history workflow


So now let's take a look a the Activity Place framework in detail. To do so I just used the GWT Activity Place MVP tutorial code found here http://code.google.com/p/google-web-toolkit/downloads/detail?name=Tutorial-hellomvp-2.1.zip . I made it work with eclipse and launched the GWT application.

Then I entered the following url in my brower : http://127.0.0.1:8888/hellomvp.html?gwt.codesvr=127.0.0.1:9997#GoodbyePlace:World!

Here is what happened



A better version of the diagram focused on the second part




Once the application is launched, the PlaceHistoryHandler get the url token from the Historian. Then the PlaceHistoryHandler calls the PlaceHistoryMapper to get the Place corresponding to the url token. To do so the PlaceHistoryMapper calls the PlaceTokenizer.

Once it has the Place, the PlaceHistoryHandler ask the PlaceController to go to the new Place. It is a kind of redirection. The PlaceController simply sends a PlaceChangedEvent with the new Place wrapped inside.

The ActivityManager listen to this event and asks the ActivityMapper to give back the Activity corresponding to the Place. Then the ActivityManager starts the Activity.


@Override
public void start(AcceptsOneWidget containerWidget, EventBus eventBus)
{
    GoodbyeView goodbyeView = clientFactory.getGoodbyeView();
    goodbyeView.setName(name);
    containerWidget.setWidget(goodbyeView.asWidget());
}


At the end of the start method, the containerWidget (in this case the whole HTML page) set its widget to the new view.

Responsibilities


Here are the some of the main objects and their responsibilities

PlaceHistoryMapper : get a Place from a String (url token).
ActivityMapper : get an Activity from a Place.
ActivityManager : starts, stops the activities (it is the Master of Ceremony)

These are really the objects you want a look into if you want to change something in the frameworks like adding parameters to your urls ...

I think I will end there this article as it is long enough. I will probably detail some other things in other articles. Hope it helped !