Author: manolo
Date: Tue May  8 09:40:06 2012
New Revision: 1335396

URL: http://svn.apache.org/viewvc?rev=1335396&view=rev
Log:
Some cache improvements in client side. Fix parallel fetching of messages on 
loading

Modified:
    
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/CachingDispatchAsync.java
    
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/gin/HupaClientModule.java
    
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/gin/HupaGinjector.java
    
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListPresenter.java
    
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListView.java
    
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java
    
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageTableModel.java
    
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessageListPresenterPlace.java

Modified: 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/CachingDispatchAsync.java
URL: 
http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/CachingDispatchAsync.java?rev=1335396&r1=1335395&r2=1335396&view=diff
==============================================================================
--- 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/CachingDispatchAsync.java
 (original)
+++ 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/CachingDispatchAsync.java
 Tue May  8 09:40:06 2012
@@ -20,64 +20,112 @@
 package org.apache.hupa.client;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.google.inject.Inject;
+import org.apache.hupa.shared.rpc.GetMessageDetails;
 
-import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.dispatch.client.ExceptionHandler;
+import net.customware.gwt.dispatch.client.standard.StandardDispatchAsync;
 import net.customware.gwt.dispatch.shared.Action;
 import net.customware.gwt.dispatch.shared.Result;
 
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.inject.Inject;
+
 /**
- * Dispatcher which support caching of data in memory
+ * Dispatcher which support caching of data in memory.
+ * 
+ * It also avoids simultaneous executions of the same action, which 
+ * is very useful in development.
  * 
  */
-public class CachingDispatchAsync implements DispatchAsync {
-
-    private DispatchAsync dispatcher;
-    private Map<Action<Result>, Result> cache = new HashMap<Action<Result>, 
Result>();
+public class CachingDispatchAsync extends StandardDispatchAsync {
 
+    
     @Inject
-    public CachingDispatchAsync(DispatchAsync dispatcher) {
-        this.dispatcher = dispatcher;
+    public CachingDispatchAsync(ExceptionHandler exceptionHandler) {
+        super(exceptionHandler);
     }
 
-    /*
-     * (non-Javadoc)
-     * @see net.customware.gwt.dispatch.client.DispatchAsync#execute(A, 
com.google.gwt.user.client.rpc.AsyncCallback)
-     */
+    private Map<Action<Result>, Result> cache = new HashMap<Action<Result>, 
Result>();
+    
+    private HashSet<Class<?>> running = new HashSet<Class<?>>();
+
+    @Override
     public <A extends Action<R>, R extends Result> void execute(final A action,
             final AsyncCallback<R> callback) {
-        dispatcher.execute(action, callback);
+        
+        if (action instanceof GetMessageDetails) {
+            executeWithCache(action, callback);
+        } else {
+            if (GWT.isProdMode()) {
+                super.execute(action, callback);
+            } else {
+                executeOneRequestPerAction(action, callback);
+            }
+        }
+    }
+    
+    /**
+     * Avoid parallel executions of the same action
+     */
+    public <A extends Action<R>, R extends Result> void 
executeOneRequestPerAction (
+            final A action, final AsyncCallback<R> callback) {
+
+        final Class<?> clz = action.getClass();
+        if (running.contains(clz)) {
+            System.err.println("ATTENTION: avoiding a parallel execution of 
the action: " + action.getClass().getName());
+            new RuntimeException().printStackTrace();
+            
+            return;
+        } else {
+            running.add(clz);
+            super.execute(action, new AsyncCallback<R>() {
+                public void onFailure(Throwable caught) {
+                    running.remove(clz);
+                    callback.onFailure(caught);
+                }
+                public void onSuccess(final R result) {
+                    running.remove(clz);
+                    callback.onSuccess(result);
+                }
+            });
+         }
     }
 
     /**
-     * Execute the give Action. If the Action was executed before it will get 
fetched from the cache
-     * 
-     * @param <A> Action implementation
-     * @param <R> Result implementation
-     * @param action the action
-     * @param callback the callback
+     * If the Action was executed before it will get fetched from the cache
      */
     @SuppressWarnings("unchecked")
     public <A extends Action<R>, R extends Result> void executeWithCache(
             final A action, final AsyncCallback<R> callback) {
         Result r = cache.get(action);
+
+        final Class<?> clz = action.getClass();
+        if (running.contains(clz)) {
+            System.out.println("Contanins " + clz);
+            return;
+        } else {
+            System.out.println("new " + clz);
+            running.add(clz);
+        }
+        
         if (r != null) {
             callback.onSuccess((R) r);
         } else {
-            dispatcher.execute(action, new AsyncCallback<R>() {
-
+            super.execute(action, new AsyncCallback<R>() {
                 public void onFailure(Throwable caught) {
+                    running.remove(clz);
                     callback.onFailure(caught);
                 }
 
                 public void onSuccess(R result) {
+                    running.remove(clz);
                     cache.put((Action<Result>) action, (Result) result);
                     callback.onSuccess(result);
                 }
-
             });
         }
     }

Modified: 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/gin/HupaClientModule.java
URL: 
http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/gin/HupaClientModule.java?rev=1335396&r1=1335395&r2=1335396&view=diff
==============================================================================
--- 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/gin/HupaClientModule.java
 (original)
+++ 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/gin/HupaClientModule.java
 Tue May  8 09:40:06 2012
@@ -19,6 +19,9 @@
 
 package org.apache.hupa.client.gin;
 
+import net.customware.gwt.dispatch.client.DefaultExceptionHandler;
+import net.customware.gwt.dispatch.client.DispatchAsync;
+import net.customware.gwt.dispatch.client.ExceptionHandler;
 import net.customware.gwt.presenter.client.DefaultEventBus;
 import net.customware.gwt.presenter.client.EventBus;
 import net.customware.gwt.presenter.client.gin.AbstractPresenterModule;
@@ -53,6 +56,7 @@ import org.apache.hupa.client.rf.HupaReq
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.shared.SimpleEventBus;
 import com.google.inject.Provider;
+import com.google.inject.Provides;
 import com.google.inject.Singleton;
 
 public class HupaClientModule extends AbstractPresenterModule {
@@ -69,22 +73,35 @@ public class HupaClientModule extends Ab
         bindPresenter(MessageSendPresenter.class, 
MessageSendPresenter.Display.class, MessageSendView.class);
         bindPresenter(AppPresenter.class, AppPresenter.Display.class, 
AppView.class);
         bindPresenter(ContactsPresenter.class, 
ContactsPresenter.Display.class, ContactsView.class);
-        bind(CachingDispatchAsync.class);
         bind(PagingScrollTableRowDragController.class).in(Singleton.class);
         bind(MessageTableModel.class).in(Singleton.class);
         bind(LoginPresenterPlace.class).in(Singleton.class);
         bind(IMAPMessageListPresenterPlace.class).in(Singleton.class);
         bind(MessageSendPresenterPlace.class).in(Singleton.class);
         bind(ContactsPresenterPlace.class).in(Singleton.class);
+
+        // Used by dispatch. Note that GWT 2.4 has its own ExceptionHandler 
etc in other namespace
+        bind(ExceptionHandler.class).to(DefaultExceptionHandler.class);
         
+        // RF Stuff, Eventbus has a different namespace than gwt-dispatch
         bind(com.google.gwt.event.shared.EventBus.class)
             .to(SimpleEventBus.class)
             .in(Singleton.class);
         bind(HupaRequestFactory.class)
             .toProvider(HupaClientModule.RequestFactoryProvider.class)
             .in(Singleton.class);
+
+    }
+    
+    @Provides
+    @Singleton
+    protected DispatchAsync provideDispatchAsync(ExceptionHandler 
exceptionHandler) {
+        return new CachingDispatchAsync( exceptionHandler );
     }
     
+    /**
+     * RF Stuff 
+     */
     public static class RequestFactoryProvider implements 
Provider<HupaRequestFactory> {
         private static final com.google.gwt.event.shared.EventBus eventBus = 
new SimpleEventBus();
         public HupaRequestFactory get() {

Modified: 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/gin/HupaGinjector.java
URL: 
http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/gin/HupaGinjector.java?rev=1335396&r1=1335395&r2=1335396&view=diff
==============================================================================
--- 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/gin/HupaGinjector.java
 (original)
+++ 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/gin/HupaGinjector.java
 Tue May  8 09:40:06 2012
@@ -28,7 +28,7 @@ import org.apache.hupa.client.rf.HupaReq
 import com.google.gwt.inject.client.GinModules;
 import com.google.gwt.inject.client.Ginjector;
 
-@GinModules({StandardDispatchModule.class,HupaClientModule.class})
+@GinModules({/*StandardDispatchModule.class,*/ HupaClientModule.class})
 public interface HupaGinjector extends Ginjector {
     AppPresenter getAppPresenter();
     PlaceManager getPlaceManager();

Modified: 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListPresenter.java
URL: 
http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListPresenter.java?rev=1335396&r1=1335395&r2=1335396&view=diff
==============================================================================
--- 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListPresenter.java
 (original)
+++ 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListPresenter.java
 Tue May  8 09:40:06 2012
@@ -404,20 +404,28 @@ public class IMAPMessageListPresenter ex
 
     @Override
     protected void onRevealDisplay() {
-        display.reloadData();  
+        if (user != null && folder != null) {
+            display.reloadData();  
+        }
     }
     
     public void revealDisplay(User user, IMAPFolder folder, String 
searchValue) {
         this.user = user;
        
-        if (this.folder == null || 
this.folder.getFullName().equals(folder.getFullName()) == false 
-                || (searchValue == null && this.searchValue != null) || 
(searchValue != null && searchValue.equals(this.searchValue) == false)) {
+        if (this.user == null 
+            || !this.user.getName().equals(user.getName()) 
+            || this.folder == null 
+            || !this.folder.getFullName().equals(folder.getFullName()) 
+            || (searchValue == null && this.searchValue != null) 
+            || (searchValue != null && searchValue.equals(this.searchValue) == 
false)) {
             display.reset();
             display.deselectAllMessages();
         }
         display.setExpandLoading(false);
         this.searchValue = searchValue;
         this.folder = folder;
+        
+
         revealDisplay();
     }
 

Modified: 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListView.java
URL: 
http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListView.java?rev=1335396&r1=1335395&r2=1335396&view=diff
==============================================================================
--- 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListView.java
 (original)
+++ 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/IMAPMessageListView.java
 Tue May  8 09:40:06 2012
@@ -474,7 +474,7 @@ public class IMAPMessageListView extends
         pageBox.setSelectedIndex(0);
         cTableModel.clearCache();
         cTableModel.setRowCount(CachedTableModel.UNKNOWN_ROW_COUNT);
-        mailTable.gotoFirstPage();
+//        mailTable.gotoFirstPage();
     }
 
     /*

Modified: 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java
URL: 
http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java?rev=1335396&r1=1335395&r2=1335396&view=diff
==============================================================================
--- 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java
 (original)
+++ 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MainPresenter.java
 Tue May  8 09:40:06 2012
@@ -24,20 +24,20 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
+import net.customware.gwt.dispatch.client.DispatchAsync;
 import net.customware.gwt.presenter.client.EventBus;
 import net.customware.gwt.presenter.client.widget.WidgetContainerDisplay;
 import net.customware.gwt.presenter.client.widget.WidgetContainerPresenter;
 
-import org.apache.hupa.client.CachingDispatchAsync;
 import org.apache.hupa.client.HupaCallback;
 import org.apache.hupa.client.mvp.MessageSendPresenter.Type;
 import org.apache.hupa.client.widgets.HasDialog;
 import org.apache.hupa.client.widgets.IMAPTreeItem;
 import org.apache.hupa.shared.data.IMAPFolder;
 import org.apache.hupa.shared.data.Message;
+import org.apache.hupa.shared.data.Message.IMAPFlag;
 import org.apache.hupa.shared.data.MessageDetails;
 import org.apache.hupa.shared.data.User;
-import org.apache.hupa.shared.data.Message.IMAPFlag;
 import org.apache.hupa.shared.events.BackEvent;
 import org.apache.hupa.shared.events.BackEventHandler;
 import org.apache.hupa.shared.events.DecreaseUnseenEvent;
@@ -129,7 +129,7 @@ public class MainPresenter extends Widge
 
     }
 
-    private CachingDispatchAsync cachingDispatcher;
+    private DispatchAsync dispatcher;
     private User user;
     private IMAPFolder folder;
     private String searchValue;
@@ -140,10 +140,10 @@ public class MainPresenter extends Widge
     private HasEditable editableTreeItem;
     
     @Inject
-    public MainPresenter(MainPresenter.Display display, EventBus bus, 
CachingDispatchAsync cachingDispatcher, IMAPMessageListPresenter 
messageListPresenter, IMAPMessagePresenter messagePresenter,
+    public MainPresenter(MainPresenter.Display display, EventBus bus, 
DispatchAsync cachingDispatcher, IMAPMessageListPresenter messageListPresenter, 
IMAPMessagePresenter messagePresenter,
             MessageSendPresenter sendPresenter) {
         super(display, bus, messageListPresenter, messagePresenter, 
sendPresenter);
-        this.cachingDispatcher = cachingDispatcher;
+        this.dispatcher = cachingDispatcher;
         this.messageListPresenter = messageListPresenter;
         this.messagePresenter = messagePresenter;
         this.sendPresenter = sendPresenter;
@@ -152,7 +152,7 @@ public class MainPresenter extends Widge
 
     protected void loadTreeItems() {
         display.setLoadingFolders(true);
-        cachingDispatcher.execute(new FetchFolders(), new 
HupaCallback<FetchFoldersResult>(cachingDispatcher, eventBus, display) {
+        dispatcher.execute(new FetchFolders(), new 
HupaCallback<FetchFoldersResult>(dispatcher, eventBus, display) {
             public void callback(FetchFoldersResult result) {
                 display.bindTreeItems(createTreeNodes(result.getFolders()));
                 // disable
@@ -183,7 +183,7 @@ public class MainPresenter extends Widge
                         IMAPFolder iFolder = new IMAPFolder((String) 
event.getOldValue());
                         final String newName = (String) event.getNewValue();
                         if (iFolder.getFullName().equalsIgnoreCase(newName) == 
false) {
-                            cachingDispatcher.execute(new 
RenameFolder(iFolder, newName), new 
HupaCallback<GenericResult>(cachingDispatcher, eventBus) {
+                            dispatcher.execute(new RenameFolder(iFolder, 
newName), new HupaCallback<GenericResult>(dispatcher, eventBus) {
                                 public void callback(GenericResult result) {
                                     folder.setFullName(newName);
                                 }
@@ -255,14 +255,6 @@ public class MainPresenter extends Widge
         sendPresenter.revealDisplay();
     }
 
-    /**
-     * Reset the presenter and display
-     */
-    private void reset() {
-        // clear the cache
-        cachingDispatcher.clear();
-    }
-
 
     @Override
     protected void onBind() {
@@ -289,7 +281,7 @@ public class MainPresenter extends Widge
                 }
 
                 display.setLoadingMessage(true);
-                cachingDispatcher.executeWithCache(new 
GetMessageDetails(event.getFolder(), message.getUid()), new 
HupaCallback<GetMessageDetailsResult>(cachingDispatcher, eventBus, display) {
+                dispatcher.execute(new GetMessageDetails(event.getFolder(), 
message.getUid()), new HupaCallback<GetMessageDetailsResult>(dispatcher, 
eventBus, display) {
                     public void callback(GetMessageDetailsResult result) {
                         if (decreaseUnseen) {
                             eventBus.fireEvent(new DecreaseUnseenEvent(user, 
folder));
@@ -430,7 +422,7 @@ public class MainPresenter extends Widge
         registerHandler(display.getDeleteConfirmClick().addClickHandler(new 
ClickHandler() {
 
             public void onClick(ClickEvent event) {
-                cachingDispatcher.execute(new DeleteFolder(folder), new 
AsyncCallback<GenericResult>() {
+                dispatcher.execute(new DeleteFolder(folder), new 
AsyncCallback<GenericResult>() {
 
                     public void onFailure(Throwable caught) {
                         GWT.log("ERROR while deleting", caught);
@@ -454,7 +446,7 @@ public class MainPresenter extends Widge
                         final IMAPTreeItem item = (IMAPTreeItem) 
event.getSource();
                         final String newValue = (String) event.getNewValue();
                         if 
(event.getEventType().equals(EditEvent.EventType.Stop)) {
-                            cachingDispatcher.execute(new CreateFolder(new 
IMAPFolder(newValue.trim())), new AsyncCallback<GenericResult>() {
+                            dispatcher.execute(new CreateFolder(new 
IMAPFolder(newValue.trim())), new AsyncCallback<GenericResult>() {
 
                                 public void onFailure(Throwable caught) {
                                     GWT.log("Error while create folder", 
caught);
@@ -487,8 +479,9 @@ public class MainPresenter extends Widge
 
             public void onLogin(LoginEvent event) {
                 user = event.getUser();
-                folder = new 
IMAPFolder(user.getSettings().getInboxFolderName());
-                messageListPresenter.revealDisplay(user, folder, null);
+                folder = new 
IMAPFolder(user.getSettings().getInboxFolderName());;
+                searchValue = null;
+                showMessageTable(user, folder, searchValue);
             }
             
         }));
@@ -498,15 +491,6 @@ public class MainPresenter extends Widge
 
     }
 
-
-    @Override
-    protected void onUnbind() {
-        reset();
-
-        super.onUnbind();
-    }
-
-    
     public void revealDisplay(User user) {
         this.user = user;
         loadTreeItems();  
@@ -515,8 +499,8 @@ public class MainPresenter extends Widge
     
     @Override
     protected void onRevealDisplay() {
-        showMessageTable(user, folder, searchValue);
-        super.onRevealDisplay();
+//        showMessageTable(user, folder, searchValue);
+//        super.onRevealDisplay();
     }
     
     public void openLink(String url) {

Modified: 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageTableModel.java
URL: 
http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageTableModel.java?rev=1335396&r1=1335395&r2=1335396&view=diff
==============================================================================
--- 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageTableModel.java
 (original)
+++ 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/MessageTableModel.java
 Tue May  8 09:40:06 2012
@@ -122,9 +122,9 @@ public class MessageTableModel extends M
                 // Update folder information before notifying presenter
                 folder.setMessageCount(result.getRealCount());
                 folder.setUnseenMessageCount(result.getRealUnreadCount());
-                // Notify presenter to update folder tree view
-                eventBus.fireEvent(new MessagesReceivedEvent(folder, 
result.getMessages()));
-                TableModelHelper.Response<Message> response = new 
TableModelHelper.Response<Message>() {
+                
+                setRowCount(result.getRealCount());
+                callback.onRowsReady(request, new 
TableModelHelper.Response<Message>() {
                     @Override
                     public Iterator<Message> getRowValues() {
                         if (result != null && result.getMessages() != null) {
@@ -133,9 +133,10 @@ public class MessageTableModel extends M
                             return new ArrayList<Message>().iterator();
                         }
                     }
-                };
-                setRowCount(result.getRealCount());
-                callback.onRowsReady(request,response);
+                });
+                
+                // Notify presenter to update folder tree view
+                eventBus.fireEvent(new MessagesReceivedEvent(folder, 
result.getMessages()));
             }
         }); 
     }

Modified: 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessageListPresenterPlace.java
URL: 
http://svn.apache.org/viewvc/james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessageListPresenterPlace.java?rev=1335396&r1=1335395&r2=1335396&view=diff
==============================================================================
--- 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessageListPresenterPlace.java
 (original)
+++ 
james/hupa/trunk/client/src/main/java/org/apache/hupa/client/mvp/place/IMAPMessageListPresenterPlace.java
 Tue May  8 09:40:06 2012
@@ -55,7 +55,6 @@ public class IMAPMessageListPresenterPla
         } catch (NumberFormatException e) {
             // ignore
         }
-        presenter.getDisplay().goToPage(page);
         
         int rowsPerPageIndex = 0;
         try {
@@ -70,8 +69,9 @@ public class IMAPMessageListPresenterPla
         String searchValue = request.getParameter(SEARCH, "");
         presenter.getDisplay().getSearchValue().setValue(searchValue);
         
+        presenter.getDisplay().goToPage(page);
+        
         GWT.log("PRES="+request.toString(),null);
-
     }
 
     @Override



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to