I was asked how to transfer the server Stacktrace to the client.
Warning:
Before you implement this in your application, you should consider the security implication. A long time ago the server stack traces could be visualized in the Client. A security Audit mentioned that this is not a recommended practice.
I found this note from Ivan Motsch mentioning the change:
01.06.2011 imo
Internal security audit
- server stack traces must not be sent to client
- server log must contain all exceptions (except intended business logic exceptions)
- enhanced access control on gui remote service calls: see enahncements on IAccessControlService.checkServiceTunnelAccess
- adding logout service and calling it from IClientSession.stop();
How to do it:
1/ You need your own TransactionDelegate class:
The easiest way is to extend DefaultTransactionDelegate and to override replaceOutboundException(Throwable):
import org.eclipse.scout.rt.server.DefaultTransactionDelegate;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
public class MyAppTransactionDelegate extends DefaultTransactionDelegate {
public MyAppTransactionDelegate(Bundle[] loaderBundles, Version requestMinVersion, boolean debug) {
super(loaderBundles, requestMinVersion, debug);
}
@Override
protected Throwable replaceOutboundException(Throwable t) {
return t;
}
}
In our case we do not want to replace anything so we just return the exception.
2/ After that you need your own service tunnel (MyAppServiceTunnelServlet) that will work with your TransactionDelegate class created in step 1:
import org.eclipse.scout.rt.server.ServiceTunnelServlet;
import org.eclipse.scout.rt.shared.servicetunnel.ServiceTunnelRequest;
import org.eclipse.scout.rt.shared.servicetunnel.ServiceTunnelResponse;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
public class MyAppServiceTunnelServlet extends ServiceTunnelServlet {
private static final long serialVersionUID = 1L;
@Override
protected ServiceTunnelResponse runServerJobTransactionWithDelegate(ServiceTunnelRequest req, Bundle[] loaderBundles, Version requestMinVersion, boolean debug) throws Exception {
return new MyAppTransactionDelegate(loaderBundles, requestMinVersion, debug).invoke(req);
}
}
3/ Register your service tunnel servlet in the server XML. Search for the servlet declaration with the alias "/process" and replace the class attribute with your new class created in step 2:
<servlet
alias="/process"
class="myapp.server.servlets.MyAppServiceTunnelServlet">
<init-param
name="min-version"
value="0.0.0">
</init-param>
</servlet>
That's it, you will see the server stacktrace in the client. Depending on your use case you can improve the replaceOutboundException(Throwable) method defined in step 1.
I hope it helps. Feel free to discuss the approach.
.