3 Replies Latest reply on Feb 25, 2014 11:26 AM by Viliam Kasala

    Webapplication exception on rest request causes ClasscastException

    Gerhard Visagie Newbie

      I have a rest interface exposed for clients to call. Furing processing in the bean, we do the following:

       

      throw new WebApplicationException(HttpURLConnection.HTTP_NOT_FOUND);

       

      What we are now seeing is the following in the logs:

       

      ervice() for servlet RestEasy threw exception: org.jboss.resteasy.spi.UnhandledException: java.lang.ClassCastException: org.switchyard.component.bean.BeanComponentException cannot be cast to java.lang.String

              at org.jboss.resteasy.core.SynchronousDispatcher.handleApplicationException(SynchronousDispatcher.java:340) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.core.SynchronousDispatcher.handleException(SynchronousDispatcher.java:214) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.core.SynchronousDispatcher.handleInvokerException(SynchronousDispatcher.java:190) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:540) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:502) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:119) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:208) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:55) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:50) [resteasy-jaxrs-2.3.2.Final.jar:]

              at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]

              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)

              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)

              at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)

              at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)

              at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)

              at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

              at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

              at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368)

              at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)

              at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671)

              at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930)

              at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_21]

      Caused by: java.lang.ClassCastException: org.switchyard.component.bean.BeanComponentException cannot be cast to java.lang.String

              at com.sun.proxy.$Proxy44.sendPairingRequest(Unknown Source)

              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_21]

              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_21]

              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_21]

              at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_21]

              at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:155) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.core.ResourceMethod.invokeOnTarget(ResourceMethod.java:257) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:222) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.core.ResourceMethod.invoke(ResourceMethod.java:211) [resteasy-jaxrs-2.3.2.Final.jar:]

              at org.jboss.resteasy.core.SynchronousDispatcher.getResponse(SynchronousDispatcher.java:525) [resteasy-jaxrs-2.3.2.Final.jar:]

              ... 18 more

       

      Which I found was being caused by this in org.switchyard.component.bean.ServiceProxyHandler :

       

                  } catch (Exception ex) {

                      String errMsg = "Invocation of operation '" + invocation.getMethod().getName()

                              + "' on bean component '" + _serviceBean.getClass().getName() + "failed.";

                      // write error details to log

                      if (exchangePattern == ExchangePattern.IN_ONLY) {

                          _logger.warn(errMsg, ex);

                      } else if (_logger.isDebugEnabled()) {

                          _logger.debug(errMsg, ex);

                      }

       

                      // if exchange supports fault, send one

                      if (exchangePattern == ExchangePattern.IN_OUT) {

                          Throwable faultContent = ex;

                          if (faultContent instanceof InvocationTargetException) {

                              faultContent = ((InvocationTargetException)ex).getTargetException();

                          }

                          throw new BeanComponentException(faultContent);

                      }

       

                  }

       

       

      What I am doing wrong?

       

      EDIT:

       

      Attached is a sample project (out of elipse). I have tested this and get EXACTLY the same problem. In the target folder is jar file that can be deployed to SY 080.

        • 1. Re: Webapplication exception on rest request causes ClasscastException
          Keith Babo Master

          Bottom line here is that RESTEasy gateway needs to introduce special handling for fault states, which I describe in this JIRA:

          https://issues.jboss.org/browse/SWITCHYARD-1601


          The bean component is just wrapping a runtime exception, so it's not the source of the problem here.

           

          It's not a dead end though as this can easily be addressed by adding a custom message composer which maps the exception to the expected return type of your JAX-RS interface.  I have attached a modified version of your project which includes three changes:

           

          1) A new ErrorMapper message composer class.

          2) switchyard.xml updated to point to custom composer.

          3) A new unit test added to demonstrate it works.

           

          My example is trivial and hacky.  You can actually get pretty sophisticated here if you like.  For example, you could return a javax.ws.rs.core.Response object from your JAX-RS interface and then in your composer populate that object with response code, message, etc.

          • 2. Re: Webapplication exception on rest request causes ClasscastException
            Gerhard Visagie Newbie

            Thanks Keith;

             

            I was sure that they worked in the past, but as my collegue pointed out, the error codes I was seeing could have been actual 403 and 404's and not because they were thrown by the app.

            • 3. Re: Webapplication exception on rest request causes ClasscastException
              Viliam Kasala Newbie

              Hi,

               

              I have a few questions about Switchyard Rest binding and custom message composer. I would be very gratefull, if you answer my questions.

               

              My goal is to return different http response codes. I am not sure if I understand the second option "For example, you could return a javax.ws.rs.core.Response object from your JAX-RS interface and then in your composer populate that object with response code, message, etc. "

               

              Also I am not sure, if I understand 'rest-binding' quickstart. Because  WarehouseResource's getItem method has return type of Response and in WarehouseService the return type of the same method is Item. I don't understand this usage and how it works. Could you explain it to me?

               

              Can I use instead of Response return type the Item type and also use custom mapper to modify http response code?

               

              I hope I write it clear enough. Thank you very much for the answer and for your time.

               

              Thanks!