5 Replies Latest reply on Dec 7, 2007 5:54 PM by derek.adams

    change HTTP status code in a WS fault

    james_chiu

      Hi,


      We are using JBoss WS 1.2.1 in our server side.

      Our client side is implemented in Flex and it communicates with the server side through JBoss WS.

      Flex can?t not handle a WebFault that gives HTTP status code = 500.

      Therefore, we are looking for a way that we can change HTTP status code from 500 to 200 when throwing an exception.



      Would be very appreciated if you can shed some light how to change HTTP status code from 500 to 200.


      Use a handler, servlet, ?

      Thanks,

      James

        • 1. Re: change HTTP status code in a WS fault
          wpfeiffe

          James,

          Sorry I don't have an answer for you on this, but I just ran into this a few days ago and was wondering if you had a solution.

          So far I considered creating my own wrapper obect that would be returned by all web services and would contain fault info.

          Also considered dropping JBossWS and using xFire as I've seen examples on how to set the status code with xFire (some dissension concerning whether it actually works though).

          Also considered just doing a rest style xml return which flex seems to handle quite nicely.

          Really my preference is to do some kind of interceptor that would let me set the status code. I already do some pre-processing of my hibernate return objects to kill the proxies which is believe should be in an interceptor as well. Just not sure where to start there.

          Anyway, I'd be interested in hearing how you solve this, if you do.

          Thanks,

          Bill Pfeiffer

          • 2. Re: change HTTP status code in a WS fault
            oskar.carlstedt

            Hi All!

            I'm not sure if this works, but an idéa might be to implement a simple servlet filter that you put in front of the servlet. The filter will then invoke the http request, check the response code and change it if necessary.

            A normal servlet has a filter chain, and I think you can configure one in web.xml for this kind of servlet too.

            Best regards
            Oskar

            • 3. Re: change HTTP status code in a WS fault
              wpfeiffe

              Oskar,

              I could be wrong on this, but I don't think you have direct access to the servlet handling in the context where JBossWS deploys the web services (like you would within a regular servlet container).

              I think the handlers are meant to allow for this type of pre-post processing, but I haven't seen any examples of using handlers to access the http mechanisms such as the status code return, but maybe it can. I haven't looked too far into it yet.

              Bill

              • 4. Re: change HTTP status code in a WS fault
                axstevens

                Something along the following lines if you can configure in a filter.

                But to a previous posters point. How do you get a filter configured when @WebService is a Session Bean, nice <web-app> example in user guide is for POJO. I guess use HTTP request/response context properties in SOAPHandler? Haven't looked to see if they are popuated yet.

                But anyway kind of problemattic with a lot of servlet filter resources already written for authentication, etc.


                public class AdobeStatusFilter implements Filter {
                 Logger log = Logger.getLogger(AdobeStatusFilter.class);
                 private FilterConfig filterConfig = null;
                
                 public void init(FilterConfig filterConfig) throws ServletException {
                 this.filterConfig = filterConfig;
                 }
                
                 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
                 AdobeResponseWrapper wrapper = new AdobeResponseWrapper((HttpServletResponse) resp);
                 HttpServletResponse response = (HttpServletResponse)resp;
                 chain.doFilter(req, wrapper);
                 }
                
                 public void destroy() {
                 this.filterConfig = null;
                 }
                
                }


                public class AdobeResponseWrapper extends HttpServletResponseWrapper {
                
                 private int statusCode;
                 public AdobeResponseWrapper(HttpServletResponse response) {
                 super(response);
                 }
                 public int getStatus() {
                 return statusCode;
                 }
                 public void sendError(int errorCode) throws IOException {
                 this.statusCode = adjust(errorCode);
                 super.sendError(this.statusCode);
                 }
                 public void sendError(int errorCode, String errorMessage) throws IOException {
                 this.statusCode = adjust(errorCode);
                 super.sendError(this.statusCode, errorMessage);
                 }
                 public void setStatus(int statusCode) {
                 this.statusCode = adjust(statusCode);
                 super.setStatus(this.statusCode);
                 }
                 public void setStatus(int statusCode, String message) {
                 this.statusCode = adjust(statusCode);
                 super.setStatus(this.statusCode, message);
                 }
                
                 private int adjust(int errorCode) {
                 return errorCode == HttpServletResponse.SC_INTERNAL_SERVER_ERROR ?
                 HttpServletResponse.SC_OK : errorCode;
                 }
                
                
                }


                • 5. Re: change HTTP status code in a WS fault
                  derek.adams

                  The only way I could figure out to do it was to change the JBossWS source code in RequestHandlerImpl. It's a small change, but since it violates the "must return a 500 on fault" rule, I doubt it's going to get added as a perm fix. I wish there was a way to make flex work with the 500 error code :-( ... The fix is for the 2.0.0.GA source under org.jboss.wsf.stack.jbws.RequestHandlerImpl at line 287.. change it to..

                  if (httpResponse != null && code == null && isFault)
                   {
                   httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                   }
                  


                  This way.. if the response code is set in a handler, it overrides the 500 response code. The only thing left to do is register a handler on the web service via the @HandlerChain annotation. The handler should have the following method...

                  /*
                   * (non-Javadoc)
                   *
                   * @see javax.xml.ws.handler.Handler#close(javax.xml.ws.handler.MessageContext)
                   */
                   public void close(MessageContext context) {
                   context.put(MessageContextJAXWS.HTTP_RESPONSE_CODE, new Integer(200));
                   context.setScope(MessageContextJAXWS.HTTP_RESPONSE_CODE, Scope.APPLICATION);
                   }
                  


                  And.. voila.. it should work with Flex. Note that this will change all 500 responses from web services to 200s. A better approach might be to add code to the handler to check if it's Flex requesting the data (via the ServletRequst passed in the message context) and only change the code in that instance.

                  Hope that helps,
                  Derek