Hi,

I am using *Dropwizard v1.1.3* with *Java 1.8* to implement a *SOAP Service*. 
I found that if I raise exceptions in my *SOAP* resource class then these 
get converted to a *SOAP Fault* message of the form:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/";>
    <soap:Body>
        <soap:Fault>
            <faultcode>soap:Server</faultcode>
            <faultstring>...my error message goes here...</faultstring>
        </soap:Fault>
    </soap:Body>
</soap:Envelope>

This is not an issue as it was what I expected.

My *SOAP* resource raises *WebApplicationException* messages which has a 
facility to also indicate what *HTTP* status code to return to the client, 
e.g.:

throw new WebApplicationException("something went wrong", 
HttpStatus.SC_UNPROCESSABLE_ENTITY);

What I found was that no matter what *HTTP* status code I specify in the 
*WebApplicationException*, the client always gets a status code of *500*.

I therefore thought I'd create my own exception mapper that created a *SOAP 
Fault* and returned the correct *HTTP* status code. I therefore created 
this class:

public class SoapException extends RuntimeException

{

    private static final long serialVersionUID = 1L;


    private final int statusCode;


    public SoapException(final String message, final int statusCode)

    {

        super(message);


        this.statusCode = statusCode;

    }


    public int getStatusCode()

    {

        return statusCode;

    }

}

and changed my exceptions to use this as follows:

throw new SoapException("something went wrong", 
HttpStatus.SC_UNPROCESSABLE_ENTITY);

I also created an exception mapper as follows:

import javax.ws.rs.core.MediaType;

import javax.ws.rs.core.Response;

import javax.ws.rs.ext.ExceptionMapper;


public class SoapExceptionMapper implements ExceptionMapper<SoapException>

{

    private static final String FAULT_TEMPLATE =

                    "<soap:Envelope 
xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\";>\n" +

                                    "    <soap:Body>\n" +

                                    "        <soap:Fault>\n" +

                                    "            
<faultcode>soap:%s</faultcode>\n" +

                                    "            
<faultstring>%s</faultstring>\n" +

                                    "        </soap:Fault>\n" +

                                    "    </soap:Body>\n" +

                                    "</soap:Envelope>";


    @Override

    public Response toResponse(final SoapException exception)

    {

        final int statusCode = exception.getStatusCode();

        final String faultMessage = String.format(FAULT_TEMPLATE, statusCode 
>= 500 ? "Server" : "Client", exception.getMessage());

        return Response.status(statusCode).entity(faultMessage
).type(MediaType.TEXT_XML).build();

    }

}

and registered this mapper in my main application as follows:

import com.roskart.dropwizard.jaxws.EndpointBuilder;

import com.roskart.dropwizard.jaxws.JAXWSBundle;


import io.dropwizard.Application;

import io.dropwizard.setup.Bootstrap;

import io.dropwizard.setup.Environment;


public class MyApp extends Application<MyAppConfiguration>

{

    private static final JAXWSBundle<Object> JAX_WS_BUNDLE = new 
JAXWSBundle<>("/soap");


    public static void main(final String[] args) throws Exception

    {

        new MyApp().run(args);

    }


    @Override

    public String getName()

    {

        return "my app";

    }


    @Override

    public void initialize(final Bootstrap<MyAppConfiguration> bootstrap)

    {

        bootstrap.addBundle(JAX_WS_BUNDLE);

    }


    @Override

    public void run(final MyAppConfiguration configuration, final 
Environment environment)

    {

        environment.jersey().register(new SoapExceptionMapper());


        JAX_WS_BUNDLE.publishEndpoint(new EndpointBuilder("/", new 
MySoapService(configuration));

    }

}

After doing all this I found that my exception mapper is never invoked.

Am I doing something wrong here? Is there a better mechanism for achieving 
what I want (i.e. have application-specific HTTP status codes returned to 
the client on errors)?

For reference, my SOAP resource implements the following interface:

import javax.jws.WebMethod;

import javax.jws.WebParam;

import javax.jws.WebResult;

import javax.jws.WebService;

import javax.jws.soap.SOAPBinding;

import javax.jws.soap.SOAPBinding.ParameterStyle;

import javax.jws.soap.SOAPBinding.Style;

import javax.jws.soap.SOAPBinding.Use;


@WebService(name="mySoapService", targetNamespace="http://my.app.com";)

@SOAPBinding(style=Style.DOCUMENT, use=Use.LITERAL, 
parameterStyle=ParameterStyle.WRAPPED)

public interface MySoapService

{

    @WebMethod(operationName="GetStuff", action="http://my.app.com/GetStuff";
)

    @WebResult(name="Stuff")

    Stuff getProducts(@WebParam(name="Request") StuffRequest request);

}

and I see this stack trace when I raise the exception:

org.apache.cxf.interceptor.Fault: something went wrong

at org.apache.cxf.service.invoker.AbstractInvoker.createFault(
AbstractInvoker.java:162)

at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.createFault(
AbstractJAXWSMethodInvoker.java:267)

at org.apache.cxf.service.invoker.AbstractInvoker.invoke(
AbstractInvoker.java:128)

at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.invoke(
AbstractJAXWSMethodInvoker.java:232)

at org.apache.cxf.jaxws.JAXWSMethodInvoker.invoke(JAXWSMethodInvoker.java:85
)

at org.apache.cxf.service.invoker.AbstractInvoker.invoke(
AbstractInvoker.java:74)

at com.roskart.dropwizard.jaxws.ValidatingInvoker.invoke(
ValidatingInvoker.java:68)

at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(
ServiceInvokerInterceptor.java:59)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

at java.util.concurrent.FutureTask.run(FutureTask.java:266)

at org.apache.cxf.interceptor.ServiceInvokerInterceptor$2.run(
ServiceInvokerInterceptor.java:126)

at org.apache.cxf.workqueue.SynchronousExecutor.execute(
SynchronousExecutor.java:37)

at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(
ServiceInvokerInterceptor.java:131)

at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(
PhaseInterceptorChain.java:308)

at org.apache.cxf.transport.ChainInitiationObserver.onMessage(
ChainInitiationObserver.java:121)

at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(
AbstractHTTPDestination.java:262)

at org.apache.cxf.transport.servlet.ServletController.invokeDestination(
ServletController.java:234)

at org.apache.cxf.transport.servlet.ServletController.invoke(
ServletController.java:208)

at org.apache.cxf.transport.servlet.ServletController.invoke(
ServletController.java:160)

at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(
CXFNonSpringServlet.java:180)

at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(
AbstractHTTPServlet.java:299)

at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(
AbstractHTTPServlet.java:218)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)

at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(
AbstractHTTPServlet.java:274)

at io.dropwizard.jetty.NonblockingServletHolder.handle(
NonblockingServletHolder.java:49)

at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(
ServletHandler.java:1650)

at io.dropwizard.servlets.ThreadNameFilter.doFilter(ThreadNameFilter.java:34
)

at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(
ServletHandler.java:1637)

at io.dropwizard.jersey.filter.AllowedMethodsFilter.handle(
AllowedMethodsFilter.java:50)

at io.dropwizard.jersey.filter.AllowedMethodsFilter.doFilter(
AllowedMethodsFilter.java:44)

at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(
ServletHandler.java:1637)

at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533
)

at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(
ScopedHandler.java:188)

at org.eclipse.jetty.server.handler.ContextHandler.doHandle(
ContextHandler.java:1253)

at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(
ScopedHandler.java:168)

at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)

at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(
ScopedHandler.java:166)

at org.eclipse.jetty.server.handler.ContextHandler.doScope(
ContextHandler.java:1155)

at org.eclipse.jetty.server.handler.ScopedHandler.handle(
ScopedHandler.java:141)

at org.eclipse.jetty.server.handler.HandlerWrapper.handle(
HandlerWrapper.java:132)

at com.codahale.metrics.jetty9.InstrumentedHandler.handle(
InstrumentedHandler.java:241)

at io.dropwizard.jetty.ContextRoutingHandler.handle(
ContextRoutingHandler.java:38)

at org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(
GzipHandler.java:454)

at io.dropwizard.jetty.BiDiGzipHandler.handle(BiDiGzipHandler.java:68)

at org.eclipse.jetty.server.handler.RequestLogHandler.handle(
RequestLogHandler.java:56)

at org.eclipse.jetty.server.handler.StatisticsHandler.handle(
StatisticsHandler.java:169)

at org.eclipse.jetty.server.handler.HandlerWrapper.handle(
HandlerWrapper.java:132)

at org.eclipse.jetty.server.Server.handle(Server.java:564)

at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:317)

at org.eclipse.jetty.server.HttpConnection.onFillable(
HttpConnection.java:251)

at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(
AbstractConnection.java:279)

at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110)

at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)

at org.eclipse.jetty.util.thread.Invocable.invokePreferred(
Invocable.java:128)

at org.eclipse.jetty.util.thread.Invocable$InvocableExecutor.invoke(
Invocable.java:222)

at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(
EatWhatYouKill.java:294)

at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(
EatWhatYouKill.java:126)

at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(
QueuedThreadPool.java:673)

at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(
QueuedThreadPool.java:591)

at java.lang.Thread.run(Thread.java:745)
        ...


Thanks in advance.

-- 
You received this message because you are subscribed to the Google Groups 
"dropwizard-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to dropwizard-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to