Getting started with Ext-GWT: The Mail reference application
For this entry, being the first, I would like to help the Ext-GWT community (especially those newly introduced to the framework) grasp a firm understanding of the reference “Mail” application, specifically the MVC structure found in this app. I have found that understanding these reference applications (especially the MVC) goes a long way toward using the Ext-GWT framework in a manner for which it was intended.
Some pre-requisites
- Familiarity with the MVC design pattern
- Knowing how to put together a Google Web Toolkit application. See the GWT Documentation, as it is very good.
- Having downloaded the Ext-GWT (GXT) framework from Ext JS. I will be using the code from the gxt-1.1.3 release.
- A brief perusal of the GXT code base and mail application source code
Also, see the Ext-GWT documentation center for more details on setting up a project using the framework. Darrell Meyer, the lead developer for the framework, has put together some very good tutorials for setting up your workspace in Eclipse and what requirements are necessary for getting a project up and running.
Stepping through the source structure
Let’s get started by stepping through the source code to get an understanding of where everything is, what its role is, and finally, to transition us to the MVC discussion.
To see the actual source for the reference application, move to the root of the GXT distribution (we’ll call that GXT_HOME) and navigate to GXT_HOME/samples/mail. From there you can click into the ’src’ folder and see the directory structure for the app, com/extjs/gxt/samples/mail. You’ll notice that the structure follows the recommended GWT application structure.
com/extjs/gxt/samples/mail
/client/ /public/ /server/ /Mail.gwt.xml
You’ll find the GWT application Module XML file here. If you understand the GWT module XML document, what it does and why it’s used, you’ll see that for the mail reference application, there isn’t anything too complicated:
From line 2 we can see we inherit a GXT module named ‘Resources’. From line 4 we see that there is a GWT-RPC servlet defined for the path ‘/service’. Lastly, we can see from line 5 that our entry-point class is com.extjs.gxt.samples.mail.client.Mail.
/com/extjs/gxt/samples/mail/client
/model/ /mvc/ /widget/ /AppEvents.java /Mail.java /MailService.java /MailServiceAsync.java
This is the folder for our GWT/GXT client-side source. The GWT entry-point class, Mail.java, is here along with our GWT-RPC MailService (MailService.java and MailServiceAsync.java). There is also another class, AppEvents.java, that is used to enumerate the different application events that can be passed to our mvc controllers (discussed below).
/com/extjs/gxt/samples/mail/client/model
/MailModel.java
This is the only one model object defined for this application. Of course, in your applications, you will probably define quite a few more. I say defined because there are other client-side models used for this application: MailItem and Folder. These models are defined in the GXT Resources module (see the Mail.gwt.xml for how the Resources module is included).
The models described here, and used on the client side, should (in my opinion) be used only for client-side organizing of data structures (grids), forms, and other user-interface components (trees, tables, combo boxes, etc). These should not be the same domain objects used in your business-layer. GXT is a client-side, user-interface framework, and models defined for the client side should serve client-side purposes.
MailModel.java source code:
public class MailModel extends BaseTreeModel {
private Folder inbox;
private Folder sent;
private Folder trash;
public MailModel() {
inbox = new Folder("Inbox");
sent = new Folder("Sent Items");
trash = new Folder("Trash");
List items = TestData.getMailItems();
int count = items.size();
List inlist = new ArrayList();
List sentlist = new ArrayList();
for (int i = 0; i < count; i++) {
MailItem item = (MailItem) items.get(i);
if (i < (count / 2)) {
inlist.add(item);
} else {
sentlist.add(item);
}
}
inbox.set("children", inlist);
sent.set("children", sentlist);
trash.set("children", new ArrayList());
add(inbox);
add(sent);
add(trash);
}
...
}
If you take a look at the MailModel.java class, you’ll notice that its primary purpose is to model the mail part of the application (with Tasks and Contacts being the other parts). It has an inbox, sent, and trash folders. In this simplistic application, also notice that the mail items are being populated right here in the model, line 12, and that the inbox/sent folders are being populated with a simple for-loop line 18-25). This will most likely NOT be the case for your applications, as you’ll probably want to populate the models with some server-side data.
/com/extjs/gxt/samples/mail/client/mvc
/AppController.java /AppView.java /ContactController.java /ContactFolderView.java /ContactView.java /MailController.java /MailFolderView.java /MailView.java /TaskController.java /TaskFolderView.java /TaskView.java
You’ll find all of our MVC controllers and views in this folder. The AppController is the main controller responsible for setting up our entire app. I will go into more detail on this and the other controllers in the MVC section (below).
/com/extjs/gxt/samples/mail/client/widget
/ContactPanel.java /LoginDialog.java /MailItemPanel.java /MailListPanel.java /TaskPanel.java
This folder contains all of the application-specific widgets. As GXT is a framework, expect to extend and customize application-specific widgets as your application requires. For this app, the widgets that are used to organize the mail list (MailListPanel.java), display the contents of a mail item (MailItemPanel.java), display contacts, and display tasks are defined here. The LoginDialog widget is the widget you first see when logging in to the application.
Each of these widgets will be instantiated by the views responsible for displaying their respective data.
For the most part, these widgets are fairly simple. I will say a few things about the LoginDialog widget. The LoginDialog widget extends from the GXT class Dialog and expects a username/password (you can enter anything with at least 4 characters) and will allow you to login only after it has been validated (has at least 4 chars and the username has a value). You can see that this behavior is enabled from the source code of the LoginDialog.java widget:
public class LoginDialog extends Dialog {
...
public LoginDialog() {
...
KeyListener keyListener = new KeyListener() {
public void componentKeyUp(ComponentEvent event) {
validate();
}
};
...
}
protected void validate() {
login.setEnabled(hasValue(userName) && hasValue(password) && password.getValue().length() > 3);
}
...
}
Once you click the “Login” button, the “onSubmit” method will be called which runs a timer (to simulate a user logging in… again.. this is trivial because it’s a sample app. In your app, you can do your login logic here) and then hides the LoginDialog widget:
@Override
protected void createButtons() {
...
login = new Button("Login");
login.disable();
login.addSelectionListener(new SelectionListener() {
public void componentSelected(ButtonEvent ce) {
onSubmit();
}
});
...
}
...
protected void onSubmit() {
buttonBar.getStatusBar().showBusy("Please wait...");
buttonBar.disable();
Timer t = new Timer() {
@Override
public void run() {
LoginDialog.this.hide();
}
};
t.schedule(2000);
}
If you’re wondering how the LoginDialog widget gets displayed, it’s part of the MVC execution. See below.
Understanding the GXT Model-View-Controller
The main structure of the mail application is controlled by the GXT MVC implementation. The overview functionality is as follows: the dispatcher fires an application event (one of the events enumerated in /client/AppEvents.java) to all of the controllers. If the controller can handle that particular event, it does. If it can’t handle the event it doesn’t do anything. The controller is responsible for executing logic and updating any models. The views that are connected to these
controllers will update accordingly after a model is updated.
For all of this to happen, the dispatcher must register the controllers to which it can fire events. Going back to our /client/Mail.java entry-point class, the dispatcher is initialized and
the controllers are passed to it:
public class Mail implements EntryPoint {
public void onModuleLoad() {
...
Dispatcher dispatcher = Dispatcher.get();
dispatcher.addController(new AppController());
dispatcher.addController(new MailController());
dispatcher.addController(new TaskController());
dispatcher.addController(new ContactController());
...
}
}
At this point, we have the four controllers registered with the dispatcher. Now that the dispatcher has controllers, it can fire events to these controllers:
public class Mail implements EntryPoint {
public void onModuleLoad() {
...
dispatcher.dispatch(AppEvents.Login);
...
}
}
Again notice, the event we fire is derived from our AppEvents.java file; in this case we’re firing the ‘Login’ event.
Only controllers that can handle the ‘Login’ event will service this event. Which controllers are that? The ones that explicitly register for this event. In the case of the mail application, the AppController is the only controller that can handle ‘Login’ events. We can tell this by looking at the constructor for the AppController:
public class AppController extends Controller {
private AppView appView;
private MailServiceAsync service;
public AppController() {
registerEventTypes(AppEvents.Init);
registerEventTypes(AppEvents.Login);
registerEventTypes(AppEvents.Error);
}
...
}
You might want to be aware of what’s going on in the background: before the dispatcher queries a controller to determine whether it can handle a particular event, the dispatcher determines whether or not the controller is initialized. If it’s not initialized, the initialize() method will be called on the controller. Inside this method is where you want to put all logic associated with setting up the controller. See the example in the AppController.initialize() method:
public void initialize() {
appView = new AppView(this);
}
Although this initialization is trivial, it is called once when the controller is initialized, and is the suggested place to put all initialization code. Hopefully that explains the mysterious initialize() method in the Controller classes.
In this example, since the AppController can handle Login events, the event is passed to the controller’s handleEvent(AppEvent event) method. This is a method that must be implemented when extending the GXT Controller class. Inside the handleEvent method, you can determine what type of event occurred and deal with it accordingly:
public class AppController extends Controller {
...
public void handleEvent(AppEvent event) {
switch (event.type) {
case AppEvents.Init:
onInit(event);
break;
case AppEvents.Login:
onLogin(event);
break;
case AppEvents.Error:
onError(event);
break;
}
}
...
protected void onError(AppEvent ae) {
System.out.println("error: " + ae.data);
}
private void onInit(AppEvent event) {
forwardToView(appView, event);
service = (MailServiceAsync) Registry.get("service");
service.getMailFolders("darrell", new AsyncCallback() {
public void onFailure(Throwable caught) {
Dispatcher.forwardEvent(AppEvents.Error, caught);
}
public void onSuccess(Folder result) {
Dispatcher.forwardEvent(AppEvents.NavMail, result);
}
});
}
private void onLogin(AppEvent event) {
forwardToView(appView, event);
}
}
When the Login event is handled by the controller, it is processed and then forwarded to the appropriate view. This again is trivial for the sample app. In a more complicated app, processing of the models would occur here, and forwarding to the view would only be necessary for some specific view-only logic. In this case, the event is forwarded to the view, however, you might notice something from looking at the source: views also implement a handleEvent method, but the AppView class doesn’t seem to be able to handle Login events:
public class AppView extends View {
public AppView(Controller controller) {
super(controller);
}
...
protected void handleEvent(AppEvent event) {
switch (event.type) {
case AppEvents.Init:
initUI();
break;
}
}
}
What happened? Very similarly that the controllers have their initialize method called before they are available to handle any events, the Views are also initialized before they handle any events. This happens only once if the view is not initialized. Thus, in this case, the initialize() method on the AppView class was called before the Login event was forwarded. You can see in the initialize() method, the view sets up the LoginDialog panel before adding anything else to the screen. Firing the Login event really had the effect of only initializing the view. The view did not directly handle the event (although it could have):
public class AppView extends View {
...
protected void initialize() {
LoginDialog dialog = new LoginDialog();
dialog.setClosable(false);
dialog.addListener(Events.Hide, new Listener() {
public void handleEvent(WindowEvent be) {
Dispatcher.forwardEvent(AppEvents.Init);
}
});
dialog.show();
}
...
}
Notice that a framework listener for the Events.Hide framework event is added to the LoginDialog widget. That means when the dialog.hide() method is called (as it will be in the onSubmit method from the LoginDialog.java class), the Events.Hide event will fire and this listener will be called. Inside the listener you can see that once the login has taken place, a new event, Init will be fired by the dispatcher to its controllers. The process for querying the controllers and forwarding the event to the appropriate controller happens again. Notice the event is being fired with the Dispatcher.forwardEvent(AppEvent e) call instead of the Dispatcher.dispatch() method. They both accomplish the same task, but I believe the Dispatcher.forwardEvent is the recommended way to make calls to the dispatcher from within controllers or views.
When the Init event is fired, the controllers are again queried to determine which controllers can handle this event. In the mail app, all of the controllers can handle the Init event. In the AppController, the onInit() method gets called for an Init event, and this does two things: forwards the event to a view (which does all of the logic for instantiating the actual widgets) and calls a GWT-RPC service method to get the mail folders from the server. When the response is sent back from the server, a new event is fired: NavMail.
public class AppController extends Controller {
...
private void onInit(AppEvent event) {
forwardToView(appView, event);
service = (MailServiceAsync) Registry.get("service");
service.getMailFolders("darrell", new AsyncCallback() {
public void onFailure(Throwable caught) {
Dispatcher.forwardEvent(AppEvents.Error, caught);
}
public void onSuccess(Folder result) {
Dispatcher.forwardEvent(AppEvents.NavMail, result);
}
});
}
...
}
The NavMail event is fired along with a folder obeject. The controller/view that handles this event can use this folder as the default folder to expand
The AppView instantiating the widgets:
public class AppView extends View {
...
protected void handleEvent(AppEvent event) {
switch (event.type) {
case AppEvents.Init:
initUI();
break;
}
}
...
private void initUI() {
viewport = new Viewport();
viewport.setLayout(new BorderLayout());
createNorth();
createWest();
createCenter();
// registry serves as a global context
Registry.register("viewport", viewport);
Registry.register("west", west);
Registry.register("center", center);
RootPanel.get().add(viewport);
}
}
Additionally, note that the AppController is just one of the controllers that handles the Init event. The other controllers also handle the event, and set up their views and models accordingly.
When the NavMail event is fired, the only controller that can handle that event, the MailController, forwards it on to its two views: MailView and MailFolderView. MailView sets up the widgets to display the list of mail (MailListPanel) and the mail-item content (MailItemPanel); MailFolderView loads the mail items associated with the folder that was passed along with the event when the NavMail event is handled.
public class MailFolderView extends View {
...
protected void handleEvent(AppEvent event) {
switch (event.type) {
case AppEvents.Init:
initUI();
break;
}
if (event.type == AppEvents.NavMail) {
Folder f = (Folder) event.data;
if (f != null) {
loader.addListener(Loader.Load, new LoadListener() {
@Override
public void loaderLoad(LoadEvent le) {
loader.removeLoadListener(this);
}
});
loader.load(f);
}
}
}
...
}
Note that the reason you see the mail widgets and mail items when you login is because all of these events (Login, Init, NavMail, executed and the controllers and views worked as designed: the controllers handled the events, the views updated their widgets (or the widgets updated themselves).
If I have left something out, or you feel something should have been explained in more detail, please leave me a comment!
November 20th, 2008 at 6:35 am
Hi,
Thanks for your excellent article, it helped me get a better understanding of the mvc infrastrucutre in gxt. Something I could not figure out: Why are the widgets sometimes created in initialize() of the view (e.g. MailView) and sometimes in initUi() triggered by the INIT event (e.g. MailForlderView)?
And related to this: How can we be sure that when MailFolderView.initUi() gets executed the registry already contains the “center ” container (Registry.get(”center”) - since this container is registered in the initUI method of the AppView - both for the init event. Does it depend on the orders the controllers are added to the Dispatcher (which would be ugly)?
November 20th, 2008 at 5:49 pm
hi googelybear,
to answer your first question, there probably isn’t a very good reason. since this app is a trivial app, i’m guessing darrell either overlooked it, or, wanted to demonstrate that there are multiple ways (both fine) to instantiate widgets. In my opinion, the initialize() method should take care of any thing that is required to be in place before the controller/view is usable (the object itself, not the widgets). In many cases, it could be left blank, or not even in your code (as I believe the superclass implementation leaves it blank). Setting up your actual view widgets should probably be left to an application event (Init event), thus, put into a helper method such as initUI().
Concerning your second questions, the exact answer is that, yes,it depends on the order of the controllers; and yes, this is ugly lol… It may be better in some cases to NOT rely on the Registry… for example, after the AppController tells the AppView to initialize its widgets, it could fire an event (AfterInit for example) with the “center” widget as part of its data and then the controllers that can handle the “AfterInit” event would add their widgets to that. This is a simple example of avoiding that possibility of the “center” widget not being there, but I’m sure there are many other ways to do it too. Hope this helps!
November 25th, 2008 at 2:18 am
I find it a bit odd that the MailService interface is in the client package. Wouldn’t it make more sense to have it in the server package where the implementation also exists?
Wouldn’t it also make more sense that the MailModel would be created and returned to the client in the MailServiceImpl class?
November 26th, 2008 at 8:07 am
Yes, there are cases where it makes sense to have the service interface in the same package as the implementation. However, in this case, given GWT’s mechanism (deferred binding) for finding the GWT-RPC implementation, the service interface must be in a “source” path; putting the impl and interface classes in the same package means the impl class must also be on the “source” path and very often the impl class uses libraries that GWT cannot compile. Additionally, the “async” version of your interface must also be in the source path. See the GWT docs here for more info: http://code.google.com/docreader/#p=google-web-toolkit-doc-1-5&s=google-web-toolkit-doc-1-5&t=DevGuideCreatingServices
November 27th, 2008 at 8:15 am
this is really helpful!expecting more…such as how to intergrate spring or hibernate
November 27th, 2008 at 8:23 am
Kevin,
yep, that will definitely be an upcoming entry!
December 11th, 2008 at 3:58 pm
Many thanks for this excellent article. I have spent a week struggling with GXT due to lack of decent documentation and this has made things much clearer.
Any chance on something similar explaining how the whole grid, store, binding mechanism hangs together - I’m still really lost on that one!
December 16th, 2008 at 3:20 pm
Good job!
I would be grateful for explaining how to use MVC when my app consists of grids, stores, etc..
January 30th, 2009 at 9:24 am
Hello
I have read your article.It’s very good if you use MVC in gxt wants.
But I have a question?
I have a Crm Application. In this application, there are customers, suppliers, etc.
for example : In source
AppView.java, AppController.java, LoginDialog.java
CustomerController.java, CustomerListView.java, CustomerEditView.java. (for new Customer or edit Customer)
SupplierController.java, SupplierListView.java, SupplierEditView.java.
Of course, customers and suppliers have the same Actions New, Edit, Delete etc.
If you are in Customer New Event triggers are also suppliers New Event triggers?
How can the same events from all the ListViews only to use a ListView?
I just want CustomerController.New () does not trigger SupplierController.New().
Is that possible in Gxt-Mvc or should we Mvc own logic for this case to write?
And for the Application i need a Framework(Spring, JBoss Seam) or GWT + Gxt + Hibernate with Gwt- RPC enough?
Thanks,
January 30th, 2009 at 4:13 pm
deniz,
if i understand your question correctly, the answer would be to have separate event “types” for example: you would have CustomerController listen for “NewCustomer”, “EditCustomer” and “DeleteCustomer” while the SupplierController would listen for “NewSupplier”, “EditSupplier”.. and so on.
Does this make sense?
I believe the Ext-GWT team is working on a better event-system/mvc architecture for release 2.0. When it comes out, I’ll post an entry about it.
For the application, and whether to use a component framework (spring, seam, others), i guess it depends on what you’re trying to do. I highly recommend some sort of dependency injection framework (my preference is spring) at a minimum. I will be posting a spring/gwt integration article shortly!
hope this helps. let me know whether you have any more questions.
February 3rd, 2009 at 6:31 am
Thanks.You give me a best understanding of gxt mvc.I live in Shanghai,China.If you come here,please tell me and I will host you.
March 10th, 2009 at 7:18 am
Hi, thanks for a really helpful explanation of the GXT MVC framework! I am currently using a home made MVC implementation. What I am currently missing in the GXT MVC implementation, is the possibility to exchange multiple objects between View and Control, which my own implementation can do. It seems Dispatcher.forwardEvent() takes two parameters: 1. the event type and 2. the object you want to send with it. If I need to transfer, say, 3 objects, should I then create a wrapper object or use the registry?
March 17th, 2009 at 5:55 pm
[...] Unfortunately, GXT’s MVC doesn’t have much documentation. The good news is there is a good article that explained enough that I was able to refactor my project to use [...]
March 17th, 2009 at 5:56 pm
[...] As mentioned in Testing GWT Applications, GXT’s MVC doesn’t have much documentation. The best reference documentation seems to be Christian’s Getting started with Ext-GWT: The Mail reference application. [...]
March 27th, 2009 at 3:01 pm
[...] I discovered an overview of the GXT MVC classes, guided by the sample Mail application that comes with GXT. I didn’t even know that GXT [...]
May 19th, 2009 at 10:54 am
Thank you for the excellent walk through of the code.
I am looking at the MailServiceImpl piece of the puzzle. Is this sample code thread safe? My understanding is that instance variables will be shared by all threads calling this servlet. Does some trickery in the RemoteServiveServlet make this thread safe, or do you suppose this example gets away with it because it is using a single, simple set of test data?
Thanks again for the excellent article!
May 19th, 2009 at 12:40 pm
Yes, instance variables will be shared by all threads. There is nothing in RemoteServiceServlet that changes this behavior. RemoteServiceServlet is basically a Servlet + the GWT RPC Serialization/Deserialization. Yes, the sample might get away with being ‘thread-safe’ only because it’s using a very simple, hardcoded set of test data.
July 9th, 2009 at 9:26 pm
since now all the example on gxt is too simple
I hope some one to write a tutorial with a example to cover all topics
July 30th, 2009 at 10:32 am
Where is the mail sample application?? It does not seem to have made it into GXT 2.0.
There is the explorer sample but it does not have too much resemblance with the mail sample.
Is anybody trying to migrate it to GXT 2.0?
August 13th, 2009 at 8:14 am
Hi Christian,
first of all congratulation on your fabulous work.
I din’t see a link to download the example, is there anyone and i din’t see it??
i’m begining with gxt aplications and i’m not a professional java programmer, basically i need to understand how can I set the comunication between two widgets, for example a list and a grid, making the list (on selection event) change a filter on the grid’s store and reloading it.
finally, just forgive my poor english (i’m from Argentina).
again, congratulations for your work and for share all your knowledge.
August 17th, 2009 at 9:20 am
The mail application is (was) bundled with the source-code releases. I just downloaded the latest 1.2.x release and it’s in there. I didn’t put a link in the blog post because the links/versions changed so frequently.
You generally set listeners with the widgets and fire events to communicate, or the widgets both use the same store/collection of models to display the same information. The way you described it sounds fine.
August 30th, 2009 at 11:28 am
Hi Christian,
This is a great document for gxt starters. I had spent more than a month understanding gxt docs, but your explanation has reduced effort on me.
Can you also let me understand how to design a small web application or what to keep in mind while designing small application using gxt?
Any help is appreciated.
Regards,
Satya
September 4th, 2009 at 6:50 am
Thank you for the article. It helps me to undesrtand the MVC in GXT. Before this reading I only used “Store of models -> Binding -> Widget” idea and idea of “Registry” at client side. Some thing that confused me is absence of the “registryEventTypes” function description in JavaDoc of the 2.0.1 GXT.
Regards,
Mikhail
September 14th, 2009 at 10:40 pm
This is really nice article. It helped me lot to understand EXT-GWT, which i was struggling otherwise.
Thank you for the article.
September 16th, 2009 at 12:18 pm
[...] of helpful articles on the web, one is Matt’s GXT’s MVC Framework post and the other is Christian’s Getting started with Ext-GWT: The Mail reference application. However there is little from the GXT people themselves apart from the API documentation and a mail [...]
September 30th, 2009 at 12:43 am
Hello
thx for the document, helps me better to understand.
I was wondering, Is it also possible to use MVP instead of MVC
Is there a way to do this with GXT or do I use MCP4G together with GWT and GXT
thx Toine
November 5th, 2009 at 1:16 pm
[...] aplikacji od zera sprowadzało się tak na prawdę do skopiowania i przerobienia przykładu z Mail App. Podobnie jak Matt nigdy też nie wyłapałem różnicy między metodami Dispatcher.dispatch() oraz [...]
January 18th, 2010 at 3:21 am
Your blog is very useful.Thanks for the same.
But we are unable to run the mail example in eclipse environment.
It is giving error on following imports,
import com.extjs.gxt.samples.resources.client.model.Folder;
import com.extjs.gxt.samples.resources.client.model.MailItem;
We tried to add ‘resources’ folder through ‘build path’ but still error exist.
Please reply as soon as possible.
January 19th, 2010 at 7:54 am
zip up your project and send it to me, christian.posta@gmail.com
January 20th, 2010 at 5:04 am
Hi Christian,
Nice article..
I’m researching on how to apply the internal GXT MVC structure into a GXT desktop application. I started out integrating the Login dialog from the Maill application (using the MVC structure) into the GXT dekstop.
The login is already working and upon a successful login, the desktop and shortcuts are displayed. Now, I have some questions on how to move forward. I hope you can help me out by pointing me to the right direction.
1. I’m just starting out with GXT MVC, and the only guide I have on how to implement it is the GXT mail application sample. To integrate the MVC structure into a a web desktop app, I’m planning to make a Controller and a View that corresponds to a DEsktop Shortcut/window. IS this correct?
Ex: - My desktop has a shortcut/window called My Machines (A masterlist grid of all the machines, with all machine info and CRUD)
- MachineView -> Constructs the view (grid with CRUD on a window).
- MachineController -> Registers the ShowMachineWindow event. IF the event is dispatched, this controller displays the view MachineView. This structure is repeated for every shorcut/window in the dektop.
IS this how to go about it? OR am I doing it all wrong? I’m also thinking t just have a more generic main, shortcut and window controllers with coresponding views and not a 1 window-1 controller-1 view relationship…What’s the best way to do it? Thanks!
January 20th, 2010 at 7:14 am
Hi Kurt,
Yep, you’re on the correct path!
A generic main view/controller might work well as a parent class from which all the specific view/controllers descend.
The relationship between windows to views/controllers could be 1-1-1. You may find that some windows are so similar in functionality that a controller could be used for multiple views. Either way is acceptable. Good luck!
January 22nd, 2010 at 3:44 am
Thanks a lot Christian! I’ll start doing a generic view/controller for the windows first. Thanks again!
January 26th, 2010 at 11:41 pm
First off, thanks for a great article… extremely helpful in a GXT world without documentation! I’m trying to sift through the mail app example, along with this article, and have run into a mystery I can’t seem to resolve. Who’s instantiating the MailModel? Grep’ing the entire GXT 2.1.0 distro for ‘MailModel’ shows it appears in one file - MailModel.java. Can you please help me understand how the model is being created? Thanks!
March 9th, 2010 at 1:20 pm
Hi Christian! Could you suggest/post another GXT sample application along with explaination..
There’s still only the Mail Sample that is easily available and that can help in understanding GXT. If there was another example maybe much smaller but fully implemented it would be great for many…
Thanks for the post!
March 15th, 2010 at 10:54 pm
Thank Christian,
This article is very helpful for me, hope to see more article in GXT project with explanation.
April 3rd, 2010 at 2:23 am
Hi Christian
I am trying to setup the mail application, compile in Eclipse and then deploy in Tomcat. After doing this I just get a blank page when I navigate to the mail application. I.e. the widgets are not displayed. What do I need to check here?
April 4th, 2010 at 9:33 am
Does the mail app work for you in hosted mode?
June 29th, 2010 at 5:01 pm
Hello, this article is really helpful!
Sorry, but I have some questions for you.
I’d like to validate login using a db query on login db table and then I’d like to use a session bean method to manipulate other db tables.
GXT and GWT don’t support traditional connection and statements methods, so how can I operate with dbs?
Then this is what I think in abstract:
First of all db operations for login will be in LoginDialog.onSubmit method…then to show the correct user view, AppController needs to have textfield content.
Is something wrong?
Can you explain how can I execute these tasks?
Thank you a lot for your help!
June 29th, 2010 at 5:09 pm
jan,
you’re correct, as client-side purposed frameworks, gxt and gwt don’t support server-side operations. you should do all db work on the server and pass communication using either the gwt-provided server integration utilities or using servlets directly. check this article out to get started: http://code.google.com/webtoolkit/doc/1.6/FAQ_Server.html