diff --git a/gwtp-core/gwtp-dispatch-server-guice/pom.xml b/gwtp-core/gwtp-dispatch-server-guice/pom.xml
index 213d012605..2d8d4294cc 100644
--- a/gwtp-core/gwtp-dispatch-server-guice/pom.xml
+++ b/gwtp-core/gwtp-dispatch-server-guice/pom.xml
@@ -34,6 +34,10 @@
com.gwtplatform
gwtp-dispatch-test
test
-
-
-
\ No newline at end of file
+
+
+ org.jukito
+ jukito
+
+
+
diff --git a/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionExceptionThrownByHandler.java b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionExceptionThrownByHandler.java
new file mode 100644
index 0000000000..96610f5e07
--- /dev/null
+++ b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionExceptionThrownByHandler.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright 2011 ArcBees Inc.
+ *
+ * Licensed 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 com.gwtplatform.dispatch.server;
+
+import com.gwtplatform.dispatch.shared.ActionException;
+
+public class ActionExceptionThrownByHandler extends ActionException {
+ public ActionExceptionThrownByHandler(Throwable cause) {
+ super("", cause);
+ }
+}
diff --git a/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionExceptionThrownByValidator.java b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionExceptionThrownByValidator.java
new file mode 100644
index 0000000000..f82d2be8bc
--- /dev/null
+++ b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionExceptionThrownByValidator.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright 2011 ArcBees Inc.
+ *
+ * Licensed 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 com.gwtplatform.dispatch.server;
+
+import com.gwtplatform.dispatch.shared.ActionException;
+
+public class ActionExceptionThrownByValidator extends ActionException {
+ public ActionExceptionThrownByValidator(Throwable cause) {
+ super("", cause);
+ }
+}
diff --git a/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionThrownByHandlerTest.java b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionThrownByHandlerTest.java
new file mode 100644
index 0000000000..f608ad3ae2
--- /dev/null
+++ b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionThrownByHandlerTest.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright 2011 ArcBees Inc.
+ *
+ * Licensed 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 com.gwtplatform.dispatch.server;
+
+import javax.inject.Inject;
+
+import org.jukito.JukitoModule;
+import org.jukito.JukitoRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.gwtplatform.dispatch.server.guice.DispatchServiceImpl;
+import com.gwtplatform.dispatch.server.guice.actionvalidator.DefaultActionValidator;
+import com.gwtplatform.dispatch.shared.ActionException;
+import com.gwtplatform.dispatch.shared.ServiceException;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@RunWith(JukitoRunner.class)
+public class ActionThrownByHandlerTest {
+ public static class MyModule extends JukitoModule {
+ @Override
+ protected void configureTest() {
+ install(new ServiceModule(DefaultActionValidator.class));
+ }
+ }
+
+ @Inject
+ DispatchServiceImpl service;
+
+ @Test
+ public void exceptionThrownByHandlerIsNotWrappedInActionException() throws ServiceException {
+ try {
+ service.execute("", new SomeAction());
+ fail();
+ } catch (ActionException e) {
+ assertThat(e, instanceOf(ActionExceptionThrownByHandler.class));
+ assertEquals(0, e.getStackTrace().length);
+ assertEquals(0, e.getCause().getStackTrace().length);
+ }
+ }
+}
diff --git a/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionThrownByValidatorTest.java b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionThrownByValidatorTest.java
new file mode 100644
index 0000000000..6545b351c1
--- /dev/null
+++ b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionThrownByValidatorTest.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright 2011 ArcBees Inc.
+ *
+ * Licensed 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 com.gwtplatform.dispatch.server;
+
+import javax.inject.Inject;
+
+import org.jukito.JukitoModule;
+import org.jukito.JukitoRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.gwtplatform.dispatch.server.guice.DispatchServiceImpl;
+import com.gwtplatform.dispatch.shared.ActionException;
+import com.gwtplatform.dispatch.shared.ServiceException;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@RunWith(JukitoRunner.class)
+public class ActionThrownByValidatorTest {
+ public static class MyModule extends JukitoModule {
+ @Override
+ protected void configureTest() {
+ install(new ServiceModule(ActionValidatorThatThrows.class));
+ }
+ }
+
+ @Inject
+ DispatchServiceImpl service;
+
+ @Test
+ public void exceptionThrownByValidatorIsNotWrappedInActionException() throws ServiceException {
+ try {
+ service.execute("", new SomeAction());
+ fail();
+ } catch (ActionException e) {
+ assertThat(e, instanceOf(ActionExceptionThrownByValidator.class));
+ assertEquals(0, e.getStackTrace().length);
+ assertEquals(0, e.getCause().getStackTrace().length);
+ }
+ }
+}
diff --git a/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionValidatorThatThrows.java b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionValidatorThatThrows.java
new file mode 100644
index 0000000000..992df0d805
--- /dev/null
+++ b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ActionValidatorThatThrows.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2011 ArcBees Inc.
+ *
+ * Licensed 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 com.gwtplatform.dispatch.server;
+
+import com.gwtplatform.dispatch.server.actionvalidator.ActionValidator;
+import com.gwtplatform.dispatch.shared.Action;
+import com.gwtplatform.dispatch.shared.ActionException;
+import com.gwtplatform.dispatch.shared.Result;
+
+public class ActionValidatorThatThrows implements ActionValidator {
+ @Override
+ public boolean isValid(Action extends Result> action) throws ActionException {
+ throw new ActionExceptionThrownByValidator(new Exception());
+ }
+}
diff --git a/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/HandlerThatThrowsActionException.java b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/HandlerThatThrowsActionException.java
new file mode 100644
index 0000000000..4ca686085b
--- /dev/null
+++ b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/HandlerThatThrowsActionException.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright 2011 ArcBees Inc.
+ *
+ * Licensed 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 com.gwtplatform.dispatch.server;
+
+import javax.inject.Inject;
+
+import com.gwtplatform.dispatch.server.actionhandler.AbstractActionHandler;
+import com.gwtplatform.dispatch.shared.ActionException;
+import com.gwtplatform.dispatch.shared.NoResult;
+
+public class HandlerThatThrowsActionException extends AbstractActionHandler {
+ @Inject
+ HandlerThatThrowsActionException() {
+ super(SomeAction.class);
+ }
+
+ @Override
+ public NoResult execute(SomeAction action, ExecutionContext context) throws ActionException {
+ throw new ActionExceptionThrownByHandler(new Exception());
+ }
+
+ @Override
+ public void undo(SomeAction action, NoResult result, ExecutionContext context) throws ActionException {
+ }
+}
diff --git a/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ServiceModule.java b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ServiceModule.java
new file mode 100644
index 0000000000..5d1a7647b1
--- /dev/null
+++ b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/ServiceModule.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright 2011 ArcBees Inc.
+ *
+ * Licensed 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 com.gwtplatform.dispatch.server;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Singleton;
+import com.gwtplatform.dispatch.server.actionhandler.ActionHandler;
+import com.gwtplatform.dispatch.server.actionhandlervalidator.ActionHandlerValidatorClass;
+import com.gwtplatform.dispatch.server.actionhandlervalidator.ActionHandlerValidatorMap;
+import com.gwtplatform.dispatch.server.actionhandlervalidator.ActionHandlerValidatorMapImpl;
+import com.gwtplatform.dispatch.server.actionhandlervalidator.ActionHandlerValidatorRegistry;
+import com.gwtplatform.dispatch.server.actionvalidator.ActionValidator;
+import com.gwtplatform.dispatch.server.guice.DispatchImpl;
+import com.gwtplatform.dispatch.server.guice.actionhandlervalidator.ActionHandlerValidatorLinker;
+import com.gwtplatform.dispatch.server.guice.actionhandlervalidator.LazyActionHandlerValidatorRegistryImpl;
+import com.gwtplatform.dispatch.shared.Action;
+import com.gwtplatform.dispatch.shared.Result;
+
+public class ServiceModule extends AbstractModule {
+ private final Class extends ActionValidator> actionValidator;
+
+ public ServiceModule(Class extends ActionValidator> actionValidator) {
+ this.actionValidator = actionValidator;
+ }
+
+ @Override
+ protected void configure() {
+ bind(Dispatch.class).to(DispatchImpl.class);
+ bind(ActionHandlerValidatorRegistry.class).to(
+ LazyActionHandlerValidatorRegistryImpl.class).in(Singleton.class);
+
+ bindHandler(SomeAction.class, HandlerThatThrowsActionException.class, actionValidator);
+ requestStaticInjection(ActionHandlerValidatorLinker.class);
+ }
+
+ protected , R extends Result> void bindHandler(
+ Class actionClass, Class extends ActionHandler> handlerClass,
+ Class extends ActionValidator> actionValidator) {
+
+ bind(ActionHandlerValidatorMap.class).toInstance(
+ new ActionHandlerValidatorMapImpl(actionClass,
+ new ActionHandlerValidatorClass(handlerClass, actionValidator)));
+ }
+}
diff --git a/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/SomeAction.java b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/SomeAction.java
new file mode 100644
index 0000000000..0d7afae00f
--- /dev/null
+++ b/gwtp-core/gwtp-dispatch-server-guice/src/test/java/com/gwtplatform/dispatch/server/SomeAction.java
@@ -0,0 +1,32 @@
+/**
+ * Copyright 2011 ArcBees Inc.
+ *
+ * Licensed 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 com.gwtplatform.dispatch.server;
+
+import com.gwtplatform.dispatch.shared.Action;
+import com.gwtplatform.dispatch.shared.NoResult;
+
+public class SomeAction implements Action {
+ @Override
+ public String getServiceName() {
+ return null;
+ }
+
+ @Override
+ public boolean isSecured() {
+ return false;
+ }
+}
diff --git a/gwtp-core/gwtp-dispatch-server/src/main/java/com/gwtplatform/dispatch/server/AbstractDispatchServiceImpl.java b/gwtp-core/gwtp-dispatch-server/src/main/java/com/gwtplatform/dispatch/server/AbstractDispatchServiceImpl.java
index 81f596a154..c58099a04c 100644
--- a/gwtp-core/gwtp-dispatch-server/src/main/java/com/gwtplatform/dispatch/server/AbstractDispatchServiceImpl.java
+++ b/gwtp-core/gwtp-dispatch-server/src/main/java/com/gwtplatform/dispatch/server/AbstractDispatchServiceImpl.java
@@ -48,15 +48,13 @@
public abstract class AbstractDispatchServiceImpl extends RemoteServiceServlet implements DispatchService {
private static final long serialVersionUID = -4753225025940949024L;
private static final String noSecurityCookieMessage = "You have to define a security cookie in order to use " +
- "secured actions. See com.gwtplatform.dispatch.shared" +
- ".SecurityCookie for details.";
+ "secured actions. See com.gwtplatform.dispatch.shared" +
+ ".SecurityCookie for details.";
private static final String xsrfAttackMessage = "Cookie provided by RPC doesn't match request cookie, " +
- "aborting action, possible XSRF attack. (Maybe you forgot to set " +
- "the security cookie?)";
-
+ "aborting action, possible XSRF attack. (Maybe you forgot to set " +
+ "the security cookie?)";
protected final Dispatch dispatch;
protected final Logger logger;
-
protected RequestProvider requestProvider;
protected AbstractDispatchServiceImpl(Logger logger,
@@ -71,6 +69,12 @@ public String getSecurityCookieName() {
return null;
}
+ /**
+ * {@link ActionException} and {@link ServiceException} will have their stacktraces (and stacktraces of their
+ * causes) removed for security purposes.
+ *
+ * @see {@link DispatchService} for further API docs
+ */
@Override
public Result execute(String cookieSentByRPC, Action> action) throws ActionException, ServiceException {
@@ -86,22 +90,24 @@ public Result execute(String cookieSentByRPC, Action> action) throws ActionExc
} catch (ActionException e) {
if (logger.isLoggable(Level.WARNING)) {
String newMessage = "Action exception while executing " + action.getClass().getName() + ": " +
- e.getMessage();
+ e.getMessage();
logger.log(Level.WARNING, newMessage, e);
}
- throw new ActionException(e.getMessage());
+ removeStacktraces(e);
+
+ throw e;
} catch (ServiceException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "Service exception while executing " + action.getClass().getName() + ": " +
- e.getMessage(), e);
+ e.getMessage(), e);
}
throw new ServiceException(e.getMessage());
} catch (RuntimeException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "Unexpected exception while executing " + action.getClass().getName() + ": " +
- "" + e.getMessage(), e);
+ "" + e.getMessage(), e);
}
throw new ServiceException(e.getMessage());
@@ -178,4 +184,16 @@ private boolean cookieMatch(String cookieSentByRPC) throws ServiceException {
return cookieInRequest.equals(cookieSentByRPC);
}
+
+ /**
+ * Recursively removes all stacktraces from a Throwable and its cause
+ */
+ private void removeStacktraces(Throwable e) {
+ if (e == null) {
+ return;
+ }
+
+ e.setStackTrace(new StackTraceElement[]{});
+ removeStacktraces(e.getCause());
+ }
}