Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An example exception handler for JAX-WS without code generation
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.DetailEntry;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPException;
import javax.xml.ws.Binding;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class JaxWsExceptionCatcher {
private static final class MyExceptionHandler<T> implements
InvocationHandler {
private final T port;
private MyExceptionHandler(T port) {
this.port = port;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
try {
return method.invoke(port, args);
} catch (InvocationTargetException e) {
Throwable bre = e.getTargetException().getCause();
if (bre != null && bre instanceof MyRuntimeException) {
throw bre.getCause();
}
throw e;
}
}
}
private static class MyRuntimeException extends RuntimeException {
private static final long serialVersionUID = -2143724572440079147L;
private MyRuntimeException(MyException cause) {
super(cause);
}
}
private static class MyFaultHandler implements
SOAPHandler<SOAPMessageContext> {
private final String namespace;
public MyFaultHandler(String namespace) {
this.namespace = namespace;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
try {
DetailEntry detailEntry = (DetailEntry) context.getMessage()
.getSOAPBody().getFault().getDetail()
.getDetailEntries().next();
if (detailEntry.getNamespaceURI().equals(namespace)
&& detailEntry.getLocalName().equals("MyException")) {
String code = ((Node) detailEntry.getChildElements(
new QName("code")).next()).getTextContent();
String message = ((Node) detailEntry.getChildElements(
new QName("message")).next()).getTextContent();
if (code != null && message != null) {
throw new MyRuntimeException(new MyException(code,
message));
}
}
return true;
} catch (NullPointerException e) {
// Soap fault is not in the format we expected
return true;
} catch (SOAPException e) {
return true;
}
}
@Override
public void close(MessageContext context) {
}
@Override
public Set<QName> getHeaders() {
return null;
}
}
public final static <T> T catchOn(final T port, String namespace) {
Binding binding = ((BindingProvider) port).getBinding();
List<Handler> handlerChain = binding.getHandlerChain();
handlerChain.add(new MyFaultHandler(namespace));
binding.setHandlerChain(handlerChain);
Object pi = Proxy.newProxyInstance(port.getClass().getClassLoader(),
port.getClass().getInterfaces(),
new MyExceptionHandler<T>(port));
return (T) pi;
}
}
@agaoglu
Copy link
Author

agaoglu commented Dec 6, 2011

See the post for some explanation on using this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment