Exception chaining is evil (because of hidden dependencies) - the solution is: 📎
But the decoupling can be (partially) achived in more simple way. Instead of stopping the exceptions chaining, the super-exception in your hierarchy should implement the java.io.Externalizable or Serializable in a special way. Instead of serializing everything, only the payload in String/XML format should be passed across the network boundaries. In that case it is not needed for the client to have all the libraries of the chained exceptions in the classpath.
To implement this you have either implement the "secret" methods from the java.io.Serializable interface:
private void writeObject(java.io.ObjectOutputStream out)In case you have an own hierarchy it is enough to implement the interface in the top-level exception.
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
or implement the Externalizable interface and so the methods:
void writeExternal(ObjectOutput out)
throws IOException
void readExternal(ObjectInput in)
throws IOException,
ClassNotFoundException
With this strategy you can pass chained exceptions to the client. But it is not always possible to catch all "technology exceptions" in a session facade.
Sometimes exceptions do occur after the completions of the transaction (e.g. optimistic collision). In that case you still need the business delegate.