You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by lr...@apache.org on 2009/02/11 22:29:49 UTC

svn commit: r743517 - in /incubator/shindig/trunk/java: common/src/main/java/org/apache/shindig/protocol/ common/src/test/java/org/apache/shindig/protocol/ social-api/src/test/java/org/apache/shindig/social/opensocial/service/

Author: lryan
Date: Wed Feb 11 21:29:49 2009
New Revision: 743517

URL: http://svn.apache.org/viewvc?rev=743517&view=rev
Log:
Add support for a cross-cutting handler execution listener. Useful for containers to do logging, request extensions

Added:
    incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/HandlerExecutionListener.java
Modified:
    incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DataServiceServlet.java
    incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DefaultHandlerRegistry.java
    incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java
    incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DataServiceServletTest.java
    incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DefaultHandlerRegistryTest.java
    incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java
    incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/ActivityHandlerTest.java
    incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/AppDataHandlerTest.java
    incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/PersonHandlerTest.java

Modified: incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DataServiceServlet.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DataServiceServlet.java?rev=743517&r1=743516&r2=743517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DataServiceServlet.java (original)
+++ incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DataServiceServlet.java Wed Feb 11 21:29:49 2009
@@ -99,17 +99,8 @@
       HttpServletResponse servletResponse, SecurityToken token,
       BeanConverter converter) throws IOException {
 
-    // TODO Rework to allow sub-services
-    String path = servletRequest.getPathInfo();
-
-    // TODO - This shouldnt be on BaseRequestItem
-    String method = servletRequest.getParameter(X_HTTP_METHOD_OVERRIDE);
-    if (method == null) {
-      method = servletRequest.getMethod();
-    }
-
     // Always returns a non-null handler.
-    RestHandler handler = dispatcher.getRestHandler(path, method.toUpperCase());
+    RestHandler handler = getRestHandler(servletRequest);
 
     Reader bodyReader = null;
     if (!servletRequest.getMethod().equals("GET") && !servletRequest.getMethod().equals("HEAD")) {
@@ -139,6 +130,19 @@
     }
   }
 
+  protected RestHandler getRestHandler(HttpServletRequest servletRequest) {
+    // TODO Rework to allow sub-services
+    String path = servletRequest.getPathInfo();
+
+    // TODO - This shouldnt be on BaseRequestItem
+    String method = servletRequest.getParameter(X_HTTP_METHOD_OVERRIDE);
+    if (method == null) {
+      method = servletRequest.getMethod();
+    }
+
+    // Always returns a non-null handler.
+    return dispatcher.getRestHandler(path, method.toUpperCase());
+  }
 
   BeanConverter getConverterForRequest(HttpServletRequest servletRequest) {
     String formatString = null;

Modified: incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DefaultHandlerRegistry.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DefaultHandlerRegistry.java?rev=743517&r1=743516&r2=743517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DefaultHandlerRegistry.java (original)
+++ incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/DefaultHandlerRegistry.java Wed Feb 11 21:29:49 2009
@@ -62,6 +62,7 @@
 
   private final Injector injector;
   private final BeanJsonConverter beanJsonConverter;
+  private final HandlerExecutionListener executionListener;
 
   /**
    * Creates a dispatcher with the specified handler classes
@@ -72,9 +73,11 @@
   @Inject
   public DefaultHandlerRegistry(Injector injector,
                                 @Named("org.apache.shindig.handlers")Set handlers,
-                                BeanJsonConverter beanJsonConverter) {
+                                BeanJsonConverter beanJsonConverter,
+                                HandlerExecutionListener executionListener) {
     this.injector = injector;
     this.beanJsonConverter = beanJsonConverter;
+    this.executionListener = executionListener;
     addHandlers(handlers.toArray());
   }
 
@@ -175,8 +178,13 @@
         Constructor reqItemConstructor =
             requestItemType.getConstructor(Map.class, SecurityToken.class, BeanConverter.class,
                 BeanJsonConverter.class);
+        String opName = m.getName();
+        if (!StringUtils.isEmpty(op.name())) {
+          opName = op.name();
+        }
         RestInvocationHandler restHandler = new RestInvocationHandler(service, op, m, handler,
-            beanJsonConverter, reqItemConstructor);
+            beanJsonConverter, reqItemConstructor,
+            new ExecutionListenerWrapper(service.name(), opName, executionListener));
         String serviceName = service.name();
 
         Map<String, SortedSet<RestPath>> methods = serviceMethodPathMap.get(serviceName);
@@ -221,14 +229,15 @@
             requestItemType.getConstructor(JSONObject.class, SecurityToken.class,
                 BeanConverter.class,
                 BeanJsonConverter.class);
-        RpcInvocationHandler rpcHandler =
-            new RpcInvocationHandler(m, handler, beanJsonConverter, reqItemConstructor);
-        String defaultName = service.name() + "." + m.getName();
+        String opName = m.getName();
         // Use the override if its defined
         if (op.name().length() > 0) {
-          defaultName = service.name() + "." + op.name();
+          opName = op.name();
         }
-        rpcOperations.put(defaultName, rpcHandler);
+        RpcInvocationHandler rpcHandler =
+            new RpcInvocationHandler(m, handler, beanJsonConverter, reqItemConstructor,
+                new ExecutionListenerWrapper(service.name(), opName, executionListener));
+        rpcOperations.put(service.name() + "." + opName, rpcHandler);
       }
     } catch (NoSuchMethodException nme) {
       logger.log(Level.INFO, "No RPC binding for " + service.name() + "." + m.getName());
@@ -236,6 +245,26 @@
   }
 
   /**
+   * Utility wrapper for the HandlerExecutionListener
+   */
+  private static class ExecutionListenerWrapper {
+    final String service;
+    final String operation;
+    final HandlerExecutionListener listener;
+
+    ExecutionListenerWrapper(String service, String operation,
+        HandlerExecutionListener listener) {
+      this.service = service;
+      this.operation = operation;
+      this.listener = listener;
+    }
+
+    private void executing(RequestItem req) {
+      listener.executing(service, operation, req);
+    }
+  }
+
+  /**
    * Proxy binding for an RPC operation. We allow binding to methods that
    * return non-Future types by wrapping them in ImmediateFuture.
    */
@@ -244,14 +273,17 @@
     Object handlerInstance;
     BeanJsonConverter beanJsonConverter;
     Constructor requestItemConstructor;
+    ExecutionListenerWrapper listener;
 
     private RpcInvocationHandler(Method receiver, Object handlerInstance,
                                  BeanJsonConverter beanJsonConverter,
-                                 Constructor reqItemConstructor) {
+                                 Constructor reqItemConstructor,
+                                 ExecutionListenerWrapper listener) {
       this.receiver = receiver;
       this.handlerInstance = handlerInstance;
       this.beanJsonConverter = beanJsonConverter;
       this.requestItemConstructor = reqItemConstructor;
+      this.listener = listener;
     }
 
     public Future execute(JSONObject rpc, SecurityToken token, BeanConverter converter) {
@@ -264,6 +296,7 @@
           item = (RequestItem) requestItemConstructor.newInstance(new JSONObject(), token,
               converter, beanJsonConverter);
         }
+        listener.executing(item);
         Object result = receiver.invoke(handlerInstance, item);
         if (result instanceof Future) {
           return (Future) result;
@@ -308,11 +341,13 @@
     final String[] expectedUrl;
     BeanJsonConverter beanJsonConverter;
     Constructor requestItemConstructor;
+    ExecutionListenerWrapper listener;
 
     private RestInvocationHandler(Service service, Operation operation,
                                   Method receiver, Object handlerInstance,
                                   BeanJsonConverter beanJsonConverter,
-                                  Constructor requestItemConstructor) {
+                                  Constructor requestItemConstructor,
+                                  ExecutionListenerWrapper listener) {
       this.service = service;
       this.operation = operation;
       this.receiver = receiver;
@@ -320,6 +355,7 @@
       expectedUrl = service.path().split("/");
       this.beanJsonConverter = beanJsonConverter;
       this.requestItemConstructor = requestItemConstructor;
+      this.listener = listener;
     }
 
     public Future<?> execute(Map<String, String[]> parameters, Reader body,
@@ -331,6 +367,7 @@
         }
         RequestItem item = (RequestItem) requestItemConstructor.newInstance(parameters, token,
             converter, beanJsonConverter);
+        listener.executing(item);
         Object result = receiver.invoke(handlerInstance, item);
         if (result instanceof Future) {
           return (Future) result;
@@ -489,6 +526,7 @@
       return new RestInvocationWrapper(parsedParams, handler);
     }
 
+
     /**
      * Rank based on the number of consant parts they accept, where the constant parts occur
      * and lexical ordering.

Added: incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/HandlerExecutionListener.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/HandlerExecutionListener.java?rev=743517&view=auto
==============================================================================
--- incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/HandlerExecutionListener.java (added)
+++ incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/HandlerExecutionListener.java Wed Feb 11 21:29:49 2009
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shindig.protocol;
+
+import com.google.inject.ImplementedBy;
+
+/**
+ * Called by the handler dispatcher prior to executing a handler. Used to allow
+ * containers to implement cross-cutting features such as request logging.
+ */
+@ImplementedBy(HandlerExecutionListener.NoOpHandlerExecutionListener.class)
+public interface HandlerExecutionListener {
+
+  /**
+   * Called prior to executing a REST or RPC handler
+   * @param service Name of the service being called
+   * @param operation Name of operation being called
+   * @param request being executed
+   */
+  void executing(String service, String operation, RequestItem request);
+
+  /**
+   * Default no-op implementation
+   */
+  public static class NoOpHandlerExecutionListener implements HandlerExecutionListener {
+
+    public void executing(String service, String operation, RequestItem request) {
+      // No-op
+    }
+  }
+}
+

Modified: incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java?rev=743517&r1=743516&r2=743517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java (original)
+++ incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/protocol/JsonRpcServlet.java Wed Feb 11 21:29:49 2009
@@ -100,7 +100,7 @@
     // into single requests.
     for (int i = 0; i < batch.length(); i++) {
       JSONObject batchObj = batch.getJSONObject(i);
-      responses.add(dispatcher.getRpcHandler(batchObj).execute(token, jsonConverter));
+      responses.add(getHandler(batchObj, servletRequest).execute(token, jsonConverter));
     }
 
     // Resolve each Future into a response.
@@ -125,7 +125,7 @@
     }
 
     // getRpcHandler never returns null
-    Future future = dispatcher.getRpcHandler(request).execute(token, jsonConverter);
+    Future future = getHandler(request, servletRequest).execute(token, jsonConverter);
 
     // Resolve each Future into a response.
     // TODO: should use shared deadline across each request
@@ -134,6 +134,14 @@
     servletResponse.getWriter().write(result.toString());
   }
 
+  /**
+   * Wrap call to dispatcher to allow for implementation specific overrides
+   * and servlet-request contextual handling
+   */
+  protected RpcHandler getHandler(JSONObject rpc, HttpServletRequest request) {
+    return dispatcher.getRpcHandler(rpc);
+  }
+
   private JSONObject getJSONResponse(String key, ResponseItem responseItem) throws JSONException {
     JSONObject result = new JSONObject();
     if (key != null) {

Modified: incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DataServiceServletTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DataServiceServletTest.java?rev=743517&r1=743516&r2=743517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DataServiceServletTest.java (original)
+++ incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DataServiceServletTest.java Wed Feb 11 21:29:49 2009
@@ -73,7 +73,8 @@
     EasyMock.expect(atomConverter.getContentType()).andReturn("application/atom+xml").anyTimes();
 
     HandlerRegistry registry = new DefaultHandlerRegistry(null,
-        Sets.newHashSet(new TestHandler()), jsonConverter);
+        Sets.newHashSet(new TestHandler()), jsonConverter,
+        new HandlerExecutionListener.NoOpHandlerExecutionListener());
 
     servlet.setHandlerRegistry(registry);
 

Modified: incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DefaultHandlerRegistryTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DefaultHandlerRegistryTest.java?rev=743517&r1=743516&r2=743517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DefaultHandlerRegistryTest.java (original)
+++ incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/DefaultHandlerRegistryTest.java Wed Feb 11 21:29:49 2009
@@ -45,7 +45,8 @@
   protected void setUp() throws Exception {
     super.setUp();
     registry = new DefaultHandlerRegistry(null,
-        Sets.newHashSet(new TestHandler()), null);
+        Sets.newHashSet(new TestHandler()), null,
+        new HandlerExecutionListener.NoOpHandlerExecutionListener());
   }
 
   public void testGetHandlerRPC() throws Exception {

Modified: incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java?rev=743517&r1=743516&r2=743517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java (original)
+++ incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/protocol/JsonRpcServletTest.java Wed Feb 11 21:29:49 2009
@@ -68,7 +68,8 @@
     atomConverter = mockControl.createMock(BeanConverter.class);
 
     HandlerRegistry registry = new DefaultHandlerRegistry(null,
-        Sets.newHashSet(new TestHandler()), jsonConverter);
+        Sets.newHashSet(new TestHandler()), jsonConverter,
+        new HandlerExecutionListener.NoOpHandlerExecutionListener());
 
     servlet.setHandlerRegistry(registry);
     servlet.setBeanConverters(jsonConverter, xmlConverter, atomConverter);

Modified: incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/ActivityHandlerTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/ActivityHandlerTest.java?rev=743517&r1=743516&r2=743517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/ActivityHandlerTest.java (original)
+++ incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/ActivityHandlerTest.java Wed Feb 11 21:29:49 2009
@@ -24,6 +24,7 @@
 import org.apache.shindig.config.JsonContainerConfig;
 import org.apache.shindig.expressions.Expressions;
 import org.apache.shindig.protocol.DefaultHandlerRegistry;
+import org.apache.shindig.protocol.HandlerExecutionListener;
 import org.apache.shindig.protocol.HandlerRegistry;
 import org.apache.shindig.protocol.RestHandler;
 import org.apache.shindig.protocol.RestfulCollection;
@@ -81,7 +82,8 @@
 
     containerConfig = new JsonContainerConfig(config, new Expressions());
     handler = new ActivityHandler(activityService, containerConfig);
-    registry = new DefaultHandlerRegistry(null, Sets.newHashSet(handler), converter);
+    registry = new DefaultHandlerRegistry(null, Sets.newHashSet(handler), converter,
+        new HandlerExecutionListener.NoOpHandlerExecutionListener());
   }
 
   private void assertHandleGetForGroup(GroupId.Type group) throws Exception {

Modified: incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/AppDataHandlerTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/AppDataHandlerTest.java?rev=743517&r1=743516&r2=743517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/AppDataHandlerTest.java (original)
+++ incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/AppDataHandlerTest.java Wed Feb 11 21:29:49 2009
@@ -22,6 +22,7 @@
 import org.apache.shindig.common.util.ImmediateFuture;
 import org.apache.shindig.protocol.DataCollection;
 import org.apache.shindig.protocol.DefaultHandlerRegistry;
+import org.apache.shindig.protocol.HandlerExecutionListener;
 import org.apache.shindig.protocol.HandlerRegistry;
 import org.apache.shindig.protocol.ResponseError;
 import org.apache.shindig.protocol.RestHandler;
@@ -67,7 +68,8 @@
     converter = mock(BeanJsonConverter.class);
     appDataService = mock(AppDataService.class);
     AppDataHandler handler = new AppDataHandler(appDataService);
-    registry = new DefaultHandlerRegistry(null, Sets.newHashSet(handler), converter);
+    registry = new DefaultHandlerRegistry(null, Sets.newHashSet(handler), converter,
+        new HandlerExecutionListener.NoOpHandlerExecutionListener());
   }
 
   private void assertHandleGetForGroup(GroupId.Type group) throws Exception {

Modified: incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/PersonHandlerTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/PersonHandlerTest.java?rev=743517&r1=743516&r2=743517&view=diff
==============================================================================
--- incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/PersonHandlerTest.java (original)
+++ incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/service/PersonHandlerTest.java Wed Feb 11 21:29:49 2009
@@ -24,6 +24,7 @@
 import org.apache.shindig.config.JsonContainerConfig;
 import org.apache.shindig.expressions.Expressions;
 import org.apache.shindig.protocol.DefaultHandlerRegistry;
+import org.apache.shindig.protocol.HandlerExecutionListener;
 import org.apache.shindig.protocol.HandlerRegistry;
 import org.apache.shindig.protocol.RestHandler;
 import org.apache.shindig.protocol.RestfulCollection;
@@ -89,7 +90,8 @@
 
     containerConfig = new JsonContainerConfig(config, new Expressions());
     handler = new PersonHandler(personService, containerConfig);
-    registry = new DefaultHandlerRegistry(null, Sets.newHashSet(handler), converter);
+    registry = new DefaultHandlerRegistry(null, Sets.newHashSet(handler), converter,
+        new HandlerExecutionListener.NoOpHandlerExecutionListener());
   }
 
   public void testHandleGetAllNoParams() throws Exception {